WINGs: commit all mapped toplevels on every event loop flush

Widgets that paint directly to their view backing (fill_rect,
draw_line, W_DrawRelief, W_PaintText) without going through the
DOUBLE_BUFFER pixmap_copy path never triggered a surface commit.
The painted content stayed in the pixman buffer but was never
submitted to the compositor — making popup menus, radio buttons,
text fields, sliders, and other controls appear empty/stale.

Fix: W_WLClientCommitAllToplevels() iterates all mapped toplevels
and commits their surfaces. Called from wl_flush() which runs once
per event loop iteration (in waitForEvent). This ensures any
direct-paint operations become visible on the next frame regardless
of which render path was used.
This commit is contained in:
Window Maker 2026-05-24 19:41:14 +02:00
parent db915281e0
commit b52ca0747c
2 changed files with 22 additions and 0 deletions

View File

@ -584,6 +584,22 @@ W_WLClientBeginMove(WNativeWindow window)
return True;
}
/* ------------------------------------------------------------------ */
void
W_WLClientCommitAllToplevels(void)
{
for (int i = 0; i < WLC_TOPTABLE_SIZE; i++) {
WLClientToplevel *top = wlc_toptable[i].top;
if (top && top->mapped && top->configured && top->buf && top->buf->wl_buf) {
wl_surface_attach(top->surface, top->buf->wl_buf, 0, 0);
wl_surface_damage_buffer(top->surface, 0, 0,
top->buf->width, top->buf->height);
wl_surface_commit(top->surface);
}
}
}
/* ------------------------------------------------------------------ */
/* Input: wl_pointer / wl_keyboard listeners */
/* ------------------------------------------------------------------ */

View File

@ -157,11 +157,17 @@ wl_check_typed_window(void *ectx, WNativeWindow w, int type, WMEvent *ev)
return False;
}
extern void W_WLClientCommitAllToplevels(void);
static void
wl_flush(void *ectx, Bool discard)
{
WLEventCtx *ctx = ectx;
(void)discard;
/* Commit any toplevel surfaces that may have been painted into
* since the last flush (direct fill_rect, draw_line, etc. don't
* trigger individual commits). */
W_WLClientCommitAllToplevels();
/* Pump the wlroots event loop so pointer/key events arrive in our queue.
* This is called from waitForEvent/WMMaskEvent when the queue is empty. */
if (ctx->dispatch_fn)