1use std::{
10 any::{Any, TypeId},
11 collections::HashMap,
12 fmt,
13 hash::{Hash, Hasher},
14 sync::Arc,
15};
16
17use rustc_hash::FxHasher;
18use smallvec::SmallVec;
19
20use crate::{
21 AccessibilityActionHandler, AccessibilityNode, ComputedData, Constraint, FocusGroupNode,
22 FocusProperties, FocusRequester, FocusScopeNode, FocusState, FocusTraversalPolicy, ImeInput,
23 KeyboardInput, MeasurementError, PointerInput, PxPosition,
24 clipboard::ClipboardInputModifierNode,
25 focus::{FocusDirection, FocusNode, FocusRevealRequest},
26 layout::{
27 LayoutInput, LayoutResult, MeasureScope, PlacementResult, PlacementScope, RenderInput,
28 },
29 prop::CallbackWith,
30 runtime::{TesseraRuntime, ensure_build_phase},
31 winit::window::CursorIcon,
32};
33
34pub type ParentDataMap = HashMap<TypeId, Arc<dyn Any + Send + Sync>>;
36
37pub trait LayoutModifierChild {
39 fn measure(&mut self, constraint: &Constraint) -> Result<ComputedData, MeasurementError>;
41
42 fn place(&mut self, position: PxPosition);
44}
45
46pub struct LayoutModifierInput<'a> {
48 pub layout_input: &'a LayoutInput<'a>,
50}
51
52impl LayoutModifierInput<'_> {
53 pub fn placement<R>(&self, calculate: impl FnOnce() -> R) -> R {
59 let _phase = crate::runtime::push_phase(crate::runtime::RuntimePhase::Place);
60 calculate()
61 }
62}
63
64pub trait DrawModifierContent {
66 fn draw(&mut self, input: &mut RenderInput<'_>);
68}
69
70pub struct DrawModifierContext<'a, 'b> {
72 pub render_input: &'a mut RenderInput<'b>,
74}
75
76pub trait LayoutModifierNode: Send + Sync + 'static {
86 fn measure(&self, _scope: &mut MeasureScope<'_>) -> Result<LayoutResult, MeasurementError> {
88 Err(MeasurementError::MeasureFnFailed(
89 "layout node does not implement pure measure".to_string(),
90 ))
91 }
92
93 fn measure_content(
95 &self,
96 _input: &LayoutModifierInput<'_>,
97 _child: &mut dyn LayoutModifierChild,
98 ) -> Result<LayoutResult, MeasurementError> {
99 Err(MeasurementError::MeasureFnFailed(
100 "layout node does not implement wrapped measure".to_string(),
101 ))
102 }
103
104 fn measure_eq(&self, other: &Self) -> bool
106 where
107 Self: Sized + PartialEq,
108 {
109 self == other
110 }
111
112 fn placement_eq(&self, other: &Self) -> bool
114 where
115 Self: Sized + PartialEq,
116 {
117 self == other
118 }
119
120 fn place_children(
128 &self,
129 _scope: &PlacementScope<'_>,
130 _inner: &PlacementResult,
131 ) -> Option<PlacementResult> {
132 None
133 }
134}
135
136pub trait PlacementModifierNode: Send + Sync + 'static {
139 fn diagnostic_name(&self) -> &'static str {
141 std::any::type_name::<Self>()
142 }
143 fn transform_position(&self, position: PxPosition) -> PxPosition;
145}
146
147pub trait DrawModifierNode: Send + Sync + 'static {
149 fn diagnostic_name(&self) -> &'static str {
151 std::any::type_name::<Self>()
152 }
153
154 fn draw(&self, ctx: &mut DrawModifierContext<'_, '_>, content: &mut dyn DrawModifierContent);
160}
161
162pub trait ParentDataModifierNode: Any + Send + Sync + 'static {
164 fn apply_parent_data(&self, data: &mut ParentDataMap);
166
167 fn equivalent(&self, _other: &dyn ParentDataModifierNode) -> bool {
172 false
173 }
174}
175
176pub trait BuildModifierNode: Any + Send + Sync {
178 fn apply(&self, _runtime: &mut TesseraRuntime) {}
180
181 fn materialize(&self, _context: &mut ModifierBuildContext) -> Option<Modifier> {
186 None
187 }
188
189 fn nested_scroll_connection(&self) -> Option<crate::nested_scroll::NestedScrollConnection> {
191 None
192 }
193}
194
195pub struct ModifierBuildContext {
201 instance: u64,
202 owner: u64,
203 path: Vec<u64>,
204 state_positions: SmallVec<[(TypeId, usize); 4]>,
205 clock_positions: SmallVec<[(TypeId, usize); 4]>,
206}
207
208fn next_type_position(positions: &mut SmallVec<[(TypeId, usize); 4]>, id: TypeId) -> usize {
209 if let Some((_, next)) = positions.iter_mut().find(|(kind, _)| *kind == id) {
210 let position = *next;
211 *next = next.checked_add(1).expect("modifier position exhausted");
212 position
213 } else {
214 positions.push((id, 1));
215 0
216 }
217}
218
219fn modifier_type_key(id: TypeId) -> u64 {
220 let mut hasher = FxHasher::default();
221 id.hash(&mut hasher);
222 hasher.finish()
223}
224
225impl ModifierBuildContext {
226 pub fn state<T: Send + Sync + 'static>(&mut self, init: impl FnOnce() -> T) -> crate::State<T> {
231 let ordinal = next_type_position(&mut self.state_positions, TypeId::of::<T>());
232 crate::runtime::modifier_state(self.instance, &self.path, ordinal, init)
233 }
234
235 pub fn receive_frame_nanos<F>(&mut self, callback: F)
237 where
238 F: FnMut(u64) -> crate::FrameNanosControl + Send + 'static,
239 {
240 let callback_type = TypeId::of::<F>();
241 let ordinal = next_type_position(&mut self.clock_positions, callback_type);
242 let mut path = self.path.clone();
243 path.push(u64::MAX);
244 path.push(modifier_type_key(callback_type));
245 crate::runtime::modifier_frame_receiver(
246 self.instance,
247 self.owner,
248 &path,
249 ordinal,
250 callback,
251 );
252 }
253
254 pub fn nested_scroll_parent(&self) -> Option<crate::nested_scroll::NestedScrollConnection> {
256 crate::nested_scroll::NestedScrollConnection::nearest()
257 }
258}
259
260pub trait SemanticsModifierNode: Send + Sync + 'static {
262 fn apply(
264 &self,
265 accessibility: &mut AccessibilityNode,
266 action_handler: &mut Option<AccessibilityActionHandler>,
267 );
268}
269
270pub trait PointerInputModifierNode: Send + Sync + 'static {
272 fn on_pointer_input(&self, input: PointerInput<'_>);
279}
280
281pub trait CursorModifierNode: Send + Sync + 'static {
283 fn cursor_icon(&self) -> CursorIcon;
286}
287
288pub trait KeyboardInputModifierNode: Send + Sync + 'static {
290 fn on_keyboard_input(&self, input: KeyboardInput<'_>);
292}
293
294pub trait ImeInputModifierNode: Send + Sync + 'static {
296 fn on_ime_input(&self, input: ImeInput<'_>);
298}
299
300pub trait ModifierCapabilityExt {
308 fn push_layout<N>(self, node: N) -> Self
310 where
311 N: LayoutModifierNode + PartialEq;
312
313 fn push_placement<N>(self, node: N) -> Self
315 where
316 N: PlacementModifierNode + PartialEq;
317
318 fn push_draw<N>(self, node: N) -> Self
320 where
321 N: DrawModifierNode;
322
323 fn push_parent_data<N>(self, node: N) -> Self
325 where
326 N: ParentDataModifierNode;
327
328 fn push_build<N>(self, node: N) -> Self
330 where
331 N: BuildModifierNode;
332
333 fn push_semantics<N>(self, node: N) -> Self
335 where
336 N: SemanticsModifierNode;
337
338 fn push_pointer_preview_input<N>(self, node: N) -> Self
341 where
342 N: PointerInputModifierNode;
343
344 fn push_pointer_input<N>(self, node: N) -> Self
346 where
347 N: PointerInputModifierNode;
348
349 fn push_pointer_final_input<N>(self, node: N) -> Self
352 where
353 N: PointerInputModifierNode;
354
355 fn push_keyboard_preview_input<N>(self, node: N) -> Self
358 where
359 N: KeyboardInputModifierNode;
360
361 fn push_keyboard_input<N>(self, node: N) -> Self
363 where
364 N: KeyboardInputModifierNode;
365
366 fn push_clipboard_input<N>(self, node: N) -> Self
368 where
369 N: ClipboardInputModifierNode;
370
371 fn push_ime_preview_input<N>(self, node: N) -> Self
373 where
374 N: ImeInputModifierNode;
375
376 fn push_ime_input<N>(self, node: N) -> Self
378 where
379 N: ImeInputModifierNode;
380}
381
382#[derive(Clone, PartialEq, Eq)]
383pub(crate) enum FocusModifierRegistration {
384 Target(Option<FocusNode>),
385 Scope(Option<FocusScopeNode>),
386 Group(Option<FocusGroupNode>),
387 Restorer {
388 scope: Option<FocusScopeNode>,
389 fallback: Option<FocusRequester>,
390 },
391}
392
393#[derive(Clone, PartialEq, Eq)]
394enum FocusModifierOp {
395 Requester(FocusRequester),
396 Registration(FocusModifierRegistration),
397 Properties(Arc<FocusProperties>),
398 PreferredTabStop(bool),
399 TraversalPolicy(FocusTraversalPolicy),
400 ChangedHandler(CallbackWith<FocusState>),
401 EventHandler(CallbackWith<FocusState>),
402 BeyondBoundsHandler(CallbackWith<FocusDirection, bool>),
403 RevealHandler(CallbackWith<FocusRevealRequest, bool>),
404}
405
406pub(crate) trait ErasedLayoutModifierNode: Send + Sync + 'static {
407 fn node(&self) -> Arc<dyn LayoutModifierNode>;
408
409 fn eq(&self, other: &dyn ErasedLayoutModifierNode) -> bool;
410
411 fn measure_eq(&self, other: &dyn ErasedLayoutModifierNode) -> bool;
412
413 fn placement_eq(&self, other: &dyn ErasedLayoutModifierNode) -> bool;
414
415 fn hash_node(&self, state: &mut dyn Hasher);
416
417 fn as_any(&self) -> &dyn Any;
418}
419
420pub(crate) trait ErasedPlacementModifierNode: Send + Sync + 'static {
421 fn node(&self) -> Arc<dyn PlacementModifierNode>;
422
423 fn eq(&self, other: &dyn ErasedPlacementModifierNode) -> bool;
424
425 fn hash_node(&self, state: &mut dyn Hasher);
426
427 fn as_any(&self) -> &dyn Any;
428}
429
430struct ComparableLayoutModifierNode<N>
431where
432 N: LayoutModifierNode + PartialEq,
433{
434 node: Arc<N>,
435}
436
437impl<N> ErasedLayoutModifierNode for ComparableLayoutModifierNode<N>
438where
439 N: LayoutModifierNode + PartialEq,
440{
441 fn node(&self) -> Arc<dyn LayoutModifierNode> {
442 self.node.clone()
443 }
444
445 fn eq(&self, other: &dyn ErasedLayoutModifierNode) -> bool {
446 other
447 .as_any()
448 .downcast_ref::<Self>()
449 .is_some_and(|other| self.node.as_ref() == other.node.as_ref())
450 }
451
452 fn measure_eq(&self, other: &dyn ErasedLayoutModifierNode) -> bool {
453 other
454 .as_any()
455 .downcast_ref::<Self>()
456 .is_some_and(|other| self.node.measure_eq(other.node.as_ref()))
457 }
458
459 fn placement_eq(&self, other: &dyn ErasedLayoutModifierNode) -> bool {
460 other
461 .as_any()
462 .downcast_ref::<Self>()
463 .is_some_and(|other| self.node.placement_eq(other.node.as_ref()))
464 }
465
466 fn hash_node(&self, state: &mut dyn Hasher) {
467 let mut concrete = std::collections::hash_map::DefaultHasher::new();
470 TypeId::of::<N>().hash(&mut concrete);
471 state.write_u64(concrete.finish());
472 }
473
474 fn as_any(&self) -> &dyn Any {
475 self
476 }
477}
478
479struct ComparablePlacementModifierNode<N>
480where
481 N: PlacementModifierNode + PartialEq,
482{
483 node: Arc<N>,
484}
485
486impl<N> ErasedPlacementModifierNode for ComparablePlacementModifierNode<N>
487where
488 N: PlacementModifierNode + PartialEq,
489{
490 fn node(&self) -> Arc<dyn PlacementModifierNode> {
491 self.node.clone()
492 }
493
494 fn eq(&self, other: &dyn ErasedPlacementModifierNode) -> bool {
495 other
496 .as_any()
497 .downcast_ref::<Self>()
498 .is_some_and(|other| self.node.as_ref() == other.node.as_ref())
499 }
500
501 fn hash_node(&self, state: &mut dyn Hasher) {
502 let mut concrete = std::collections::hash_map::DefaultHasher::new();
505 TypeId::of::<N>().hash(&mut concrete);
506 state.write_u64(concrete.finish());
507 }
508
509 fn as_any(&self) -> &dyn Any {
510 self
511 }
512}
513
514#[derive(Clone)]
515enum ModifierAction {
516 Layout(Arc<dyn ErasedLayoutModifierNode>),
517 Placement(Arc<dyn ErasedPlacementModifierNode>),
518 Draw(Arc<dyn DrawModifierNode>),
519 ParentData(Arc<dyn ParentDataModifierNode>),
520 Build(Arc<dyn BuildModifierNode>),
521 Semantics(Arc<dyn SemanticsModifierNode>),
522 Cursor(Arc<dyn CursorModifierNode>),
523 PointerPreviewInput(Arc<dyn PointerInputModifierNode>),
524 PointerInput(Arc<dyn PointerInputModifierNode>),
525 PointerFinalInput(Arc<dyn PointerInputModifierNode>),
526 KeyboardPreviewInput(Arc<dyn KeyboardInputModifierNode>),
527 KeyboardInput(Arc<dyn KeyboardInputModifierNode>),
528 ClipboardInput(Arc<dyn ClipboardInputModifierNode>),
529 ImePreviewInput(Arc<dyn ImeInputModifierNode>),
530 ImeInput(Arc<dyn ImeInputModifierNode>),
531 Focus(FocusModifierOp),
532 GloballyPositioned(crate::component_tree::GloballyPositionedHandler),
533}
534
535impl ModifierAction {
536 fn layout_node(&self) -> Option<&dyn ErasedLayoutModifierNode> {
537 match self {
538 Self::Layout(node) => Some(node.as_ref()),
539 _ => None,
540 }
541 }
542}
543
544#[derive(Clone)]
545pub(crate) enum OrderedModifierAction {
546 Layout,
547 Placement(Arc<dyn ErasedPlacementModifierNode>),
548 Draw(Arc<dyn DrawModifierNode>),
549 ParentData,
550 Cursor(Arc<dyn CursorModifierNode>),
551 PointerPreviewInput(Arc<dyn PointerInputModifierNode>),
552 PointerInput(Arc<dyn PointerInputModifierNode>),
553 PointerFinalInput(Arc<dyn PointerInputModifierNode>),
554 KeyboardPreviewInput(Arc<dyn KeyboardInputModifierNode>),
555 KeyboardInput(Arc<dyn KeyboardInputModifierNode>),
556 ClipboardInput(Arc<dyn ClipboardInputModifierNode>),
557 ImePreviewInput(Arc<dyn ImeInputModifierNode>),
558 ImeInput(Arc<dyn ImeInputModifierNode>),
559}
560
561#[derive(Clone)]
567enum ModifierElement {
568 Empty,
569 Action(ModifierAction),
570 Combined(Arc<ModifierCombination>),
571}
572
573struct ModifierCombination {
574 outer: ModifierElement,
575 inner: ModifierElement,
576}
577
578impl Default for ModifierElement {
579 fn default() -> Self {
580 Self::Empty
581 }
582}
583
584impl ModifierElement {
585 fn is_empty(&self) -> bool {
586 matches!(self, Self::Empty)
587 }
588
589 fn then(self, inner: Self) -> Self {
590 match (self, inner) {
591 (lhs, Self::Empty) => lhs,
592 (Self::Empty, rhs) => rhs,
593 (outer, inner) => Self::Combined(Arc::new(ModifierCombination { outer, inner })),
594 }
595 }
596
597 fn fold_actions<'a, F>(&'a self, visit: &mut F)
598 where
599 F: FnMut(&'a ModifierAction),
600 {
601 match self {
602 Self::Empty => {}
603 Self::Action(action) => visit(action),
604 Self::Combined(combination) => {
605 combination.outer.fold_actions(visit);
606 combination.inner.fold_actions(visit);
607 }
608 }
609 }
610
611 fn actions(&self) -> impl Iterator<Item = &ModifierAction> {
612 let mut pending = SmallVec::<[&Self; 8]>::new();
613 pending.push(self);
614 std::iter::from_fn(move || {
615 while let Some(element) = pending.pop() {
616 match element {
617 Self::Empty => {}
618 Self::Action(action) => return Some(action),
619 Self::Combined(combination) => {
620 pending.push(&combination.inner);
621 pending.push(&combination.outer);
622 }
623 }
624 }
625 None
626 })
627 }
628
629 fn for_each_action_outer_first<F>(&self, visit: &mut F)
630 where
631 F: FnMut(ModifierAction),
632 {
633 match self {
634 Self::Empty => {}
635 Self::Action(action) => visit(action.clone()),
636 Self::Combined(combination) => {
637 combination.inner.for_each_action_outer_first(visit);
638 combination.outer.for_each_action_outer_first(visit);
639 }
640 }
641 }
642}
643
644#[derive(Clone, Default)]
646pub struct Modifier {
647 element: ModifierElement,
648}
649
650pub trait FocusModifierExt {
652 fn focusable(self) -> Modifier;
654
655 fn focus_requester(self, requester: FocusRequester) -> Modifier;
657
658 fn focus_properties(self, properties: FocusProperties) -> Modifier;
660
661 fn preferred_tab_stop(self, preferred: bool) -> Modifier;
664
665 fn focus_group(self) -> Modifier;
667
668 fn focus_scope_with(self, scope: FocusScopeNode) -> Modifier;
670
671 fn focus_group_with(self, group: FocusGroupNode) -> Modifier;
673
674 fn focus_restorer(self, fallback: Option<FocusRequester>) -> Modifier;
676
677 fn focus_restorer_with(
679 self,
680 scope: FocusScopeNode,
681 fallback: Option<FocusRequester>,
682 ) -> Modifier;
683
684 fn focus_traversal_policy(self, policy: FocusTraversalPolicy) -> Modifier;
686
687 fn on_focus_changed<F>(self, handler: F) -> Modifier
689 where
690 F: Into<CallbackWith<FocusState>>;
691
692 fn on_focus_event<F>(self, handler: F) -> Modifier
694 where
695 F: Into<CallbackWith<FocusState>>;
696
697 fn focus_beyond_bounds_handler<F>(self, handler: F) -> Modifier
699 where
700 F: Into<CallbackWith<FocusDirection, bool>>;
701
702 fn focus_reveal_handler<F>(self, handler: F) -> Modifier
705 where
706 F: Into<CallbackWith<FocusRevealRequest, bool>>;
707
708 fn on_globally_positioned<F>(self, handler: F) -> Modifier
711 where
712 F: Into<CallbackWith<crate::PxRect>>;
713
714 fn on_globally_positioned_precise<F>(self, handler: F) -> Modifier
716 where
717 F: Into<CallbackWith<crate::FloatRect>>;
718
719 fn on_local_to_window<F>(self, handler: F) -> Modifier
721 where
722 F: Into<CallbackWith<crate::LocalToWindow>>;
723
724 fn on_layout_coordinates<F>(self, handler: F) -> Modifier
727 where
728 F: Into<CallbackWith<crate::LayoutCoordinates>>;
729}
730
731pub trait CursorModifierExt {
733 fn hover_cursor_icon(self, icon: CursorIcon) -> Modifier;
735}
736
737impl Modifier {
738 pub fn on_layout_size_changed<F>(self, handler: F) -> Self
743 where
744 F: Into<CallbackWith<crate::PxSize>>,
745 {
746 self.push_action(ModifierAction::GloballyPositioned(
747 crate::component_tree::GloballyPositionedHandler::Size(handler.into()),
748 ))
749 }
750
751 pub fn on_visible_window_bounds<F>(self, handler: F) -> Self
756 where
757 F: Into<CallbackWith<Option<crate::FloatRect>>>,
758 {
759 self.push_action(ModifierAction::GloballyPositioned(
760 crate::component_tree::GloballyPositionedHandler::Visible(handler.into()),
761 ))
762 }
763
764 pub fn layout_coordinate_space(self) -> Self {
768 self.push_build(LayoutCoordinateSpace)
769 }
770
771 pub fn on_layout_rect_in_space<F>(self, handler: F) -> Self
777 where
778 F: Into<CallbackWith<crate::FloatRect>>,
779 {
780 self.push_action(ModifierAction::GloballyPositioned(
781 crate::component_tree::GloballyPositionedHandler::InSpace(handler.into()),
782 ))
783 }
784
785 pub fn new() -> Self {
787 Self::default()
788 }
789
790 fn push_action(self, action: ModifierAction) -> Self {
791 Self {
792 element: self.element.then(ModifierElement::Action(action)),
793 }
794 }
795
796 pub fn then(self, other: Modifier) -> Self {
798 Self {
799 element: self.element.then(other.element),
800 }
801 }
802
803 pub(crate) fn push_layout<N>(self, node: N) -> Self
804 where
805 N: LayoutModifierNode + PartialEq,
806 {
807 self.push_action(ModifierAction::Layout(Arc::new(
808 ComparableLayoutModifierNode {
809 node: Arc::new(node),
810 },
811 )))
812 }
813
814 pub(crate) fn push_placement<N>(self, node: N) -> Self
815 where
816 N: PlacementModifierNode + PartialEq,
817 {
818 self.push_action(ModifierAction::Placement(Arc::new(
819 ComparablePlacementModifierNode {
820 node: Arc::new(node),
821 },
822 )))
823 }
824
825 pub(crate) fn push_draw<N>(self, node: N) -> Self
826 where
827 N: DrawModifierNode,
828 {
829 self.push_action(ModifierAction::Draw(Arc::new(node)))
830 }
831
832 pub(crate) fn push_parent_data<N>(self, node: N) -> Self
833 where
834 N: ParentDataModifierNode,
835 {
836 self.push_action(ModifierAction::ParentData(Arc::new(node)))
837 }
838
839 pub(crate) fn push_build<N>(self, node: N) -> Self
840 where
841 N: BuildModifierNode,
842 {
843 self.push_action(ModifierAction::Build(Arc::new(node)))
844 }
845
846 pub(crate) fn push_semantics<N>(self, node: N) -> Self
847 where
848 N: SemanticsModifierNode,
849 {
850 self.push_action(ModifierAction::Semantics(Arc::new(node)))
851 }
852
853 fn push_cursor<N>(self, node: N) -> Self
854 where
855 N: CursorModifierNode,
856 {
857 self.push_action(ModifierAction::Cursor(Arc::new(node)))
858 }
859
860 pub(crate) fn push_pointer_preview_input<N>(self, node: N) -> Self
861 where
862 N: PointerInputModifierNode,
863 {
864 self.push_action(ModifierAction::PointerPreviewInput(Arc::new(node)))
865 }
866
867 pub(crate) fn push_pointer_input<N>(self, node: N) -> Self
868 where
869 N: PointerInputModifierNode,
870 {
871 self.push_action(ModifierAction::PointerInput(Arc::new(node)))
872 }
873
874 pub(crate) fn push_pointer_final_input<N>(self, node: N) -> Self
875 where
876 N: PointerInputModifierNode,
877 {
878 self.push_action(ModifierAction::PointerFinalInput(Arc::new(node)))
879 }
880
881 pub(crate) fn push_keyboard_preview_input<N>(self, node: N) -> Self
882 where
883 N: KeyboardInputModifierNode,
884 {
885 self.push_action(ModifierAction::KeyboardPreviewInput(Arc::new(node)))
886 }
887
888 pub(crate) fn push_keyboard_input<N>(self, node: N) -> Self
889 where
890 N: KeyboardInputModifierNode,
891 {
892 self.push_action(ModifierAction::KeyboardInput(Arc::new(node)))
893 }
894
895 pub(crate) fn push_clipboard_input<N>(self, node: N) -> Self
896 where
897 N: ClipboardInputModifierNode,
898 {
899 self.push_action(ModifierAction::ClipboardInput(Arc::new(node)))
900 }
901
902 pub(crate) fn push_ime_preview_input<N>(self, node: N) -> Self
903 where
904 N: ImeInputModifierNode,
905 {
906 self.push_action(ModifierAction::ImePreviewInput(Arc::new(node)))
907 }
908
909 pub(crate) fn push_ime_input<N>(self, node: N) -> Self
910 where
911 N: ImeInputModifierNode,
912 {
913 self.push_action(ModifierAction::ImeInput(Arc::new(node)))
914 }
915
916 fn push_focus_requester(self, requester: FocusRequester) -> Self {
917 self.push_focus_op(FocusModifierOp::Requester(requester))
918 }
919
920 fn push_focus_target(self) -> Self {
921 self.push_focus_op(FocusModifierOp::Registration(
922 FocusModifierRegistration::Target(None),
923 ))
924 }
925
926 fn push_focus_scope_with(self, scope: FocusScopeNode) -> Self {
927 self.push_focus_op(FocusModifierOp::Registration(
928 FocusModifierRegistration::Scope(Some(scope)),
929 ))
930 }
931
932 fn push_focus_group(self) -> Self {
933 self.push_focus_op(FocusModifierOp::Registration(
934 FocusModifierRegistration::Group(None),
935 ))
936 }
937
938 fn push_focus_group_with(self, group: FocusGroupNode) -> Self {
939 self.push_focus_op(FocusModifierOp::Registration(
940 FocusModifierRegistration::Group(Some(group)),
941 ))
942 }
943
944 fn push_focus_restorer(self, fallback: Option<FocusRequester>) -> Self {
945 self.push_focus_op(FocusModifierOp::Registration(
946 FocusModifierRegistration::Restorer {
947 scope: None,
948 fallback,
949 },
950 ))
951 }
952
953 fn push_focus_restorer_with(
954 self,
955 scope: FocusScopeNode,
956 fallback: Option<FocusRequester>,
957 ) -> Self {
958 self.push_focus_op(FocusModifierOp::Registration(
959 FocusModifierRegistration::Restorer {
960 scope: Some(scope),
961 fallback,
962 },
963 ))
964 }
965
966 fn push_focus_properties(self, properties: FocusProperties) -> Self {
967 self.push_focus_op(FocusModifierOp::Properties(Arc::new(properties)))
968 }
969
970 fn push_focus_traversal_policy(self, policy: FocusTraversalPolicy) -> Self {
971 self.push_focus_op(FocusModifierOp::TraversalPolicy(policy))
972 }
973
974 fn push_focus_changed_handler(self, handler: CallbackWith<FocusState>) -> Self {
975 self.push_focus_op(FocusModifierOp::ChangedHandler(handler))
976 }
977
978 fn push_focus_event_handler(self, handler: CallbackWith<FocusState>) -> Self {
979 self.push_focus_op(FocusModifierOp::EventHandler(handler))
980 }
981
982 fn push_focus_beyond_bounds_handler(self, handler: CallbackWith<FocusDirection, bool>) -> Self {
983 self.push_focus_op(FocusModifierOp::BeyondBoundsHandler(handler))
984 }
985
986 fn push_focus_reveal_handler(self, handler: CallbackWith<FocusRevealRequest, bool>) -> Self {
987 self.push_focus_op(FocusModifierOp::RevealHandler(handler))
988 }
989
990 fn push_globally_positioned(self, handler: CallbackWith<crate::PxRect>) -> Self {
991 self.push_action(ModifierAction::GloballyPositioned(
992 crate::component_tree::GloballyPositionedHandler::Pixels(handler),
993 ))
994 }
995
996 fn push_focus_op(self, op: FocusModifierOp) -> Self {
997 self.push_action(ModifierAction::Focus(op))
998 }
999
1000 pub fn nested_scroll(self, connection: crate::nested_scroll::NestedScrollConnection) -> Self {
1002 self.push_build(connection)
1003 }
1004
1005 pub(crate) fn nested_scroll_connection(
1006 &self,
1007 ) -> Option<crate::nested_scroll::NestedScrollConnection> {
1008 let mut connection = None;
1009 self.element.for_each_action_outer_first(&mut |action| {
1010 if let ModifierAction::Build(node) = action {
1011 if let Some(attached) = node.nested_scroll_connection() {
1012 connection = Some(attached);
1013 }
1014 }
1015 });
1016 connection
1017 }
1018
1019 fn materialize(self, instance: u64, owner: u64, path: &[u64]) -> Self {
1020 fn expand(
1021 element: &ModifierElement,
1022 instance: u64,
1023 owner: u64,
1024 path: &[u64],
1025 positions: &mut SmallVec<[(TypeId, usize); 4]>,
1026 ) -> Option<ModifierElement> {
1027 match element {
1028 ModifierElement::Empty => None,
1029 ModifierElement::Action(action) => {
1030 let ModifierAction::Build(node) = action else {
1031 return None;
1032 };
1033 let kind = node.as_ref().type_id();
1034 let position = next_type_position(positions, kind);
1035 let mut path = path.to_vec();
1036 path.push(modifier_type_key(kind));
1037 path.push(position as u64);
1038 let mut context = ModifierBuildContext {
1039 instance,
1040 owner,
1041 path: path.clone(),
1042 state_positions: SmallVec::new(),
1043 clock_positions: SmallVec::new(),
1044 };
1045 node.materialize(&mut context)
1046 .map(|modifier| modifier.materialize(instance, owner, &path).element)
1047 }
1048 ModifierElement::Combined(combination) => {
1049 let ModifierCombination { outer, inner } = combination.as_ref();
1050 let first = expand(outer, instance, owner, path, positions);
1051 let second = expand(inner, instance, owner, path, positions);
1052 if first.is_none() && second.is_none() {
1053 return None;
1054 }
1055 Some(
1056 first
1057 .unwrap_or_else(|| outer.clone())
1058 .then(second.unwrap_or_else(|| inner.clone())),
1059 )
1060 }
1061 }
1062 }
1063 assert!(path.len() < 64, "recursive modifier materialization");
1064 match expand(&self.element, instance, owner, path, &mut SmallVec::new()) {
1065 Some(element) => Self { element },
1066 None => self,
1067 }
1068 }
1069
1070 pub fn attach(self) {
1072 ensure_build_phase();
1073
1074 let (instance, owner) = TesseraRuntime::with(|runtime| {
1075 let node = runtime
1076 .component_tree
1077 .current_node()
1078 .expect("modifier attachment requires a node");
1079 (node.instance_logic_id, node.instance_key)
1080 });
1081 let materialized =
1082 self.materialize(instance, owner, &crate::runtime::modifier_attachment_path());
1083
1084 TesseraRuntime::with_mut(|runtime| {
1085 runtime.append_current_modifier(materialized.clone());
1086 });
1087 crate::nested_scroll::attachment_changed();
1088
1089 let mut accessibility = AccessibilityNode::new();
1090 let mut action_handler = None;
1091 let mut has_semantics = false;
1092 materialized
1093 .element
1094 .fold_actions(&mut |action| match action {
1095 ModifierAction::Build(node) => {
1096 TesseraRuntime::with_mut(|runtime| node.apply(runtime));
1097 }
1098 ModifierAction::Semantics(node) => {
1099 has_semantics = true;
1100 node.apply(&mut accessibility, &mut action_handler);
1101 }
1102 ModifierAction::Focus(op) => {
1103 TesseraRuntime::with_mut(|runtime| {
1104 apply_focus_op(runtime::FocusModifierRuntime::new(runtime), op.clone());
1105 });
1106 }
1107 ModifierAction::GloballyPositioned(handler) => {
1108 TesseraRuntime::with_mut(|runtime| {
1109 runtime.push_current_globally_positioned_handler(handler.clone());
1110 });
1111 }
1112 _ => {}
1113 });
1114
1115 TesseraRuntime::with_mut(|runtime| {
1116 runtime
1117 .set_current_accessibility(has_semantics.then_some(accessibility), action_handler);
1118 });
1119 }
1120
1121 pub fn run<F>(self, child: F)
1123 where
1124 F: Fn() + Send + Sync + 'static,
1125 {
1126 self.attach();
1127 child();
1128 }
1129
1130 pub fn is_empty(&self) -> bool {
1132 self.element.is_empty()
1133 }
1134
1135 pub(crate) fn ordered_actions(&self) -> Vec<OrderedModifierAction> {
1136 let mut actions = Vec::new();
1137 self.element.fold_actions(&mut |action| {
1138 let action = match action {
1139 ModifierAction::Layout(_) => OrderedModifierAction::Layout,
1140 ModifierAction::Placement(node) => OrderedModifierAction::Placement(node.clone()),
1141 ModifierAction::Draw(node) => OrderedModifierAction::Draw(node.clone()),
1142 ModifierAction::ParentData(_) => OrderedModifierAction::ParentData,
1143 ModifierAction::Cursor(node) => OrderedModifierAction::Cursor(node.clone()),
1144 ModifierAction::PointerPreviewInput(node) => {
1145 OrderedModifierAction::PointerPreviewInput(node.clone())
1146 }
1147 ModifierAction::PointerInput(node) => {
1148 OrderedModifierAction::PointerInput(node.clone())
1149 }
1150 ModifierAction::PointerFinalInput(node) => {
1151 OrderedModifierAction::PointerFinalInput(node.clone())
1152 }
1153 ModifierAction::KeyboardPreviewInput(node) => {
1154 OrderedModifierAction::KeyboardPreviewInput(node.clone())
1155 }
1156 ModifierAction::KeyboardInput(node) => {
1157 OrderedModifierAction::KeyboardInput(node.clone())
1158 }
1159 ModifierAction::ClipboardInput(node) => {
1160 OrderedModifierAction::ClipboardInput(node.clone())
1161 }
1162 ModifierAction::ImePreviewInput(node) => {
1163 OrderedModifierAction::ImePreviewInput(node.clone())
1164 }
1165 ModifierAction::ImeInput(node) => OrderedModifierAction::ImeInput(node.clone()),
1166 ModifierAction::Build(_)
1167 | ModifierAction::Semantics(_)
1168 | ModifierAction::Focus(_)
1169 | ModifierAction::GloballyPositioned(_) => return,
1170 };
1171 actions.push(action);
1172 });
1173 actions
1174 }
1175
1176 pub(crate) fn input_geometry_eq(&self, other: &Self) -> bool {
1177 let shape = |modifier: &Self| {
1178 let mut pointer = false;
1179 let mut actions = SmallVec::<[_; 4]>::new();
1180 modifier.element.fold_actions(&mut |action| {
1181 pointer |= matches!(
1182 action,
1183 ModifierAction::Cursor(_)
1184 | ModifierAction::PointerPreviewInput(_)
1185 | ModifierAction::PointerInput(_)
1186 | ModifierAction::PointerFinalInput(_)
1187 );
1188 if !matches!(
1189 action,
1190 ModifierAction::Build(_)
1191 | ModifierAction::Semantics(_)
1192 | ModifierAction::Focus(_)
1193 | ModifierAction::GloballyPositioned(_)
1194 ) {
1195 actions.push(std::mem::discriminant(action));
1196 }
1197 });
1198 (pointer, actions)
1199 };
1200 let (left_pointer, left) = shape(self);
1201 let (right_pointer, right) = shape(other);
1202 (!left_pointer && !right_pointer) || (left_pointer == right_pointer && left == right)
1203 }
1204
1205 pub(crate) fn has_pointer_input(&self) -> bool {
1206 let mut pointer = false;
1207 self.element.fold_actions(&mut |action| {
1208 pointer |= matches!(
1209 action,
1210 ModifierAction::Cursor(_)
1211 | ModifierAction::PointerPreviewInput(_)
1212 | ModifierAction::PointerInput(_)
1213 | ModifierAction::PointerFinalInput(_)
1214 );
1215 });
1216 pointer
1217 }
1218
1219 pub(crate) fn has_input_geometry(&self) -> bool {
1220 let mut input = false;
1221 self.element.fold_actions(&mut |action| {
1222 input |= matches!(
1223 action,
1224 ModifierAction::Cursor(_)
1225 | ModifierAction::PointerPreviewInput(_)
1226 | ModifierAction::PointerInput(_)
1227 | ModifierAction::PointerFinalInput(_)
1228 | ModifierAction::KeyboardPreviewInput(_)
1229 | ModifierAction::KeyboardInput(_)
1230 | ModifierAction::ImePreviewInput(_)
1231 | ModifierAction::ImeInput(_)
1232 );
1233 });
1234 input
1235 }
1236
1237 pub(crate) fn resolve_placement(
1238 &self,
1239 mut position: PxPosition,
1240 instance: u64,
1241 ) -> (PxPosition, Vec<PxPosition>) {
1242 let pointer = self.has_pointer_input();
1243 let mut positions = Vec::new();
1244 self.element.fold_actions(&mut |action| {
1245 if let ModifierAction::Placement(node) = action {
1246 crate::work::record(
1247 instance,
1248 crate::WorkPhase::Transform,
1249 node.node().diagnostic_name(),
1250 );
1251 position = node.node().transform_position(position);
1252 }
1253 if pointer
1254 && !matches!(
1255 action,
1256 ModifierAction::Build(_)
1257 | ModifierAction::Semantics(_)
1258 | ModifierAction::Focus(_)
1259 | ModifierAction::GloballyPositioned(_)
1260 )
1261 {
1262 positions.push(position);
1263 }
1264 });
1265 (position, positions)
1266 }
1267
1268 fn select_actions<'a, T>(
1269 &'a self,
1270 mut select: impl FnMut(&'a ModifierAction) -> Option<T>,
1271 ) -> SmallVec<[T; 4]> {
1272 let mut selected = SmallVec::new();
1273 self.element.fold_actions(&mut |action| {
1274 if let Some(value) = select(action) {
1275 selected.push(value);
1276 }
1277 });
1278 selected
1279 }
1280
1281 fn selected_actions_eq<'a, T>(
1282 &'a self,
1283 other: &'a Self,
1284 select: impl Fn(&'a ModifierAction) -> Option<T>,
1285 mut eq: impl FnMut(T, T) -> bool,
1286 ) -> bool {
1287 let lhs = self.select_actions(&select);
1288 let rhs = other.select_actions(select);
1289 lhs.len() == rhs.len() && lhs.into_iter().zip(rhs).all(|(lhs, rhs)| eq(lhs, rhs))
1290 }
1291
1292 pub(crate) fn layout_modifiers(&self) -> SmallVec<[Arc<dyn LayoutModifierNode>; 4]> {
1293 self.select_actions(|action| action.layout_node().map(|node| node.node()))
1294 }
1295
1296 pub(crate) fn layout_measure_eq(&self, other: &Self) -> bool {
1297 self.selected_actions_eq(other, ModifierAction::layout_node, |lhs, rhs| {
1298 lhs.measure_eq(rhs)
1299 })
1300 }
1301
1302 pub(crate) fn layout_placement_eq(&self, other: &Self) -> bool {
1303 self.selected_actions_eq(other, ModifierAction::layout_node, |lhs, rhs| {
1304 lhs.placement_eq(rhs)
1305 })
1306 }
1307
1308 pub(crate) fn position_eq(&self, other: &Self) -> bool {
1309 self.selected_actions_eq(
1310 other,
1311 |action| match action {
1312 ModifierAction::Placement(node) => Some(node.as_ref()),
1313 _ => None,
1314 },
1315 |lhs, rhs| lhs.eq(rhs),
1316 )
1317 }
1318
1319 pub(crate) fn parent_data<T: Clone + Send + Sync + 'static>(&self) -> Option<T> {
1320 let mut data = ParentDataMap::default();
1321 self.element.fold_actions(&mut |action| {
1322 if let ModifierAction::ParentData(node) = action {
1323 node.apply_parent_data(&mut data);
1324 }
1325 });
1326 data.get(&TypeId::of::<T>())?.downcast_ref::<T>().cloned()
1327 }
1328
1329 pub(crate) fn parent_data_eq(&self, other: &Self) -> bool {
1330 self.selected_actions_eq(
1331 other,
1332 |action| match action {
1333 ModifierAction::ParentData(node) => Some(node),
1334 _ => None,
1335 },
1336 |lhs, rhs| Arc::ptr_eq(lhs, rhs) || lhs.equivalent(rhs.as_ref()),
1337 )
1338 }
1339}
1340
1341impl ModifierCapabilityExt for Modifier {
1342 fn push_clipboard_input<N>(self, node: N) -> Self
1343 where
1344 N: ClipboardInputModifierNode,
1345 {
1346 Modifier::push_clipboard_input(self, node)
1347 }
1348 fn push_layout<N>(self, node: N) -> Self
1349 where
1350 N: LayoutModifierNode + PartialEq,
1351 {
1352 Modifier::push_layout(self, node)
1353 }
1354
1355 fn push_placement<N>(self, node: N) -> Self
1356 where
1357 N: PlacementModifierNode + PartialEq,
1358 {
1359 Modifier::push_placement(self, node)
1360 }
1361
1362 fn push_draw<N>(self, node: N) -> Self
1363 where
1364 N: DrawModifierNode,
1365 {
1366 Modifier::push_draw(self, node)
1367 }
1368
1369 fn push_parent_data<N>(self, node: N) -> Self
1370 where
1371 N: ParentDataModifierNode,
1372 {
1373 Modifier::push_parent_data(self, node)
1374 }
1375
1376 fn push_build<N>(self, node: N) -> Self
1377 where
1378 N: BuildModifierNode,
1379 {
1380 Modifier::push_build(self, node)
1381 }
1382
1383 fn push_semantics<N>(self, node: N) -> Self
1384 where
1385 N: SemanticsModifierNode,
1386 {
1387 Modifier::push_semantics(self, node)
1388 }
1389
1390 fn push_pointer_preview_input<N>(self, node: N) -> Self
1391 where
1392 N: PointerInputModifierNode,
1393 {
1394 Modifier::push_pointer_preview_input(self, node)
1395 }
1396
1397 fn push_pointer_input<N>(self, node: N) -> Self
1398 where
1399 N: PointerInputModifierNode,
1400 {
1401 Modifier::push_pointer_input(self, node)
1402 }
1403
1404 fn push_pointer_final_input<N>(self, node: N) -> Self
1405 where
1406 N: PointerInputModifierNode,
1407 {
1408 Modifier::push_pointer_final_input(self, node)
1409 }
1410
1411 fn push_keyboard_preview_input<N>(self, node: N) -> Self
1412 where
1413 N: KeyboardInputModifierNode,
1414 {
1415 Modifier::push_keyboard_preview_input(self, node)
1416 }
1417
1418 fn push_keyboard_input<N>(self, node: N) -> Self
1419 where
1420 N: KeyboardInputModifierNode,
1421 {
1422 Modifier::push_keyboard_input(self, node)
1423 }
1424
1425 fn push_ime_preview_input<N>(self, node: N) -> Self
1426 where
1427 N: ImeInputModifierNode,
1428 {
1429 Modifier::push_ime_preview_input(self, node)
1430 }
1431
1432 fn push_ime_input<N>(self, node: N) -> Self
1433 where
1434 N: ImeInputModifierNode,
1435 {
1436 Modifier::push_ime_input(self, node)
1437 }
1438}
1439
1440#[derive(Clone, Copy)]
1441struct StaticCursorModifierNode {
1442 icon: CursorIcon,
1443}
1444
1445impl CursorModifierNode for StaticCursorModifierNode {
1446 fn cursor_icon(&self) -> CursorIcon {
1447 self.icon
1448 }
1449}
1450
1451impl CursorModifierExt for Modifier {
1452 fn hover_cursor_icon(self, icon: CursorIcon) -> Modifier {
1453 self.push_cursor(StaticCursorModifierNode { icon })
1454 }
1455}
1456
1457impl FocusModifierExt for Modifier {
1458 fn focusable(self) -> Modifier {
1459 self.push_focus_target()
1460 }
1461
1462 fn focus_requester(self, requester: FocusRequester) -> Modifier {
1463 self.push_focus_requester(requester)
1464 }
1465
1466 fn focus_properties(self, properties: FocusProperties) -> Modifier {
1467 self.push_focus_properties(properties)
1468 }
1469
1470 fn preferred_tab_stop(self, preferred: bool) -> Modifier {
1471 self.push_focus_op(FocusModifierOp::PreferredTabStop(preferred))
1472 }
1473
1474 fn focus_group(self) -> Modifier {
1475 self.push_focus_group()
1476 }
1477
1478 fn focus_scope_with(self, scope: FocusScopeNode) -> Modifier {
1479 self.push_focus_scope_with(scope)
1480 }
1481
1482 fn focus_group_with(self, group: FocusGroupNode) -> Modifier {
1483 self.push_focus_group_with(group)
1484 }
1485
1486 fn focus_restorer(self, fallback: Option<FocusRequester>) -> Modifier {
1487 self.push_focus_restorer(fallback)
1488 }
1489
1490 fn focus_restorer_with(
1491 self,
1492 scope: FocusScopeNode,
1493 fallback: Option<FocusRequester>,
1494 ) -> Modifier {
1495 self.push_focus_restorer_with(scope, fallback)
1496 }
1497
1498 fn focus_traversal_policy(self, policy: FocusTraversalPolicy) -> Modifier {
1499 self.push_focus_traversal_policy(policy)
1500 }
1501
1502 fn on_focus_changed<F>(self, handler: F) -> Modifier
1503 where
1504 F: Into<CallbackWith<FocusState>>,
1505 {
1506 self.push_focus_changed_handler(handler.into())
1507 }
1508
1509 fn on_focus_event<F>(self, handler: F) -> Modifier
1510 where
1511 F: Into<CallbackWith<FocusState>>,
1512 {
1513 self.push_focus_event_handler(handler.into())
1514 }
1515
1516 fn focus_beyond_bounds_handler<F>(self, handler: F) -> Modifier
1517 where
1518 F: Into<CallbackWith<FocusDirection, bool>>,
1519 {
1520 self.push_focus_beyond_bounds_handler(handler.into())
1521 }
1522
1523 fn focus_reveal_handler<F>(self, handler: F) -> Modifier
1524 where
1525 F: Into<CallbackWith<FocusRevealRequest, bool>>,
1526 {
1527 self.push_focus_reveal_handler(handler.into())
1528 }
1529
1530 fn on_globally_positioned<F>(self, handler: F) -> Modifier
1531 where
1532 F: Into<CallbackWith<crate::PxRect>>,
1533 {
1534 self.push_globally_positioned(handler.into())
1535 }
1536
1537 fn on_globally_positioned_precise<F>(self, handler: F) -> Modifier
1538 where
1539 F: Into<CallbackWith<crate::FloatRect>>,
1540 {
1541 self.push_action(ModifierAction::GloballyPositioned(
1542 crate::component_tree::GloballyPositionedHandler::Precise(handler.into()),
1543 ))
1544 }
1545
1546 fn on_local_to_window<F>(self, handler: F) -> Modifier
1547 where
1548 F: Into<CallbackWith<crate::LocalToWindow>>,
1549 {
1550 self.push_action(ModifierAction::GloballyPositioned(
1551 crate::component_tree::GloballyPositionedHandler::Transform(handler.into()),
1552 ))
1553 }
1554
1555 fn on_layout_coordinates<F>(self, handler: F) -> Modifier
1556 where
1557 F: Into<CallbackWith<crate::LayoutCoordinates>>,
1558 {
1559 self.push_action(ModifierAction::GloballyPositioned(
1560 crate::component_tree::GloballyPositionedHandler::Coordinates(handler.into()),
1561 ))
1562 }
1563}
1564
1565impl fmt::Debug for Modifier {
1566 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1567 f.debug_struct("Modifier")
1568 .field("is_empty", &self.element.is_empty())
1569 .finish()
1570 }
1571}
1572
1573fn modifier_action_eq(lhs: &ModifierAction, rhs: &ModifierAction) -> bool {
1574 match (lhs, rhs) {
1575 (ModifierAction::Layout(lhs), ModifierAction::Layout(rhs)) => lhs.eq(rhs.as_ref()),
1576 (ModifierAction::Placement(lhs), ModifierAction::Placement(rhs)) => lhs.eq(rhs.as_ref()),
1577 (ModifierAction::Draw(lhs), ModifierAction::Draw(rhs)) => Arc::ptr_eq(lhs, rhs),
1578 (ModifierAction::ParentData(lhs), ModifierAction::ParentData(rhs)) => Arc::ptr_eq(lhs, rhs),
1579 (ModifierAction::Build(lhs), ModifierAction::Build(rhs)) => Arc::ptr_eq(lhs, rhs),
1580 (ModifierAction::Semantics(lhs), ModifierAction::Semantics(rhs)) => Arc::ptr_eq(lhs, rhs),
1581 (ModifierAction::Cursor(lhs), ModifierAction::Cursor(rhs)) => Arc::ptr_eq(lhs, rhs),
1582 (ModifierAction::PointerPreviewInput(lhs), ModifierAction::PointerPreviewInput(rhs)) => {
1583 Arc::ptr_eq(lhs, rhs)
1584 }
1585 (ModifierAction::PointerInput(lhs), ModifierAction::PointerInput(rhs)) => {
1586 Arc::ptr_eq(lhs, rhs)
1587 }
1588 (ModifierAction::PointerFinalInput(lhs), ModifierAction::PointerFinalInput(rhs)) => {
1589 Arc::ptr_eq(lhs, rhs)
1590 }
1591 (ModifierAction::KeyboardPreviewInput(lhs), ModifierAction::KeyboardPreviewInput(rhs)) => {
1592 Arc::ptr_eq(lhs, rhs)
1593 }
1594 (ModifierAction::KeyboardInput(lhs), ModifierAction::KeyboardInput(rhs)) => {
1595 Arc::ptr_eq(lhs, rhs)
1596 }
1597 (ModifierAction::ClipboardInput(lhs), ModifierAction::ClipboardInput(rhs)) => {
1598 Arc::ptr_eq(lhs, rhs)
1599 }
1600 (ModifierAction::ImePreviewInput(lhs), ModifierAction::ImePreviewInput(rhs)) => {
1601 Arc::ptr_eq(lhs, rhs)
1602 }
1603 (ModifierAction::ImeInput(lhs), ModifierAction::ImeInput(rhs)) => Arc::ptr_eq(lhs, rhs),
1604 (ModifierAction::Focus(lhs), ModifierAction::Focus(rhs)) => lhs == rhs,
1605 (ModifierAction::GloballyPositioned(lhs), ModifierAction::GloballyPositioned(rhs)) => {
1606 lhs == rhs
1607 }
1608 _ => false,
1609 }
1610}
1611
1612struct LayoutCoordinateSpace;
1613
1614impl BuildModifierNode for LayoutCoordinateSpace {
1615 fn apply(&self, runtime: &mut TesseraRuntime) {
1616 if let Some(node) = runtime.component_tree.current_node_mut() {
1617 node.layout_coordinate_space = true;
1618 }
1619 }
1620}
1621
1622fn hash_arc<T: ?Sized, H: Hasher>(value: &Arc<T>, state: &mut H) {
1623 std::ptr::hash(Arc::as_ptr(value), state);
1624}
1625
1626fn hash_modifier_action<H: Hasher>(action: &ModifierAction, state: &mut H) {
1627 std::mem::discriminant(action).hash(state);
1628 match action {
1629 ModifierAction::Layout(node) => node.hash_node(state),
1630 ModifierAction::Placement(node) => node.hash_node(state),
1631 ModifierAction::Draw(node) => hash_arc(node, state),
1632 ModifierAction::ParentData(node) => hash_arc(node, state),
1633 ModifierAction::Build(node) => hash_arc(node, state),
1634 ModifierAction::Semantics(node) => hash_arc(node, state),
1635 ModifierAction::Cursor(node) => hash_arc(node, state),
1636 ModifierAction::PointerPreviewInput(node) => hash_arc(node, state),
1637 ModifierAction::PointerInput(node) => hash_arc(node, state),
1638 ModifierAction::PointerFinalInput(node) => hash_arc(node, state),
1639 ModifierAction::KeyboardPreviewInput(node) => hash_arc(node, state),
1640 ModifierAction::KeyboardInput(node) => hash_arc(node, state),
1641 ModifierAction::ClipboardInput(node) => hash_arc(node, state),
1642 ModifierAction::ImePreviewInput(node) => hash_arc(node, state),
1643 ModifierAction::ImeInput(node) => hash_arc(node, state),
1644 ModifierAction::Focus(op) => hash_focus_op(op, state),
1645 ModifierAction::GloballyPositioned(handler) => {
1646 std::ptr::hash(
1647 handler as *const crate::component_tree::GloballyPositionedHandler,
1648 state,
1649 );
1650 }
1651 }
1652}
1653
1654fn hash_focus_op<H: Hasher>(op: &FocusModifierOp, state: &mut H) {
1655 std::mem::discriminant(op).hash(state);
1656 match op {
1657 FocusModifierOp::Requester(value) => value.hash(state),
1658 FocusModifierOp::Registration(FocusModifierRegistration::Target(node)) => {
1659 0u8.hash(state);
1660 node.map(|node| node.handle_id()).hash(state);
1661 }
1662 FocusModifierOp::Registration(FocusModifierRegistration::Scope(node)) => {
1663 1u8.hash(state);
1664 node.map(|node| node.handle_id()).hash(state);
1665 }
1666 FocusModifierOp::Registration(FocusModifierRegistration::Group(node)) => {
1667 2u8.hash(state);
1668 node.map(|node| node.handle_id()).hash(state);
1669 }
1670 FocusModifierOp::Registration(FocusModifierRegistration::Restorer { scope, fallback }) => {
1671 3u8.hash(state);
1672 scope.map(|node| node.handle_id()).hash(state);
1673 fallback.hash(state);
1674 }
1675 FocusModifierOp::Properties(value) => {
1676 value.can_focus.hash(state);
1677 value.can_request_focus.hash(state);
1678 value.skip_traversal.hash(state);
1679 value.preferred_tab_stop.hash(state);
1680 value.next.hash(state);
1681 value.previous.hash(state);
1682 value.up.hash(state);
1683 value.down.hash(state);
1684 value.left.hash(state);
1685 value.right.hash(state);
1686 value.enter.hash(state);
1687 value.exit.hash(state);
1688 }
1689 FocusModifierOp::TraversalPolicy(value) => value.hash(state),
1690 FocusModifierOp::PreferredTabStop(value) => value.hash(state),
1691 FocusModifierOp::ChangedHandler(value) => hash_callback_bits(value, state),
1692 FocusModifierOp::EventHandler(value) => hash_callback_bits(value, state),
1693 FocusModifierOp::BeyondBoundsHandler(value) => hash_callback_bits(value, state),
1694 FocusModifierOp::RevealHandler(value) => hash_callback_bits(value, state),
1695 }
1696}
1697
1698fn hash_callback_bits<T, R, H: Hasher>(callback: &CallbackWith<T, R>, state: &mut H) {
1699 let bytes = unsafe {
1700 std::slice::from_raw_parts(
1701 (callback as *const CallbackWith<T, R>).cast::<u8>(),
1702 std::mem::size_of::<CallbackWith<T, R>>(),
1703 )
1704 };
1705 bytes.hash(state);
1706}
1707
1708impl PartialEq for Modifier {
1709 fn eq(&self, other: &Self) -> bool {
1710 let mut lhs = self.element.actions();
1711 let mut rhs = other.element.actions();
1712 loop {
1713 match (lhs.next(), rhs.next()) {
1714 (Some(lhs), Some(rhs)) if modifier_action_eq(lhs, rhs) => {}
1715 (None, None) => return true,
1716 _ => return false,
1717 }
1718 }
1719 }
1720}
1721
1722impl Eq for Modifier {}
1723
1724impl Hash for Modifier {
1725 fn hash<H: Hasher>(&self, state: &mut H) {
1726 let mut count = 0usize;
1727 self.element.fold_actions(&mut |action| {
1728 hash_modifier_action(action, state);
1729 count += 1;
1730 });
1731 count.hash(state);
1732 }
1733}
1734
1735mod runtime {
1736 use super::FocusModifierRegistration;
1737 use crate::{
1738 FocusProperties, FocusRequester, FocusScopeNode, FocusState, FocusTraversalPolicy,
1739 focus::{FocusDirection, FocusRevealRequest},
1740 prop::CallbackWith,
1741 runtime::TesseraRuntime,
1742 };
1743
1744 pub(super) struct FocusModifierRuntime<'a> {
1745 runtime: &'a mut TesseraRuntime,
1746 }
1747
1748 impl<'a> FocusModifierRuntime<'a> {
1749 pub(super) fn new(runtime: &'a mut TesseraRuntime) -> Self {
1750 Self { runtime }
1751 }
1752
1753 pub(super) fn bind_requester(&mut self, requester: FocusRequester) {
1754 self.runtime.bind_current_focus_requester(requester);
1755 }
1756
1757 pub(super) fn ensure_registration(&mut self, registration: FocusModifierRegistration) {
1758 match registration {
1759 FocusModifierRegistration::Target(node) => {
1760 let node = node.unwrap_or_else(|| {
1761 self.runtime
1762 .current_focus_target_handle()
1763 .unwrap_or_else(|| {
1764 crate::runtime::persistent_focus_target_for_current_instance(
1765 "__tessera_focus_target",
1766 )
1767 })
1768 });
1769 self.runtime.ensure_current_focus_target(node);
1770 }
1771 FocusModifierRegistration::Scope(scope) => {
1772 let scope = scope.unwrap_or_else(|| {
1773 self.runtime
1774 .current_focus_scope_handle()
1775 .unwrap_or_else(|| {
1776 crate::runtime::persistent_focus_scope_for_current_instance(
1777 "__tessera_focus_scope",
1778 )
1779 })
1780 });
1781 self.runtime.ensure_current_focus_scope(scope);
1782 }
1783 FocusModifierRegistration::Group(group) => {
1784 let group = group.unwrap_or_else(|| {
1785 self.runtime
1786 .current_focus_group_handle()
1787 .unwrap_or_else(|| {
1788 crate::runtime::persistent_focus_group_for_current_instance(
1789 "__tessera_focus_group",
1790 )
1791 })
1792 });
1793 self.runtime.ensure_current_focus_group(group);
1794 }
1795 FocusModifierRegistration::Restorer { scope, fallback } => {
1796 let scope: FocusScopeNode = scope.unwrap_or_else(|| {
1797 self.runtime
1798 .current_focus_scope_handle()
1799 .unwrap_or_else(|| {
1800 crate::runtime::persistent_focus_scope_for_current_instance(
1801 "__tessera_focus_scope",
1802 )
1803 })
1804 });
1805 self.runtime.ensure_current_focus_scope(scope);
1806 if let Some(fallback) = fallback {
1807 self.runtime.set_current_focus_restorer_fallback(fallback);
1808 }
1809 }
1810 }
1811 }
1812
1813 pub(super) fn set_properties(&mut self, properties: FocusProperties) {
1814 self.runtime.set_current_focus_properties(properties);
1815 }
1816
1817 pub(super) fn set_preferred_tab_stop(&mut self, preferred: bool) {
1818 self.runtime.set_current_preferred_tab_stop(preferred);
1819 }
1820
1821 pub(super) fn set_traversal_policy(&mut self, policy: FocusTraversalPolicy) {
1822 self.runtime.set_current_focus_traversal_policy(policy);
1823 }
1824
1825 pub(super) fn set_changed_handler(&mut self, handler: CallbackWith<FocusState>) {
1826 self.runtime.set_current_focus_changed_handler(handler);
1827 }
1828
1829 pub(super) fn set_event_handler(&mut self, handler: CallbackWith<FocusState>) {
1830 self.runtime.set_current_focus_event_handler(handler);
1831 }
1832
1833 pub(super) fn set_beyond_bounds_handler(
1834 &mut self,
1835 handler: CallbackWith<FocusDirection, bool>,
1836 ) {
1837 self.runtime
1838 .set_current_focus_beyond_bounds_handler(handler);
1839 }
1840
1841 pub(super) fn set_reveal_handler(
1842 &mut self,
1843 handler: CallbackWith<FocusRevealRequest, bool>,
1844 ) {
1845 self.runtime.set_current_focus_reveal_handler(handler);
1846 }
1847 }
1848}
1849
1850fn apply_focus_op(runtime: runtime::FocusModifierRuntime<'_>, op: FocusModifierOp) {
1851 let mut runtime = runtime;
1852 match op {
1853 FocusModifierOp::Requester(requester) => runtime.bind_requester(requester),
1854 FocusModifierOp::Registration(registration) => runtime.ensure_registration(registration),
1855 FocusModifierOp::Properties(properties) => runtime.set_properties(*properties),
1856 FocusModifierOp::PreferredTabStop(preferred) => runtime.set_preferred_tab_stop(preferred),
1857 FocusModifierOp::TraversalPolicy(policy) => runtime.set_traversal_policy(policy),
1858 FocusModifierOp::ChangedHandler(handler) => runtime.set_changed_handler(handler),
1859 FocusModifierOp::EventHandler(handler) => runtime.set_event_handler(handler),
1860 FocusModifierOp::BeyondBoundsHandler(handler) => runtime.set_beyond_bounds_handler(handler),
1861 FocusModifierOp::RevealHandler(handler) => runtime.set_reveal_handler(handler),
1862 }
1863}
1864
1865#[cfg(test)]
1866mod tests {
1867 use std::{
1868 collections::hash_map::DefaultHasher,
1869 hash::{Hash, Hasher},
1870 };
1871
1872 use super::{FocusModifierOp, Modifier, ModifierAction};
1873
1874 fn flag(value: bool) -> Modifier {
1875 Modifier::new().push_action(ModifierAction::Focus(FocusModifierOp::PreferredTabStop(
1876 value,
1877 )))
1878 }
1879
1880 #[test]
1881 fn modifier_equality_flattens_different_groupings_and_checks_all_actions() {
1882 let left = flag(true).then(flag(false)).then(flag(true));
1883 let right = flag(true).then(flag(false).then(flag(true)));
1884 assert_eq!(left, right);
1885
1886 let mut left_hash = DefaultHasher::new();
1887 let mut right_hash = DefaultHasher::new();
1888 left.hash(&mut left_hash);
1889 right.hash(&mut right_hash);
1890 assert_eq!(left_hash.finish(), right_hash.finish());
1891
1892 assert_ne!(left, flag(true).then(flag(true)).then(flag(true)));
1893 assert_ne!(left, right.then(flag(false)));
1894 }
1895}