wl: another frontend's picture is not ours to show

e64e4ea took the picture out of the owner poll and argued a later take
could not show a stale one: "either our own key replaced it, or the
engine suppressed the send because our snapshot is that same picture".
The second half is the hole.  redraw() returns before it drains when the
picture has not changed, and under Wayland wl is drawc's only reader, so
every IBus interaction leaves its last picture sitting there -- the mode
mark after Ctrl+T, a hanja list, whatever was up.  Press a bare modifier
in a text-input-v3 window while IBus owns the engine: keymeaningful(0) is
false, the engine changes nothing, the send is suppressed, and grabkey's
takedraw puts the other window's candidates on our popup surface.

I could not make it visible.  checkowner() runs later in the same loop
iteration, finds we are not the owner and hides it, and both commits
leave in one wl_display_flush, so the compositor renders nothing between
them.  What is wrong is the rule: README says an IBus client under
Wayland "shows no candidates, because the popup belongs to the Wayland
frontend", and that is now true by construction rather than by luck.

leave() and flushpending() already take only while engaged, so the guard
costs nothing where it is and covers all three callers.  The drain still
happens either way, which is what keeps drawc and lastdraw in step.
Phases A-G under headless sway at both scales; the phase E hanja popup
is unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 23:25:53 +09:00
parent 650f00812d
commit 0f128a46b3

5
wl.c
View File

@@ -314,14 +314,15 @@ popup(Drawcmd *dc)
/* /*
* drawc is empty or holds exactly what the engine last published, so one * drawc is empty or holds exactly what the engine last published, so one
* take is enough. lastdraw follows the engine and not our surface, so * take is enough. lastdraw follows the engine and not our surface, so
* take it wherever the two can part. * take it wherever the two can part -- but show it only while the engine
* is ours: what it drew for another frontend is not ours to put up.
*/ */
static void static void
takedraw(void) takedraw(void)
{ {
Drawcmd dc; Drawcmd dc;
if(channbrecv(drawc, &dc) > 0) if(channbrecv(drawc, &dc) > 0 && engaged)
popup(&dc); popup(&dc);
} }