diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index f0d0b3ce2..543bd2cc0 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -88,9 +88,16 @@ struct sway_container { double saved_x, saved_y; double saved_width, saved_height; + // These are in layout coordinates. double content_x, content_y; int content_width, content_height; + // In most cases this is the same as the content x and y, but if the view + // refuses to resize to the content dimensions then it can be smaller. + // These are in layout coordinates. + double surface_x, surface_y; + double surface_width, surface_height; + enum sway_fullscreen_mode fullscreen_mode; enum sway_container_border border; diff --git a/sway/desktop/render.c b/sway/desktop/render.c index fa27500ec..9102dc344 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -204,9 +204,9 @@ static void render_view_toplevels(struct sway_view *view, .alpha = alpha, }; // Render all toplevels without descending into popups - double ox = view->container->current.content_x - + double ox = view->container->surface_x - output->wlr_output->lx - view->geometry.x; - double oy = view->container->current.content_y - + double oy = view->container->surface_y - output->wlr_output->ly - view->geometry.y; output_surface_for_each_surface(output, view->surface, ox, oy, render_surface_iterator, &data); @@ -240,9 +240,9 @@ static void render_saved_view(struct sway_view *view, return; } struct wlr_box box = { - .x = view->container->current.content_x - output->wlr_output->lx - + .x = view->container->surface_x - output->wlr_output->lx - view->saved_geometry.x, - .y = view->container->current.content_y - output->wlr_output->ly - + .y = view->container->surface_y - output->wlr_output->ly - view->saved_geometry.y, .width = view->saved_buffer_width, .height = view->saved_buffer_height, @@ -1004,7 +1004,6 @@ void output_render(struct sway_output *output, struct timespec *when, wlr_renderer_clear(renderer, clear_color); } - // TODO: handle views smaller than the output if (fullscreen_con->view) { if (fullscreen_con->view->saved_buffer) { render_saved_view(fullscreen_con->view, output, damage, 1.0f); diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 9155f0a17..e0c3a5d1e 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -249,6 +249,26 @@ static void apply_container_state(struct sway_container *container, desktop_damage_box(&box); } + // If the view hasn't responded to the configure, center it within + // the container. This is important for fullscreen views which + // refuse to resize to the size of the output. + if (view && view->surface) { + if (view->surface->current.width < container->width) { + container->surface_x = container->content_x + + (container->content_width - view->surface->current.width) / 2; + } else { + container->surface_x = container->content_x; + } + if (view->surface->current.height < container->height) { + container->surface_y = container->content_y + + (container->content_height - view->surface->current.height) / 2; + } else { + container->surface_y = container->content_y; + } + container->surface_width = view->surface->current.width; + container->surface_height = view->surface->current.height; + } + if (!container->node.destroying) { container_discover_outputs(container); } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 007b0a94d..b5dcfb0fb 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -291,10 +291,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); struct sway_container *con = view->container; - if ((new_geo.width != con->content_width || - new_geo.height != con->content_height) && - container_is_floating(con)) { - // A floating view has unexpectedly sent a new size + if ((new_geo.width != con->surface_width || + new_geo.height != con->surface_height)) { + // The view has unexpectedly sent a new size desktop_damage_view(view); view_update_size(view, new_geo.width, new_geo.height); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 386e350ea..a7ea163f5 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -284,10 +284,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo); struct sway_container *con = view->container; - if ((new_geo.width != con->content_width || - new_geo.height != con->content_height) && - container_is_floating(con)) { - // A floating view has unexpectedly sent a new size + if ((new_geo.width != con->surface_width || + new_geo.height != con->surface_height)) { + // The view has unexpectedly sent a new size desktop_damage_view(view); view_update_size(view, new_geo.width, new_geo.height); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index d9e1b0a91..e0d307e86 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -333,10 +333,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { get_geometry(view, &new_geo); struct sway_container *con = view->container; - if ((new_geo.width != con->content_width || - new_geo.height != con->content_height) && - container_is_floating(con)) { - // A floating view has unexpectedly sent a new size + if ((new_geo.width != con->surface_width || + new_geo.height != con->surface_height)) { + // The view has unexpectedly sent a new size // eg. The Firefox "Save As" dialog when downloading a file desktop_damage_view(view); view_update_size(view, new_geo.width, new_geo.height); diff --git a/sway/tree/container.c b/sway/tree/container.c index d8ad3bc04..1cf5c8e75 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -169,8 +169,8 @@ static struct sway_container *surface_at_view(struct sway_container *con, double return NULL; } struct sway_view *view = con->view; - double view_sx = lx - con->content_x + view->geometry.x; - double view_sy = ly - con->content_y + view->geometry.y; + double view_sx = lx - con->surface_x + view->geometry.x; + double view_sy = ly - con->surface_y + view->geometry.y; double _sx, _sy; struct wlr_surface *_surface = NULL; diff --git a/sway/tree/view.c b/sway/tree/view.c index 561c6ef1f..9ccb2a31c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -673,15 +673,22 @@ void view_unmap(struct sway_view *view) { } void view_update_size(struct sway_view *view, int width, int height) { - if (!sway_assert(container_is_floating(view->container), - "Expected a floating container")) { - return; + struct sway_container *con = view->container; + + if (container_is_floating(con)) { + con->content_width = width; + con->content_height = height; + con->current.content_width = width; + con->current.content_height = height; + container_set_geometry_from_content(con); + } else { + con->surface_x = con->content_x + (con->content_width - width) / 2; + con->surface_y = con->content_y + (con->content_height - height) / 2; + con->surface_x = fmax(con->surface_x, con->content_x); + con->surface_y = fmax(con->surface_y, con->content_y); } - view->container->content_width = width; - view->container->content_height = height; - view->container->current.content_width = width; - view->container->current.content_height = height; - container_set_geometry_from_content(view->container); + con->surface_width = width; + con->surface_width = height; } static const struct sway_view_child_impl subsurface_impl;