From e063d8fa87d44b9be77a14048c706f1e34dbc3cf Mon Sep 17 00:00:00 2001 From: lkn Date: Sun, 7 Jun 2026 11:24:00 +0200 Subject: [PATCH] WINGs Wayland: fix popup dropdown blank gray box and motion highlight rendering Three related fixes for WINGs popup menus on Wayland: 1. wl_client_toplevel_resize: update pending_w/h after resize (wclient_wl.c:545-546). Without this, the configure handler sees stale pending dimensions and creates a wrong-sized buffer, discarding the one containing the menu text. 2. Export wl_redisplay_depth (wview_wl.c:288) so render and font backends can detect when they are called from within a full redisplay cycle vs. from an event handler. 3. Add cascade+commit to render_wl_fill_rect (wrender_wl.c:162-183) and wl_draw_string (wfont_wl.c:183-208) when not inside a redisplay cycle. This makes motion-driven highlight changes (text color, background fill) immediately visible by compositing up the view tree and committing the toplevel wl_surface. --- WINGs/wclient_wl.c | 2 ++ WINGs/wfont_wl.c | 26 ++++++++++++++++++++++++++ WINGs/wrender_wl.c | 22 ++++++++++++++++++++++ WINGs/wview_wl.c | 2 +- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/WINGs/wclient_wl.c b/WINGs/wclient_wl.c index 6eccec9..508805d 100644 --- a/WINGs/wclient_wl.c +++ b/WINGs/wclient_wl.c @@ -542,6 +542,8 @@ wl_client_toplevel_resize(struct W_View *view, int width, int height) if (top->buf) wlclient_destroy_shm_buffer(top->buf); top->buf = nb; W_SetViewBacking(view->window, nb->image); + top->pending_w = width; + top->pending_h = height; } static void diff --git a/WINGs/wfont_wl.c b/WINGs/wfont_wl.c index af1ed3b..679432e 100644 --- a/WINGs/wfont_wl.c +++ b/WINGs/wfont_wl.c @@ -178,6 +178,32 @@ wl_draw_string(void *sctx, void *handle, WMDrawable d, blit_alpha_to_pixman(dst, buf, stride, pw, ph, x, y, r, g, b, a); wfree(buf); + + /* Outside a full redisplay cycle, propagate dirty region up the + * view tree and commit the toplevel so text changes become visible + * immediately (e.g. menu highlight text on pointer motion). */ + + extern int wl_redisplay_depth; + extern void (*W_ViewCommitBackingFn)(unsigned long id); + extern W_View *W_GetViewForWindow(WNativeWindow id); + if (wl_redisplay_depth == 0 && (unsigned long)d >= 0x10000000 + && (unsigned long)d < 0x30000000) { + W_View *v = W_GetViewForWindow((WNativeWindow)(unsigned long)d); + if (v && !v->flags.alreadyDead) { + while (v && v->parent && !v->flags.alreadyDead) { + pixman_image_t *vs = (pixman_image_t *)W_GetViewBacking(v->window); + pixman_image_t *pd = (pixman_image_t *)W_GetViewBacking(v->parent->window); + if (vs && pd) + pixman_image_composite32(PIXMAN_OP_OVER, vs, NULL, pd, + 0, 0, 0, 0, + v->pos.x, v->pos.y, + v->size.width, v->size.height); + v = v->parent; + } + if (v && !v->flags.alreadyDead && W_ViewCommitBackingFn) + W_ViewCommitBackingFn((unsigned long)v->window); + } + } } static void diff --git a/WINGs/wrender_wl.c b/WINGs/wrender_wl.c index ba33e72..a88d401 100644 --- a/WINGs/wrender_wl.c +++ b/WINGs/wrender_wl.c @@ -56,6 +56,7 @@ render_wl_pixmap_free(void *rctx, WMDrawable pm) extern W_View *W_GetViewForWindow(WNativeWindow id); extern void (*W_ViewCommitBackingFn)(unsigned long id); +extern int wl_redisplay_depth; static void render_wl_pixmap_copy(void *rctx, WMDrawable src, WMDrawable dst, @@ -158,6 +159,27 @@ render_wl_fill_rect(void *rctx, WMDrawable d, WMColor *color, pixman_color_t pc = wm_color_to_pixman(color); pixman_image_fill_rectangles(PIXMAN_OP_OVER, dst, &pc, 1, &(pixman_rectangle16_t){x, y, w, h}); + /* Outside a full redisplay cycle, propagate dirty region up the + * view tree and commit the toplevel so the change becomes visible + * immediately (e.g. menu highlight on pointer motion). */ + if (wl_redisplay_depth == 0 && (unsigned long)d >= 0x10000000 + && (unsigned long)d < 0x30000000) { + W_View *v = W_GetViewForWindow((WNativeWindow)(unsigned long)d); + if (v && !v->flags.alreadyDead) { + while (v && v->parent && !v->flags.alreadyDead) { + pixman_image_t *vs = W_GetViewBacking(v->window); + pixman_image_t *pd = W_GetViewBacking(v->parent->window); + if (vs && pd) + pixman_image_composite32(PIXMAN_OP_OVER, vs, NULL, pd, + 0, 0, 0, 0, + v->pos.x, v->pos.y, + v->size.width, v->size.height); + v = v->parent; + } + if (v && !v->flags.alreadyDead && W_ViewCommitBackingFn) + W_ViewCommitBackingFn((unsigned long)v->window); + } + } } static void diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index 133c5db..705564e 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -285,7 +285,7 @@ static void wl_lower(void *vctx, W_View *view) static void wl_map_subviews(void *vctx, W_View *view); -static int wl_redisplay_depth = 0; +int wl_redisplay_depth = 0; int W_WL_Realizing = 0; static void wl_map(void *vctx, W_View *view)