@@ -84,6 +84,7 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
8484 } ,
8585 TextInputEvent :: Leave { surface } => {
8686 text_input_data. surface = None ;
87+ text_input_data. last_preedit_empty = true ;
8788
8889 // Always issue a disable.
8990 text_input. disable ( ) ;
@@ -129,6 +130,13 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
129130 None => return ,
130131 } ;
131132
133+ // Just in case some IME sends an event for the disabled window.
134+ if let Some ( window) = windows. get ( & window_id) {
135+ if window. lock ( ) . unwrap ( ) . text_input_state ( ) . is_none ( ) {
136+ return ;
137+ }
138+ } ;
139+
132140 // The events are sent to the user separately, so
133141 // CAUTION: events must always arrive in the order compatible with the application
134142 // order specified by the text-input-v3 protocol:
@@ -153,14 +161,17 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
153161 ) ;
154162 }
155163
156- // Clear preedit, unless all we'll be doing next is sending a new preedit.
164+ // Clear preedit, unless all we'll be doing next is sending a new preedit and
165+ // the last preedit wasn't empty.
157166 if text_input_data. pending_commit . is_some ( )
158- || text_input_data. pending_preedit . is_none ( )
167+ || ( text_input_data. pending_preedit . is_none ( )
168+ && !text_input_data. last_preedit_empty )
159169 {
160170 state. events_sink . push_window_event (
161171 WindowEvent :: Ime ( Ime :: Preedit ( String :: new ( ) , None ) ) ,
162172 window_id,
163173 ) ;
174+ text_input_data. last_preedit_empty = true ;
164175 }
165176
166177 // Send `Commit`.
@@ -175,6 +186,7 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
175186 let cursor_range =
176187 preedit. cursor_begin . map ( |b| ( b, preedit. cursor_end . unwrap_or ( b) ) ) ;
177188
189+ text_input_data. last_preedit_empty = false ;
178190 state. events_sink . push_window_event (
179191 WindowEvent :: Ime ( Ime :: Preedit ( preedit. text , cursor_range) ) ,
180192 window_id,
@@ -238,7 +250,6 @@ pub struct TextInputData {
238250 inner : std:: sync:: Mutex < TextInputDataInner > ,
239251}
240252
241- #[ derive( Default ) ]
242253pub struct TextInputDataInner {
243254 /// The `WlSurface` we're performing input to.
244255 surface : Option < WlSurface > ,
@@ -251,6 +262,21 @@ pub struct TextInputDataInner {
251262
252263 /// The text around the cursor to delete on `done`
253264 pending_delete : Option < DeleteSurroundingText > ,
265+
266+ /// Last preedit empty.
267+ last_preedit_empty : bool ,
268+ }
269+
270+ impl Default for TextInputDataInner {
271+ fn default ( ) -> Self {
272+ Self {
273+ surface : None ,
274+ pending_commit : None ,
275+ pending_preedit : None ,
276+ pending_delete : None ,
277+ last_preedit_empty : true ,
278+ }
279+ }
254280}
255281
256282/// The state of the preedit.
0 commit comments