diff --git a/src/event_loop/app_data.rs b/src/event_loop/app_data.rs index 7190450..68d8296 100644 --- a/src/event_loop/app_data.rs +++ b/src/event_loop/app_data.rs @@ -248,6 +248,9 @@ pub struct AppData /// Set after the first commit of a rendered buffer on the main surface. /// Used to drive `App::on_first_frame_committed` exactly once. pub first_frame_committed: bool, + /// Focus request deferred because the target widget was absent from + /// `widget_rects` (e.g. read_only, not yet rebuilt). Retried next draw. + pub focus_retry: Option, } impl AppData diff --git a/src/event_loop/run.rs b/src/event_loop/run.rs index c46e3a2..0a6f77f 100644 --- a/src/event_loop/run.rs +++ b/src/event_loop/run.rs @@ -329,6 +329,7 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> view_dirty: true, overlays_dirty: true, first_frame_committed: false, + focus_retry: None, }; // Register a calloop channel so the app can send messages from any thread. @@ -809,7 +810,8 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> // Walks main + every overlay because the targeted widget can live // on any of them (a search field on a launcher overlay, a text // edit on a dialog modal, …). - if let Some( id ) = data.app.take_focus_request() + let focus_id = data.app.take_focus_request().or_else( || data.focus_retry.take() ); + if let Some( id ) = focus_id { let mut hit: Option<( SurfaceFocus, usize )> = data.main.widget_rects.iter() .find( |w| w.id == Some( id ) ) @@ -840,6 +842,10 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> } } } + } else { + data.focus_retry = Some( id ); + data.view_dirty = true; + data.main.request_redraw(); } } }