aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2019-01-28 16:00:34 +1000
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-01-28 01:17:21 -0500
commit0a9ff774ad77d5c650c03c0ac3501983f3cb0d19 (patch)
tree08cb652bb05cc7003b30f93f78d62f84e965fe8f
parentMerge pull request #3423 from RyanDwyer/fullscreen-global (diff)
downloadsway-0a9ff774ad77d5c650c03c0ac3501983f3cb0d19.tar.gz
sway-0a9ff774ad77d5c650c03c0ac3501983f3cb0d19.tar.zst
sway-0a9ff774ad77d5c650c03c0ac3501983f3cb0d19.zip
Center surface inside container when it's too small
The goal here is to center fullscreen views when they are both too small for the output and refuse to resize to the output's dimensions. It has the side effect of also centering the view when it's too small for its container. Example clients that have this behaviour are emersion's hello-wayland and weston. It works by introducing surface_{x,y,width,height} properties to the container struct. The x and y represent layout-local coordinates where the surface will be rendered. The width and height are only used to track the surface's previous dimensions so we can detect when the client has resized it and recenter and apply damage accordingly. The new surface properties are calculated when a transaction is applied, as well as when a view resizes itself unexpectedly. The latter is done in view_update_size. This function was previously restricted to views which are floating, but can now be called for any views. For views which refuse to resize *smaller* than a particular size, such as gnome-calculator, the surface is still anchored to the top left as per the current behaviour.
-rw-r--r--include/sway/tree/container.h7
-rw-r--r--sway/desktop/render.c9
-rw-r--r--sway/desktop/transaction.c20
-rw-r--r--sway/desktop/xdg_shell.c7
-rw-r--r--sway/desktop/xdg_shell_v6.c7
-rw-r--r--sway/desktop/xwayland.c7
-rw-r--r--sway/tree/container.c4
-rw-r--r--sway/tree/view.c23
8 files changed, 57 insertions, 27 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index f0d0b3ce..543bd2cc 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -88,9 +88,16 @@ struct sway_container {
88 double saved_x, saved_y; 88 double saved_x, saved_y;
89 double saved_width, saved_height; 89 double saved_width, saved_height;
90 90
91 // These are in layout coordinates.
91 double content_x, content_y; 92 double content_x, content_y;
92 int content_width, content_height; 93 int content_width, content_height;
93 94
95 // In most cases this is the same as the content x and y, but if the view
96 // refuses to resize to the content dimensions then it can be smaller.
97 // These are in layout coordinates.
98 double surface_x, surface_y;
99 double surface_width, surface_height;
100
94 enum sway_fullscreen_mode fullscreen_mode; 101 enum sway_fullscreen_mode fullscreen_mode;
95 102
96 enum sway_container_border border; 103 enum sway_container_border border;
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index fa27500e..9102dc34 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -204,9 +204,9 @@ static void render_view_toplevels(struct sway_view *view,
204 .alpha = alpha, 204 .alpha = alpha,
205 }; 205 };
206 // Render all toplevels without descending into popups 206 // Render all toplevels without descending into popups
207 double ox = view->container->current.content_x - 207 double ox = view->container->surface_x -
208 output->wlr_output->lx - view->geometry.x; 208 output->wlr_output->lx - view->geometry.x;
209 double oy = view->container->current.content_y - 209 double oy = view->container->surface_y -
210 output->wlr_output->ly - view->geometry.y; 210 output->wlr_output->ly - view->geometry.y;
211 output_surface_for_each_surface(output, view->surface, ox, oy, 211 output_surface_for_each_surface(output, view->surface, ox, oy,
212 render_surface_iterator, &data); 212 render_surface_iterator, &data);
@@ -240,9 +240,9 @@ static void render_saved_view(struct sway_view *view,
240 return; 240 return;
241 } 241 }
242 struct wlr_box box = { 242 struct wlr_box box = {
243 .x = view->container->current.content_x - output->wlr_output->lx - 243 .x = view->container->surface_x - output->wlr_output->lx -
244 view->saved_geometry.x, 244 view->saved_geometry.x,
245 .y = view->container->current.content_y - output->wlr_output->ly - 245 .y = view->container->surface_y - output->wlr_output->ly -
246 view->saved_geometry.y, 246 view->saved_geometry.y,
247 .width = view->saved_buffer_width, 247 .width = view->saved_buffer_width,
248 .height = view->saved_buffer_height, 248 .height = view->saved_buffer_height,
@@ -1004,7 +1004,6 @@ void output_render(struct sway_output *output, struct timespec *when,
1004 wlr_renderer_clear(renderer, clear_color); 1004 wlr_renderer_clear(renderer, clear_color);
1005 } 1005 }
1006 1006
1007 // TODO: handle views smaller than the output
1008 if (fullscreen_con->view) { 1007 if (fullscreen_con->view) {
1009 if (fullscreen_con->view->saved_buffer) { 1008 if (fullscreen_con->view->saved_buffer) {
1010 render_saved_view(fullscreen_con->view, output, damage, 1.0f); 1009 render_saved_view(fullscreen_con->view, output, damage, 1.0f);
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 9155f0a1..e0c3a5d1 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -249,6 +249,26 @@ static void apply_container_state(struct sway_container *container,
249 desktop_damage_box(&box); 249 desktop_damage_box(&box);
250 } 250 }
251 251
252 // If the view hasn't responded to the configure, center it within
253 // the container. This is important for fullscreen views which
254 // refuse to resize to the size of the output.
255 if (view && view->surface) {
256 if (view->surface->current.width < container->width) {
257 container->surface_x = container->content_x +
258 (container->content_width - view->surface->current.width) / 2;
259 } else {
260 container->surface_x = container->content_x;
261 }
262 if (view->surface->current.height < container->height) {
263 container->surface_y = container->content_y +
264 (container->content_height - view->surface->current.height) / 2;
265 } else {
266 container->surface_y = container->content_y;
267 }
268 container->surface_width = view->surface->current.width;
269 container->surface_height = view->surface->current.height;
270 }
271
252 if (!container->node.destroying) { 272 if (!container->node.destroying) {
253 container_discover_outputs(container); 273 container_discover_outputs(container);
254 } 274 }
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 007b0a94..b5dcfb0f 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) {
291 wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); 291 wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
292 struct sway_container *con = view->container; 292 struct sway_container *con = view->container;
293 293
294 if ((new_geo.width != con->content_width || 294 if ((new_geo.width != con->surface_width ||
295 new_geo.height != con->content_height) && 295 new_geo.height != con->surface_height)) {
296 container_is_floating(con)) { 296 // The view has unexpectedly sent a new size
297 // A floating view has unexpectedly sent a new size
298 desktop_damage_view(view); 297 desktop_damage_view(view);
299 view_update_size(view, new_geo.width, new_geo.height); 298 view_update_size(view, new_geo.width, new_geo.height);
300 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); 299 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 386e350e..a7ea163f 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) {
284 wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo); 284 wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo);
285 struct sway_container *con = view->container; 285 struct sway_container *con = view->container;
286 286
287 if ((new_geo.width != con->content_width || 287 if ((new_geo.width != con->surface_width ||
288 new_geo.height != con->content_height) && 288 new_geo.height != con->surface_height)) {
289 container_is_floating(con)) { 289 // The view has unexpectedly sent a new size
290 // A floating view has unexpectedly sent a new size
291 desktop_damage_view(view); 290 desktop_damage_view(view);
292 view_update_size(view, new_geo.width, new_geo.height); 291 view_update_size(view, new_geo.width, new_geo.height);
293 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); 292 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index d9e1b0a9..e0d307e8 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) {
333 get_geometry(view, &new_geo); 333 get_geometry(view, &new_geo);
334 struct sway_container *con = view->container; 334 struct sway_container *con = view->container;
335 335
336 if ((new_geo.width != con->content_width || 336 if ((new_geo.width != con->surface_width ||
337 new_geo.height != con->content_height) && 337 new_geo.height != con->surface_height)) {
338 container_is_floating(con)) { 338 // The view has unexpectedly sent a new size
339 // A floating view has unexpectedly sent a new size
340 // eg. The Firefox "Save As" dialog when downloading a file 339 // eg. The Firefox "Save As" dialog when downloading a file
341 desktop_damage_view(view); 340 desktop_damage_view(view);
342 view_update_size(view, new_geo.width, new_geo.height); 341 view_update_size(view, new_geo.width, new_geo.height);
diff --git a/sway/tree/container.c b/sway/tree/container.c
index d8ad3bc0..1cf5c8e7 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
169 return NULL; 169 return NULL;
170 } 170 }
171 struct sway_view *view = con->view; 171 struct sway_view *view = con->view;
172 double view_sx = lx - con->content_x + view->geometry.x; 172 double view_sx = lx - con->surface_x + view->geometry.x;
173 double view_sy = ly - con->content_y + view->geometry.y; 173 double view_sy = ly - con->surface_y + view->geometry.y;
174 174
175 double _sx, _sy; 175 double _sx, _sy;
176 struct wlr_surface *_surface = NULL; 176 struct wlr_surface *_surface = NULL;
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 561c6ef1..9ccb2a31 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -673,15 +673,22 @@ void view_unmap(struct sway_view *view) {
673} 673}
674 674
675void view_update_size(struct sway_view *view, int width, int height) { 675void view_update_size(struct sway_view *view, int width, int height) {
676 if (!sway_assert(container_is_floating(view->container), 676 struct sway_container *con = view->container;
677 "Expected a floating container")) { 677
678 return; 678 if (container_is_floating(con)) {
679 con->content_width = width;
680 con->content_height = height;
681 con->current.content_width = width;
682 con->current.content_height = height;
683 container_set_geometry_from_content(con);
684 } else {
685 con->surface_x = con->content_x + (con->content_width - width) / 2;
686 con->surface_y = con->content_y + (con->content_height - height) / 2;
687 con->surface_x = fmax(con->surface_x, con->content_x);
688 con->surface_y = fmax(con->surface_y, con->content_y);
679 } 689 }
680 view->container->content_width = width; 690 con->surface_width = width;
681 view->container->content_height = height; 691 con->surface_width = height;
682 view->container->current.content_width = width;
683 view->container->current.content_height = height;
684 container_set_geometry_from_content(view->container);
685} 692}
686 693
687static const struct sway_view_child_impl subsurface_impl; 694static const struct sway_view_child_impl subsurface_impl;