From f6adb117c96e9628369cc633426f057538104c70 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sun, 16 Aug 2026 20:23:29 +0900 Subject: [PATCH] fix(popup): raise the popup whenever it is shown The popup window is created once at startup and only mapped afterwards, and MapWindow does not restack, so every application window (or WM frame) opened after the daemon sat above it: candidates and preedit were invisible in those windows until the daemon restarted. Configure the window above its siblings on every show. The XIM live test now checks the popup stacks above a client window created after the daemon. --- tests/xim_live_test.c | 36 ++++++++++++++++++++++++++++++++++++ win.c | 8 +++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/tests/xim_live_test.c b/tests/xim_live_test.c index e23cb09..7b93588 100644 --- a/tests/xim_live_test.c +++ b/tests/xim_live_test.c @@ -608,6 +608,41 @@ testcallbacks(Display *dpy, XIM im, Window win) return 1; } +/* + * The popup is the one viewable override-redirect window on the private + * display; created before the client window, it must still stack above it. + */ +static int +popupabove(Display *dpy, Window client) +{ + XWindowAttributes wa; + Window root, parent, *kids; + unsigned i, n; + int64_t deadline; + int above; + + deadline = nowms() + Eventtimeout; + for(;;){ + above = 0; + root = DefaultRootWindow(dpy); + if(!XQueryTree(dpy, root, &root, &parent, &kids, &n)) + return fail("query the window tree"); + for(i = 0; i < n; i++){ + if(kids[i] == client) + above = 1; + else if(XGetWindowAttributes(dpy, kids[i], &wa) && + wa.override_redirect && wa.map_state == IsViewable) + break; + } + XFree(kids); + if(i < n) + return above || fail("popup is stacked below the client"); + if(leftms(deadline) == 0) + return fail("popup did not appear"); + pump(dpy, 20); + } +} + static int testnothing(Display *dpy, XIM im, Window win) { @@ -628,6 +663,7 @@ testnothing(Display *dpy, XIM im, Window win) } pump(dpy, 100); if(!sendkey(dpy, ic, win, XK_r, 0, commit, sizeof commit) || + !popupabove(dpy, win) || !sendkey(dpy, ic, win, XK_k, 0, commit, sizeof commit) || !sendkey(dpy, ic, win, XK_Return, 0, commit, sizeof commit)){ XDestroyIC(ic); diff --git a/win.c b/win.c index ed7d6ec..f0c57cb 100644 --- a/win.c +++ b/win.c @@ -316,7 +316,7 @@ winshow(Drawcmd *dc) Area area; Popup p; int ax, ay, px, py, x, y; - u32int vals[4]; + u32int vals[5]; xcb_query_pointer_reply_t *ptr; xcb_query_pointer_cookie_t cookie; @@ -339,14 +339,16 @@ winshow(Drawcmd *dc) if(p.w <= 0 || p.h <= 0 || !resizebacking(p.w, p.h)) return 0; popupposition(&dc->caret, px, py, &area, p.w, p.h, &x, &y); + /* Mapping does not restack: raise above windows opened since. */ vals[0] = x; vals[1] = y; vals[2] = p.w; vals[3] = p.h; + vals[4] = XCB_STACK_MODE_ABOVE; xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | - XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, - vals); + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | + XCB_CONFIG_WINDOW_STACK_MODE, vals); popupdraw(img, dc, &p); putimage(p.w, p.h); xcb_map_window(conn, win);