diff --git a/src/backend/wayland/wl_client.c b/src/backend/wayland/wl_client.c index 8b49aa6..38b4769 100644 --- a/src/backend/wayland/wl_client.c +++ b/src/backend/wayland/wl_client.c @@ -40,8 +40,14 @@ wl_window_get_client_attrs(WNativeWindow win, WClientAttributes *out) } } else if (v && v->xdg_surface && v->xdg_surface->surface) { out->map_state = WCLIENT_VIEWABLE; - out->width = v->xdg_surface->surface->current.width; - out->height = v->xdg_surface->surface->current.height; + struct wlr_box geo = v->xdg_surface->geometry; + if (geo.width > 0 && geo.height > 0) { + out->width = geo.width; + out->height = geo.height; + } else { + out->width = v->xdg_surface->surface->current.width; + out->height = v->xdg_surface->surface->current.height; + } } else { out->map_state = WCLIENT_UNMAPPED; } diff --git a/src/backend/wayland/wl_xdg.c b/src/backend/wayland/wl_xdg.c index b38ecac..f42f14a 100644 --- a/src/backend/wayland/wl_xdg.c +++ b/src/backend/wayland/wl_xdg.c @@ -319,17 +319,21 @@ handle_toplevel_map(struct wl_listener *listener, void *data) view_attach_scene_destroy_listener(view); /* Deferred reparent: move client surface under its * frame grouping tree now that the node exists. */ + struct wlr_box geo = view->xdg_surface->geometry; if (view->frame_id) { struct wl_frame_buf *_pfb = frame_buf_find(view->frame_id); if (_pfb && _pfb->tree) wlr_scene_node_reparent(&view->scene_node->node, _pfb->tree); - /* Position at relative offset within frame tree */ + /* Position at relative offset within frame tree, + * adjusted for CSD geometry offset (shadows). */ wlr_scene_node_set_position(&view->scene_node->node, - view->frame_rel_x, view->frame_rel_y); + view->frame_rel_x - geo.x, + view->frame_rel_y - geo.y); } else { wlr_scene_node_set_position(&view->scene_node->node, - view->x, view->y); + view->x - geo.x, + view->y - geo.y); } } } @@ -558,17 +562,21 @@ handle_toplevel_commit(struct wl_listener *listener, void *data) if (view->scene_node && view->frame_id) { struct wl_frame_buf *ffb = frame_buf_find(view->frame_id); if (ffb && ffb->tree && view->scene_node->node.parent != ffb->tree) { + struct wlr_box geo = view->xdg_surface->geometry; wlr_scene_node_reparent(&view->scene_node->node, ffb->tree); wlr_scene_node_set_position(&view->scene_node->node, - view->frame_rel_x, view->frame_rel_y); + view->frame_rel_x - geo.x, + view->frame_rel_y - geo.y); } } /* When the client commits a buffer at a new size (e.g. after interactive - * resize), update the WM frame to match. */ + * resize), update the WM frame to match. Use xdg geometry (excludes + * CSD shadows) when available, fall back to surface size. */ if (view->xdg_surface && view->xdg_surface->surface && view->frame_id) { - int cw = view->xdg_surface->surface->current.width; - int ch = view->xdg_surface->surface->current.height; + struct wlr_box geo = view->xdg_surface->geometry; + int cw = (geo.width > 0) ? geo.width : view->xdg_surface->surface->current.width; + int ch = (geo.height > 0) ? geo.height : view->xdg_surface->surface->current.height; if (cw > 0 && ch > 0) { WObjDescriptor *desc = wm_backend->context_find(view->id, WM_CTX_CLIENT_WIN); if (desc && desc->parent_type == WCLASS_WINDOW) {