diff --git a/crates/common/src/event_messages.rs b/crates/common/src/event_messages.rs index 008e6eb2e..f20d904bd 100644 --- a/crates/common/src/event_messages.rs +++ b/crates/common/src/event_messages.rs @@ -28,6 +28,8 @@ pub enum EventMessage { ActionRequestEvent(ActionRequestEvent), /// Focus the given accessibility NodeID FocusAccessibilityNode(NodeId), + /// Queue a focus the given accessibility NodeID + QueueFocusAccessibilityNode(NodeId), /// Focus the next accessibility Node FocusNextAccessibilityNode, /// Focus the previous accessibility Node diff --git a/crates/hooks/src/use_focus.rs b/crates/hooks/src/use_focus.rs index 7f516aedd..6afcf8ce3 100644 --- a/crates/hooks/src/use_focus.rs +++ b/crates/hooks/src/use_focus.rs @@ -31,6 +31,15 @@ impl UseFocus { } } + /// Queue a focus to this node + pub fn queue_focus(&mut self) { + if !*self.is_focused.peek() { + self.platform + .send(EventMessage::QueueFocusAccessibilityNode(self.id)) + .ok(); + } + } + /// Get the node focus ID pub fn id(&self) -> AccessibilityId { self.id diff --git a/crates/renderer/src/app.rs b/crates/renderer/src/app.rs index 7eb4de182..64534273f 100644 --- a/crates/renderer/src/app.rs +++ b/crates/renderer/src/app.rs @@ -45,6 +45,7 @@ pub struct App { pub(crate) plugins: PluginsManager, pub(crate) measure_layout_on_next_render: bool, pub(crate) default_fonts: Vec, + pub(crate) queued_focus_node: Option, } impl App { @@ -111,6 +112,7 @@ impl App { plugins, measure_layout_on_next_render: false, default_fonts, + queued_focus_node: None, } } @@ -229,6 +231,10 @@ impl App { rdom, &mut self.accessibility.accessibility_manager().lock().unwrap(), ); + + if let Some(node_id) = self.queued_focus_node.take() { + self.focus_node(node_id) + } } /// Send an event @@ -287,6 +293,10 @@ impl App { .focus_node(node_id, &self.platform_sender, &self.window_env.window) } + pub fn queue_focus_node(&mut self, node_id: AccessibilityId) { + self.queued_focus_node = Some(node_id); + } + pub fn focus_next_node(&self, direction: AccessibilityFocusDirection) { self.accessibility.focus_next_node( direction, diff --git a/crates/renderer/src/event_loop.rs b/crates/renderer/src/event_loop.rs index 2098d0d3c..196bbad75 100644 --- a/crates/renderer/src/event_loop.rs +++ b/crates/renderer/src/event_loop.rs @@ -44,6 +44,9 @@ pub fn run_event_loop( Event::UserEvent(EventMessage::FocusAccessibilityNode(node_id)) => { app.focus_node(node_id); } + Event::UserEvent(EventMessage::QueueFocusAccessibilityNode(node_id)) => { + app.queue_focus_node(node_id); + } Event::UserEvent(EventMessage::RequestRerender) => { app.window_env.window.request_redraw(); } diff --git a/examples/floating_editors.rs b/examples/floating_editors.rs index 9d46cff1a..4597fa6af 100644 --- a/examples/floating_editors.rs +++ b/examples/floating_editors.rs @@ -174,7 +174,7 @@ fn Editor() -> Element { let font_weight = if *is_bold.read() { "bold" } else { "normal" }; use_hook(|| { - focus_manager.focus(); + focus_manager.queue_focus(); }); let onclick = move |_: MouseEvent| { @@ -195,9 +195,12 @@ fn Editor() -> Element { } }; + let focus_id = focus_manager.attribute(); + rsx!( rect { onclick, + focus_id, width: "100%", height: "100%", rect {