tessera_ui/
modifier.rs

1//! Modifier chains for node-local layout, drawing, focus, semantics, and other
2//! node-scoped behavior.
3//!
4//! ## Usage
5//!
6//! Build reusable modifier chains that attach behavior directly to the current
7//! component node.
8
9use std::{
10    any::{Any, TypeId},
11    collections::HashMap,
12    fmt,
13    hash::{Hash, Hasher},
14    sync::Arc,
15};
16
17use smallvec::SmallVec;
18
19use crate::{
20    AccessibilityActionHandler, AccessibilityNode, ComputedData, Constraint, FocusGroupNode,
21    FocusProperties, FocusRequester, FocusScopeNode, FocusState, FocusTraversalPolicy, ImeInput,
22    KeyboardInput, MeasurementError, PointerInput, PxPosition,
23    focus::{FocusDirection, FocusNode, FocusRevealRequest},
24    layout::{LayoutInput, LayoutOutput, RenderInput},
25    prop::CallbackWith,
26    runtime::{TesseraRuntime, ensure_build_phase},
27    winit::window::CursorIcon,
28};
29
30/// Parent-data payloads collected from modifier nodes.
31pub type ParentDataMap = HashMap<TypeId, Arc<dyn Any + Send + Sync>>;
32
33/// Child measurement entry used by layout modifier nodes.
34pub trait LayoutModifierChild {
35    /// Measures the wrapped content under the given constraint.
36    fn measure(&mut self, constraint: &Constraint) -> Result<ComputedData, MeasurementError>;
37
38    /// Places the wrapped content at the provided relative position.
39    fn place(&mut self, position: PxPosition, output: &mut LayoutOutput<'_>);
40}
41
42/// Input passed to layout modifier nodes.
43pub struct LayoutModifierInput<'a> {
44    /// The original layout input for the current node.
45    pub layout_input: &'a LayoutInput<'a>,
46}
47
48/// Output produced by a layout modifier node.
49pub struct LayoutModifierOutput {
50    /// Final computed size for the current node.
51    pub size: ComputedData,
52}
53
54/// Draw continuation used by draw modifier nodes.
55pub trait DrawModifierContent {
56    /// Records the wrapped content.
57    fn draw(&mut self, input: &RenderInput<'_>);
58}
59
60/// Draw input passed to draw modifier nodes.
61pub struct DrawModifierContext<'a> {
62    /// The render input for the current node.
63    pub render_input: &'a RenderInput<'a>,
64}
65
66/// A node-local layout modifier.
67pub trait LayoutModifierNode: Send + Sync + 'static {
68    /// Measures and places the wrapped content.
69    fn measure(
70        &self,
71        input: &LayoutModifierInput<'_>,
72        child: &mut dyn LayoutModifierChild,
73        output: &mut LayoutOutput<'_>,
74    ) -> Result<LayoutModifierOutput, MeasurementError>;
75}
76
77/// A node-local draw modifier.
78pub trait DrawModifierNode: Send + Sync + 'static {
79    /// Records drawing behavior around the wrapped content.
80    fn draw(&self, ctx: &mut DrawModifierContext<'_>, content: &mut dyn DrawModifierContent);
81}
82
83/// A node-local parent-data modifier.
84pub trait ParentDataModifierNode: Send + Sync + 'static {
85    /// Applies parent data visible to the parent layout.
86    fn apply_parent_data(&self, data: &mut ParentDataMap);
87}
88
89/// A node-local build modifier.
90pub trait BuildModifierNode: Send + Sync + 'static {
91    /// Applies build-time effects to the current component node.
92    fn apply(&self, runtime: &mut TesseraRuntime);
93}
94
95/// A node-local semantics modifier.
96pub trait SemanticsModifierNode: Send + Sync + 'static {
97    /// Applies accessibility metadata and optional action handling.
98    fn apply(
99        &self,
100        accessibility: &mut AccessibilityNode,
101        action_handler: &mut Option<AccessibilityActionHandler>,
102    );
103}
104
105/// A node-local pointer input modifier.
106pub trait PointerInputModifierNode: Send + Sync + 'static {
107    /// Handles pointer input for the current node.
108    ///
109    /// Pointer modifiers should operate on pointer-specific event flow and
110    /// local interaction state. Cross-cutting concerns such as semantics,
111    /// hover cursors, and IME publication should use their dedicated modifier
112    /// or session APIs.
113    fn on_pointer_input(&self, input: PointerInput<'_>);
114}
115
116/// A node-local hover cursor modifier.
117pub trait CursorModifierNode: Send + Sync + 'static {
118    /// Returns the cursor icon that should be used when the pointer hovers this
119    /// node.
120    fn cursor_icon(&self) -> CursorIcon;
121}
122
123/// A node-local keyboard input modifier.
124pub trait KeyboardInputModifierNode: Send + Sync + 'static {
125    /// Handles keyboard input for the current node.
126    fn on_keyboard_input(&self, input: KeyboardInput<'_>);
127}
128
129/// A node-local IME input modifier.
130pub trait ImeInputModifierNode: Send + Sync + 'static {
131    /// Handles IME input for the current node.
132    fn on_ime_input(&self, input: ImeInput<'_>);
133}
134
135/// Low-level modifier primitive API for framework crates that build semantic
136/// modifier extensions.
137///
138/// This trait is intended for crates such as `tessera-foundation` and
139/// `tessera-components` that implement higher-level `Modifier` extensions. Most
140/// application code should prefer those semantic extensions instead of calling
141/// these methods directly.
142pub trait ModifierCapabilityExt {
143    /// Appends a layout modifier node to the current modifier chain.
144    fn push_layout<N>(self, node: N) -> Self
145    where
146        N: LayoutModifierNode;
147
148    /// Appends a draw modifier node to the current modifier chain.
149    fn push_draw<N>(self, node: N) -> Self
150    where
151        N: DrawModifierNode;
152
153    /// Appends a parent-data modifier node to the current modifier chain.
154    fn push_parent_data<N>(self, node: N) -> Self
155    where
156        N: ParentDataModifierNode;
157
158    /// Appends a build modifier node to the current modifier chain.
159    fn push_build<N>(self, node: N) -> Self
160    where
161        N: BuildModifierNode;
162
163    /// Appends a semantics modifier node to the current modifier chain.
164    fn push_semantics<N>(self, node: N) -> Self
165    where
166        N: SemanticsModifierNode;
167
168    /// Appends a preview pointer-input modifier node to the current modifier
169    /// chain.
170    fn push_pointer_preview_input<N>(self, node: N) -> Self
171    where
172        N: PointerInputModifierNode;
173
174    /// Appends a pointer-input modifier node to the current modifier chain.
175    fn push_pointer_input<N>(self, node: N) -> Self
176    where
177        N: PointerInputModifierNode;
178
179    /// Appends a final pointer-input modifier node to the current modifier
180    /// chain.
181    fn push_pointer_final_input<N>(self, node: N) -> Self
182    where
183        N: PointerInputModifierNode;
184
185    /// Appends a preview keyboard-input modifier node to the current modifier
186    /// chain.
187    fn push_keyboard_preview_input<N>(self, node: N) -> Self
188    where
189        N: KeyboardInputModifierNode;
190
191    /// Appends a keyboard-input modifier node to the current modifier chain.
192    fn push_keyboard_input<N>(self, node: N) -> Self
193    where
194        N: KeyboardInputModifierNode;
195
196    /// Appends a preview IME-input modifier node to the current modifier chain.
197    fn push_ime_preview_input<N>(self, node: N) -> Self
198    where
199        N: ImeInputModifierNode;
200
201    /// Appends an IME-input modifier node to the current modifier chain.
202    fn push_ime_input<N>(self, node: N) -> Self
203    where
204        N: ImeInputModifierNode;
205}
206
207#[derive(Clone, PartialEq, Eq)]
208pub(crate) enum FocusModifierRegistration {
209    Target(Option<FocusNode>),
210    Scope(Option<FocusScopeNode>),
211    Group(Option<FocusGroupNode>),
212    Restorer {
213        scope: Option<FocusScopeNode>,
214        fallback: Option<FocusRequester>,
215    },
216}
217
218#[derive(Clone, PartialEq, Eq)]
219enum FocusModifierOp {
220    Requester(FocusRequester),
221    Registration(FocusModifierRegistration),
222    Properties(FocusProperties),
223    TraversalPolicy(FocusTraversalPolicy),
224    ChangedHandler(CallbackWith<FocusState>),
225    EventHandler(CallbackWith<FocusState>),
226    BeyondBoundsHandler(CallbackWith<FocusDirection, bool>),
227    RevealHandler(CallbackWith<FocusRevealRequest, bool>),
228}
229
230#[derive(Clone)]
231enum ModifierAction {
232    Layout(Arc<dyn LayoutModifierNode>),
233    Draw(Arc<dyn DrawModifierNode>),
234    ParentData(Arc<dyn ParentDataModifierNode>),
235    Build(Arc<dyn BuildModifierNode>),
236    Semantics(Arc<dyn SemanticsModifierNode>),
237    Cursor(Arc<dyn CursorModifierNode>),
238    PointerPreviewInput(Arc<dyn PointerInputModifierNode>),
239    PointerInput(Arc<dyn PointerInputModifierNode>),
240    PointerFinalInput(Arc<dyn PointerInputModifierNode>),
241    KeyboardPreviewInput(Arc<dyn KeyboardInputModifierNode>),
242    KeyboardInput(Arc<dyn KeyboardInputModifierNode>),
243    ImePreviewInput(Arc<dyn ImeInputModifierNode>),
244    ImeInput(Arc<dyn ImeInputModifierNode>),
245    Focus(FocusModifierOp),
246}
247
248#[derive(Clone)]
249struct ModifierLink {
250    prev: Option<Arc<ModifierLink>>,
251    action: ModifierAction,
252}
253
254fn collect_actions(mut node: Option<Arc<ModifierLink>>) -> Vec<ModifierAction> {
255    let mut actions: SmallVec<[ModifierAction; 8]> = SmallVec::new();
256    while let Some(current) = node {
257        actions.push(current.action.clone());
258        node = current.prev.clone();
259    }
260    actions.into_vec()
261}
262
263/// A persistent handle to a modifier chain.
264#[derive(Clone, Default)]
265pub struct Modifier {
266    tail: Option<Arc<ModifierLink>>,
267}
268
269/// Focus-specific modifier extensions for [`Modifier`].
270pub trait FocusModifierExt {
271    /// Registers a focus target for this subtree.
272    fn focusable(self) -> Modifier;
273
274    /// Binds an explicit focus requester to this subtree.
275    fn focus_requester(self, requester: FocusRequester) -> Modifier;
276
277    /// Applies explicit focus properties to this subtree.
278    fn focus_properties(self, properties: FocusProperties) -> Modifier;
279
280    /// Registers a traversal-only focus group for this subtree.
281    fn focus_group(self) -> Modifier;
282
283    /// Registers an explicit focus scope handle for this subtree.
284    fn focus_scope_with(self, scope: FocusScopeNode) -> Modifier;
285
286    /// Registers an explicit focus group handle for this subtree.
287    fn focus_group_with(self, group: FocusGroupNode) -> Modifier;
288
289    /// Registers a focus scope with restore behavior for this subtree.
290    fn focus_restorer(self, fallback: Option<FocusRequester>) -> Modifier;
291
292    /// Registers an explicit focus restorer scope for this subtree.
293    fn focus_restorer_with(
294        self,
295        scope: FocusScopeNode,
296        fallback: Option<FocusRequester>,
297    ) -> Modifier;
298
299    /// Applies a traversal policy to the current focus group or scope.
300    fn focus_traversal_policy(self, policy: FocusTraversalPolicy) -> Modifier;
301
302    /// Registers a callback that runs when the subtree focus state changes.
303    fn on_focus_changed<F>(self, handler: F) -> Modifier
304    where
305        F: Into<CallbackWith<FocusState>>;
306
307    /// Registers a callback that observes focus events for this subtree.
308    fn on_focus_event<F>(self, handler: F) -> Modifier
309    where
310        F: Into<CallbackWith<FocusState>>;
311
312    /// Registers a callback that moves focus beyond the current viewport.
313    fn focus_beyond_bounds_handler<F>(self, handler: F) -> Modifier
314    where
315        F: Into<CallbackWith<FocusDirection, bool>>;
316
317    /// Registers a callback that reveals the focused target within the
318    /// viewport.
319    fn focus_reveal_handler<F>(self, handler: F) -> Modifier
320    where
321        F: Into<CallbackWith<FocusRevealRequest, bool>>;
322}
323
324/// Cursor-specific modifier extensions for [`Modifier`].
325pub trait CursorModifierExt {
326    /// Sets the cursor icon used while the pointer hovers this node.
327    fn hover_cursor_icon(self, icon: CursorIcon) -> Modifier;
328}
329
330impl Modifier {
331    /// Creates an empty modifier chain.
332    pub fn new() -> Self {
333        ensure_build_phase();
334        Self::default()
335    }
336
337    fn push_action(self, action: ModifierAction) -> Self {
338        ensure_build_phase();
339        Self {
340            tail: Some(Arc::new(ModifierLink {
341                prev: self.tail,
342                action,
343            })),
344        }
345    }
346
347    /// Appends another modifier chain after this one.
348    pub fn then(mut self, other: Modifier) -> Self {
349        let actions = collect_actions(other.tail);
350        for action in actions.into_iter().rev() {
351            self = self.push_action(action);
352        }
353        self
354    }
355
356    pub(crate) fn push_layout<N>(self, node: N) -> Self
357    where
358        N: LayoutModifierNode,
359    {
360        self.push_action(ModifierAction::Layout(Arc::new(node)))
361    }
362
363    pub(crate) fn push_draw<N>(self, node: N) -> Self
364    where
365        N: DrawModifierNode,
366    {
367        self.push_action(ModifierAction::Draw(Arc::new(node)))
368    }
369
370    pub(crate) fn push_parent_data<N>(self, node: N) -> Self
371    where
372        N: ParentDataModifierNode,
373    {
374        self.push_action(ModifierAction::ParentData(Arc::new(node)))
375    }
376
377    pub(crate) fn push_build<N>(self, node: N) -> Self
378    where
379        N: BuildModifierNode,
380    {
381        self.push_action(ModifierAction::Build(Arc::new(node)))
382    }
383
384    pub(crate) fn push_semantics<N>(self, node: N) -> Self
385    where
386        N: SemanticsModifierNode,
387    {
388        self.push_action(ModifierAction::Semantics(Arc::new(node)))
389    }
390
391    fn push_cursor<N>(self, node: N) -> Self
392    where
393        N: CursorModifierNode,
394    {
395        self.push_action(ModifierAction::Cursor(Arc::new(node)))
396    }
397
398    pub(crate) fn push_pointer_preview_input<N>(self, node: N) -> Self
399    where
400        N: PointerInputModifierNode,
401    {
402        self.push_action(ModifierAction::PointerPreviewInput(Arc::new(node)))
403    }
404
405    pub(crate) fn push_pointer_input<N>(self, node: N) -> Self
406    where
407        N: PointerInputModifierNode,
408    {
409        self.push_action(ModifierAction::PointerInput(Arc::new(node)))
410    }
411
412    pub(crate) fn push_pointer_final_input<N>(self, node: N) -> Self
413    where
414        N: PointerInputModifierNode,
415    {
416        self.push_action(ModifierAction::PointerFinalInput(Arc::new(node)))
417    }
418
419    pub(crate) fn push_keyboard_preview_input<N>(self, node: N) -> Self
420    where
421        N: KeyboardInputModifierNode,
422    {
423        self.push_action(ModifierAction::KeyboardPreviewInput(Arc::new(node)))
424    }
425
426    pub(crate) fn push_keyboard_input<N>(self, node: N) -> Self
427    where
428        N: KeyboardInputModifierNode,
429    {
430        self.push_action(ModifierAction::KeyboardInput(Arc::new(node)))
431    }
432
433    pub(crate) fn push_ime_preview_input<N>(self, node: N) -> Self
434    where
435        N: ImeInputModifierNode,
436    {
437        self.push_action(ModifierAction::ImePreviewInput(Arc::new(node)))
438    }
439
440    pub(crate) fn push_ime_input<N>(self, node: N) -> Self
441    where
442        N: ImeInputModifierNode,
443    {
444        self.push_action(ModifierAction::ImeInput(Arc::new(node)))
445    }
446
447    fn push_focus_requester(self, requester: FocusRequester) -> Self {
448        self.push_focus_op(FocusModifierOp::Requester(requester))
449    }
450
451    fn push_focus_target(self) -> Self {
452        self.push_focus_op(FocusModifierOp::Registration(
453            FocusModifierRegistration::Target(None),
454        ))
455    }
456
457    fn push_focus_scope_with(self, scope: FocusScopeNode) -> Self {
458        self.push_focus_op(FocusModifierOp::Registration(
459            FocusModifierRegistration::Scope(Some(scope)),
460        ))
461    }
462
463    fn push_focus_group(self) -> Self {
464        self.push_focus_op(FocusModifierOp::Registration(
465            FocusModifierRegistration::Group(None),
466        ))
467    }
468
469    fn push_focus_group_with(self, group: FocusGroupNode) -> Self {
470        self.push_focus_op(FocusModifierOp::Registration(
471            FocusModifierRegistration::Group(Some(group)),
472        ))
473    }
474
475    fn push_focus_restorer(self, fallback: Option<FocusRequester>) -> Self {
476        self.push_focus_op(FocusModifierOp::Registration(
477            FocusModifierRegistration::Restorer {
478                scope: None,
479                fallback,
480            },
481        ))
482    }
483
484    fn push_focus_restorer_with(
485        self,
486        scope: FocusScopeNode,
487        fallback: Option<FocusRequester>,
488    ) -> Self {
489        self.push_focus_op(FocusModifierOp::Registration(
490            FocusModifierRegistration::Restorer {
491                scope: Some(scope),
492                fallback,
493            },
494        ))
495    }
496
497    fn push_focus_properties(self, properties: FocusProperties) -> Self {
498        self.push_focus_op(FocusModifierOp::Properties(properties))
499    }
500
501    fn push_focus_traversal_policy(self, policy: FocusTraversalPolicy) -> Self {
502        self.push_focus_op(FocusModifierOp::TraversalPolicy(policy))
503    }
504
505    fn push_focus_changed_handler(self, handler: CallbackWith<FocusState>) -> Self {
506        self.push_focus_op(FocusModifierOp::ChangedHandler(handler))
507    }
508
509    fn push_focus_event_handler(self, handler: CallbackWith<FocusState>) -> Self {
510        self.push_focus_op(FocusModifierOp::EventHandler(handler))
511    }
512
513    fn push_focus_beyond_bounds_handler(self, handler: CallbackWith<FocusDirection, bool>) -> Self {
514        self.push_focus_op(FocusModifierOp::BeyondBoundsHandler(handler))
515    }
516
517    fn push_focus_reveal_handler(self, handler: CallbackWith<FocusRevealRequest, bool>) -> Self {
518        self.push_focus_op(FocusModifierOp::RevealHandler(handler))
519    }
520
521    fn push_focus_op(self, op: FocusModifierOp) -> Self {
522        self.push_action(ModifierAction::Focus(op))
523    }
524
525    /// Attaches this modifier chain to the current component node.
526    pub fn attach(self) {
527        ensure_build_phase();
528
529        let actions = collect_actions(self.tail.clone());
530        TesseraRuntime::with_mut(|runtime| {
531            runtime.append_current_modifier(self.clone());
532        });
533
534        let mut accessibility = AccessibilityNode::new();
535        let mut action_handler = None;
536        let mut has_semantics = false;
537        for action in actions.into_iter().rev() {
538            match action {
539                ModifierAction::Build(node) => {
540                    TesseraRuntime::with_mut(|runtime| node.apply(runtime));
541                }
542                ModifierAction::Semantics(node) => {
543                    has_semantics = true;
544                    node.apply(&mut accessibility, &mut action_handler);
545                }
546                ModifierAction::Focus(op) => {
547                    TesseraRuntime::with_mut(|runtime| {
548                        apply_focus_op(runtime::FocusModifierRuntime::new(runtime), op);
549                    });
550                }
551                _ => {}
552            }
553        }
554
555        TesseraRuntime::with_mut(|runtime| {
556            runtime.set_current_accessibility(has_semantics.then_some(accessibility));
557            runtime.set_current_accessibility_action_handler(action_handler);
558        });
559    }
560
561    /// Attaches this modifier chain to the current node and then runs `child`.
562    pub fn run<F>(self, child: F)
563    where
564        F: Fn() + Send + Sync + 'static,
565    {
566        self.attach();
567        child();
568    }
569
570    /// Returns true when the modifier has no actions.
571    pub fn is_empty(&self) -> bool {
572        self.tail.is_none()
573    }
574
575    pub(crate) fn layout_nodes(&self) -> Vec<Arc<dyn LayoutModifierNode>> {
576        collect_actions(self.tail.clone())
577            .into_iter()
578            .filter_map(|action| match action {
579                ModifierAction::Layout(node) => Some(node),
580                _ => None,
581            })
582            .collect()
583    }
584
585    pub(crate) fn draw_nodes(&self) -> Vec<Arc<dyn DrawModifierNode>> {
586        collect_actions(self.tail.clone())
587            .into_iter()
588            .filter_map(|action| match action {
589                ModifierAction::Draw(node) => Some(node),
590                _ => None,
591            })
592            .collect()
593    }
594
595    pub(crate) fn apply_parent_data(&self, data: &mut ParentDataMap) {
596        for action in collect_actions(self.tail.clone()).into_iter().rev() {
597            if let ModifierAction::ParentData(node) = action {
598                node.apply_parent_data(data);
599            }
600        }
601    }
602
603    pub(crate) fn pointer_preview_input_nodes(&self) -> Vec<Arc<dyn PointerInputModifierNode>> {
604        collect_actions(self.tail.clone())
605            .into_iter()
606            .filter_map(|action| match action {
607                ModifierAction::PointerPreviewInput(node) => Some(node),
608                _ => None,
609            })
610            .collect()
611    }
612
613    pub(crate) fn pointer_input_nodes(&self) -> Vec<Arc<dyn PointerInputModifierNode>> {
614        collect_actions(self.tail.clone())
615            .into_iter()
616            .filter_map(|action| match action {
617                ModifierAction::PointerInput(node) => Some(node),
618                _ => None,
619            })
620            .collect()
621    }
622
623    pub(crate) fn pointer_final_input_nodes(&self) -> Vec<Arc<dyn PointerInputModifierNode>> {
624        collect_actions(self.tail.clone())
625            .into_iter()
626            .filter_map(|action| match action {
627                ModifierAction::PointerFinalInput(node) => Some(node),
628                _ => None,
629            })
630            .collect()
631    }
632
633    pub(crate) fn keyboard_preview_input_nodes(&self) -> Vec<Arc<dyn KeyboardInputModifierNode>> {
634        collect_actions(self.tail.clone())
635            .into_iter()
636            .filter_map(|action| match action {
637                ModifierAction::KeyboardPreviewInput(node) => Some(node),
638                _ => None,
639            })
640            .collect()
641    }
642
643    pub(crate) fn keyboard_input_nodes(&self) -> Vec<Arc<dyn KeyboardInputModifierNode>> {
644        collect_actions(self.tail.clone())
645            .into_iter()
646            .filter_map(|action| match action {
647                ModifierAction::KeyboardInput(node) => Some(node),
648                _ => None,
649            })
650            .collect()
651    }
652
653    pub(crate) fn ime_preview_input_nodes(&self) -> Vec<Arc<dyn ImeInputModifierNode>> {
654        collect_actions(self.tail.clone())
655            .into_iter()
656            .filter_map(|action| match action {
657                ModifierAction::ImePreviewInput(node) => Some(node),
658                _ => None,
659            })
660            .collect()
661    }
662
663    pub(crate) fn ime_input_nodes(&self) -> Vec<Arc<dyn ImeInputModifierNode>> {
664        collect_actions(self.tail.clone())
665            .into_iter()
666            .filter_map(|action| match action {
667                ModifierAction::ImeInput(node) => Some(node),
668                _ => None,
669            })
670            .collect()
671    }
672
673    pub(crate) fn has_pointer_input_nodes(&self) -> bool {
674        collect_actions(self.tail.clone())
675            .into_iter()
676            .any(|action| {
677                matches!(
678                    action,
679                    ModifierAction::PointerPreviewInput(_)
680                        | ModifierAction::PointerInput(_)
681                        | ModifierAction::PointerFinalInput(_)
682                )
683            })
684    }
685
686    pub(crate) fn cursor_icon(&self) -> Option<CursorIcon> {
687        collect_actions(self.tail.clone())
688            .into_iter()
689            .find_map(|action| match action {
690                ModifierAction::Cursor(node) => Some(node.cursor_icon()),
691                _ => None,
692            })
693    }
694
695    pub(crate) fn has_cursor_icon(&self) -> bool {
696        self.cursor_icon().is_some()
697    }
698}
699
700impl ModifierCapabilityExt for Modifier {
701    fn push_layout<N>(self, node: N) -> Self
702    where
703        N: LayoutModifierNode,
704    {
705        Modifier::push_layout(self, node)
706    }
707
708    fn push_draw<N>(self, node: N) -> Self
709    where
710        N: DrawModifierNode,
711    {
712        Modifier::push_draw(self, node)
713    }
714
715    fn push_parent_data<N>(self, node: N) -> Self
716    where
717        N: ParentDataModifierNode,
718    {
719        Modifier::push_parent_data(self, node)
720    }
721
722    fn push_build<N>(self, node: N) -> Self
723    where
724        N: BuildModifierNode,
725    {
726        Modifier::push_build(self, node)
727    }
728
729    fn push_semantics<N>(self, node: N) -> Self
730    where
731        N: SemanticsModifierNode,
732    {
733        Modifier::push_semantics(self, node)
734    }
735
736    fn push_pointer_preview_input<N>(self, node: N) -> Self
737    where
738        N: PointerInputModifierNode,
739    {
740        Modifier::push_pointer_preview_input(self, node)
741    }
742
743    fn push_pointer_input<N>(self, node: N) -> Self
744    where
745        N: PointerInputModifierNode,
746    {
747        Modifier::push_pointer_input(self, node)
748    }
749
750    fn push_pointer_final_input<N>(self, node: N) -> Self
751    where
752        N: PointerInputModifierNode,
753    {
754        Modifier::push_pointer_final_input(self, node)
755    }
756
757    fn push_keyboard_preview_input<N>(self, node: N) -> Self
758    where
759        N: KeyboardInputModifierNode,
760    {
761        Modifier::push_keyboard_preview_input(self, node)
762    }
763
764    fn push_keyboard_input<N>(self, node: N) -> Self
765    where
766        N: KeyboardInputModifierNode,
767    {
768        Modifier::push_keyboard_input(self, node)
769    }
770
771    fn push_ime_preview_input<N>(self, node: N) -> Self
772    where
773        N: ImeInputModifierNode,
774    {
775        Modifier::push_ime_preview_input(self, node)
776    }
777
778    fn push_ime_input<N>(self, node: N) -> Self
779    where
780        N: ImeInputModifierNode,
781    {
782        Modifier::push_ime_input(self, node)
783    }
784}
785
786#[derive(Clone, Copy)]
787struct StaticCursorModifierNode {
788    icon: CursorIcon,
789}
790
791impl CursorModifierNode for StaticCursorModifierNode {
792    fn cursor_icon(&self) -> CursorIcon {
793        self.icon
794    }
795}
796
797impl CursorModifierExt for Modifier {
798    fn hover_cursor_icon(self, icon: CursorIcon) -> Modifier {
799        self.push_cursor(StaticCursorModifierNode { icon })
800    }
801}
802
803impl FocusModifierExt for Modifier {
804    fn focusable(self) -> Modifier {
805        self.push_focus_target()
806    }
807
808    fn focus_requester(self, requester: FocusRequester) -> Modifier {
809        self.push_focus_requester(requester)
810    }
811
812    fn focus_properties(self, properties: FocusProperties) -> Modifier {
813        self.push_focus_properties(properties)
814    }
815
816    fn focus_group(self) -> Modifier {
817        self.push_focus_group()
818    }
819
820    fn focus_scope_with(self, scope: FocusScopeNode) -> Modifier {
821        self.push_focus_scope_with(scope)
822    }
823
824    fn focus_group_with(self, group: FocusGroupNode) -> Modifier {
825        self.push_focus_group_with(group)
826    }
827
828    fn focus_restorer(self, fallback: Option<FocusRequester>) -> Modifier {
829        self.push_focus_restorer(fallback)
830    }
831
832    fn focus_restorer_with(
833        self,
834        scope: FocusScopeNode,
835        fallback: Option<FocusRequester>,
836    ) -> Modifier {
837        self.push_focus_restorer_with(scope, fallback)
838    }
839
840    fn focus_traversal_policy(self, policy: FocusTraversalPolicy) -> Modifier {
841        self.push_focus_traversal_policy(policy)
842    }
843
844    fn on_focus_changed<F>(self, handler: F) -> Modifier
845    where
846        F: Into<CallbackWith<FocusState>>,
847    {
848        self.push_focus_changed_handler(handler.into())
849    }
850
851    fn on_focus_event<F>(self, handler: F) -> Modifier
852    where
853        F: Into<CallbackWith<FocusState>>,
854    {
855        self.push_focus_event_handler(handler.into())
856    }
857
858    fn focus_beyond_bounds_handler<F>(self, handler: F) -> Modifier
859    where
860        F: Into<CallbackWith<FocusDirection, bool>>,
861    {
862        self.push_focus_beyond_bounds_handler(handler.into())
863    }
864
865    fn focus_reveal_handler<F>(self, handler: F) -> Modifier
866    where
867        F: Into<CallbackWith<FocusRevealRequest, bool>>,
868    {
869        self.push_focus_reveal_handler(handler.into())
870    }
871}
872
873impl fmt::Debug for Modifier {
874    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
875        f.debug_struct("Modifier")
876            .field("is_empty", &self.tail.is_none())
877            .finish()
878    }
879}
880
881impl PartialEq for Modifier {
882    fn eq(&self, other: &Self) -> bool {
883        match (&self.tail, &other.tail) {
884            (None, None) => true,
885            (Some(lhs), Some(rhs)) => Arc::ptr_eq(lhs, rhs),
886            _ => false,
887        }
888    }
889}
890
891impl Eq for Modifier {}
892
893impl Hash for Modifier {
894    fn hash<H: Hasher>(&self, state: &mut H) {
895        match &self.tail {
896            Some(node) => std::ptr::hash(Arc::as_ptr(node), state),
897            None => 0u8.hash(state),
898        }
899    }
900}
901
902mod runtime {
903    use super::FocusModifierRegistration;
904    use crate::{
905        FocusProperties, FocusRequester, FocusScopeNode, FocusState, FocusTraversalPolicy,
906        focus::{FocusDirection, FocusRevealRequest},
907        prop::CallbackWith,
908        runtime::TesseraRuntime,
909    };
910
911    pub(super) struct FocusModifierRuntime<'a> {
912        runtime: &'a mut TesseraRuntime,
913    }
914
915    impl<'a> FocusModifierRuntime<'a> {
916        pub(super) fn new(runtime: &'a mut TesseraRuntime) -> Self {
917            Self { runtime }
918        }
919
920        pub(super) fn bind_requester(&mut self, requester: FocusRequester) {
921            self.runtime.bind_current_focus_requester(requester);
922        }
923
924        pub(super) fn ensure_registration(&mut self, registration: FocusModifierRegistration) {
925            match registration {
926                FocusModifierRegistration::Target(node) => {
927                    let node = node.unwrap_or_else(|| {
928                        self.runtime
929                            .current_focus_target_handle()
930                            .unwrap_or_else(|| {
931                                crate::runtime::persistent_focus_target_for_current_instance(
932                                    "__tessera_focus_target",
933                                )
934                            })
935                    });
936                    self.runtime.ensure_current_focus_target(node);
937                }
938                FocusModifierRegistration::Scope(scope) => {
939                    let scope = scope.unwrap_or_else(|| {
940                        self.runtime
941                            .current_focus_scope_handle()
942                            .unwrap_or_else(|| {
943                                crate::runtime::persistent_focus_scope_for_current_instance(
944                                    "__tessera_focus_scope",
945                                )
946                            })
947                    });
948                    self.runtime.ensure_current_focus_scope(scope);
949                }
950                FocusModifierRegistration::Group(group) => {
951                    let group = group.unwrap_or_else(|| {
952                        self.runtime
953                            .current_focus_group_handle()
954                            .unwrap_or_else(|| {
955                                crate::runtime::persistent_focus_group_for_current_instance(
956                                    "__tessera_focus_group",
957                                )
958                            })
959                    });
960                    self.runtime.ensure_current_focus_group(group);
961                }
962                FocusModifierRegistration::Restorer { scope, fallback } => {
963                    let scope: FocusScopeNode = scope.unwrap_or_else(|| {
964                        self.runtime
965                            .current_focus_scope_handle()
966                            .unwrap_or_else(|| {
967                                crate::runtime::persistent_focus_scope_for_current_instance(
968                                    "__tessera_focus_scope",
969                                )
970                            })
971                    });
972                    self.runtime.ensure_current_focus_scope(scope);
973                    if let Some(fallback) = fallback {
974                        self.runtime.set_current_focus_restorer_fallback(fallback);
975                    }
976                }
977            }
978        }
979
980        pub(super) fn set_properties(&mut self, properties: FocusProperties) {
981            self.runtime.set_current_focus_properties(properties);
982        }
983
984        pub(super) fn set_traversal_policy(&mut self, policy: FocusTraversalPolicy) {
985            self.runtime.set_current_focus_traversal_policy(policy);
986        }
987
988        pub(super) fn set_changed_handler(&mut self, handler: CallbackWith<FocusState>) {
989            self.runtime.set_current_focus_changed_handler(handler);
990        }
991
992        pub(super) fn set_event_handler(&mut self, handler: CallbackWith<FocusState>) {
993            self.runtime.set_current_focus_event_handler(handler);
994        }
995
996        pub(super) fn set_beyond_bounds_handler(
997            &mut self,
998            handler: CallbackWith<FocusDirection, bool>,
999        ) {
1000            self.runtime
1001                .set_current_focus_beyond_bounds_handler(handler);
1002        }
1003
1004        pub(super) fn set_reveal_handler(
1005            &mut self,
1006            handler: CallbackWith<FocusRevealRequest, bool>,
1007        ) {
1008            self.runtime.set_current_focus_reveal_handler(handler);
1009        }
1010    }
1011}
1012
1013fn apply_focus_op(runtime: runtime::FocusModifierRuntime<'_>, op: FocusModifierOp) {
1014    let mut runtime = runtime;
1015    match op {
1016        FocusModifierOp::Requester(requester) => runtime.bind_requester(requester),
1017        FocusModifierOp::Registration(registration) => runtime.ensure_registration(registration),
1018        FocusModifierOp::Properties(properties) => runtime.set_properties(properties),
1019        FocusModifierOp::TraversalPolicy(policy) => runtime.set_traversal_policy(policy),
1020        FocusModifierOp::ChangedHandler(handler) => runtime.set_changed_handler(handler),
1021        FocusModifierOp::EventHandler(handler) => runtime.set_event_handler(handler),
1022        FocusModifierOp::BeyondBoundsHandler(handler) => runtime.set_beyond_bounds_handler(handler),
1023        FocusModifierOp::RevealHandler(handler) => runtime.set_reveal_handler(handler),
1024    }
1025}