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.
This commit is contained in:
lkn 2026-06-07 11:24:00 +02:00
parent 69903b23a7
commit e063d8fa87
4 changed files with 51 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)