wl: a deactivate hands the pending text back

Two things arrive as a deactivate.  When the focus moved, the compositor
sent the text input its leave first, and sway's handle_im_commit finds no
focused text input and drops the whole commit -- which is what the old
comment described.  But a client that merely disabled its text input
still holds the focus: sway relays that deactivate only in that case
(handle_text_input_disable returns early once the surface is unfocused),
so the commit would have been delivered, and half a syllable was thrown
away instead.  A GtkEntry losing the focus to a button in its own window
is that case.

XIM and IBus both hand the text back there and drop it only when the
client itself is gone -- ibus.c keeps the two apart as flushcontext and
releasecontext.  This gives the Wayland frontend the same halves.  The
commit that goes nowhere costs one empty request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 21:21:07 +09:00
parent 841d93ac35
commit 40fd4ab551

10
wl.c
View File

@@ -352,10 +352,11 @@ releasegrab(void)
} }
/* /*
* The context is going: give the client its keys back. The engine's * The context is going: give the client its keys back and the pending
* pending text goes nowhere, because the compositor sends the text input * text, as a lost focus does everywhere else. A client that only
* its leave before it sends us the deactivate, and a commit with nothing * disabled its text input still holds the focus and takes the commit;
* focused to take it is dropped whatever serial it carries. * when the focus itself moved, the compositor sent the text input its
* leave first and drops the commit whatever serial it carries.
*/ */
static void static void
leave(void) leave(void)
@@ -365,6 +366,7 @@ leave(void)
releasekeys(); releasekeys();
if(engaged){ if(engaged){
sendrequest(Keyrelease, 0, 0, &res); sendrequest(Keyrelease, 0, 0, &res);
answer(&res, "");
engaged = 0; engaged = 0;
takedraw(); takedraw();
} }