From 95684c3550294e79d74481379ef10dfb88c25576 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Sat, 2 Sep 2023 14:12:49 +0100 Subject: [PATCH] make sure focus is handled properly --- src/context.rs | 41 ++++++++++++++++++++++++++++---- src/event.rs | 16 +++++++++++++ src/view.rs | 3 +++ src/window_handle.rs | 56 +++++++++++--------------------------------- 4 files changed, 70 insertions(+), 46 deletions(-) diff --git a/src/context.rs b/src/context.rs index 88ec1e9c..dbc8a661 100644 --- a/src/context.rs +++ b/src/context.rs @@ -604,6 +604,42 @@ impl AppState { } } } + + pub(crate) fn get_event_listener( + &self, + id: Id, + listener: &EventListener, + ) -> Option<&impl Fn(&Event) -> bool> { + self.view_states + .get(&id) + .and_then(|s| s.event_listeners.get(listener)) + } + + pub(crate) fn focus_changed(&mut self, old: Option, new: Option) { + if let Some(old_id) = old { + // To remove the styles applied by the Focus selector + if self.has_style_for_sel(old_id, StyleSelector::Focus) + || self.has_style_for_sel(old_id, StyleSelector::FocusVisible) + { + self.request_layout(old_id); + } + if let Some(action) = self.get_event_listener(old_id, &EventListener::FocusLost) { + (*action)(&Event::FocusLost); + } + } + + if let Some(id) = new { + // To apply the styles of the Focus selector + if self.has_style_for_sel(id, StyleSelector::Focus) + || self.has_style_for_sel(id, StyleSelector::FocusVisible) + { + self.request_layout(id); + } + if let Some(action) = self.get_event_listener(id, &EventListener::FocusGained) { + (*action)(&Event::FocusGained); + } + } + } } /// A bundle of helper methods to be used by `View::event` handlers @@ -663,10 +699,7 @@ impl<'a> EventCx<'a> { id: Id, listener: &EventListener, ) -> Option<&impl Fn(&Event) -> bool> { - self.app_state - .view_states - .get(&id) - .and_then(|s| s.event_listeners.get(listener)) + self.app_state.get_event_listener(id, listener) } /// translate a window-positioned event to the local coordinate system of a view diff --git a/src/event.rs b/src/event.rs index 1dd21389..7529c0d2 100644 --- a/src/event.rs +++ b/src/event.rs @@ -58,6 +58,8 @@ pub enum Event { WindowClosed, WindowResized(Size), WindowMoved(Point), + FocusGained, + FocusLost, } impl Event { @@ -67,6 +69,8 @@ impl Event { | Event::PointerUp(_) | Event::PointerMove(_) | Event::PointerWheel(_) + | Event::FocusGained + | Event::FocusLost | Event::ImeEnabled | Event::ImeDisabled | Event::ImePreedit { .. } @@ -88,6 +92,8 @@ impl Event { | Event::PointerWheel(_) => true, Event::KeyDown(_) | Event::KeyUp(_) + | Event::FocusGained + | Event::FocusLost | Event::ImeEnabled | Event::ImeDisabled | Event::ImePreedit { .. } @@ -118,6 +124,8 @@ impl Event { Event::PointerDown(_) | Event::PointerUp(_) | Event::PointerWheel(_) + | Event::FocusGained + | Event::FocusLost | Event::ImeEnabled | Event::ImeDisabled | Event::ImePreedit { .. } @@ -142,6 +150,8 @@ impl Event { Event::PointerWheel(pointer_event) => Some(pointer_event.pos), Event::KeyDown(_) | Event::KeyUp(_) + | Event::FocusGained + | Event::FocusLost | Event::ImeEnabled | Event::ImeDisabled | Event::ImePreedit { .. } @@ -170,6 +180,8 @@ impl Event { } Event::KeyDown(_) | Event::KeyUp(_) + | Event::FocusGained + | Event::FocusLost | Event::ImeEnabled | Event::ImeDisabled | Event::ImePreedit { .. } @@ -196,6 +208,8 @@ impl Event { } Event::KeyDown(_) | Event::KeyUp(_) + | Event::FocusGained + | Event::FocusLost | Event::ImeEnabled | Event::ImeDisabled | Event::ImePreedit { .. } @@ -226,6 +240,8 @@ impl Event { Event::WindowMoved(_) => Some(EventListener::WindowMoved), Event::WindowGotFocus => Some(EventListener::WindowGotFocus), Event::WindowLostFocus => Some(EventListener::WindowLostFocus), + Event::FocusLost => Some(EventListener::FocusLost), + Event::FocusGained => Some(EventListener::FocusGained), } } } diff --git a/src/view.rs b/src/view.rs index a4c894bf..f33673ab 100644 --- a/src/view.rs +++ b/src/view.rs @@ -143,6 +143,9 @@ pub trait View { let _ = app_state.taffy.remove(node); id.remove_id_path(); app_state.view_states.remove(&id); + if app_state.focus == Some(id) { + app_state.focus = None; + } } fn debug_name(&self) -> std::borrow::Cow<'static, str> { diff --git a/src/window_handle.rs b/src/window_handle.rs index f3b2b3eb..9f63a1cb 100644 --- a/src/window_handle.rs +++ b/src/window_handle.rs @@ -123,10 +123,16 @@ impl WindowHandle { processed |= self .view .event_main(&mut cx, Some(&id_path.0), event.clone()); + } else { + cx.app_state.focus = None; } - } else if let Some(listener) = event.listener() { - if let Some(action) = cx.get_event_listener(self.view.id(), &listener) { - processed |= (*action)(&event); + } + + if !processed { + if let Some(listener) = event.listener() { + if let Some(action) = cx.get_event_listener(self.view.id(), &listener) { + processed |= (*action)(&event); + } } } @@ -220,33 +226,7 @@ impl WindowHandle { } } if was_focused != cx.app_state.focus { - if let Some(old_id) = was_focused { - // To remove the styles applied by the Focus selector - if cx.app_state.has_style_for_sel(old_id, StyleSelector::Focus) - || cx - .app_state - .has_style_for_sel(old_id, StyleSelector::FocusVisible) - { - cx.app_state.request_layout(old_id); - } - if let Some(action) = cx.get_event_listener(old_id, &EventListener::FocusLost) { - (*action)(&event); - } - } - - if let Some(id) = cx.app_state.focus { - // To apply the styles of the Focus selector - if cx.app_state.has_style_for_sel(id, StyleSelector::Focus) - || cx - .app_state - .has_style_for_sel(id, StyleSelector::FocusVisible) - { - cx.app_state.request_layout(id); - } - if let Some(action) = cx.get_event_listener(id, &EventListener::FocusGained) { - (*action)(&event); - } - } + cx.app_state.focus_changed(was_focused, cx.app_state.focus); } self.process_update(); @@ -464,18 +444,10 @@ impl WindowHandle { cx.app_state.request_layout(id); } UpdateMessage::Focus(id) => { - let old = cx.app_state.focus; - cx.app_state.focus = Some(id); - - if let Some(old_id) = old { - // To remove the styles applied by the Focus selector - if cx.app_state.has_style_for_sel(old_id, StyleSelector::Focus) { - cx.app_state.request_layout(old_id); - } - } - - if cx.app_state.has_style_for_sel(id, StyleSelector::Focus) { - cx.app_state.request_layout(id); + if cx.app_state.focus != Some(id) { + let old = cx.app_state.focus; + cx.app_state.focus = Some(id); + cx.app_state.focus_changed(old, cx.app_state.focus); } } UpdateMessage::Active(id) => {