diff --git a/src/app.rs b/src/app.rs index 8fb6238..c5ee34c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -865,6 +865,9 @@ pub trait App: 'static /// view before it is focused. A widget that never appears is dropped. fn take_focus_request( &mut self ) -> Option { None } + /// Return `true` once to drop the keyboard focus, which folds the on-screen keyboard; a [`take_focus_request`](Self::take_focus_request) in the same cycle wins. + fn take_blur_request( &mut self ) -> bool { false } + /// Called on every pointer motion (mouse move, button press, button /// release). `x`, `y` are in physical pixels of the main surface, /// the same coordinate space as widget rects. Default: no-op. diff --git a/src/event_loop/app_data.rs b/src/event_loop/app_data.rs index e8f767e..07ad927 100644 --- a/src/event_loop/app_data.rs +++ b/src/event_loop/app_data.rs @@ -259,6 +259,8 @@ pub struct AppData /// Surface currently holding keyboard focus (updated on keyboard /// enter/leave). pub keyboard_focus: SurfaceFocus, + /// The current press landed on the widget that already held the focus, not the press that gives it. + pub press_on_focused: bool, /// Per-touch-id tracking of which surface each active touch belongs to /// (populated on `down`, cleared on `up`/`cancel`). pub touch_focus: HashMap, diff --git a/src/event_loop/run.rs b/src/event_loop/run.rs index c594a96..eabc991 100644 --- a/src/event_loop/run.rs +++ b/src/event_loop/run.rs @@ -362,6 +362,7 @@ pub( crate ) fn try_run( mut app: A ) -> Result<(), RunError> canvas_pool: Vec::new(), pointer_focus: SurfaceFocus::Main, keyboard_focus: SurfaceFocus::Main, + press_on_focused: false, touch_focus: std::collections::HashMap::new(), cached_view: None, cached_overlays: None, @@ -912,6 +913,14 @@ pub( crate ) fn try_run( mut app: A ) -> Result<(), RunError> } } + if data.app.take_blur_request() + { + let qh = data.qh.clone(); + let focus = data.keyboard_focus; + data.set_focus( focus, None, &qh ); + data.focus_retry = None; + } + // Focus the widget with the requested WidgetId if the app requests it. // Walks main + every overlay because the targeted widget can live // on any of them (a search field on a launcher overlay, a text diff --git a/src/event_loop/text_editing/selection.rs b/src/event_loop/text_editing/selection.rs index 0d13b44..ce58807 100644 --- a/src/event_loop/text_editing/selection.rs +++ b/src/event_loop/text_editing/selection.rs @@ -127,7 +127,7 @@ impl AppData find_handlers( &self.surface( focus ).frame.widget_rects, idx ), Some( WidgetHandlers::TextEdit { select_on_focus: true, .. } ), ); - if select_on_focus { return; } + if select_on_focus && !self.press_on_focused { return; } let ( rect, value, multiline, secure, align, font_size ) = match self.text_input_geometry( focus, idx ) { Some( v ) => v, @@ -161,7 +161,7 @@ impl AppData find_handlers( &self.surface( focus ).frame.widget_rects, idx ), Some( WidgetHandlers::TextEdit { select_on_focus: true, .. } ), ); - if select_on_focus { return; } + if select_on_focus && !self.press_on_focused { return; } let ( rect, value, multiline, secure, align, font_size ) = match self.text_input_geometry( focus, idx ) { Some( v ) => v, diff --git a/src/input/pointer/press.rs b/src/input/pointer/press.rs index 90d6568..4633905 100644 --- a/src/input/pointer/press.rs +++ b/src/input/pointer/press.rs @@ -181,6 +181,7 @@ impl AppData ss.needs_redraw = true; result }; + self.press_on_focused = outcome.hit_idx.is_some() && self.surface( focus ).focused_idx == outcome.hit_idx; self.set_focus( focus, outcome.hit_idx, qh ); if let Some( msg ) = outcome.initial_slider_msg { diff --git a/src/input/touch/mod.rs b/src/input/touch/mod.rs index a59d508..9f92cb2 100644 --- a/src/input/touch/mod.rs +++ b/src/input/touch/mod.rs @@ -159,6 +159,7 @@ impl TouchHandler for AppData ss.needs_redraw = true; result }; + self.press_on_focused = outcome.hit_idx.is_some() && self.surface( focus ).focused_idx == outcome.hit_idx; self.set_focus( focus, outcome.hit_idx, qh ); if let Some( msg ) = outcome.initial_slider_msg {