wayland: use xdg geometry instead of surface size for CSD clients
Firefox and other CSD clients include invisible shadow borders in their surface buffer. Use xdg_surface->geometry (the client-declared content rect) for: - reporting client width/height to the WM frame - sizing the frame on commit - offsetting the scene node so shadows are outside the frame bounds Falls back to surface->current.width/height when geometry is unset.
This commit is contained in:
parent
e0edd782d8
commit
1ee10d37f5
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue