diff --git a/src/event_loop/focus.rs b/src/event_loop/focus.rs index 0dda36f..02f2f06 100644 --- a/src/event_loop/focus.rs +++ b/src/event_loop/focus.rs @@ -80,6 +80,23 @@ impl AppData .and_then( |s| s.on_dismiss ) } + /// After a rebuild: a focused text input that vanished from the frame + /// would otherwise keep the text-input protocol (and the OSK) active. + pub( crate ) fn reconcile_text_focus( &mut self, focus: SurfaceFocus ) + { + if surface_focused_text_input( self.surface( focus ) ) { return; } + let ss = self.surface_mut( focus ); + if let Some( idx ) = ss.focused_idx.take() + { + ss.pending_text_values.remove( &idx ); + } + ss.focused_id = None; + ss.request_redraw(); + self.deactivate_text_input(); + self.app.on_text_input_focused( false ); + self.dirty_caches(); + } + pub( crate ) fn set_focus( &mut self, focus: SurfaceFocus, idx: Option, qh: &QueueHandle ) { let was_text_input; @@ -168,3 +185,15 @@ impl AppData } } } + +/// Whether the surface's focused widget is a text input in its current frame. +pub( crate ) fn surface_focused_text_input( ss: &super::surface::SurfaceState ) -> bool +{ + let by_id = ss.focused_id.and_then( |id| + { + ss.frame.widget_rects.iter().find( |w| w.id == Some( id ) ).map( |w| &w.handlers ) + } ); + by_id + .or_else( || ss.focused_idx.and_then( |i| find_handlers( &ss.frame.widget_rects, i ) ) ) + .is_some_and( |h| h.is_text_input() ) +} diff --git a/src/event_loop/frame.rs b/src/event_loop/frame.rs index 653be6c..b2ac7cd 100644 --- a/src/event_loop/frame.rs +++ b/src/event_loop/frame.rs @@ -12,6 +12,7 @@ use crate::types::{ Color, Rect }; use crate::widget::Element; use super::AppData; +use super::focus::surface_focused_text_input; use super::surface::{ SurfaceFocus, SurfaceState }; use crate::draw::gles::{ draw_surface_full_gpu, draw_surface_partial_gpu }; use crate::draw::software::{ draw_surface_full, draw_surface_partial }; @@ -47,8 +48,13 @@ pub( crate ) fn draw_frame( data: &mut AppData ) -> bool let qh = &data.qh; let mut first_commit_now = false; + let mut text_focus_rebuilt: Vec = Vec::new(); if data.main.configured && data.main.needs_redraw && !data.main.frame_pending { + if surface_focused_text_input( &data.main ) + { + text_focus_rebuilt.push( SurfaceFocus::Main ); + } let req_frame = | wl: &WlSurface | { let _ = wl.frame( qh, SurfaceFocus::Main ); }; draw_surface::( &mut data.main, @@ -104,6 +110,10 @@ pub( crate ) fn draw_frame( data: &mut AppData ) -> bool { if !ss.configured || !ss.needs_redraw || ss.frame_pending { continue; } let focus = SurfaceFocus::Overlay( spec.id ); + if surface_focused_text_input( ss ) + { + text_focus_rebuilt.push( focus ); + } let req_frame = | wl: &WlSurface | { let _ = wl.frame( qh, focus ); }; let bg = Color::rgba( 0.0, 0.0, 0.0, 0.0 ); draw_surface::( @@ -123,6 +133,11 @@ pub( crate ) fn draw_frame( data: &mut AppData ) -> bool } } + for focus in text_focus_rebuilt + { + data.reconcile_text_focus( focus ); + } + first_commit_now }