From b52ca0747c4f5da1cce587e289636433f6607909 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sun, 24 May 2026 19:41:14 +0200 Subject: [PATCH] WINGs: commit all mapped toplevels on every event loop flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- WINGs/wclient_wl.c | 16 ++++++++++++++++ WINGs/wevent_wl.c | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/WINGs/wclient_wl.c b/WINGs/wclient_wl.c index 565a63c..59a6d4b 100644 --- a/WINGs/wclient_wl.c +++ b/WINGs/wclient_wl.c @@ -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 */ /* ------------------------------------------------------------------ */ diff --git a/WINGs/wevent_wl.c b/WINGs/wevent_wl.c index 490a105..c4e5c18 100644 --- a/WINGs/wevent_wl.c +++ b/WINGs/wevent_wl.c @@ -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)