wayland: fix dockapp rendering in dock tiles (WIP)

- Reparent owner's client_win surface into dock tile frame_buf tree
- Raise client scene_node above tile background
- Don't disable scene_node on unmap if reparented into a frame
- Handle OR views and XWayland child windows in client_reparent
- Diagnostics still in place
This commit is contained in:
lkn 2026-06-28 00:59:34 +02:00
parent f9f65613ba
commit 14db9aecb3
3 changed files with 54 additions and 5 deletions

View File

@ -86,6 +86,15 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y)
wlr_scene_node_reparent(&v->scene_node->node, parent_fb->tree); wlr_scene_node_reparent(&v->scene_node->node, parent_fb->tree);
/* Position at relative offset within the tree */ /* Position at relative offset within the tree */
wlr_scene_node_set_position(&v->scene_node->node, x, y); wlr_scene_node_set_position(&v->scene_node->node, x, y);
/* Raise above frame decoration (icon tile background) */
wlr_scene_node_raise_to_top(&v->scene_node->node);
wwarning("wl_client_reparent: view 0x%lx scene_node reparented to frame 0x%lx tree=%p at (%d,%d) enabled=%d",
(unsigned long)client, (unsigned long)new_parent,
(void*)parent_fb->tree, x, y,
v->scene_node->node.enabled);
} else {
wwarning("wl_client_reparent: view 0x%lx has NO scene_node, frame 0x%lx",
(unsigned long)client, (unsigned long)new_parent);
} }
} }
return; return;
@ -108,6 +117,35 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y)
} }
} }
/* XWayland child window (e.g. dockapp icon_window 0x400011) that has
* no separate wlr_xwayland_surface. XWayland composites it into the
* parent surface. Find the parent toplevel whose children list
* contains this window ID and reparent it into the dock tile. */
if (client > 0 && client < 0x10000000) {
struct wl_frame_buf *parent_fb = frame_buf_find(new_parent);
if (parent_fb && parent_fb->tree) {
struct wl_toplevel_view *tv;
wl_list_for_each(tv, &wl_state.toplevel_list, link) {
if (!tv->xw_surface || !tv->scene_node)
continue;
/* Check if 'client' is a child of this surface */
struct wlr_xwayland_surface *child;
wl_list_for_each(child, &tv->xw_surface->children, parent_link) {
if (child->window_id == (xcb_window_t)client) {
wlr_scene_node_reparent(&tv->scene_node->node, parent_fb->tree);
wlr_scene_node_set_position(&tv->scene_node->node, x, y);
tv->frame_id = new_parent;
tv->frame_rel_x = x;
tv->frame_rel_y = y;
tv->x = parent_fb->x + x;
tv->y = parent_fb->y + y;
return;
}
}
}
}
}
/* Reparent to root = dialog teardown: destroy the child frame_buf */ /* Reparent to root = dialog teardown: destroy the child frame_buf */

View File

@ -166,7 +166,10 @@ wl_window_unmap(WNativeWindow win)
{ {
struct wl_toplevel_view *v = wl_find_view_by_id(win); struct wl_toplevel_view *v = wl_find_view_by_id(win);
if (v && v->scene_node) { if (v && v->scene_node) {
wlr_scene_node_set_enabled(&v->scene_node->node, false); /* Don't disable if reparented into a frame_buf (e.g. dockapp in
* dock tile) — the frame's tree controls visibility. */
if (!v->frame_id)
wlr_scene_node_set_enabled(&v->scene_node->node, false);
return; return;
} }
struct wl_frame_buf *fb = frame_buf_find(win); struct wl_frame_buf *fb = frame_buf_find(win);

View File

@ -811,10 +811,18 @@ static void set_dockapp_in_icon(WIcon *icon)
/* Set the icon border */ /* Set the icon border */
wm_backend->window_set_border_width((WNativeWindow)icon->icon_win, 0); wm_backend->window_set_border_width((WNativeWindow)icon->icon_win, 0);
/* Put the dock application in the icon */ /* Put the dock application in the icon.
wm_backend->client_reparent((WNativeWindow)icon->icon_win, icon->core->window, * On Wayland, the icon_win child window has no separate surface —
(wPreferences.icon_size - w) / 2, * XWayland composites it into the parent toplevel. Reparent the
(wPreferences.icon_size - h) / 2); * owner's main client_win instead so its surface appears in the tile. */
{
WNativeWindow reparent_win = (WNativeWindow)icon->icon_win;
if (icon->owner && icon->owner->client_win)
reparent_win = icon->owner->client_win;
wm_backend->client_reparent(reparent_win, icon->core->window,
(wPreferences.icon_size - w) / 2,
(wPreferences.icon_size - h) / 2);
}
/* Show it and save */ /* Show it and save */
wm_backend->window_map((WNativeWindow)icon->icon_win); wm_backend->window_map((WNativeWindow)icon->icon_win);