diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index a59aea3..3ba7560 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -4076,6 +4076,7 @@ frame_buf_button_at(int px, int py) wl_list_for_each(fb, &wl_state.frame_list, link) { if (!fb->parent_id) continue; /* top-level root */ if (!fb->scene_buf) continue; /* no scene node */ + if (!fb->scene_buf->node.enabled) continue; /* hidden */ /* Buttons are small children of the titlebar with enabled scene_bufs. * Skip large nodes (titlebars, resizebars) by size threshold. */ if (px < fb->x || px >= fb->x + fb->width) continue; @@ -4270,9 +4271,11 @@ wl_frame_configure(WNativeWindow win, int x, int y, int width, int height) fb->height = height; fb->base.width = width; fb->base.height = height; - /* Detach old buffer from scene so it picks up new dimensions on next commit */ + /* Notify scene graph of new size — required for hit-testing. + * wlroots caches buffer dimensions; without this, clicks beyond + * the old size would miss this scene_buf. */ if (fb->scene_buf) - wlr_scene_buffer_set_buffer(fb->scene_buf, NULL); + wlr_scene_buffer_set_dest_size(fb->scene_buf, width, height); } /* Update absolute position tracking for children (used by hit-testing) */ @@ -4347,6 +4350,9 @@ wl_frame_paint(struct WFrameWindow *fwin) tb_fb->base.width = tb_w; tb_fb->base.height = tb_h; tb_img = tb_fb->image; + /* Notify scene graph so hit-testing covers the new size. */ + if (tb_fb->scene_buf) + wlr_scene_buffer_set_dest_size(tb_fb->scene_buf, tb_w, tb_h); } WTexture *tex = fwin->title_texture[state]; @@ -5147,8 +5153,16 @@ handle_xdg_activation_request(struct wl_listener *listener, void *data) if (desc && desc->parent_type == WCLASS_WINDOW) { WWindow *wwin = (WWindow *)desc->parent; wSetFocusTo(wScreenWithNumber(0), wwin); - if (view->scene_node) + /* Raise the entire window assembly (frame tree), not just the + * client scene_node — raising the client alone would push it + * above the titlebar and hide decorations. */ + if (view->frame_id) { + struct wl_frame_buf *fb = frame_buf_find(view->frame_id); + if (fb && fb->tree) + wlr_scene_node_raise_to_top(&fb->tree->node); + } else if (view->scene_node) { wlr_scene_node_raise_to_top(&view->scene_node->node); + } /* Move to front of toplevel list (Z-order). */ wl_list_remove(&view->link); wl_list_insert(wl_state.toplevel_list.prev, &view->link); @@ -6395,7 +6409,6 @@ wl_window_map(WNativeWindow win) struct wl_toplevel_view *v = wl_find_view_by_id(win); if (v && v->scene_node) { wlr_scene_node_set_enabled(&v->scene_node->node, true); - wlr_scene_node_raise_to_top(&v->scene_node->node); return; } if (v) @@ -6581,8 +6594,9 @@ static void wl_window_resize(WNativeWindow win, int w, int h) fb->height = h; fb->base.width = w; fb->base.height = h; + /* Update scene graph's cached buffer size for hit-testing. */ if (fb->scene_buf) - wlr_scene_buffer_set_buffer(fb->scene_buf, NULL); + wlr_scene_buffer_set_dest_size(fb->scene_buf, w, h); } } static void wl_window_set_border(WNativeWindow win, unsigned long pixel) @@ -6856,8 +6870,20 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y) existing->rel_y = y; existing->x = parent_fb->x + x; existing->y = parent_fb->y + y; - if (existing->scene_buf) - wlr_scene_node_set_position(&existing->scene_buf->node, x, y); + if (existing->scene_buf) { + /* Ensure it's under the parent frame's tree, then position + * at relative offset within the tree. */ + if (parent_fb->tree && + existing->scene_buf->node.parent != parent_fb->tree) { + wlr_scene_node_reparent(&existing->scene_buf->node, + parent_fb->tree); + } + if (parent_fb->tree) + wlr_scene_node_set_position(&existing->scene_buf->node, x, y); + else + wlr_scene_node_set_position(&existing->scene_buf->node, + existing->x, existing->y); + } return; } @@ -6888,13 +6914,20 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y) fb->height = h; if (wl_state.scene) { - /* WINGs dialog box: place in WL_LAYER_FLOATING so it renders - * above normal windows but below menus and dock. */ - struct wlr_scene_tree *_wp = wl_state.level_trees[WL_LAYER_FLOATING] - ? wl_state.level_trees[WL_LAYER_FLOATING] : &wl_state.scene->tree; + /* Place the WINGs content under the parent frame's tree so it + * moves with the WM-managed dialog decorations. */ + struct wlr_scene_tree *_wp = parent_fb->tree + ? parent_fb->tree + : (wl_state.level_trees[WL_LAYER_FLOATING] + ? wl_state.level_trees[WL_LAYER_FLOATING] + : &wl_state.scene->tree); fb->scene_buf = wlr_scene_buffer_create(_wp, &fb->base); if (fb->scene_buf) { - wlr_scene_node_set_position(&fb->scene_buf->node, fb->x, fb->y); + /* If under the frame tree, use relative coords; otherwise absolute. */ + if (parent_fb->tree) + wlr_scene_node_set_position(&fb->scene_buf->node, x, y); + else + wlr_scene_node_set_position(&fb->scene_buf->node, fb->x, fb->y); wlr_scene_node_set_enabled(&fb->scene_buf->node, false); } }