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