WINGs/wayland: commit correct topLevel view after child widget repaint

The upward compositing walk in render_wl_pixmap_copy, render_wl_fill_rect,
and wl_draw_string traverses from the repainted widget to the root view.
Previously, the commit at the end targeted the root view or searched its
direct children for a topLevel — this found the main window instead of
the dialog containing the widget that actually changed.

Fix: track the topLevel ancestor during the upward walk and commit that
specific view. This ensures dialog widgets (buttons, lists) have their
visual feedback rendered to the correct scene_buf.
This commit is contained in:
lkn 2026-06-21 17:55:35 +02:00
parent c9f0fc8370
commit a3413a8402
2 changed files with 22 additions and 22 deletions

View File

@ -190,7 +190,10 @@ wl_draw_string(void *sctx, void *handle, WMDrawable d,
&& (unsigned long)d < 0x30000000) {
W_View *v = W_GetViewForWindow((WNativeWindow)(unsigned long)d);
if (v && !v->flags.alreadyDead) {
W_View *topLevel = NULL;
while (v && v->parent && !v->flags.alreadyDead) {
if (v->flags.topLevel)
topLevel = v;
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)
@ -200,8 +203,10 @@ wl_draw_string(void *sctx, void *handle, WMDrawable d,
v->size.width, v->size.height);
v = v->parent;
}
if (v && !v->flags.alreadyDead && W_ViewCommitBackingFn)
W_ViewCommitBackingFn((unsigned long)v->window);
if (v && v->flags.topLevel)
topLevel = v;
if (topLevel && !topLevel->flags.alreadyDead && W_ViewCommitBackingFn)
W_ViewCommitBackingFn((unsigned long)topLevel->window);
}
}
}

View File

@ -74,7 +74,10 @@ render_wl_pixmap_copy(void *rctx, WMDrawable src, WMDrawable dst,
if ((unsigned long)dst >= 0x10000000 && (unsigned long)dst < 0x30000000) {
W_View *view = W_GetViewForWindow((WNativeWindow)(unsigned long)dst);
if (view && view->flags.alreadyDead) return;
W_View *topLevel = NULL;
while (view && view->parent && !view->flags.alreadyDead) {
if (view->flags.topLevel)
topLevel = view;
pixman_image_t *vs = (pixman_image_t *)W_GetViewBacking(view->window);
pixman_image_t *pd = (pixman_image_t *)W_GetViewBacking(view->parent->window);
if (vs && pd) {
@ -85,24 +88,11 @@ render_wl_pixmap_copy(void *rctx, WMDrawable src, WMDrawable dst,
}
view = view->parent;
}
/* Commit the toplevel surface. If the cascade walked up to a
* root view that has no client backing, commit the nearest
* topLevel child instead. */
if (view && !view->flags.alreadyDead && W_ViewCommitBackingFn) {
/* Check if the topmost parent is committable */
if (view->flags.topLevel) {
W_ViewCommitBackingFn((unsigned long)view->window);
} else {
/* Walk down to find a topLevel child that has a backing */
W_View *top = view->childrenList;
while (top) {
if (top->flags.topLevel && top->flags.realized) {
W_ViewCommitBackingFn((unsigned long)top->window);
break;
}
top = top->nextSister;
}
}
/* Also check the final view (root might be topLevel) */
if (view && view->flags.topLevel)
topLevel = view;
if (topLevel && !topLevel->flags.alreadyDead && W_ViewCommitBackingFn) {
W_ViewCommitBackingFn((unsigned long)topLevel->window);
}
}
}
@ -182,7 +172,10 @@ render_wl_fill_rect(void *rctx, WMDrawable d, WMColor *color,
&& (unsigned long)d < 0x30000000) {
W_View *v = W_GetViewForWindow((WNativeWindow)(unsigned long)d);
if (v && !v->flags.alreadyDead) {
W_View *topLevel = NULL;
while (v && v->parent && !v->flags.alreadyDead) {
if (v->flags.topLevel)
topLevel = v;
pixman_image_t *vs = W_GetViewBacking(v->window);
pixman_image_t *pd = W_GetViewBacking(v->parent->window);
if (vs && pd)
@ -192,8 +185,10 @@ render_wl_fill_rect(void *rctx, WMDrawable d, WMColor *color,
v->size.width, v->size.height);
v = v->parent;
}
if (v && !v->flags.alreadyDead && W_ViewCommitBackingFn)
W_ViewCommitBackingFn((unsigned long)v->window);
if (v && v->flags.topLevel)
topLevel = v;
if (topLevel && !topLevel->flags.alreadyDead && W_ViewCommitBackingFn)
W_ViewCommitBackingFn((unsigned long)topLevel->window);
}
}
}