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