1use std::{
9 ptr::NonNull,
10 sync::atomic::{AtomicU64, Ordering},
11};
12
13use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
14
15use crate::{
16 NodeId, PxRect,
17 component_tree::{
18 ComponentNodeMetaDatas, ComponentNodeTree, nearest_replay_boundary_instance_key,
19 },
20 execution_context::{with_execution_context, with_execution_context_mut},
21 prop::CallbackWith,
22 px::PxSize,
23 runtime::{
24 TesseraRuntime, focus_read_subscribers, focus_requester_read_subscribers,
25 has_persistent_focus_handle, record_replay_boundary_invalidation_for_instance_key,
26 track_focus_read_dependency, track_focus_requester_read_dependency,
27 },
28};
29
30static NEXT_FOCUS_TARGET_ID: AtomicU64 = AtomicU64::new(1);
31static NEXT_FOCUS_REQUESTER_ID: AtomicU64 = AtomicU64::new(1);
32const ROOT_SCOPE_ID: FocusHandleId = 0;
33
34pub(crate) type FocusHandleId = u64;
35pub(crate) type FocusRequesterId = u64;
36
37fn next_focus_handle_id() -> FocusHandleId {
38 NEXT_FOCUS_TARGET_ID.fetch_add(1, Ordering::Relaxed)
39}
40
41fn next_focus_requester_id() -> FocusRequesterId {
42 NEXT_FOCUS_REQUESTER_ID.fetch_add(1, Ordering::Relaxed)
43}
44
45fn with_bound_focus_owner<R>(f: impl FnOnce(&FocusOwner) -> R) -> Option<R> {
46 let ptr = with_execution_context(|context| context.current_focus_owner_stack.last().copied())?;
47 Some(unsafe { f(ptr.as_ref()) })
50}
51
52fn with_bound_focus_owner_mut<R>(f: impl FnOnce(&mut FocusOwner) -> R) -> Option<R> {
53 let ptr = with_execution_context(|context| context.current_focus_owner_stack.last().copied())?;
54 Some(unsafe { f(&mut *ptr.as_ptr()) })
57}
58
59fn with_focus_owner<R>(f: impl FnOnce(&FocusOwner) -> R) -> R {
60 let mut f = Some(f);
61 if let Some(result) = with_bound_focus_owner(|owner| {
62 f.take().expect("focus owner callback should run once")(owner)
63 }) {
64 return result;
65 }
66 TesseraRuntime::with(|runtime| {
67 f.take().expect("focus owner callback should run once")(
68 runtime.component_tree.focus_owner(),
69 )
70 })
71}
72
73fn with_focus_owner_mut<R>(f: impl FnOnce(&mut FocusOwner) -> R) -> R {
74 let mut f = Some(f);
75 if let Some(result) = with_bound_focus_owner_mut(|owner| {
76 f.take().expect("focus owner callback should run once")(owner)
77 }) {
78 return result;
79 }
80 let result = TesseraRuntime::with_mut(|runtime| {
81 f.take().expect("focus owner callback should run once")(
82 runtime.component_tree.focus_owner_mut(),
83 )
84 });
85 flush_pending_focus_callbacks();
86 result
87}
88
89pub(crate) struct FocusOwnerBindingGuard {
90 active: bool,
91}
92
93impl Drop for FocusOwnerBindingGuard {
94 fn drop(&mut self) {
95 if !self.active {
96 return;
97 }
98 with_execution_context_mut(|context| {
99 let popped = context.current_focus_owner_stack.pop();
100 debug_assert!(popped.is_some(), "focus owner binding stack underflow");
101 });
102 self.active = false;
103 }
104}
105
106pub(crate) fn bind_focus_owner(owner: &mut FocusOwner) -> FocusOwnerBindingGuard {
107 with_execution_context_mut(|context| {
108 context.current_focus_owner_stack.push(NonNull::from(owner));
109 });
110 FocusOwnerBindingGuard { active: true }
111}
112
113#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
129pub enum FocusState {
130 #[default]
132 Inactive,
133 ActiveParent,
135 Active,
137 Captured,
139}
140
141impl FocusState {
142 pub fn has_focus(self) -> bool {
144 !matches!(self, Self::Inactive)
145 }
146
147 pub fn is_focused(self) -> bool {
149 matches!(self, Self::Active | Self::Captured)
150 }
151
152 pub fn is_captured(self) -> bool {
154 matches!(self, Self::Captured)
155 }
156}
157
158#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
163pub enum FocusDirection {
164 Next,
166 Previous,
168 Up,
170 Down,
172 Left,
174 Right,
176 Enter,
178 Exit,
180}
181
182#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
184pub enum FocusTraversalStrategy {
185 Linear,
187 Horizontal,
189 Vertical,
191 Spatial,
193}
194
195#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
214pub struct FocusTraversalPolicy {
215 pub strategy: FocusTraversalStrategy,
217 pub wrap: bool,
219 pub tab_navigation: bool,
221}
222
223impl FocusTraversalPolicy {
224 pub const fn new(strategy: FocusTraversalStrategy) -> Self {
226 Self {
227 strategy,
228 wrap: false,
229 tab_navigation: false,
230 }
231 }
232
233 pub const fn linear() -> Self {
235 Self::new(FocusTraversalStrategy::Linear)
236 }
237
238 pub const fn horizontal() -> Self {
240 Self::new(FocusTraversalStrategy::Horizontal)
241 }
242
243 pub const fn vertical() -> Self {
245 Self::new(FocusTraversalStrategy::Vertical)
246 }
247
248 pub const fn spatial() -> Self {
250 Self::new(FocusTraversalStrategy::Spatial)
251 }
252
253 pub const fn wrap(mut self, wrap: bool) -> Self {
255 self.wrap = wrap;
256 self
257 }
258
259 pub const fn tab_navigation(mut self, tab_navigation: bool) -> Self {
262 self.tab_navigation = tab_navigation;
263 self
264 }
265
266 fn scoped_direction(self, direction: FocusDirection) -> Option<FocusDirection> {
267 if self.tab_navigation {
268 match direction {
269 FocusDirection::Next | FocusDirection::Previous => return Some(direction),
270 _ => {}
271 }
272 }
273
274 match self.strategy {
275 FocusTraversalStrategy::Linear => match direction {
276 FocusDirection::Left | FocusDirection::Up => Some(FocusDirection::Previous),
277 FocusDirection::Right | FocusDirection::Down => Some(FocusDirection::Next),
278 _ => None,
279 },
280 FocusTraversalStrategy::Horizontal => match direction {
281 FocusDirection::Left => Some(FocusDirection::Previous),
282 FocusDirection::Right => Some(FocusDirection::Next),
283 _ => None,
284 },
285 FocusTraversalStrategy::Vertical => match direction {
286 FocusDirection::Up => Some(FocusDirection::Previous),
287 FocusDirection::Down => Some(FocusDirection::Next),
288 _ => None,
289 },
290 FocusTraversalStrategy::Spatial => match direction {
291 FocusDirection::Left
292 | FocusDirection::Right
293 | FocusDirection::Up
294 | FocusDirection::Down => Some(direction),
295 _ => None,
296 },
297 }
298 }
299}
300
301#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
303pub struct FocusRevealRequest {
304 pub target_rect: PxRect,
306 pub viewport_rect: PxRect,
308}
309
310impl FocusRevealRequest {
311 pub(crate) const fn new(target_rect: PxRect, viewport_rect: PxRect) -> Self {
313 Self {
314 target_rect,
315 viewport_rect,
316 }
317 }
318}
319
320#[derive(Clone, Copy, Debug, PartialEq, Eq)]
345pub struct FocusProperties {
346 pub can_focus: bool,
348 pub can_request_focus: bool,
350 pub skip_traversal: bool,
352 pub next: Option<FocusRequester>,
354 pub previous: Option<FocusRequester>,
356 pub up: Option<FocusRequester>,
358 pub down: Option<FocusRequester>,
360 pub left: Option<FocusRequester>,
362 pub right: Option<FocusRequester>,
364 pub enter: Option<FocusRequester>,
366 pub exit: Option<FocusRequester>,
368}
369
370impl FocusProperties {
371 pub fn new() -> Self {
373 Self::default()
374 }
375
376 pub fn can_focus(mut self, can_focus: bool) -> Self {
378 self.can_focus = can_focus;
379 self
380 }
381
382 pub fn can_request_focus(mut self, can_request_focus: bool) -> Self {
384 self.can_request_focus = can_request_focus;
385 self
386 }
387
388 pub fn skip_traversal(mut self, skip_traversal: bool) -> Self {
390 self.skip_traversal = skip_traversal;
391 self
392 }
393
394 pub fn next(mut self, requester: FocusRequester) -> Self {
396 self.next = Some(requester);
397 self
398 }
399
400 pub fn previous(mut self, requester: FocusRequester) -> Self {
402 self.previous = Some(requester);
403 self
404 }
405
406 pub fn up(mut self, requester: FocusRequester) -> Self {
408 self.up = Some(requester);
409 self
410 }
411
412 pub fn down(mut self, requester: FocusRequester) -> Self {
414 self.down = Some(requester);
415 self
416 }
417
418 pub fn left(mut self, requester: FocusRequester) -> Self {
420 self.left = Some(requester);
421 self
422 }
423
424 pub fn right(mut self, requester: FocusRequester) -> Self {
426 self.right = Some(requester);
427 self
428 }
429
430 pub fn enter(mut self, requester: FocusRequester) -> Self {
432 self.enter = Some(requester);
433 self
434 }
435
436 pub fn exit(mut self, requester: FocusRequester) -> Self {
438 self.exit = Some(requester);
439 self
440 }
441}
442
443impl Default for FocusProperties {
444 fn default() -> Self {
445 Self {
446 can_focus: true,
447 can_request_focus: true,
448 skip_traversal: false,
449 next: None,
450 previous: None,
451 up: None,
452 down: None,
453 left: None,
454 right: None,
455 enter: None,
456 exit: None,
457 }
458 }
459}
460
461#[derive(Clone, Copy, Debug, PartialEq, Eq)]
462pub(crate) enum FocusRegistrationKind {
463 Target,
464 Scope,
465 Group,
466}
467
468#[derive(Clone, Copy, Debug, PartialEq, Eq)]
469pub(crate) struct FocusRegistration {
470 pub(crate) id: FocusHandleId,
471 pub(crate) kind: FocusRegistrationKind,
472 pub(crate) properties: FocusProperties,
473}
474
475impl FocusRegistration {
476 pub(crate) fn target(node: FocusNode) -> Self {
477 Self {
478 id: node.id,
479 kind: FocusRegistrationKind::Target,
480 properties: FocusProperties::default(),
481 }
482 }
483
484 pub(crate) fn scope(scope: FocusScopeNode) -> Self {
485 Self {
486 id: scope.id,
487 kind: FocusRegistrationKind::Scope,
488 properties: FocusProperties::default().can_focus(false),
489 }
490 }
491
492 pub(crate) fn group(group: FocusGroupNode) -> Self {
493 Self {
494 id: group.id,
495 kind: FocusRegistrationKind::Group,
496 properties: FocusProperties::default()
497 .can_focus(false)
498 .can_request_focus(false),
499 }
500 }
501}
502
503#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
519pub struct FocusRequester {
520 id: FocusRequesterId,
521}
522
523impl FocusRequester {
524 pub fn new() -> Self {
526 Self {
527 id: next_focus_requester_id(),
528 }
529 }
530
531 pub fn request_focus(&self) {
533 with_focus_owner_mut(|owner| owner.request_focus_by_requester(self.id));
534 }
535
536 pub fn clear_focus(&self) {
538 with_focus_owner_mut(|owner| owner.clear_focus_by_requester(self.id));
539 }
540
541 pub fn unfocus(&self) {
543 self.clear_focus();
544 }
545
546 pub fn capture_focus(&self) {
549 with_focus_owner_mut(|owner| owner.capture_focus_by_requester(self.id));
550 }
551
552 pub fn free_focus(&self) {
554 with_focus_owner_mut(|owner| owner.free_focus_by_requester(self.id));
555 }
556
557 pub fn state(&self) -> FocusState {
559 track_focus_requester_read_dependency(self.id);
560 with_focus_owner(|owner| owner.state_of_requester(self.id))
561 }
562
563 pub fn has_focus(&self) -> bool {
565 self.state().has_focus()
566 }
567
568 pub fn is_focused(&self) -> bool {
570 self.state().is_focused()
571 }
572
573 pub fn is_captured(&self) -> bool {
575 self.state().is_captured()
576 }
577
578 pub(crate) fn requester_id(self) -> FocusRequesterId {
579 self.id
580 }
581}
582
583impl Default for FocusRequester {
584 fn default() -> Self {
585 Self::new()
586 }
587}
588
589#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
594pub(crate) struct FocusNode {
595 id: FocusHandleId,
596}
597
598impl FocusNode {
599 pub(crate) fn new() -> Self {
600 Self {
601 id: next_focus_handle_id(),
602 }
603 }
604
605 pub(crate) fn handle_id(self) -> FocusHandleId {
606 self.id
607 }
608
609 pub(crate) fn from_handle_id(id: FocusHandleId) -> Self {
610 Self { id }
611 }
612}
613
614impl Default for FocusNode {
615 fn default() -> Self {
616 Self::new()
617 }
618}
619
620#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
635pub struct FocusScopeNode {
636 id: FocusHandleId,
637}
638
639impl FocusScopeNode {
640 pub fn new() -> Self {
642 Self {
643 id: next_focus_handle_id(),
644 }
645 }
646
647 pub(crate) fn handle_id(self) -> FocusHandleId {
648 self.id
649 }
650
651 pub(crate) fn from_handle_id(id: FocusHandleId) -> Self {
652 Self { id }
653 }
654
655 pub fn request_focus(&self) {
658 with_focus_owner_mut(|owner| owner.request_focus(self.id));
659 }
660
661 pub fn clear_focus(&self) {
663 with_focus_owner_mut(|owner| owner.clear_focus(self.id));
664 }
665
666 pub fn restore_focus(&self) {
668 with_focus_owner_mut(|owner| owner.restore_focus(self.id));
669 }
670
671 pub fn move_focus(&self, direction: FocusDirection) -> bool {
673 with_focus_owner_mut(|owner| owner.move_focus_in_scope(self.id, direction, false))
674 }
675
676 pub fn cycle_focus(&self, direction: FocusDirection) -> bool {
678 with_focus_owner_mut(|owner| owner.move_focus_in_scope(self.id, direction, true))
679 }
680
681 pub fn state(&self) -> FocusState {
683 track_focus_read_dependency(self.id);
684 with_focus_owner(|owner| owner.state_of(self.id))
685 }
686
687 pub fn has_focus(&self) -> bool {
689 self.state().has_focus()
690 }
691
692 pub fn is_focused(&self) -> bool {
694 self.state().is_focused()
695 }
696}
697
698impl Default for FocusScopeNode {
699 fn default() -> Self {
700 Self::new()
701 }
702}
703
704#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
719pub struct FocusGroupNode {
720 id: FocusHandleId,
721}
722
723impl FocusGroupNode {
724 pub fn new() -> Self {
726 Self {
727 id: next_focus_handle_id(),
728 }
729 }
730
731 pub(crate) fn handle_id(self) -> FocusHandleId {
732 self.id
733 }
734
735 pub(crate) fn from_handle_id(id: FocusHandleId) -> Self {
736 Self { id }
737 }
738
739 pub fn move_focus(&self, direction: FocusDirection) -> bool {
741 with_focus_owner_mut(|owner| owner.move_focus_in_scope(self.id, direction, false))
742 }
743
744 pub fn cycle_focus(&self, direction: FocusDirection) -> bool {
746 with_focus_owner_mut(|owner| owner.move_focus_in_scope(self.id, direction, true))
747 }
748
749 pub fn state(&self) -> FocusState {
751 track_focus_read_dependency(self.id);
752 with_focus_owner(|owner| owner.state_of(self.id))
753 }
754
755 pub fn has_focus(&self) -> bool {
757 self.state().has_focus()
758 }
759
760 pub fn is_focused(&self) -> bool {
762 self.state().is_focused()
763 }
764}
765
766impl Default for FocusGroupNode {
767 fn default() -> Self {
768 Self::new()
769 }
770}
771
772#[derive(Clone, Copy, Debug, Default)]
785pub struct FocusManager;
786
787impl FocusManager {
788 pub fn current() -> Self {
790 Self
791 }
792
793 pub fn clear_focus(self, force: bool) {
795 with_focus_owner_mut(|owner| {
796 owner.clear_focus_global(force);
797 });
798 }
799
800 pub fn move_focus(self, direction: FocusDirection) -> bool {
802 with_focus_owner_mut(|owner| owner.move_focus(direction))
803 }
804}
805
806#[derive(Clone, Copy, Debug)]
807struct FocusAttachment {
808 host_replay_boundary_key: u64,
809 live_node_id: Option<NodeId>,
810 focus_rect: Option<PxRect>,
811 traversal_order: Option<u64>,
812 parent: FocusHandleId,
813 scope_parent: FocusHandleId,
814}
815
816impl FocusAttachment {
817 fn root_scope() -> Self {
818 Self {
819 host_replay_boundary_key: 0,
820 live_node_id: None,
821 focus_rect: None,
822 traversal_order: None,
823 parent: ROOT_SCOPE_ID,
824 scope_parent: ROOT_SCOPE_ID,
825 }
826 }
827}
828
829#[derive(Clone, Copy, Debug)]
830struct FocusTreeNode {
831 kind: FocusRegistrationKind,
832 attachment: Option<FocusAttachment>,
833 last_parent: FocusHandleId,
834 last_scope_parent: FocusHandleId,
835 props: FocusProperties,
836 traversal_policy: Option<FocusTraversalPolicy>,
837 state: FocusState,
838 last_focused_descendant: Option<FocusHandleId>,
839 restorer_fallback: Option<FocusRequesterId>,
840}
841
842impl FocusTreeNode {
843 fn new_root_scope() -> Self {
844 Self {
845 kind: FocusRegistrationKind::Scope,
846 attachment: Some(FocusAttachment::root_scope()),
847 last_parent: ROOT_SCOPE_ID,
848 last_scope_parent: ROOT_SCOPE_ID,
849 props: FocusProperties::default()
850 .can_focus(false)
851 .can_request_focus(false)
852 .skip_traversal(true),
853 traversal_policy: None,
854 state: FocusState::Inactive,
855 last_focused_descendant: None,
856 restorer_fallback: None,
857 }
858 }
859
860 fn new(kind: FocusRegistrationKind) -> Self {
861 Self {
862 kind,
863 attachment: None,
864 last_parent: ROOT_SCOPE_ID,
865 last_scope_parent: ROOT_SCOPE_ID,
866 props: FocusProperties::default(),
867 traversal_policy: None,
868 state: FocusState::Inactive,
869 last_focused_descendant: None,
870 restorer_fallback: None,
871 }
872 }
873
874 fn is_attached(&self) -> bool {
875 self.attachment.is_some()
876 }
877}
878
879#[derive(Clone)]
880pub(crate) struct PendingFocusCallbackInvocation {
881 callback: CallbackWith<FocusState>,
882 state: FocusState,
883}
884
885impl PendingFocusCallbackInvocation {
886 pub(crate) fn new(callback: CallbackWith<FocusState>, state: FocusState) -> Self {
887 Self { callback, state }
888 }
889
890 pub(crate) fn invoke(self) {
891 self.callback.call(self.state);
892 }
893}
894
895#[derive(Clone, Copy, Debug)]
896pub(crate) struct FocusNotification {
897 pub handle_id: FocusHandleId,
898 pub state: FocusState,
899 pub changed: bool,
900}
901
902#[derive(Clone, Copy, Debug)]
903enum FocusCommand {
904 Request(FocusHandleId),
905 Clear(FocusHandleId),
906 Capture(FocusHandleId),
907 Free(FocusHandleId),
908 Restore(FocusHandleId),
909}
910
911#[derive(Default)]
913pub(crate) struct FocusOwner {
914 nodes: HashMap<FocusHandleId, FocusTreeNode>,
915 children_by_parent: HashMap<FocusHandleId, Vec<FocusHandleId>>,
916 requester_bindings: HashMap<FocusRequesterId, FocusHandleId>,
917 requesters_by_handle: HashMap<FocusHandleId, Vec<FocusRequesterId>>,
918 active: Option<FocusHandleId>,
919 captured: Option<FocusHandleId>,
920 suspended: Option<FocusHandleId>,
921 owner_focused: bool,
922 pending: Vec<FocusCommand>,
923 pending_notifications: Vec<FocusNotification>,
924 pending_reveal: Option<FocusHandleId>,
925}
926
927impl FocusOwner {
928 pub(crate) fn new() -> Self {
929 let mut nodes = HashMap::default();
930 nodes.insert(ROOT_SCOPE_ID, FocusTreeNode::new_root_scope());
931 Self {
932 nodes,
933 children_by_parent: HashMap::default(),
934 requester_bindings: HashMap::default(),
935 requesters_by_handle: HashMap::default(),
936 active: None,
937 captured: None,
938 suspended: None,
939 owner_focused: true,
940 pending: Vec::new(),
941 pending_notifications: Vec::new(),
942 pending_reveal: None,
943 }
944 }
945
946 pub(crate) fn reset(&mut self) {
947 *self = Self::new();
948 }
949
950 pub(crate) fn state_of(&self, id: FocusHandleId) -> FocusState {
951 self.nodes
952 .get(&id)
953 .filter(|node| node.is_attached())
954 .map(|node| node.state)
955 .unwrap_or(FocusState::Inactive)
956 }
957
958 pub(crate) fn active_component_node_id(&self) -> Option<NodeId> {
959 let active = self.active?;
960 self.nodes
961 .get(&active)
962 .and_then(|node| node.attachment)
963 .and_then(|attachment| attachment.live_node_id)
964 }
965
966 pub(crate) fn component_node_id_of(&self, id: FocusHandleId) -> Option<NodeId> {
967 self.nodes
968 .get(&id)
969 .and_then(|node| node.attachment)
970 .and_then(|attachment| attachment.live_node_id)
971 }
972
973 pub(crate) fn active_handle_id(&self) -> Option<FocusHandleId> {
974 self.active
975 }
976
977 pub(crate) fn take_pending_reveal(&mut self) -> Option<FocusHandleId> {
978 self.pending_reveal.take()
979 }
980
981 pub(crate) fn state_of_requester(&self, id: FocusRequesterId) -> FocusState {
982 self.requester_bindings
983 .get(&id)
984 .copied()
985 .map(|handle_id| self.state_of(handle_id))
986 .unwrap_or(FocusState::Inactive)
987 }
988
989 pub(crate) fn request_focus_by_requester(&mut self, id: FocusRequesterId) {
990 if let Some(handle_id) = self.requester_bindings.get(&id).copied() {
991 self.request_focus(handle_id);
992 }
993 }
994
995 pub(crate) fn clear_focus_by_requester(&mut self, id: FocusRequesterId) {
996 if let Some(handle_id) = self.requester_bindings.get(&id).copied() {
997 self.clear_focus(handle_id);
998 }
999 }
1000
1001 pub(crate) fn capture_focus_by_requester(&mut self, id: FocusRequesterId) {
1002 if let Some(handle_id) = self.requester_bindings.get(&id).copied() {
1003 self.capture_focus(handle_id);
1004 }
1005 }
1006
1007 pub(crate) fn free_focus_by_requester(&mut self, id: FocusRequesterId) {
1008 if let Some(handle_id) = self.requester_bindings.get(&id).copied() {
1009 self.free_focus(handle_id);
1010 }
1011 }
1012
1013 pub(crate) fn request_focus(&mut self, id: FocusHandleId) {
1014 if !self.apply_command(FocusCommand::Request(id)) {
1015 self.pending.push(FocusCommand::Request(id));
1016 }
1017 }
1018
1019 pub(crate) fn clear_focus(&mut self, id: FocusHandleId) {
1020 if !self.apply_command(FocusCommand::Clear(id)) {
1021 self.pending.push(FocusCommand::Clear(id));
1022 }
1023 }
1024
1025 pub(crate) fn capture_focus(&mut self, id: FocusHandleId) {
1026 if !self.apply_command(FocusCommand::Capture(id)) {
1027 self.pending.push(FocusCommand::Capture(id));
1028 }
1029 }
1030
1031 pub(crate) fn free_focus(&mut self, id: FocusHandleId) {
1032 if !self.apply_command(FocusCommand::Free(id)) {
1033 self.pending.push(FocusCommand::Free(id));
1034 }
1035 }
1036
1037 pub(crate) fn restore_focus(&mut self, id: FocusHandleId) {
1038 if !self.apply_command(FocusCommand::Restore(id)) {
1039 self.pending.push(FocusCommand::Restore(id));
1040 }
1041 }
1042
1043 pub(crate) fn set_owner_focused(&mut self, focused: bool) {
1044 if self.owner_focused == focused {
1045 return;
1046 }
1047
1048 let previous_states = self.snapshot_live_states();
1049 self.owner_focused = focused;
1050 if focused {
1051 if let Some(suspended) = self.suspended.take() {
1052 if let Some(target) = self.resolve_request_target(suspended) {
1053 self.active = Some(target);
1054 self.pending_reveal = Some(target);
1055 } else {
1056 self.suspended = Some(suspended);
1057 }
1058 }
1059 } else {
1060 self.suspended = self.active;
1061 self.active = None;
1062 self.captured = None;
1063 self.pending_reveal = None;
1064 }
1065 self.recompute_states();
1066 self.notify_state_changes(previous_states);
1067 }
1068
1069 pub(crate) fn sync_from_component_tree(&mut self, root_node: NodeId, tree: &ComponentNodeTree) {
1070 self.nodes
1071 .entry(ROOT_SCOPE_ID)
1072 .or_insert_with(FocusTreeNode::new_root_scope);
1073
1074 let previous_states = self.snapshot_live_states();
1075 let previous_requester_bindings = self.requester_bindings.clone();
1076 for node in self.nodes.values_mut() {
1077 let is_root_scope = matches!(
1078 node.attachment,
1079 Some(FocusAttachment {
1080 host_replay_boundary_key: 0,
1081 ..
1082 })
1083 );
1084 if !is_root_scope {
1085 node.attachment = None;
1086 node.state = FocusState::Inactive;
1087 }
1088 }
1089 self.children_by_parent.clear();
1090 self.children_by_parent.insert(ROOT_SCOPE_ID, Vec::new());
1091 self.requester_bindings.clear();
1092 self.requesters_by_handle.clear();
1093 if let Some(root) = self.nodes.get_mut(&ROOT_SCOPE_ID) {
1094 root.attachment = Some(FocusAttachment::root_scope());
1095 root.state = FocusState::Inactive;
1096 }
1097
1098 let mut seen = HashSet::default();
1099 self.collect_focus_nodes(root_node, tree, ROOT_SCOPE_ID, ROOT_SCOPE_ID, &mut seen);
1100
1101 self.repair_after_sync();
1102 self.recompute_states();
1103 self.notify_state_changes(previous_states);
1104 self.notify_requester_binding_changes(previous_requester_bindings);
1105 }
1106
1107 pub(crate) fn sync_layout_from_component_tree(
1108 &mut self,
1109 root_node: NodeId,
1110 tree: &ComponentNodeTree,
1111 metadatas: &ComponentNodeMetaDatas,
1112 ) {
1113 let handles_by_node_id: HashMap<NodeId, FocusHandleId> = self
1114 .nodes
1115 .iter()
1116 .filter_map(|(&handle_id, node)| {
1117 node.attachment
1118 .and_then(|attachment| attachment.live_node_id)
1119 .map(|node_id| (node_id, handle_id))
1120 })
1121 .collect();
1122
1123 for node in self.nodes.values_mut() {
1124 if let Some(attachment) = node.attachment.as_mut() {
1125 attachment.focus_rect = None;
1126 attachment.traversal_order = None;
1127 }
1128 }
1129
1130 let mut next_traversal_order = 0_u64;
1131 self.assign_layout_info_for_subtree(
1132 root_node,
1133 tree,
1134 metadatas,
1135 &handles_by_node_id,
1136 &mut next_traversal_order,
1137 );
1138 self.sort_children_by_traversal_order();
1139 }
1140
1141 pub(crate) fn commit_pending(&mut self) {
1142 if self.pending.is_empty() {
1143 return;
1144 }
1145
1146 let previous_states = self.snapshot_live_states();
1147 let commands = std::mem::take(&mut self.pending);
1148 for command in commands {
1149 if !self.apply_command_inner(command) {
1150 self.pending.push(command);
1151 }
1152 }
1153 self.recompute_states();
1154 self.notify_state_changes(previous_states);
1155 }
1156
1157 pub(crate) fn take_pending_notifications(&mut self) -> Vec<FocusNotification> {
1158 std::mem::take(&mut self.pending_notifications)
1159 }
1160
1161 pub(crate) fn clear_focus_global(&mut self, force: bool) -> bool {
1162 let previous_states = self.snapshot_live_states();
1163 let cleared = if self.active.is_some() && (force || self.captured.is_none()) {
1164 self.active = None;
1165 self.captured = None;
1166 self.pending_reveal = None;
1167 true
1168 } else {
1169 false
1170 };
1171 self.recompute_states();
1172 self.notify_state_changes(previous_states);
1173 cleared
1174 }
1175
1176 pub(crate) fn move_focus(&mut self, direction: FocusDirection) -> bool {
1177 if !self.owner_focused {
1178 return false;
1179 }
1180 let previous_states = self.snapshot_live_states();
1181 let moved = self
1182 .resolve_policy_move_target(direction)
1183 .or_else(|| self.resolve_move_target(direction))
1184 .is_some_and(|target| self.set_active(target));
1185 self.recompute_states();
1186 self.notify_state_changes(previous_states);
1187 moved
1188 }
1189
1190 pub(crate) fn move_focus_in_scope(
1191 &mut self,
1192 scope_id: FocusHandleId,
1193 direction: FocusDirection,
1194 wrap: bool,
1195 ) -> bool {
1196 if !self.owner_focused {
1197 return false;
1198 }
1199 let previous_states = self.snapshot_live_states();
1200 let moved = self
1201 .resolve_move_target_in_scope(scope_id, direction, wrap)
1202 .is_some_and(|target| self.set_active(target));
1203 self.recompute_states();
1204 self.notify_state_changes(previous_states);
1205 moved
1206 }
1207
1208 fn resolve_policy_move_target(&self, direction: FocusDirection) -> Option<FocusHandleId> {
1209 let active = self
1210 .active
1211 .and_then(|current| self.resolve_request_target(current))?;
1212 let (owner_id, policy) = self.nearest_traversal_policy_owner(active)?;
1213 let scoped_direction = policy.scoped_direction(direction)?;
1214 self.resolve_move_target_in_scope(owner_id, scoped_direction, policy.wrap)
1215 }
1216
1217 fn nearest_traversal_policy_owner(
1218 &self,
1219 start: FocusHandleId,
1220 ) -> Option<(FocusHandleId, FocusTraversalPolicy)> {
1221 let mut current = Some(start);
1222 while let Some(id) = current {
1223 let node = self.nodes.get(&id)?;
1224 if matches!(
1225 node.kind,
1226 FocusRegistrationKind::Scope | FocusRegistrationKind::Group
1227 ) && let Some(policy) = node.traversal_policy
1228 {
1229 return Some((id, policy));
1230 }
1231 current = (id != ROOT_SCOPE_ID).then_some(node.last_parent);
1232 }
1233 None
1234 }
1235
1236 fn collect_focus_nodes(
1237 &mut self,
1238 node_id: NodeId,
1239 tree: &ComponentNodeTree,
1240 parent_focus_id: FocusHandleId,
1241 current_scope_id: FocusHandleId,
1242 seen: &mut HashSet<FocusHandleId>,
1243 ) {
1244 let Some(node_ref) = tree.get(node_id) else {
1245 return;
1246 };
1247 let node = node_ref.get();
1248
1249 let mut next_parent_focus_id = parent_focus_id;
1250 let mut next_scope_id = current_scope_id;
1251
1252 if let Some(registration) = node.focus_registration {
1253 if !seen.insert(registration.id) {
1254 debug_assert!(
1255 false,
1256 "Focus handle {} was registered on multiple component nodes in the same frame",
1257 registration.id
1258 );
1259 }
1260 let entry = self
1261 .nodes
1262 .entry(registration.id)
1263 .or_insert_with(|| FocusTreeNode::new(registration.kind));
1264 let host_replay_boundary_key = nearest_replay_boundary_instance_key(node_id, tree);
1265 entry.kind = registration.kind;
1266 entry.last_parent = parent_focus_id;
1267 entry.last_scope_parent = current_scope_id;
1268 entry.attachment = Some(FocusAttachment {
1269 host_replay_boundary_key,
1270 live_node_id: Some(node_id),
1271 focus_rect: None,
1272 traversal_order: None,
1273 parent: parent_focus_id,
1274 scope_parent: current_scope_id,
1275 });
1276 entry.props = registration.properties;
1277 entry.traversal_policy = node.focus_traversal_policy;
1278 entry.restorer_fallback = (registration.kind == FocusRegistrationKind::Scope)
1279 .then(|| {
1280 node.focus_restorer_fallback
1281 .map(|fallback| fallback.requester_id())
1282 })
1283 .flatten();
1284
1285 self.children_by_parent
1286 .entry(parent_focus_id)
1287 .or_default()
1288 .push(registration.id);
1289 self.children_by_parent.entry(registration.id).or_default();
1290 if let Some(requester) = node.focus_requester_binding {
1291 let replaced = self
1292 .requester_bindings
1293 .insert(requester.requester_id(), registration.id);
1294 debug_assert!(
1295 replaced.is_none() || replaced == Some(registration.id),
1296 "FocusRequester {} was bound to multiple focus nodes in the same frame",
1297 requester.requester_id()
1298 );
1299 self.requesters_by_handle
1300 .entry(registration.id)
1301 .or_default()
1302 .push(requester.requester_id());
1303 }
1304
1305 next_parent_focus_id = registration.id;
1306 if registration.kind == FocusRegistrationKind::Scope {
1307 next_scope_id = registration.id;
1308 }
1309 } else if node.focus_requester_binding.is_some() {
1310 debug_assert!(
1311 false,
1312 "focus_requester requires focus_target or focus_scope on the same component node"
1313 );
1314 }
1315
1316 for child_id in node_id.children(tree) {
1317 self.collect_focus_nodes(child_id, tree, next_parent_focus_id, next_scope_id, seen);
1318 }
1319 }
1320
1321 fn assign_layout_info_for_subtree(
1322 &mut self,
1323 node_id: NodeId,
1324 tree: &ComponentNodeTree,
1325 metadatas: &ComponentNodeMetaDatas,
1326 handles_by_node_id: &HashMap<NodeId, FocusHandleId>,
1327 next_traversal_order: &mut u64,
1328 ) {
1329 if let Some(handle_id) = handles_by_node_id.get(&node_id).copied() {
1330 let focus_rect = metadatas.get(&node_id).and_then(|metadata| {
1331 let abs_position = metadata.abs_position?;
1332 let computed_data = metadata.computed_data?;
1333 let node_rect = PxRect::from_position_size(
1334 abs_position,
1335 PxSize::new(computed_data.width, computed_data.height),
1336 );
1337 Some(if let Some(clip_rect) = metadata.event_clip_rect {
1338 clip_rect.intersection(&node_rect).unwrap_or(PxRect::ZERO)
1339 } else {
1340 node_rect
1341 })
1342 });
1343 if let Some(node) = self.nodes.get_mut(&handle_id)
1344 && let Some(attachment) = node.attachment.as_mut()
1345 {
1346 attachment.focus_rect = focus_rect;
1347 attachment.traversal_order = Some(*next_traversal_order);
1348 }
1349 *next_traversal_order += 1;
1350 }
1351
1352 let mut children: Vec<_> = node_id.children(tree).enumerate().collect();
1353 children.sort_by_key(|(composition_order, child_id)| {
1354 let placement_order = metadatas
1355 .get(child_id)
1356 .and_then(|metadata| metadata.placement_order)
1357 .unwrap_or(u64::MAX);
1358 (placement_order, *composition_order as u64)
1359 });
1360
1361 for (_, child_id) in children {
1362 self.assign_layout_info_for_subtree(
1363 child_id,
1364 tree,
1365 metadatas,
1366 handles_by_node_id,
1367 next_traversal_order,
1368 );
1369 }
1370 }
1371
1372 fn sort_children_by_traversal_order(&mut self) {
1373 let order_by_handle: HashMap<FocusHandleId, (u64, u64)> = self
1374 .nodes
1375 .iter()
1376 .map(|(&handle_id, node)| {
1377 (
1378 handle_id,
1379 (
1380 node.attachment
1381 .and_then(|attachment| attachment.traversal_order)
1382 .unwrap_or(u64::MAX),
1383 node.attachment
1384 .map(|attachment| attachment.host_replay_boundary_key)
1385 .unwrap_or(u64::MAX),
1386 ),
1387 )
1388 })
1389 .collect();
1390
1391 for children in self.children_by_parent.values_mut() {
1392 children.sort_by_key(|child| {
1393 order_by_handle
1394 .get(child)
1395 .copied()
1396 .unwrap_or((u64::MAX, u64::MAX))
1397 });
1398 }
1399 }
1400
1401 fn repair_after_sync(&mut self) {
1402 if self
1403 .active
1404 .is_some_and(|id| !self.nodes.get(&id).is_some_and(|node| node.is_attached()))
1405 {
1406 let previous_active = self.active;
1407 if !previous_active.is_some_and(|id| self.should_wait_for_reattach(id)) {
1408 let previous_active = self.active.take();
1409 self.active = previous_active.and_then(|id| self.restore_from_detached(id));
1410 self.captured = None;
1411 if let Some(active) = self.active {
1412 self.update_scope_restore_chain(active);
1413 self.pending_reveal = Some(active);
1414 }
1415 }
1416 }
1417
1418 if self
1419 .captured
1420 .is_some_and(|id| !self.nodes.get(&id).is_some_and(|node| node.is_attached()))
1421 {
1422 self.captured = None;
1423 }
1424
1425 if self.owner_focused
1426 && self.active.is_none()
1427 && let Some(suspended) = self.suspended
1428 && let Some(target) = self.resolve_request_target(suspended)
1429 {
1430 self.active = Some(target);
1431 self.suspended = None;
1432 self.pending_reveal = Some(target);
1433 }
1434
1435 if self.active.is_some_and(|id| {
1436 self.nodes.get(&id).is_some_and(|node| {
1437 node.is_attached() && (!self.can_focus(id) || !self.can_request_focus(id))
1438 })
1439 }) {
1440 self.active = None;
1441 self.captured = None;
1442 self.pending_reveal = None;
1443 }
1444
1445 let live_ids = self
1446 .nodes
1447 .iter()
1448 .filter_map(|(&id, node)| node.is_attached().then_some(id))
1449 .collect::<HashSet<_>>();
1450 for node in self.nodes.values_mut() {
1451 if node
1452 .last_focused_descendant
1453 .is_some_and(|last| !live_ids.contains(&last))
1454 {
1455 node.last_focused_descendant = None;
1456 }
1457 if node
1458 .restorer_fallback
1459 .is_some_and(|fallback| !self.requester_bindings.contains_key(&fallback))
1460 {
1461 node.restorer_fallback = None;
1462 }
1463 }
1464 }
1465
1466 fn should_wait_for_reattach(&self, id: FocusHandleId) -> bool {
1467 let Some(node) = self.nodes.get(&id) else {
1468 return false;
1469 };
1470 if node.is_attached() {
1471 return false;
1472 }
1473 if has_persistent_focus_handle(id) {
1474 return true;
1475 }
1476 let waiting_scope_id = node.last_scope_parent;
1477 waiting_scope_id != ROOT_SCOPE_ID
1478 && self
1479 .nodes
1480 .get(&waiting_scope_id)
1481 .is_some_and(|scope| !scope.is_attached())
1482 }
1483
1484 pub(crate) fn remove_handles(
1485 &mut self,
1486 removed_handles: &HashSet<FocusHandleId>,
1487 removed_requesters: &HashSet<FocusRequesterId>,
1488 ) {
1489 if removed_handles.is_empty() && removed_requesters.is_empty() {
1490 return;
1491 }
1492
1493 let previous_states = self.snapshot_live_states();
1494 let previous_requester_bindings = self.requester_bindings.clone();
1495
1496 for requester_id in removed_requesters {
1497 self.requester_bindings.remove(requester_id);
1498 }
1499 for requesters in self.requesters_by_handle.values_mut() {
1500 requesters.retain(|requester_id| !removed_requesters.contains(requester_id));
1501 }
1502
1503 let active_was_removed = self.active.filter(|id| removed_handles.contains(id));
1504 if active_was_removed.is_some() {
1505 self.active = active_was_removed.and_then(|id| self.restore_from_detached(id));
1506 self.captured = None;
1507 if let Some(active) = self.active {
1508 self.update_scope_restore_chain(active);
1509 self.pending_reveal = Some(active);
1510 } else {
1511 self.pending_reveal = None;
1512 }
1513 }
1514
1515 if self
1516 .captured
1517 .is_some_and(|id| removed_handles.contains(&id))
1518 {
1519 self.captured = None;
1520 }
1521 if self
1522 .suspended
1523 .is_some_and(|id| removed_handles.contains(&id))
1524 {
1525 self.suspended = None;
1526 }
1527
1528 for handle_id in removed_handles {
1529 self.nodes.remove(handle_id);
1530 self.children_by_parent.remove(handle_id);
1531 self.requesters_by_handle.remove(handle_id);
1532 }
1533 for children in self.children_by_parent.values_mut() {
1534 children.retain(|child| !removed_handles.contains(child));
1535 }
1536 for node in self.nodes.values_mut() {
1537 if node
1538 .last_focused_descendant
1539 .is_some_and(|candidate| removed_handles.contains(&candidate))
1540 {
1541 node.last_focused_descendant = None;
1542 }
1543 if node
1544 .restorer_fallback
1545 .is_some_and(|requester_id| removed_requesters.contains(&requester_id))
1546 {
1547 node.restorer_fallback = None;
1548 }
1549 }
1550
1551 self.recompute_states();
1552 self.notify_state_changes(previous_states);
1553 self.notify_requester_binding_changes(previous_requester_bindings);
1554 }
1555
1556 fn apply_command(&mut self, command: FocusCommand) -> bool {
1557 let previous_states = self.snapshot_live_states();
1558 let applied = self.apply_command_inner(command);
1559 self.recompute_states();
1560 self.notify_state_changes(previous_states);
1561 applied
1562 }
1563
1564 fn apply_command_inner(&mut self, command: FocusCommand) -> bool {
1565 match command {
1566 FocusCommand::Request(id) => {
1567 if !self.owner_focused {
1568 self.suspended = Some(id);
1569 return true;
1570 }
1571 let Some(target) = self.resolve_request_target(id) else {
1572 return false;
1573 };
1574 self.set_active(target)
1575 }
1576 FocusCommand::Clear(id) => self.clear_active_for(id),
1577 FocusCommand::Capture(id) => {
1578 if self.active == Some(id)
1579 && self.nodes.get(&id).is_some_and(|node| node.is_attached())
1580 {
1581 self.captured = Some(id);
1582 true
1583 } else {
1584 false
1585 }
1586 }
1587 FocusCommand::Free(id) => {
1588 if self.captured == Some(id) {
1589 self.captured = None;
1590 true
1591 } else {
1592 false
1593 }
1594 }
1595 FocusCommand::Restore(id) => {
1596 let Some(target) = self.resolve_restore_candidate(id) else {
1597 return false;
1598 };
1599 self.set_active(target)
1600 }
1601 }
1602 }
1603
1604 fn set_active(&mut self, target: FocusHandleId) -> bool {
1605 if self.captured.is_some() && self.captured != Some(target) {
1606 return false;
1607 }
1608 let changed = self.active != Some(target) || self.captured.is_some_and(|id| id != target);
1609 self.active = Some(target);
1610 if self.captured.is_some_and(|id| id != target) {
1611 self.captured = None;
1612 }
1613 self.update_scope_restore_chain(target);
1614 if changed {
1615 self.pending_reveal = Some(target);
1616 }
1617 changed
1618 }
1619
1620 fn clear_active_for(&mut self, id: FocusHandleId) -> bool {
1621 let Some(active) = self.active else {
1622 return false;
1623 };
1624 let affects_active = active == id || self.is_ancestor(id, active);
1625 if !affects_active {
1626 return false;
1627 }
1628 if self.captured.is_some() {
1629 return false;
1630 }
1631
1632 self.active = None;
1633 self.captured = None;
1634 self.pending_reveal = None;
1635 true
1636 }
1637
1638 fn resolve_move_target(&self, direction: FocusDirection) -> Option<FocusHandleId> {
1639 if let Some(active) = self.active
1640 && let Some(explicit) = self.resolve_explicit_direction_target(active, direction)
1641 {
1642 return Some(explicit);
1643 }
1644
1645 if matches!(
1646 direction,
1647 FocusDirection::Left
1648 | FocusDirection::Right
1649 | FocusDirection::Up
1650 | FocusDirection::Down
1651 ) && let Some(target) = self.resolve_geometric_move_target(direction)
1652 {
1653 return Some(target);
1654 }
1655
1656 let candidates = self.traversable_focus_handles();
1657 if candidates.is_empty() {
1658 return None;
1659 }
1660
1661 let forward = matches!(
1662 direction,
1663 FocusDirection::Next
1664 | FocusDirection::Down
1665 | FocusDirection::Right
1666 | FocusDirection::Enter
1667 );
1668
1669 let Some(active) = self
1670 .active
1671 .and_then(|current| self.resolve_request_target(current))
1672 else {
1673 return if forward {
1674 candidates.first().copied()
1675 } else {
1676 candidates.last().copied()
1677 };
1678 };
1679
1680 let Some(index) = candidates.iter().position(|candidate| *candidate == active) else {
1681 return if forward {
1682 candidates.first().copied()
1683 } else {
1684 candidates.last().copied()
1685 };
1686 };
1687
1688 if forward {
1689 candidates.get(index + 1).copied()
1690 } else if index > 0 {
1691 candidates.get(index - 1).copied()
1692 } else {
1693 None
1694 }
1695 }
1696
1697 fn resolve_move_target_in_scope(
1698 &self,
1699 scope_id: FocusHandleId,
1700 direction: FocusDirection,
1701 wrap: bool,
1702 ) -> Option<FocusHandleId> {
1703 let candidates = self.traversable_focus_handles_in_scope(scope_id);
1704 if candidates.is_empty() {
1705 return None;
1706 }
1707
1708 let active = self
1709 .active
1710 .and_then(|current| self.resolve_request_target(current))
1711 .filter(|current| self.is_ancestor(scope_id, *current));
1712
1713 if let Some(active) = active
1714 && let Some(explicit) = self.resolve_explicit_direction_target(active, direction)
1715 && self.is_ancestor(scope_id, explicit)
1716 {
1717 return Some(explicit);
1718 }
1719
1720 if matches!(
1721 direction,
1722 FocusDirection::Left
1723 | FocusDirection::Right
1724 | FocusDirection::Up
1725 | FocusDirection::Down
1726 ) && let Some(target) =
1727 self.resolve_geometric_move_target_in_candidates(direction, &candidates, active)
1728 {
1729 return Some(target);
1730 }
1731
1732 let forward = matches!(
1733 direction,
1734 FocusDirection::Next
1735 | FocusDirection::Down
1736 | FocusDirection::Right
1737 | FocusDirection::Enter
1738 );
1739
1740 let Some(active) = active else {
1741 return if forward {
1742 candidates.first().copied()
1743 } else {
1744 candidates.last().copied()
1745 };
1746 };
1747
1748 let Some(index) = candidates.iter().position(|candidate| *candidate == active) else {
1749 return if forward {
1750 candidates.first().copied()
1751 } else {
1752 candidates.last().copied()
1753 };
1754 };
1755
1756 if forward {
1757 candidates
1758 .get(index + 1)
1759 .copied()
1760 .or_else(|| wrap.then_some(candidates.first().copied()).flatten())
1761 } else if index > 0 {
1762 candidates.get(index - 1).copied()
1763 } else if wrap {
1764 candidates.last().copied()
1765 } else {
1766 None
1767 }
1768 }
1769
1770 fn resolve_geometric_move_target(&self, direction: FocusDirection) -> Option<FocusHandleId> {
1771 let active = self.active.and_then(|id| self.resolve_request_target(id))?;
1772 let focused_rect = self.nodes.get(&active)?.attachment?.focus_rect?;
1773 let mut best_candidate = initial_best_candidate_rect(focused_rect, direction);
1774 let mut best_handle = None;
1775
1776 for handle_id in self.traversable_focus_handles() {
1777 if handle_id == active {
1778 continue;
1779 }
1780 let Some(candidate_rect) = self
1781 .nodes
1782 .get(&handle_id)
1783 .and_then(|node| node.attachment)
1784 .and_then(|attachment| attachment.focus_rect)
1785 else {
1786 continue;
1787 };
1788 if !is_eligible_focus_rect(candidate_rect) {
1789 continue;
1790 }
1791 if is_better_focus_candidate(candidate_rect, best_candidate, focused_rect, direction) {
1792 best_candidate = candidate_rect;
1793 best_handle = Some(handle_id);
1794 }
1795 }
1796
1797 best_handle
1798 }
1799
1800 fn resolve_geometric_move_target_in_candidates(
1801 &self,
1802 direction: FocusDirection,
1803 candidates: &[FocusHandleId],
1804 active: Option<FocusHandleId>,
1805 ) -> Option<FocusHandleId> {
1806 let active = active?;
1807 let focused_rect = self.nodes.get(&active)?.attachment?.focus_rect?;
1808 let mut best_candidate = initial_best_candidate_rect(focused_rect, direction);
1809 let mut best_handle = None;
1810
1811 for &handle_id in candidates {
1812 if handle_id == active {
1813 continue;
1814 }
1815 let Some(candidate_rect) = self
1816 .nodes
1817 .get(&handle_id)
1818 .and_then(|node| node.attachment)
1819 .and_then(|attachment| attachment.focus_rect)
1820 else {
1821 continue;
1822 };
1823 if !is_eligible_focus_rect(candidate_rect) {
1824 continue;
1825 }
1826 if is_better_focus_candidate(candidate_rect, best_candidate, focused_rect, direction) {
1827 best_candidate = candidate_rect;
1828 best_handle = Some(handle_id);
1829 }
1830 }
1831
1832 best_handle
1833 }
1834
1835 fn resolve_request_target(&self, id: FocusHandleId) -> Option<FocusHandleId> {
1836 let node = self.nodes.get(&id)?;
1837 if !node.is_attached() {
1838 return None;
1839 }
1840 match node.kind {
1841 FocusRegistrationKind::Target => self.can_request_focus(id).then_some(id),
1842 FocusRegistrationKind::Scope => self
1843 .resolve_restore_candidate(id)
1844 .or_else(|| self.first_focusable_descendant(id))
1845 .or_else(|| self.can_request_focus(id).then_some(id)),
1846 FocusRegistrationKind::Group => self
1847 .first_focusable_descendant(id)
1848 .or_else(|| self.can_request_focus(id).then_some(id)),
1849 }
1850 }
1851
1852 fn resolve_requester_target(&self, requester_id: FocusRequesterId) -> Option<FocusHandleId> {
1853 self.requester_bindings.get(&requester_id).copied()
1854 }
1855
1856 fn resolve_explicit_direction_target(
1857 &self,
1858 id: FocusHandleId,
1859 direction: FocusDirection,
1860 ) -> Option<FocusHandleId> {
1861 let requester = self.nodes.get(&id).and_then(|node| match direction {
1862 FocusDirection::Next => node.props.next,
1863 FocusDirection::Previous => node.props.previous,
1864 FocusDirection::Up => node.props.up,
1865 FocusDirection::Down => node.props.down,
1866 FocusDirection::Left => node.props.left,
1867 FocusDirection::Right => node.props.right,
1868 FocusDirection::Enter => node.props.enter,
1869 FocusDirection::Exit => node.props.exit,
1870 })?;
1871 let handle_id = self.resolve_requester_target(requester.requester_id())?;
1872 self.resolve_request_target(handle_id)
1873 }
1874
1875 fn resolve_restore_candidate(&self, id: FocusHandleId) -> Option<FocusHandleId> {
1876 let scope = self.nodes.get(&id)?;
1877 if !scope.is_attached() || scope.kind != FocusRegistrationKind::Scope {
1878 return None;
1879 }
1880 scope
1881 .last_focused_descendant
1882 .filter(|candidate| self.can_request_focus(*candidate))
1883 .or_else(|| {
1884 scope
1885 .restorer_fallback
1886 .and_then(|requester_id| self.resolve_requester_target(requester_id))
1887 .and_then(|candidate| self.resolve_request_target(candidate))
1888 })
1889 .or_else(|| self.first_focusable_descendant(id))
1890 }
1891
1892 fn traversable_focus_handles(&self) -> Vec<FocusHandleId> {
1893 let mut ordered = Vec::new();
1894 self.collect_traversable_focus_handles(ROOT_SCOPE_ID, &mut ordered);
1895 ordered
1896 }
1897
1898 fn traversable_focus_handles_in_scope(&self, scope_id: FocusHandleId) -> Vec<FocusHandleId> {
1899 let mut ordered = Vec::new();
1900 self.collect_traversable_focus_handles(scope_id, &mut ordered);
1901 ordered
1902 }
1903
1904 fn collect_traversable_focus_handles(
1905 &self,
1906 parent: FocusHandleId,
1907 ordered: &mut Vec<FocusHandleId>,
1908 ) {
1909 let Some(children) = self.children_by_parent.get(&parent) else {
1910 return;
1911 };
1912 for &child in children {
1913 if self.is_traversable_focus_handle(child) {
1914 ordered.push(child);
1915 }
1916 self.collect_traversable_focus_handles(child, ordered);
1917 }
1918 }
1919
1920 fn is_traversable_focus_handle(&self, id: FocusHandleId) -> bool {
1921 self.nodes.get(&id).is_some_and(|node| {
1922 node.is_attached()
1923 && !node.props.skip_traversal
1924 && node.props.can_focus
1925 && node.props.can_request_focus
1926 })
1927 }
1928
1929 fn first_focusable_descendant(&self, parent: FocusHandleId) -> Option<FocusHandleId> {
1930 let mut stack = self
1931 .children_by_parent
1932 .get(&parent)
1933 .cloned()
1934 .unwrap_or_default();
1935 while let Some(id) = stack.first().copied() {
1936 stack.remove(0);
1937 if self.can_request_focus(id) {
1938 return Some(id);
1939 }
1940 if let Some(children) = self.children_by_parent.get(&id) {
1941 let mut descendants = children.clone();
1942 descendants.extend(stack);
1943 stack = descendants;
1944 }
1945 }
1946 None
1947 }
1948
1949 fn restore_from_detached(&self, id: FocusHandleId) -> Option<FocusHandleId> {
1950 let mut current_scope = self.nodes.get(&id).map(|node| node.last_scope_parent)?;
1951 loop {
1952 if let Some(candidate) = self.resolve_restore_candidate(current_scope) {
1953 return Some(candidate);
1954 }
1955 if current_scope == ROOT_SCOPE_ID {
1956 break;
1957 }
1958 current_scope = self
1959 .nodes
1960 .get(¤t_scope)
1961 .map(|node| node.last_scope_parent)
1962 .unwrap_or(ROOT_SCOPE_ID);
1963 }
1964 None
1965 }
1966
1967 fn update_scope_restore_chain(&mut self, target: FocusHandleId) {
1968 let mut current = Some(target);
1969 while let Some(id) = current {
1970 if let Some(node) = self.nodes.get_mut(&id)
1971 && node.kind == FocusRegistrationKind::Scope
1972 {
1973 node.last_focused_descendant = Some(target);
1974 }
1975 if id == ROOT_SCOPE_ID {
1976 break;
1977 }
1978 current = self
1979 .nodes
1980 .get(&id)
1981 .and_then(|node| node.attachment)
1982 .map(|attachment| attachment.scope_parent);
1983 if current == Some(id) {
1984 break;
1985 }
1986 }
1987 if let Some(root) = self.nodes.get_mut(&ROOT_SCOPE_ID) {
1988 root.last_focused_descendant = Some(target);
1989 }
1990 }
1991
1992 fn snapshot_live_states(&self) -> HashMap<FocusHandleId, FocusState> {
1993 self.nodes
1994 .iter()
1995 .filter_map(|(&id, node)| node.is_attached().then_some((id, node.state)))
1996 .collect()
1997 }
1998
1999 fn notify_requester_binding_changes(
2000 &self,
2001 previous_bindings: HashMap<FocusRequesterId, FocusHandleId>,
2002 ) {
2003 let mut changed = HashSet::default();
2004 for (&requester_id, &previous_handle_id) in &previous_bindings {
2005 let current = self.requester_bindings.get(&requester_id).copied();
2006 if current != Some(previous_handle_id) {
2007 changed.insert(requester_id);
2008 }
2009 }
2010 for (&requester_id, ¤t_handle_id) in &self.requester_bindings {
2011 let previous = previous_bindings.get(&requester_id).copied();
2012 if previous != Some(current_handle_id) {
2013 changed.insert(requester_id);
2014 }
2015 }
2016 for requester_id in changed {
2017 for reader in focus_requester_read_subscribers(requester_id) {
2018 record_replay_boundary_invalidation_for_instance_key(reader);
2019 }
2020 }
2021 }
2022
2023 fn notify_state_changes(&mut self, previous_states: HashMap<FocusHandleId, FocusState>) {
2024 let mut changed = HashSet::default();
2025 let mut events = HashSet::default();
2026 let mut changed_requesters = HashSet::default();
2027
2028 for (&id, &previous) in &previous_states {
2029 let current = self
2030 .nodes
2031 .get(&id)
2032 .filter(|node| node.is_attached())
2033 .map(|node| node.state)
2034 .unwrap_or(FocusState::Inactive);
2035 if previous != current {
2036 changed.insert(id);
2037 }
2038 if previous.has_focus() {
2039 events.insert(id);
2040 }
2041 }
2042
2043 for (&id, node) in &self.nodes {
2044 if !node.is_attached() {
2045 continue;
2046 }
2047 let previous = previous_states
2048 .get(&id)
2049 .copied()
2050 .unwrap_or(FocusState::Inactive);
2051 if previous != node.state {
2052 changed.insert(id);
2053 }
2054 if node.state.has_focus() {
2055 events.insert(id);
2056 }
2057 }
2058
2059 for &id in &changed {
2060 let state = self
2061 .nodes
2062 .get(&id)
2063 .filter(|node| node.is_attached())
2064 .map(|node| node.state)
2065 .unwrap_or(FocusState::Inactive);
2066 self.pending_notifications.push(FocusNotification {
2067 handle_id: id,
2068 state,
2069 changed: true,
2070 });
2071 for reader in focus_read_subscribers(id) {
2072 record_replay_boundary_invalidation_for_instance_key(reader);
2073 }
2074 if let Some(node) = self.nodes.get(&id)
2075 && let Some(attachment) = node.attachment
2076 && attachment.host_replay_boundary_key != 0
2077 {
2078 record_replay_boundary_invalidation_for_instance_key(
2079 attachment.host_replay_boundary_key,
2080 );
2081 }
2082 if let Some(requesters) = self.requesters_by_handle.get(&id) {
2083 changed_requesters.extend(requesters.iter().copied());
2084 }
2085 }
2086
2087 for id in events {
2088 if changed.contains(&id) {
2089 continue;
2090 }
2091 let state = self
2092 .nodes
2093 .get(&id)
2094 .filter(|node| node.is_attached())
2095 .map(|node| node.state)
2096 .unwrap_or(FocusState::Inactive);
2097 self.pending_notifications.push(FocusNotification {
2098 handle_id: id,
2099 state,
2100 changed: false,
2101 });
2102 }
2103
2104 for requester_id in changed_requesters {
2105 for reader in focus_requester_read_subscribers(requester_id) {
2106 record_replay_boundary_invalidation_for_instance_key(reader);
2107 }
2108 }
2109 }
2110
2111 fn recompute_states(&mut self) {
2112 for node in self.nodes.values_mut() {
2113 if node.is_attached() {
2114 node.state = FocusState::Inactive;
2115 }
2116 }
2117 let Some(active) = self.active else {
2118 return;
2119 };
2120 if !self
2121 .nodes
2122 .get(&active)
2123 .is_some_and(|node| node.is_attached())
2124 {
2125 return;
2126 }
2127
2128 let mut current = Some(active);
2129 let active_state = if self.captured == Some(active) {
2130 FocusState::Captured
2131 } else {
2132 FocusState::Active
2133 };
2134 let mut first = true;
2135 while let Some(id) = current {
2136 if let Some(node) = self.nodes.get_mut(&id)
2137 && node.is_attached()
2138 {
2139 node.state = if first {
2140 active_state
2141 } else {
2142 FocusState::ActiveParent
2143 };
2144 }
2145 if id == ROOT_SCOPE_ID {
2146 break;
2147 }
2148 current = self
2149 .nodes
2150 .get(&id)
2151 .and_then(|node| node.attachment)
2152 .map(|attachment| attachment.parent);
2153 first = false;
2154 }
2155 }
2156
2157 fn can_focus(&self, id: FocusHandleId) -> bool {
2158 self.nodes
2159 .get(&id)
2160 .is_some_and(|node| node.is_attached() && node.props.can_focus)
2161 }
2162
2163 fn can_request_focus(&self, id: FocusHandleId) -> bool {
2164 self.nodes.get(&id).is_some_and(|node| {
2165 node.is_attached() && node.props.can_focus && node.props.can_request_focus
2166 })
2167 }
2168
2169 fn is_ancestor(&self, ancestor: FocusHandleId, descendant: FocusHandleId) -> bool {
2170 let mut current = Some(descendant);
2171 while let Some(id) = current {
2172 if id == ancestor {
2173 return true;
2174 }
2175 if id == ROOT_SCOPE_ID {
2176 break;
2177 }
2178 current = self
2179 .nodes
2180 .get(&id)
2181 .and_then(|node| node.attachment)
2182 .map(|attachment| attachment.parent);
2183 }
2184 false
2185 }
2186}
2187
2188fn is_eligible_focus_rect(rect: PxRect) -> bool {
2189 rect.width.0 > 0 && rect.height.0 > 0
2190}
2191
2192fn initial_best_candidate_rect(focused_rect: PxRect, direction: FocusDirection) -> PxRect {
2193 match direction {
2194 FocusDirection::Left => PxRect::new(
2195 focused_rect.x + focused_rect.width + crate::Px::new(1),
2196 focused_rect.y,
2197 focused_rect.width,
2198 focused_rect.height,
2199 ),
2200 FocusDirection::Right => PxRect::new(
2201 focused_rect.x - focused_rect.width - crate::Px::new(1),
2202 focused_rect.y,
2203 focused_rect.width,
2204 focused_rect.height,
2205 ),
2206 FocusDirection::Up => PxRect::new(
2207 focused_rect.x,
2208 focused_rect.y + focused_rect.height + crate::Px::new(1),
2209 focused_rect.width,
2210 focused_rect.height,
2211 ),
2212 FocusDirection::Down => PxRect::new(
2213 focused_rect.x,
2214 focused_rect.y - focused_rect.height - crate::Px::new(1),
2215 focused_rect.width,
2216 focused_rect.height,
2217 ),
2218 _ => focused_rect,
2219 }
2220}
2221
2222fn is_better_focus_candidate(
2223 proposed_candidate: PxRect,
2224 current_candidate: PxRect,
2225 focused_rect: PxRect,
2226 direction: FocusDirection,
2227) -> bool {
2228 if !is_focus_candidate(proposed_candidate, focused_rect, direction) {
2229 return false;
2230 }
2231 if !is_focus_candidate(current_candidate, focused_rect, direction) {
2232 return true;
2233 }
2234 if focus_beam_beats(
2235 focused_rect,
2236 proposed_candidate,
2237 current_candidate,
2238 direction,
2239 ) {
2240 return true;
2241 }
2242 if focus_beam_beats(
2243 focused_rect,
2244 current_candidate,
2245 proposed_candidate,
2246 direction,
2247 ) {
2248 return false;
2249 }
2250 weighted_focus_distance(proposed_candidate, focused_rect, direction)
2251 < weighted_focus_distance(current_candidate, focused_rect, direction)
2252}
2253
2254fn is_focus_candidate(rect: PxRect, focused_rect: PxRect, direction: FocusDirection) -> bool {
2255 match direction {
2256 FocusDirection::Left => {
2257 (focused_rect_right(focused_rect) > focused_rect_right(rect)
2258 || focused_rect.x >= focused_rect_right(rect))
2259 && focused_rect.x > rect.x
2260 }
2261 FocusDirection::Right => {
2262 (focused_rect.x < rect.x || focused_rect_right(focused_rect) <= rect.x)
2263 && focused_rect_right(focused_rect) < focused_rect_right(rect)
2264 }
2265 FocusDirection::Up => {
2266 (focused_rect_bottom(focused_rect) > focused_rect_bottom(rect)
2267 || focused_rect.y >= focused_rect_bottom(rect))
2268 && focused_rect.y > rect.y
2269 }
2270 FocusDirection::Down => {
2271 (focused_rect.y < rect.y || focused_rect_bottom(focused_rect) <= rect.y)
2272 && focused_rect_bottom(focused_rect) < focused_rect_bottom(rect)
2273 }
2274 _ => false,
2275 }
2276}
2277
2278fn weighted_focus_distance(rect: PxRect, focused_rect: PxRect, direction: FocusDirection) -> i64 {
2279 let major = major_axis_distance(rect, focused_rect, direction);
2280 let minor = minor_axis_distance(rect, focused_rect, direction);
2281 13 * major * major + minor * minor
2282}
2283
2284fn focus_beam_beats(
2285 source: PxRect,
2286 rect1: PxRect,
2287 rect2: PxRect,
2288 direction: FocusDirection,
2289) -> bool {
2290 if rect2_in_source_beam(rect2, source, direction)
2291 || !rect2_in_source_beam(rect1, source, direction)
2292 {
2293 return false;
2294 }
2295 if !is_in_direction_of_search(rect2, source, direction) {
2296 return true;
2297 }
2298 if matches!(direction, FocusDirection::Left | FocusDirection::Right) {
2299 return true;
2300 }
2301 major_axis_distance(rect1, source, direction)
2302 < major_axis_distance_to_far_edge(rect2, source, direction)
2303}
2304
2305fn rect2_in_source_beam(rect: PxRect, source: PxRect, direction: FocusDirection) -> bool {
2306 match direction {
2307 FocusDirection::Left | FocusDirection::Right => {
2308 focused_rect_bottom(rect) > source.y && rect.y < focused_rect_bottom(source)
2309 }
2310 FocusDirection::Up | FocusDirection::Down => {
2311 focused_rect_right(rect) > source.x && rect.x < focused_rect_right(source)
2312 }
2313 _ => false,
2314 }
2315}
2316
2317fn is_in_direction_of_search(rect: PxRect, source: PxRect, direction: FocusDirection) -> bool {
2318 match direction {
2319 FocusDirection::Left => source.x >= focused_rect_right(rect),
2320 FocusDirection::Right => focused_rect_right(source) <= rect.x,
2321 FocusDirection::Up => source.y >= focused_rect_bottom(rect),
2322 FocusDirection::Down => focused_rect_bottom(source) <= rect.y,
2323 _ => false,
2324 }
2325}
2326
2327fn major_axis_distance(rect: PxRect, focused_rect: PxRect, direction: FocusDirection) -> i64 {
2328 let distance = match direction {
2329 FocusDirection::Left => focused_rect.x.0 - focused_rect_right(rect).0,
2330 FocusDirection::Right => rect.x.0 - focused_rect_right(focused_rect).0,
2331 FocusDirection::Up => focused_rect.y.0 - focused_rect_bottom(rect).0,
2332 FocusDirection::Down => rect.y.0 - focused_rect_bottom(focused_rect).0,
2333 _ => 0,
2334 };
2335 i64::from(distance.max(0))
2336}
2337
2338fn major_axis_distance_to_far_edge(rect: PxRect, source: PxRect, direction: FocusDirection) -> i64 {
2339 let distance = match direction {
2340 FocusDirection::Left => source.x.0 - rect.x.0,
2341 FocusDirection::Right => focused_rect_right(rect).0 - focused_rect_right(source).0,
2342 FocusDirection::Up => source.y.0 - rect.y.0,
2343 FocusDirection::Down => focused_rect_bottom(rect).0 - focused_rect_bottom(source).0,
2344 _ => 1,
2345 };
2346 i64::from(distance.max(1))
2347}
2348
2349fn minor_axis_distance(rect: PxRect, focused_rect: PxRect, direction: FocusDirection) -> i64 {
2350 let focused_center = match direction {
2351 FocusDirection::Left | FocusDirection::Right => {
2352 focused_rect.y.0 + focused_rect.height.0 / 2
2353 }
2354 FocusDirection::Up | FocusDirection::Down => focused_rect.x.0 + focused_rect.width.0 / 2,
2355 _ => 0,
2356 };
2357 let candidate_center = match direction {
2358 FocusDirection::Left | FocusDirection::Right => rect.y.0 + rect.height.0 / 2,
2359 FocusDirection::Up | FocusDirection::Down => rect.x.0 + rect.width.0 / 2,
2360 _ => 0,
2361 };
2362 i64::from(focused_center - candidate_center)
2363}
2364
2365fn focused_rect_right(rect: PxRect) -> crate::Px {
2366 rect.x + rect.width
2367}
2368
2369fn focused_rect_bottom(rect: PxRect) -> crate::Px {
2370 rect.y + rect.height
2371}
2372
2373pub(crate) fn flush_pending_focus_callbacks() {
2374 let callbacks = TesseraRuntime::with_mut(|runtime| {
2375 runtime
2376 .component_tree
2377 .take_pending_focus_callback_invocations()
2378 });
2379 for callback in callbacks {
2380 callback.invoke();
2381 }
2382}