From 560e9ff3efd2be961693680279cc2d335b08d6e1 Mon Sep 17 00:00:00 2001 From: Jonathan GUILLOT Date: Mon, 5 Feb 2024 17:35:51 +0100 Subject: [PATCH 1/2] view: unconditionally center views in output layout Whatever type or dimensions of a view, position it at center of the output layout. Then, if it is a primary view or if it extends the output layout, send request to maximize it. The client may or may not change the view dimensions after that. If not, e.g. weston-flower, the view will be kept displayed at center instead of to left. If so, the view will expand from center to fill the whole output layout. In order to update the view position, XDG shell surface commit is now handled to check for dimension change. --- view.c | 43 ++++++++++++------------------------------- view.h | 1 + xdg_shell.c | 19 +++++++++++++++++++ xdg_shell.h | 1 + 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/view.c b/view.c index 8948580d..a8548df7 100644 --- a/view.c +++ b/view.c @@ -52,36 +52,11 @@ view_activate(struct cg_view *view, bool activate) view->impl->activate(view, activate); } -static bool +static inline bool view_extends_output_layout(struct cg_view *view, struct wlr_box *layout_box) { - int width, height; - view->impl->get_geometry(view, &width, &height); - - return (layout_box->height < height || layout_box->width < width); -} - -static void -view_maximize(struct cg_view *view, struct wlr_box *layout_box) -{ - view->lx = layout_box->x; - view->ly = layout_box->y; - - wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly); - - view->impl->maximize(view, layout_box->width, layout_box->height); -} - -static void -view_center(struct cg_view *view, struct wlr_box *layout_box) -{ - int width, height; - view->impl->get_geometry(view, &width, &height); - - view->lx = (layout_box->width - width) / 2; - view->ly = (layout_box->height - height) / 2; - - wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly); + // View width and height are expected to be set before calling this function + return (layout_box->height < view->height || layout_box->width < view->width); } void @@ -90,10 +65,16 @@ view_position(struct cg_view *view) struct wlr_box layout_box; wlr_output_layout_get_box(view->server->output_layout, NULL, &layout_box); + view->impl->get_geometry(view, &view->width, &view->height); + + // If view dimensions are not the same as output layout ones, it will be centered first + view->lx = layout_box.x + (layout_box.width - view->width) / 2; + view->ly = layout_box.y + (layout_box.height - view->height) / 2; + + wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly); + if (view_is_primary(view) || view_extends_output_layout(view, &layout_box)) { - view_maximize(view, &layout_box); - } else { - view_center(view, &layout_box); + view->impl->maximize(view, layout_box.width, layout_box.height); } } diff --git a/view.h b/view.h index 9b2ab75d..2fc8d08d 100644 --- a/view.h +++ b/view.h @@ -29,6 +29,7 @@ struct cg_view { /* The view has a position in layout coordinates. */ int lx, ly; + int width, height; enum cg_view_type type; const struct cg_view_impl *impl; diff --git a/xdg_shell.c b/xdg_shell.c index 046dbd8a..41179dd6 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -183,15 +183,34 @@ handle_xdg_shell_surface_unmap(struct wl_listener *listener, void *data) struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, unmap); struct cg_view *view = &xdg_shell_view->view; + wl_list_remove(&xdg_shell_view->commit.link); + view_unmap(view); } +static void +handle_xdg_shell_surface_commit(struct wl_listener *listener, void *data) +{ + struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, commit); + struct cg_view *view = &xdg_shell_view->view; + + // Check if view dimensions have changed + int width, height; + get_geometry(view, &width, &height); + if (width != view->width || height != view->height) { + view_position(view); + } +} + static void handle_xdg_shell_surface_map(struct wl_listener *listener, void *data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, map); struct cg_view *view = &xdg_shell_view->view; + xdg_shell_view->commit.notify = handle_xdg_shell_surface_commit; + wl_signal_add(&xdg_shell_view->xdg_toplevel->base->surface->events.commit, &xdg_shell_view->commit); + view_map(view, xdg_shell_view->xdg_toplevel->base->surface); } diff --git a/xdg_shell.h b/xdg_shell.h index 2fd506a7..6b4160de 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -15,6 +15,7 @@ struct cg_xdg_shell_view { struct wl_listener unmap; struct wl_listener map; struct wl_listener request_fullscreen; + struct wl_listener commit; }; struct cg_xdg_decoration { From 44fb937f8eb4ef1639c3cc15a19a1dfc4cb17eaa Mon Sep 17 00:00:00 2001 From: Jonathan GUILLOT Date: Mon, 15 Jan 2024 15:50:46 +0100 Subject: [PATCH 2/2] view: adjust position according to declared top left corner --- view.c | 10 +++++++--- view.h | 2 +- xdg_shell.c | 14 +++++--------- xwayland.c | 14 +++++++++----- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/view.c b/view.c index a8548df7..f325b2ae 100644 --- a/view.c +++ b/view.c @@ -65,11 +65,15 @@ view_position(struct cg_view *view) struct wlr_box layout_box; wlr_output_layout_get_box(view->server->output_layout, NULL, &layout_box); - view->impl->get_geometry(view, &view->width, &view->height); + struct wlr_box view_box; + view->impl->get_geometry(view, &view_box); // If view dimensions are not the same as output layout ones, it will be centered first - view->lx = layout_box.x + (layout_box.width - view->width) / 2; - view->ly = layout_box.y + (layout_box.height - view->height) / 2; + // Do not forget to adjust position according to top left corner declared in view geometry + view->lx = layout_box.x + (layout_box.width - view_box.width) / 2 - view_box.x; + view->ly = layout_box.y + (layout_box.height - view_box.height) / 2 - view_box.y; + view->width = view_box.width; + view->height = view_box.height; wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly); diff --git a/view.h b/view.h index 2fc8d08d..bffde48e 100644 --- a/view.h +++ b/view.h @@ -37,7 +37,7 @@ struct cg_view { struct cg_view_impl { char *(*get_title)(struct cg_view *view); - void (*get_geometry)(struct cg_view *view, int *width_out, int *height_out); + void (*get_geometry)(struct cg_view *view, struct wlr_box *view_box); bool (*is_primary)(struct cg_view *view); bool (*is_transient_for)(struct cg_view *child, struct cg_view *parent); void (*activate)(struct cg_view *view, bool activate); diff --git a/xdg_shell.c b/xdg_shell.c index 41179dd6..ef549092 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -101,14 +101,10 @@ get_title(struct cg_view *view) } static void -get_geometry(struct cg_view *view, int *width_out, int *height_out) +get_geometry(struct cg_view *view, struct wlr_box *view_box) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - struct wlr_box geom; - - wlr_xdg_surface_get_geometry(xdg_shell_view->xdg_toplevel->base, &geom); - *width_out = geom.width; - *height_out = geom.height; + wlr_xdg_surface_get_geometry(xdg_shell_view->xdg_toplevel->base, view_box); } static bool @@ -195,9 +191,9 @@ handle_xdg_shell_surface_commit(struct wl_listener *listener, void *data) struct cg_view *view = &xdg_shell_view->view; // Check if view dimensions have changed - int width, height; - get_geometry(view, &width, &height); - if (width != view->width || height != view->height) { + struct wlr_box view_box; + get_geometry(view, &view_box); + if (view_box.width != view->width || view_box.height != view->height) { view_position(view); } } diff --git a/xwayland.c b/xwayland.c index de814080..f3ea6c5b 100644 --- a/xwayland.c +++ b/xwayland.c @@ -38,18 +38,22 @@ get_title(struct cg_view *view) } static void -get_geometry(struct cg_view *view, int *width_out, int *height_out) +get_geometry(struct cg_view *view, struct wlr_box *view_box) { struct cg_xwayland_view *xwayland_view = xwayland_view_from_view(view); struct wlr_xwayland_surface *xsurface = xwayland_view->xwayland_surface; + + view_box->x = 0; + view_box->y = 0; + if (xsurface->surface == NULL) { - *width_out = 0; - *height_out = 0; + view_box->width = 0; + view_box->height = 0; return; } - *width_out = xsurface->surface->current.width; - *height_out = xsurface->surface->current.height; + view_box->width = xwayland_view->xwayland_surface->surface->current.width; + view_box->height = xwayland_view->xwayland_surface->surface->current.height; } static bool