diff --git a/view.c b/view.c index 8948580d..5a8f6ac6 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,17 @@ 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 {