Skip to main content

ferroui_base/input/
input_element.rs

1use super::gesture_recognizers::GestureRecognizerCollection;
2use super::text_input::TextInputMethodClientRequestedEventArgs;
3use super::{
4    AccessKeyHandler, KeyBinding,
5    ContextRequestedEventArgs, Cursor, ICustomKeyboardNavigation, IScrollable, FocusChangedEventArgs, FocusChangingEventArgs, FocusManager, Gestures,
6    HoldingRoutedEventArgs, IInputElement, KeyEventArgs, KeyModifiers, KeyboardNavigation, NavigationMethod,
7    PointerCaptureChangingEventArgs, PointerCaptureLostEventArgs, PointerEventArgs, PointerPressedEventArgs,
8    PointerReleasedEventArgs, PointerWheelEventArgs, TappedEventArgs, TextInputEventArgs,
9};
10use crate::interactivity::{
11    IRoutedEventArgs, Interactive, InteractiveImpl, RoutedEvent, RoutedEventArgs, RoutedEventHandlerToken,
12    RoutingStrategies,
13};
14use crate::layout::LayoutableImpl;
15use crate::visual_tree::IHostedVisualTreeRoot;
16use crate::{
17    ferro_class, ferro_impl_classes, ferro_property, ferro_routed_event, instantiate, DirectProperty,
18    FerroObjectImpl, FerroObjectImplExt, FerroProperty, FerroPropertyChangedEventArgs, Ref, StyledElementImpl,
19    StyledProperty, StyledPropertyOptions, Visual, VisualImpl, VisualImplExt, VisualTreeAttachmentEventArgs,
20};
21use crate::collections::FerroList;
22use std::cell::{Cell, OnceCell};
23use std::rc::Rc;
24
25/// Implements input-related functionality for a control.
26///
27/// The pseudoclasses `:disabled`, `:focus`, `:focus-visible`,
28/// `:focus-within` and `:pointerover` reflect the input state of the
29/// element.
30#[repr(C)]
31pub struct InputElement {
32    base: Interactive,
33    is_effectively_enabled: Cell<bool>,
34    is_focused: Cell<bool>,
35    is_keyboard_focus_within: Cell<bool>,
36    is_focus_visible: Cell<bool>,
37    is_pointer_over: Cell<bool>,
38    pub(super) is_context_menu_on_holding: Cell<bool>,
39    key_bindings: OnceCell<FerroList<Ref<KeyBinding>>>,
40    gesture_recognizers: OnceCell<GestureRecognizerCollection>,
41}
42
43ferro_class! {
44    InputElement: Interactive, virtuals InputElementImpl: InteractiveImpl {
45        /// Whether the control is enabled, as far as the control itself is
46        /// concerned. The default is the value of `is_enabled`; controls
47        /// with additional conditions (e.g. a command that cannot execute)
48        /// override this.
49        fn is_enabled_core(this) -> bool;
50        /// Whether the element is a focus scope: an element that remembers
51        /// which of its descendants was focused last.
52        fn is_focus_scope(this) -> bool;
53        /// Called when the control or one of its child elements is about to
54        /// get focus.
55        fn on_getting_focus(this, e: &FocusChangingEventArgs);
56        /// Called when the control or one of its child elements is about to
57        /// lose focus.
58        fn on_losing_focus(this, e: &FocusChangingEventArgs);
59        /// Called when the control or one of its child elements gets focus.
60        fn on_got_focus(this, e: &FocusChangedEventArgs);
61        /// Called when the control or one of its child elements loses
62        /// focus.
63        fn on_lost_focus(this, e: &FocusChangedEventArgs);
64        /// Called before the key down event occurs.
65        fn on_key_down(this, e: &KeyEventArgs);
66        /// Called before the key up event occurs.
67        fn on_key_up(this, e: &KeyEventArgs);
68        /// Called before the text input event occurs.
69        fn on_text_input(this, e: &TextInputEventArgs);
70        /// Called before the pointer entered event occurs.
71        fn on_pointer_entered(this, e: &PointerEventArgs);
72        /// Called before the pointer exited event occurs.
73        fn on_pointer_exited(this, e: &PointerEventArgs);
74        /// Called before the pointer moved event occurs.
75        fn on_pointer_moved(this, e: &PointerEventArgs);
76        /// Called before the pointer pressed event occurs.
77        fn on_pointer_pressed(this, e: &PointerPressedEventArgs);
78        /// Called before the pointer released event occurs.
79        fn on_pointer_released(this, e: &PointerReleasedEventArgs);
80        /// Called when the capture of a pointer is about to change on the
81        /// control or one of its descendants.
82        fn on_pointer_capture_changing(this, e: &PointerCaptureChangingEventArgs);
83        /// Called before the pointer capture lost event occurs.
84        fn on_pointer_capture_lost(this, e: &PointerCaptureLostEventArgs);
85        /// Called before the pointer wheel changed event occurs.
86        fn on_pointer_wheel_changed(this, e: &PointerWheelEventArgs);
87        /// Called when a tap gesture occurs on the control.
88        fn on_tapped(this, e: &TappedEventArgs);
89        /// Called when a right tap gesture occurs on the control.
90        fn on_right_tapped(this, e: &TappedEventArgs);
91        /// Called when a double-tap gesture occurs on the control.
92        fn on_double_tapped(this, e: &TappedEventArgs);
93        /// Called when a hold gesture occurs on the control.
94        fn on_holding(this, e: &HoldingRoutedEventArgs);
95        /// Called when the access key of the control is pressed. The
96        /// default focuses the control.
97        fn on_access_key(this, e: &dyn IRoutedEventArgs);
98        /// Called when focus is moving forward out of this element: lets it
99        /// name the element that should receive focus next.
100        fn get_next_tab_stop_override(this) -> Option<Ref<InputElement>>;
101        /// Called when focus is moving backward out of this element: lets
102        /// it name the element that should receive focus next.
103        fn get_previous_tab_stop_override(this) -> Option<Ref<InputElement>>;
104        /// Lets the element name the first focusable element within it.
105        fn get_first_focusable_element_override(this) -> Option<Ref<InputElement>>;
106        /// Lets the element name the last focusable element within it.
107        fn get_last_focusable_element_override(this) -> Option<Ref<InputElement>>;
108        /// Lets the element (an ancestor of the focused element) override
109        /// the tab stop chosen by tab navigation. Returns true when the tab
110        /// stop is overridden; the override is written to `new_tab_stop`.
111        fn process_tab_stop_override(
112            this,
113            focused_element: Option<&Ref<InputElement>>,
114            candidate_tab_stop_element: Option<&Ref<InputElement>>,
115            is_reverse: bool,
116            did_cycle_focus_at_root_visual: bool,
117            new_tab_stop: &mut Option<Ref<InputElement>>
118        ) -> bool;
119        /// Lets the element (an ancestor of the candidate tab stop)
120        /// override the tab stop chosen by tab navigation. Returns true
121        /// when the tab stop is overridden; the override is written to
122        /// `new_tab_stop`.
123        fn process_candidate_tab_stop_override(
124            this,
125            focused_element: Option<&Ref<InputElement>>,
126            candidate_tab_stop_element: Option<&Ref<InputElement>>,
127            overriden_candidate_tab_stop_element: Option<&Ref<InputElement>>,
128            is_reverse: bool,
129            new_tab_stop: &mut Option<Ref<InputElement>>
130        ) -> bool;
131        /// The element as a custom keyboard navigation handler, if it is
132        /// one.
133        fn as_custom_keyboard_navigation(this) -> Option<&dyn ICustomKeyboardNavigation>;
134        /// The element as a scrollable, if it is one.
135        fn as_scrollable(this) -> Option<&dyn IScrollable>;
136        /// The element as the root of a hosted visual tree (such as a
137        /// popup root), if it is one.
138        fn as_hosted_visual_tree_root(this) -> Option<&dyn IHostedVisualTreeRoot>;
139    }
140}
141crate::ferro_class_info!(InputElement { new: InputElement::new });
142
143ferro_impl_classes!(InputElement: StyledElementImpl, LayoutableImpl, InteractiveImpl);
144
145crate::ferro_overrides! { impl FerroObjectImpl for InputElement {
146    fn constructed(this: &Self) {
147        Self::parent_constructed(this);
148        this.update_pseudo_classes(Some(this.is_focused()), Some(this.is_pointer_over()));
149    }
150
151    fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
152        Self::parent_on_property_changed(this, change);
153
154        let property = change.property();
155
156        if property == Self::is_focused_property().as_property() {
157            this.update_pseudo_classes(Some(change.get_new_value::<bool>()), None);
158        } else if property == Self::is_pointer_over_property().as_property() {
159            this.update_pseudo_classes(None, Some(change.get_new_value::<bool>()));
160        } else if property == Self::is_keyboard_focus_within_property().as_property() {
161            this.pseudo_classes().set(":focus-within", change.get_new_value::<bool>());
162        } else if property == Visual::is_visible_property().as_property()
163            && !change.get_new_value::<bool>()
164            && this.is_keyboard_focus_within()
165        {
166            if let Some(focus_manager) = FocusManager::get_focus_manager(this) {
167                match (focus_manager.get_focused_element(), this.visual_parent()) {
168                    (Some(focused_element), Some(visual_parent)) => {
169                        focus_manager.clear_focus_on_element_removed(&focused_element, &visual_parent);
170                    }
171                    _ => {
172                        focus_manager.focus(None, NavigationMethod::Unspecified, KeyModifiers::NONE);
173                    }
174                }
175            }
176        }
177    }
178} }
179
180impl VisualImpl for InputElement {
181    fn on_detached_from_visual_tree_core(this: &Self, e: &VisualTreeAttachmentEventArgs) {
182        Self::parent_on_detached_from_visual_tree_core(this, e);
183
184        if this.is_focused() {
185            let root = e.attachment_point().unwrap_or(e.root_visual());
186            let focus_manager = e
187                .presentation_source()
188                .input_root()
189                .focus_manager()
190                .or_else(|| FocusManager::get_focus_manager(this));
191
192            if let Some(focus_manager) = focus_manager {
193                focus_manager.clear_focus_on_element_removed(this, root);
194            }
195        }
196
197        this.set_is_keyboard_focus_within(false);
198    }
199
200    fn on_attached_to_visual_tree_core(this: &Self, e: &VisualTreeAttachmentEventArgs) {
201        Self::parent_on_attached_to_visual_tree_core(this, e);
202        this.update_is_effectively_enabled();
203    }
204}
205
206impl InputElementImpl for InputElement {
207    fn is_enabled_core(this: &Self) -> bool {
208        this.is_enabled()
209    }
210
211    fn is_focus_scope(_this: &Self) -> bool {
212        false
213    }
214
215    fn on_getting_focus(_this: &Self, _e: &FocusChangingEventArgs) {}
216
217    fn on_losing_focus(_this: &Self, _e: &FocusChangingEventArgs) {}
218
219    fn on_got_focus(_this: &Self, _e: &FocusChangedEventArgs) {}
220
221    fn on_lost_focus(_this: &Self, _e: &FocusChangedEventArgs) {}
222
223    fn on_key_down(_this: &Self, _e: &KeyEventArgs) {}
224
225    fn on_key_up(_this: &Self, _e: &KeyEventArgs) {}
226
227    fn on_text_input(_this: &Self, _e: &TextInputEventArgs) {}
228
229    fn on_pointer_entered(_this: &Self, _e: &PointerEventArgs) {}
230
231    fn on_pointer_exited(_this: &Self, _e: &PointerEventArgs) {}
232
233    fn on_pointer_moved(_this: &Self, _e: &PointerEventArgs) {}
234
235    fn on_pointer_pressed(_this: &Self, _e: &PointerPressedEventArgs) {}
236
237    fn on_pointer_released(_this: &Self, _e: &PointerReleasedEventArgs) {}
238
239    fn on_pointer_capture_changing(_this: &Self, _e: &PointerCaptureChangingEventArgs) {}
240
241    fn on_pointer_capture_lost(_this: &Self, _e: &PointerCaptureLostEventArgs) {}
242
243    fn on_pointer_wheel_changed(_this: &Self, _e: &PointerWheelEventArgs) {}
244
245    fn on_tapped(_this: &Self, _e: &TappedEventArgs) {}
246
247    fn on_right_tapped(_this: &Self, _e: &TappedEventArgs) {}
248
249    fn on_double_tapped(_this: &Self, _e: &TappedEventArgs) {}
250
251    fn on_holding(_this: &Self, _e: &HoldingRoutedEventArgs) {}
252
253    fn on_access_key(this: &Self, _e: &dyn IRoutedEventArgs) {
254        this.focus_with(NavigationMethod::Tab, KeyModifiers::NONE);
255    }
256
257    fn get_next_tab_stop_override(_this: &Self) -> Option<Ref<InputElement>> {
258        None
259    }
260
261    fn get_previous_tab_stop_override(_this: &Self) -> Option<Ref<InputElement>> {
262        None
263    }
264
265    fn get_first_focusable_element_override(_this: &Self) -> Option<Ref<InputElement>> {
266        None
267    }
268
269    fn get_last_focusable_element_override(_this: &Self) -> Option<Ref<InputElement>> {
270        None
271    }
272
273    fn process_tab_stop_override(
274        _this: &Self,
275        _focused_element: Option<&Ref<InputElement>>,
276        _candidate_tab_stop_element: Option<&Ref<InputElement>>,
277        _is_reverse: bool,
278        _did_cycle_focus_at_root_visual: bool,
279        _new_tab_stop: &mut Option<Ref<InputElement>>,
280    ) -> bool {
281        false
282    }
283
284    fn process_candidate_tab_stop_override(
285        _this: &Self,
286        _focused_element: Option<&Ref<InputElement>>,
287        _candidate_tab_stop_element: Option<&Ref<InputElement>>,
288        _overriden_candidate_tab_stop_element: Option<&Ref<InputElement>>,
289        _is_reverse: bool,
290        _new_tab_stop: &mut Option<Ref<InputElement>>,
291    ) -> bool {
292        false
293    }
294
295    fn as_custom_keyboard_navigation(_this: &Self) -> Option<&dyn ICustomKeyboardNavigation> {
296        None
297    }
298
299    fn as_scrollable(_this: &Self) -> Option<&dyn IScrollable> {
300        None
301    }
302
303    fn as_hosted_visual_tree_root(_this: &Self) -> Option<&dyn IHostedVisualTreeRoot> {
304        None
305    }
306}
307
308/// Declares the `fn name(&self, handler) -> token` method that adds a
309/// handler for a routed event, like a C# event accessor.
310macro_rules! routed_event_accessor {
311    ($(#[$meta:meta])* $name:ident, $event:ident, $args:ty) => {
312        $(#[$meta])*
313        pub fn $name(&self, handler: impl Fn(&Interactive, &$args) + 'static) -> RoutedEventHandlerToken {
314            self.add_handler(Self::$event(), handler)
315        }
316    };
317}
318
319pub(super) use routed_event_accessor;
320
321crate::ferro_properties! { impl InputElement, also [InputElement::register_gesture_properties] {
322    // --- properties ---------------------------------------------------------
323
324    ferro_property!(
325        /// Defines the `Focusable` property.
326        pub fn focusable_property() -> StyledProperty<bool> {
327            FerroProperty::register::<InputElement, _>("Focusable", false)
328        }
329    );
330
331    ferro_property!(
332        /// Defines the `IsEnabled` property.
333        pub fn is_enabled_property() -> StyledProperty<bool> {
334            FerroProperty::register::<InputElement, _>("IsEnabled", true)
335        }
336    );
337
338    ferro_property!(
339        /// Defines the `IsEffectivelyEnabled` property.
340        pub fn is_effectively_enabled_property() -> DirectProperty<InputElement, bool> {
341            FerroProperty::register_direct::<InputElement, _>(
342                "IsEffectivelyEnabled",
343                |o| o.is_effectively_enabled(),
344                None,
345                false,
346            )
347        }
348    );
349
350    ferro_property!(
351        /// Gets or sets associated mouse cursor.
352        pub fn cursor_property() -> StyledProperty<Option<Rc<Cursor>>> {
353            FerroProperty::register_with::<InputElement, _>("Cursor", StyledPropertyOptions::new(None).inherits(true))
354        }
355    );
356
357    ferro_property!(
358        /// Defines the `IsKeyboardFocusWithin` property.
359        pub fn is_keyboard_focus_within_property() -> DirectProperty<InputElement, bool> {
360            FerroProperty::register_direct::<InputElement, _>(
361                "IsKeyboardFocusWithin",
362                |o| o.is_keyboard_focus_within(),
363                None,
364                false,
365            )
366        }
367    );
368
369    ferro_property!(
370        /// Defines the `IsFocused` property.
371        pub fn is_focused_property() -> DirectProperty<InputElement, bool> {
372            FerroProperty::register_direct::<InputElement, _>("IsFocused", |o| o.is_focused(), None, false)
373        }
374    );
375
376    ferro_property!(
377        /// Defines the `IsHitTestVisible` property.
378        pub fn is_hit_test_visible_property() -> StyledProperty<bool> {
379            FerroProperty::register::<InputElement, _>("IsHitTestVisible", true)
380        }
381    );
382
383    ferro_property!(
384        /// Defines the `IsPointerOver` property.
385        pub fn is_pointer_over_property() -> DirectProperty<InputElement, bool> {
386            FerroProperty::register_direct::<InputElement, _>("IsPointerOver", |o| o.is_pointer_over(), None, false)
387        }
388    );
389
390    ferro_property!(
391        /// Defines the `IsTabStop` property.
392        pub fn is_tab_stop_property() -> StyledProperty<bool> {
393            KeyboardNavigation::is_tab_stop_property().add_owner::<InputElement>()
394        }
395    );
396
397    ferro_property!(
398        /// Defines the `TabIndex` property.
399        pub fn tab_index_property() -> StyledProperty<i32> {
400            KeyboardNavigation::tab_index_property().add_owner::<InputElement>()
401        }
402    );
403} }
404
405impl InputElement {
406    // --- routed events ------------------------------------------------------
407
408    ferro_routed_event!(
409        /// Defines the `GotFocus` event.
410        pub fn got_focus_event() -> RoutedEvent<FocusChangedEventArgs> {
411            RoutedEvent::register::<InputElement, _>("GotFocus", RoutingStrategies::BUBBLE)
412        }
413    );
414
415    ferro_routed_event!(
416        /// Defines the `GettingFocus` event.
417        pub fn getting_focus_event() -> RoutedEvent<FocusChangingEventArgs> {
418            RoutedEvent::register::<InputElement, _>("GettingFocus", RoutingStrategies::BUBBLE)
419        }
420    );
421
422    ferro_routed_event!(
423        /// Defines the `LostFocus` event.
424        pub fn lost_focus_event() -> RoutedEvent<FocusChangedEventArgs> {
425            RoutedEvent::register::<InputElement, _>("LostFocus", RoutingStrategies::BUBBLE)
426        }
427    );
428
429    ferro_routed_event!(
430        /// Defines the `LosingFocus` event.
431        pub fn losing_focus_event() -> RoutedEvent<FocusChangingEventArgs> {
432            RoutedEvent::register::<InputElement, _>("LosingFocus", RoutingStrategies::BUBBLE)
433        }
434    );
435
436    ferro_routed_event!(
437        /// Defines the `KeyDown` event.
438        pub fn key_down_event() -> RoutedEvent<KeyEventArgs> {
439            RoutedEvent::register::<InputElement, _>("KeyDown", RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE)
440        }
441    );
442
443    ferro_routed_event!(
444        /// Defines the `KeyUp` event.
445        pub fn key_up_event() -> RoutedEvent<KeyEventArgs> {
446            RoutedEvent::register::<InputElement, _>("KeyUp", RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE)
447        }
448    );
449
450    ferro_routed_event!(
451        /// Defines the `TextInput` event.
452        pub fn text_input_event() -> RoutedEvent<TextInputEventArgs> {
453            RoutedEvent::register::<InputElement, _>(
454                "TextInput",
455                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
456            )
457        }
458    );
459
460    ferro_routed_event!(
461        /// Defines the `TextInputMethodClientRequested` event.
462        pub fn text_input_method_client_requested_event() -> RoutedEvent<TextInputMethodClientRequestedEventArgs> {
463            RoutedEvent::register::<InputElement, _>(
464                "TextInputMethodClientRequested",
465                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
466            )
467        }
468    );
469
470    ferro_routed_event!(
471        /// Defines the `PointerEntered` event.
472        pub fn pointer_entered_event() -> RoutedEvent<PointerEventArgs> {
473            RoutedEvent::register::<InputElement, _>("PointerEntered", RoutingStrategies::DIRECT)
474        }
475    );
476
477    ferro_routed_event!(
478        /// Defines the `PointerExited` event.
479        pub fn pointer_exited_event() -> RoutedEvent<PointerEventArgs> {
480            RoutedEvent::register::<InputElement, _>("PointerExited", RoutingStrategies::DIRECT)
481        }
482    );
483
484    ferro_routed_event!(
485        /// Defines the `PointerMoved` event.
486        pub fn pointer_moved_event() -> RoutedEvent<PointerEventArgs> {
487            RoutedEvent::register::<InputElement, _>(
488                "PointerMoved",
489                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
490            )
491        }
492    );
493
494    ferro_routed_event!(
495        /// Defines the `PointerPressed` event.
496        pub fn pointer_pressed_event() -> RoutedEvent<PointerPressedEventArgs> {
497            RoutedEvent::register::<InputElement, _>(
498                "PointerPressed",
499                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
500            )
501        }
502    );
503
504    ferro_routed_event!(
505        /// Defines the `PointerReleased` event.
506        pub fn pointer_released_event() -> RoutedEvent<PointerReleasedEventArgs> {
507            RoutedEvent::register::<InputElement, _>(
508                "PointerReleased",
509                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
510            )
511        }
512    );
513
514    ferro_routed_event!(
515        /// Defines the `PointerCaptureChanging` routed event.
516        pub fn pointer_capture_changing_event() -> RoutedEvent<PointerCaptureChangingEventArgs> {
517            RoutedEvent::register::<InputElement, _>("PointerCaptureChanging", RoutingStrategies::DIRECT)
518        }
519    );
520
521    ferro_routed_event!(
522        /// Defines the `PointerCaptureLost` routed event.
523        pub fn pointer_capture_lost_event() -> RoutedEvent<PointerCaptureLostEventArgs> {
524            RoutedEvent::register::<InputElement, _>("PointerCaptureLost", RoutingStrategies::DIRECT)
525        }
526    );
527
528    ferro_routed_event!(
529        /// Defines the `PointerWheelChanged` event.
530        pub fn pointer_wheel_changed_event() -> RoutedEvent<PointerWheelEventArgs> {
531            RoutedEvent::register::<InputElement, _>(
532                "PointerWheelChanged",
533                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
534            )
535        }
536    );
537
538    ferro_routed_event!(
539        /// Provides event data for the `ContextRequested` event.
540        pub fn context_requested_event() -> RoutedEvent<ContextRequestedEventArgs> {
541            RoutedEvent::register::<InputElement, _>(
542                "ContextRequested",
543                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
544            )
545        }
546    );
547
548    ferro_routed_event!(
549        /// Provides event data for the `ContextCanceled` event.
550        pub fn context_canceled_event() -> RoutedEvent<RoutedEventArgs> {
551            RoutedEvent::register::<InputElement, _>(
552                "ContextCanceled",
553                RoutingStrategies::TUNNEL | RoutingStrategies::BUBBLE,
554            )
555        }
556    );
557
558    /// The static initialisation of the class: registers the class handlers
559    /// that route the input events to the `on_*` virtual members and the
560    /// gesture synthesis.
561    fn static_constructor() {
562        // Register the routed events that no class handler below refers
563        // to, so that the registry lists every event of the class once the
564        // class is initialised.
565        Self::context_requested_event();
566        Self::context_canceled_event();
567        Self::register_gesture_events();
568
569        Self::is_enabled_property().changed().subscribe(|e| {
570            if let Some(sender) = e.sender().downcast_ref::<InputElement>() {
571                sender.update_is_effectively_enabled();
572            }
573        });
574
575        Self::got_focus_event().add_class_handler::<InputElement>(|x, e| x.on_got_focus_core(e));
576        Self::lost_focus_event().add_class_handler::<InputElement>(|x, e| x.on_lost_focus_core(e));
577        Self::getting_focus_event().add_class_handler::<InputElement>(|x, e| x.on_getting_focus(e));
578        Self::losing_focus_event().add_class_handler::<InputElement>(|x, e| x.on_losing_focus(e));
579        Self::key_down_event().add_class_handler::<InputElement>(|x, e| x.on_key_down(e));
580        Self::key_up_event().add_class_handler::<InputElement>(|x, e| x.on_key_up(e));
581        Self::text_input_event().add_class_handler::<InputElement>(|x, e| x.on_text_input(e));
582        Self::pointer_entered_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_entered_core(e));
583        Self::pointer_exited_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_exited_core(e));
584        Self::pointer_moved_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_moved(e));
585        Self::pointer_pressed_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_pressed(e));
586        Self::pointer_released_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_released(e));
587        Self::pointer_capture_changing_event()
588            .add_class_handler::<InputElement>(|x, e| x.on_pointer_capture_changing(e));
589        Self::pointer_capture_lost_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_capture_lost(e));
590        Self::pointer_wheel_changed_event().add_class_handler::<InputElement>(|x, e| x.on_pointer_wheel_changed(e));
591        Self::tapped_event().add_class_handler::<InputElement>(|x, e| x.on_tapped(e));
592        Self::right_tapped_event().add_class_handler::<InputElement>(|x, e| x.on_right_tapped(e));
593        Self::double_tapped_event().add_class_handler::<InputElement>(|x, e| x.on_double_tapped(e));
594        Self::holding_event().add_class_handler::<InputElement>(|x, e| x.on_holding(e));
595
596        Gestures::TYPE.ensure_class_init();
597        Gestures::add_tapped(|s, e| {
598            if s.is::<InputElement>() {
599                s.raise_event(e);
600            }
601        });
602        Gestures::add_right_tapped(|s, e| {
603            if s.is::<InputElement>() {
604                s.raise_event(e);
605            }
606        });
607        Gestures::add_double_tapped(|s, e| {
608            if s.is::<InputElement>() {
609                s.raise_event(e);
610            }
611        });
612        Gestures::add_holding(Self::on_preview_holding);
613
614        // Access Key Handling
615        AccessKeyHandler::access_key_event().add_class_handler::<InputElement>(|x, e| x.on_access_key(e));
616
617        // Gesture only handlers
618        Self::pointer_moved_event().add_class_handler_with::<InputElement>(
619            |x, e| x.on_gesture_pointer_moved(e),
620            Interactive::DEFAULT_ROUTES,
621            true,
622        );
623        Self::pointer_pressed_event().add_class_handler_with::<InputElement>(
624            |x, e| x.on_gesture_pointer_pressed(e),
625            Interactive::DEFAULT_ROUTES,
626            true,
627        );
628        Self::pointer_released_event().add_class_handler_with::<InputElement>(
629            |x, e| x.on_gesture_pointer_released(e),
630            Interactive::DEFAULT_ROUTES,
631            true,
632        );
633        Self::pointer_capture_lost_event().add_class_handler_with::<InputElement>(
634            |x, e| x.on_gesture_pointer_capture_lost(e),
635            Interactive::DEFAULT_ROUTES,
636            true,
637        );
638    }
639
640    /// Creates the class data; see [`crate::FerroObject::construct`].
641    pub fn construct() -> Self {
642        Self {
643            base: Interactive::construct(),
644            is_effectively_enabled: Cell::new(true),
645            is_focused: Cell::new(false),
646            is_keyboard_focus_within: Cell::new(false),
647            is_focus_visible: Cell::new(false),
648            is_pointer_over: Cell::new(false),
649            is_context_menu_on_holding: Cell::new(false),
650            key_bindings: OnceCell::new(),
651            gesture_recognizers: OnceCell::new(),
652        }
653    }
654
655    pub fn new() -> Ref<Self> {
656        instantiate(Self::construct())
657    }
658
659    // --- events -------------------------------------------------------------
660
661    routed_event_accessor!(
662        /// Occurs when the control receives focus.
663        got_focus, got_focus_event, FocusChangedEventArgs
664    );
665
666    routed_event_accessor!(
667        /// Occurs before the control receives focus.
668        getting_focus, getting_focus_event, FocusChangingEventArgs
669    );
670
671    routed_event_accessor!(
672        /// Occurs when the control loses focus.
673        lost_focus, lost_focus_event, FocusChangedEventArgs
674    );
675
676    routed_event_accessor!(
677        /// Occurs before the control loses focus.
678        losing_focus, losing_focus_event, FocusChangingEventArgs
679    );
680
681    routed_event_accessor!(
682        /// Occurs when a key is pressed while the control has focus.
683        key_down, key_down_event, KeyEventArgs
684    );
685
686    routed_event_accessor!(
687        /// Occurs when a key is released while the control has focus.
688        key_up, key_up_event, KeyEventArgs
689    );
690
691    routed_event_accessor!(
692        /// Occurs when a user typed some text while the control has focus.
693        text_input, text_input_event, TextInputEventArgs
694    );
695
696    routed_event_accessor!(
697        /// Occurs when an input element gains input focus and the input
698        /// method is looking for the corresponding client.
699        text_input_method_client_requested,
700        text_input_method_client_requested_event,
701        TextInputMethodClientRequestedEventArgs
702    );
703
704    routed_event_accessor!(
705        /// Occurs when the pointer enters the control.
706        pointer_entered, pointer_entered_event, PointerEventArgs
707    );
708
709    routed_event_accessor!(
710        /// Occurs when the pointer leaves the control.
711        pointer_exited, pointer_exited_event, PointerEventArgs
712    );
713
714    routed_event_accessor!(
715        /// Occurs when the pointer moves over the control.
716        pointer_moved, pointer_moved_event, PointerEventArgs
717    );
718
719    routed_event_accessor!(
720        /// Occurs when the pointer is pressed over the control.
721        pointer_pressed, pointer_pressed_event, PointerPressedEventArgs
722    );
723
724    routed_event_accessor!(
725        /// Occurs when the pointer is released over the control.
726        pointer_released, pointer_released_event, PointerReleasedEventArgs
727    );
728
729    routed_event_accessor!(
730        /// Occurs when the capture of a pointer is about to change on the
731        /// control.
732        pointer_capture_changing, pointer_capture_changing_event, PointerCaptureChangingEventArgs
733    );
734
735    routed_event_accessor!(
736        /// Occurs when the control or its child control loses the pointer
737        /// capture for any reason; the event will not be triggered for a
738        /// parent control if capture was transferred to another child of
739        /// that parent control.
740        pointer_capture_lost, pointer_capture_lost_event, PointerCaptureLostEventArgs
741    );
742
743    routed_event_accessor!(
744        /// Occurs when the mouse is scrolled over the control.
745        pointer_wheel_changed, pointer_wheel_changed_event, PointerWheelEventArgs
746    );
747
748    routed_event_accessor!(
749        /// Occurs when the user has completed a context input gesture, such
750        /// as a right-click.
751        context_requested, context_requested_event, ContextRequestedEventArgs
752    );
753
754    routed_event_accessor!(
755        /// Occurs when the context input gesture continues into another
756        /// gesture, to notify the element that the context flyout should
757        /// not be opened.
758        context_canceled, context_canceled_event, RoutedEventArgs
759    );
760
761    // --- property accessors -------------------------------------------------
762
763    /// Whether the control can receive focus.
764    pub fn focusable(&self) -> bool {
765        self.get_value(Self::focusable_property())
766    }
767
768    pub fn set_focusable(&self, value: bool) {
769        self.set_value(Self::focusable_property(), value)
770    }
771
772    /// Whether the control is enabled for user interaction.
773    pub fn is_enabled(&self) -> bool {
774        self.get_value(Self::is_enabled_property())
775    }
776
777    pub fn set_is_enabled(&self, value: bool) {
778        self.set_value(Self::is_enabled_property(), value)
779    }
780
781    /// The associated mouse cursor.
782    pub fn cursor(&self) -> Option<Rc<Cursor>> {
783        self.get_value(Self::cursor_property())
784    }
785
786    pub fn set_cursor(&self, value: Option<Rc<Cursor>>) {
787        self.set_value(Self::cursor_property(), value)
788    }
789
790    /// Whether keyboard focus is anywhere within the element or its visual
791    /// tree child elements.
792    #[inline]
793    pub fn is_keyboard_focus_within(&self) -> bool {
794        self.is_keyboard_focus_within.get()
795    }
796
797    pub(crate) fn set_is_keyboard_focus_within(&self, value: bool) {
798        self.set_and_raise_cell(Self::is_keyboard_focus_within_property(), &self.is_keyboard_focus_within, value);
799    }
800
801    /// Whether the control is focused.
802    #[inline]
803    pub fn is_focused(&self) -> bool {
804        self.is_focused.get()
805    }
806
807    fn set_is_focused(&self, value: bool) {
808        self.set_and_raise_cell(Self::is_focused_property(), &self.is_focused, value);
809    }
810
811    /// Whether the control is considered for hit testing.
812    pub fn is_hit_test_visible(&self) -> bool {
813        self.get_value(Self::is_hit_test_visible_property())
814    }
815
816    pub fn set_is_hit_test_visible(&self, value: bool) {
817        self.set_value(Self::is_hit_test_visible_property(), value)
818    }
819
820    /// Whether the pointer is currently over the control.
821    #[inline]
822    pub fn is_pointer_over(&self) -> bool {
823        self.is_pointer_over.get()
824    }
825
826    pub(crate) fn set_is_pointer_over(&self, value: bool) {
827        self.set_and_raise_cell(Self::is_pointer_over_property(), &self.is_pointer_over, value);
828    }
829
830    /// Whether the control is included in tab navigation.
831    pub fn is_tab_stop(&self) -> bool {
832        self.get_value(Self::is_tab_stop_property())
833    }
834
835    pub fn set_is_tab_stop(&self, value: bool) {
836        self.set_value(Self::is_tab_stop_property(), value)
837    }
838
839    /// Whether this control and all its parents are enabled.
840    #[inline]
841    pub fn is_effectively_enabled(&self) -> bool {
842        self.is_effectively_enabled.get()
843    }
844
845    fn set_is_effectively_enabled(&self, value: bool) {
846        self.set_and_raise_cell(Self::is_effectively_enabled_property(), &self.is_effectively_enabled, value);
847        self.pseudo_classes().set(":disabled", !value);
848
849        if !self.is_effectively_enabled() {
850            if let Some(focus_manager) = FocusManager::get_focus_manager(self) {
851                let is_focused_element = focus_manager
852                    .get_focused_element()
853                    .is_some_and(|focused| std::ptr::eq::<InputElement>(&*focused, self));
854
855                if is_focused_element {
856                    focus_manager.focus(None, NavigationMethod::Unspecified, KeyModifiers::NONE);
857                }
858            }
859        }
860    }
861
862    /// A value that determines the order in which elements receive focus
863    /// when the user navigates through controls by pressing the Tab key.
864    pub fn tab_index(&self) -> i32 {
865        self.get_value(Self::tab_index_property())
866    }
867
868    pub fn set_tab_index(&self, value: i32) {
869        self.set_value(Self::tab_index_property(), value)
870    }
871
872    /// The key bindings for this input element.
873    ///
874    /// The list is returned by handle: clones refer to the same list.
875    pub fn key_bindings(&self) -> FerroList<Ref<KeyBinding>> {
876        self.key_bindings.get_or_init(FerroList::new).clone()
877    }
878
879    /// The gesture recognizers attached to this input element.
880    pub fn gesture_recognizers(&self) -> GestureRecognizerCollection {
881        self.gesture_recognizers.get_or_init(|| GestureRecognizerCollection::new(&self.to_ref())).clone()
882    }
883
884    fn on_gesture_pointer_released(&self, e: &PointerReleasedEventArgs) {
885        if !e.is_gesture_recognition_skipped() {
886            if let Some(recognizers) = self.gesture_recognizers.get() {
887                if recognizers.handle_pointer_released(e) {
888                    e.set_handled(true);
889                }
890            }
891        }
892    }
893
894    fn on_gesture_pointer_capture_lost(&self, e: &PointerCaptureLostEventArgs) {
895        if let Some(recognizers) = self.gesture_recognizers.get() {
896            recognizers.handle_capture_lost(e.pointer());
897        }
898    }
899
900    fn on_gesture_pointer_pressed(&self, e: &PointerPressedEventArgs) {
901        if !e.is_gesture_recognition_skipped() {
902            if let Some(recognizers) = self.gesture_recognizers.get() {
903                if recognizers.handle_pointer_pressed(e) {
904                    e.set_handled(true);
905                }
906            }
907        }
908    }
909
910    fn on_gesture_pointer_moved(&self, e: &PointerEventArgs) {
911        if !e.is_gesture_recognition_skipped() {
912            if let Some(recognizers) = self.gesture_recognizers.get() {
913                if recognizers.handle_pointer_moved(e) {
914                    e.set_handled(true);
915                }
916            }
917        }
918    }
919
920    // --- methods ------------------------------------------------------------
921
922    /// Focuses the control, with an unspecified navigation method and no
923    /// key modifiers. Returns whether the control was focused.
924    pub fn focus(&self) -> bool {
925        self.focus_with(NavigationMethod::Unspecified, KeyModifiers::NONE)
926    }
927
928    /// Focuses the control.
929    ///
930    /// `method` is the method by which focus was changed and
931    /// `key_modifiers` any key modifiers active at the time of focus.
932    /// Returns whether the control was focused.
933    pub fn focus_with(&self, method: NavigationMethod, key_modifiers: KeyModifiers) -> bool {
934        match FocusManager::get_focus_manager(self) {
935            Some(focus_manager) => focus_manager.focus(Some(&self.to_ref()), method, key_modifiers),
936            None => false,
937        }
938    }
939
940    /// Runs the tab stop overrides of the focused element's ancestors and of
941    /// the candidate's ancestors. Returns whether the tab stop was
942    /// overridden and the overriding tab stop.
943    pub(crate) fn process_tab_stop(
944        _content_root: Option<&Ref<InputElement>>,
945        focused_element: Option<&Ref<InputElement>>,
946        candidate_tab_stop_element: Option<&Ref<InputElement>>,
947        is_reverse: bool,
948        did_cycle_focus_at_root_visual: bool,
949    ) -> (bool, Option<Ref<InputElement>>) {
950        // The override results are kept in locals and only published under
951        // the conditions below, as upstream does.
952        let new_tab_stop: Option<Ref<InputElement>> = None;
953        let mut is_tab_stop_overridden = false;
954        let mut sp_new_tab_stop: Option<Ref<InputElement>> = None;
955
956        if let Some(focused) = focused_element {
957            let (overridden, tab_stop) = focused.process_tab_stop_internal(
958                candidate_tab_stop_element,
959                is_reverse,
960                did_cycle_focus_at_root_visual,
961            );
962            is_tab_stop_overridden = overridden;
963            sp_new_tab_stop = tab_stop;
964        }
965
966        if !is_tab_stop_overridden {
967            if let Some(candidate) = candidate_tab_stop_element {
968                let (overridden, tab_stop) =
969                    candidate.process_candidate_tab_stop_internal(focused_element, None, is_reverse);
970                is_tab_stop_overridden = overridden;
971                sp_new_tab_stop = tab_stop;
972            }
973        }
974
975        // The remaining upstream branches only act on a tab stop that was
976        // already published, which never is at this point: an override is
977        // reported without a replacement element.
978        let _ = sp_new_tab_stop;
979
980        (is_tab_stop_overridden, new_tab_stop)
981    }
982
983    fn process_tab_stop_internal(
984        &self,
985        candidate_tab_stop_element: Option<&Ref<InputElement>>,
986        is_reverse: bool,
987        did_cycle_focus_at_root_visual: bool,
988    ) -> (bool, Option<Ref<InputElement>>) {
989        let this = self.to_ref();
990        let mut current = Some(this.clone());
991        let mut new_tab_stop = None;
992        let mut candidate_tab_stop_overridden = false;
993
994        while let Some(c) = current {
995            if candidate_tab_stop_overridden {
996                break;
997            }
998
999            candidate_tab_stop_overridden = c.process_tab_stop_override(
1000                Some(&this),
1001                candidate_tab_stop_element,
1002                is_reverse,
1003                did_cycle_focus_at_root_visual,
1004                &mut new_tab_stop,
1005            );
1006            current = c.parent().and_then(|parent| parent.downcast::<InputElement>().ok());
1007        }
1008
1009        (candidate_tab_stop_overridden, new_tab_stop)
1010    }
1011
1012    fn process_candidate_tab_stop_internal(
1013        &self,
1014        current_tab_stop: Option<&Ref<InputElement>>,
1015        overriden_candidate_tab_stop_element: Option<&Ref<InputElement>>,
1016        is_reverse: bool,
1017    ) -> (bool, Option<Ref<InputElement>>) {
1018        let this = self.to_ref();
1019        let mut current = Some(this.clone());
1020        let mut new_tab_stop = None;
1021        let mut candidate_tab_stop_overridden = false;
1022
1023        while let Some(c) = current {
1024            if candidate_tab_stop_overridden {
1025                break;
1026            }
1027
1028            candidate_tab_stop_overridden = c.process_candidate_tab_stop_override(
1029                current_tab_stop,
1030                Some(&this),
1031                overriden_candidate_tab_stop_element,
1032                is_reverse,
1033                &mut new_tab_stop,
1034            );
1035            current = c.parent().and_then(|parent| parent.downcast::<InputElement>().ok());
1036        }
1037
1038        (candidate_tab_stop_overridden, new_tab_stop)
1039    }
1040
1041    fn on_got_focus_core(&self, e: &FocusChangedEventArgs) {
1042        let is_focused = e.is_source(self);
1043        self.is_focus_visible.set(
1044            is_focused
1045                && (e.navigation_method == NavigationMethod::Directional
1046                    || e.navigation_method == NavigationMethod::Tab),
1047        );
1048        self.set_is_focused(is_focused);
1049        self.on_got_focus(e);
1050    }
1051
1052    fn on_lost_focus_core(&self, e: &FocusChangedEventArgs) {
1053        self.is_focus_visible.set(false);
1054        self.set_is_focused(false);
1055        self.on_lost_focus(e);
1056    }
1057
1058    /// Updates the `is_effectively_enabled` property based on the parent's
1059    /// `is_effectively_enabled`.
1060    pub fn update_is_effectively_enabled(&self) {
1061        let parent = self.get_visual_parent_of_type::<InputElement>();
1062        self.update_is_effectively_enabled_from(parent.as_deref());
1063    }
1064
1065    fn on_pointer_entered_core(&self, e: &PointerEventArgs) {
1066        self.set_is_pointer_over(true);
1067        self.on_pointer_entered(e);
1068    }
1069
1070    fn on_pointer_exited_core(&self, e: &PointerEventArgs) {
1071        self.set_is_pointer_over(false);
1072        self.on_pointer_exited(e);
1073    }
1074
1075    /// Updates the `is_effectively_enabled` property based on the parent's
1076    /// `is_effectively_enabled`.
1077    fn update_is_effectively_enabled_from(&self, parent: Option<&InputElement>) {
1078        self.set_is_effectively_enabled(
1079            self.is_enabled_core() && parent.is_none_or(InputElement::is_effectively_enabled),
1080        );
1081
1082        // PERF-SENSITIVE: this is called on the entire hierarchy.
1083        if let Some(children) = self.visual_children_snapshot() {
1084            for child in children.iter() {
1085                if let Some(child) = child.downcast_ref::<InputElement>() {
1086                    child.update_is_effectively_enabled_from(Some(self));
1087                }
1088            }
1089        }
1090    }
1091
1092    fn update_pseudo_classes(&self, is_focused: Option<bool>, is_pointer_over: Option<bool>) {
1093        if let Some(is_focused) = is_focused {
1094            self.pseudo_classes().set(":focus", is_focused);
1095            self.pseudo_classes().set(":focus-visible", self.is_focus_visible.get());
1096        }
1097
1098        if let Some(is_pointer_over) = is_pointer_over {
1099            self.pseudo_classes().set(":pointerover", is_pointer_over);
1100        }
1101    }
1102}
1103
1104impl IInputElement for InputElement {
1105    fn focusable(&self) -> bool {
1106        InputElement::focusable(self)
1107    }
1108
1109    fn is_enabled(&self) -> bool {
1110        InputElement::is_enabled(self)
1111    }
1112
1113    fn cursor(&self) -> Option<Rc<Cursor>> {
1114        InputElement::cursor(self)
1115    }
1116
1117    fn is_effectively_enabled(&self) -> bool {
1118        InputElement::is_effectively_enabled(self)
1119    }
1120
1121    fn is_effectively_visible(&self) -> bool {
1122        Visual::is_effectively_visible(self)
1123    }
1124
1125    fn is_keyboard_focus_within(&self) -> bool {
1126        InputElement::is_keyboard_focus_within(self)
1127    }
1128
1129    fn is_focused(&self) -> bool {
1130        InputElement::is_focused(self)
1131    }
1132
1133    fn is_hit_test_visible(&self) -> bool {
1134        InputElement::is_hit_test_visible(self)
1135    }
1136
1137    fn is_pointer_over(&self) -> bool {
1138        InputElement::is_pointer_over(self)
1139    }
1140
1141    fn focus(&self, method: NavigationMethod, key_modifiers: KeyModifiers) -> bool {
1142        InputElement::focus_with(self, method, key_modifiers)
1143    }
1144}