aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-25 20:56:23 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-26 08:27:07 +1000
commit27a20a488465468511de9b2307941ac1bc4db8bf (patch)
treec5c1aff483cb089870ffebec00869347eec29f4c
parentMerge pull request #2330 from progandy/set-modifier-locks (diff)
downloadsway-27a20a488465468511de9b2307941ac1bc4db8bf.tar.gz
sway-27a20a488465468511de9b2307941ac1bc4db8bf.tar.zst
sway-27a20a488465468511de9b2307941ac1bc4db8bf.zip
Allow containers to be fullscreen
-rw-r--r--include/sway/tree/container.h23
-rw-r--r--include/sway/tree/view.h6
-rw-r--r--include/sway/tree/workspace.h2
-rw-r--r--sway/commands/fullscreen.c18
-rw-r--r--sway/commands/move.c2
-rw-r--r--sway/desktop/output.c14
-rw-r--r--sway/desktop/render.c23
-rw-r--r--sway/desktop/transaction.c2
-rw-r--r--sway/desktop/xdg_shell.c4
-rw-r--r--sway/desktop/xdg_shell_v6.c4
-rw-r--r--sway/desktop/xwayland.c4
-rw-r--r--sway/input/cursor.c14
-rw-r--r--sway/input/seat.c3
-rw-r--r--sway/scratchpad.c2
-rw-r--r--sway/tree/arrange.c18
-rw-r--r--sway/tree/container.c87
-rw-r--r--sway/tree/layout.c83
-rw-r--r--sway/tree/view.c73
18 files changed, 226 insertions, 156 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 2a4be18c..c584cd92 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -60,6 +60,8 @@ struct sway_container_state {
60 double swayc_x, swayc_y; 60 double swayc_x, swayc_y;
61 double swayc_width, swayc_height; 61 double swayc_width, swayc_height;
62 62
63 bool is_fullscreen;
64
63 bool has_gaps; 65 bool has_gaps;
64 double current_gaps; 66 double current_gaps;
65 double gaps_inner; 67 double gaps_inner;
@@ -74,7 +76,6 @@ struct sway_container_state {
74 // View properties 76 // View properties
75 double view_x, view_y; 77 double view_x, view_y;
76 double view_width, view_height; 78 double view_width, view_height;
77 bool is_fullscreen;
78 79
79 enum sway_container_border border; 80 enum sway_container_border border;
80 int border_thickness; 81 int border_thickness;
@@ -84,7 +85,7 @@ struct sway_container_state {
84 bool border_right; 85 bool border_right;
85 86
86 // Workspace properties 87 // Workspace properties
87 struct sway_view *ws_fullscreen; 88 struct sway_container *ws_fullscreen;
88 struct sway_container *ws_floating; 89 struct sway_container *ws_floating;
89}; 90};
90 91
@@ -124,6 +125,8 @@ struct sway_container {
124 double saved_x, saved_y; 125 double saved_x, saved_y;
125 double saved_width, saved_height; 126 double saved_width, saved_height;
126 127
128 bool is_fullscreen;
129
127 // The gaps currently applied to the container. 130 // The gaps currently applied to the container.
128 double current_gaps; 131 double current_gaps;
129 132
@@ -335,4 +338,20 @@ bool container_has_urgent_child(struct sway_container *container);
335 */ 338 */
336void container_end_mouse_operation(struct sway_container *container); 339void container_end_mouse_operation(struct sway_container *container);
337 340
341void container_set_fullscreen(struct sway_container *container, bool enable);
342
343/**
344 * Return true if the container is fullscreen, or a child of a fullscreen split
345 * container.
346 */
347bool container_is_fullscreen_or_child(struct sway_container *container);
348
349/**
350 * Wrap the children of parent in a new container. The new container will be the
351 * only child of parent.
352 *
353 * The new container is returned.
354 */
355struct sway_container *container_wrap_children(struct sway_container *parent);
356
338#endif 357#endif
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 1972447b..7086314f 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -69,8 +69,6 @@ struct sway_view {
69 // Used when changing a view from tiled to floating. 69 // Used when changing a view from tiled to floating.
70 int natural_width, natural_height; 70 int natural_width, natural_height;
71 71
72 bool is_fullscreen;
73
74 char *title_format; 72 char *title_format;
75 enum sway_container_border border; 73 enum sway_container_border border;
76 int border_thickness; 74 int border_thickness;
@@ -251,10 +249,6 @@ void view_set_activated(struct sway_view *view, bool activated);
251 249
252void view_set_tiled(struct sway_view *view, bool tiled); 250void view_set_tiled(struct sway_view *view, bool tiled);
253 251
254void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen);
255
256void view_set_fullscreen(struct sway_view *view, bool fullscreen);
257
258void view_close(struct sway_view *view); 252void view_close(struct sway_view *view);
259 253
260void view_damage_from(struct sway_view *view); 254void view_damage_from(struct sway_view *view);
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h
index ff66da6b..5ae0ae3a 100644
--- a/include/sway/tree/workspace.h
+++ b/include/sway/tree/workspace.h
@@ -7,7 +7,7 @@ struct sway_view;
7 7
8struct sway_workspace { 8struct sway_workspace {
9 struct sway_container *swayc; 9 struct sway_container *swayc;
10 struct sway_view *fullscreen; 10 struct sway_container *fullscreen;
11 struct sway_container *floating; 11 struct sway_container *floating;
12 list_t *output_priority; 12 list_t *output_priority;
13 bool urgent; 13 bool urgent;
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c
index b423fd23..5ad06e40 100644
--- a/sway/commands/fullscreen.c
+++ b/sway/commands/fullscreen.c
@@ -14,18 +14,24 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) {
14 } 14 }
15 struct sway_container *container = 15 struct sway_container *container =
16 config->handler_context.current_container; 16 config->handler_context.current_container;
17 if (container->type != C_VIEW) { 17 if (container->type == C_WORKSPACE && container->children->length == 0) {
18 return cmd_results_new(CMD_INVALID, "fullscreen", 18 return cmd_results_new(CMD_INVALID, "fullscreen",
19 "Only views can fullscreen"); 19 "Can't fullscreen an empty workspace");
20 } 20 }
21 struct sway_view *view = container->sway_view; 21 if (container->type == C_WORKSPACE) {
22 bool wants_fullscreen = !view->is_fullscreen; 22 // Wrap the workspace's children in a container so we can fullscreen it
23 struct sway_container *workspace = container;
24 container = container_wrap_children(container);
25 workspace->layout = L_HORIZ;
26 seat_set_focus(config->handler_context.seat, container);
27 }
28 bool enable = !container->is_fullscreen;
23 29
24 if (argc) { 30 if (argc) {
25 wants_fullscreen = parse_boolean(argv[0], view->is_fullscreen); 31 enable = parse_boolean(argv[0], container->is_fullscreen);
26 } 32 }
27 33
28 view_set_fullscreen(view, wants_fullscreen); 34 container_set_fullscreen(container, enable);
29 35
30 struct sway_container *workspace = container_parent(container, C_WORKSPACE); 36 struct sway_container *workspace = container_parent(container, C_WORKSPACE);
31 arrange_windows(workspace->parent); 37 arrange_windows(workspace->parent);
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 1940043d..aede3d6c 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -196,7 +196,7 @@ static struct cmd_results *move_in_direction(struct sway_container *container,
196 "Cannot move workspaces in a direction"); 196 "Cannot move workspaces in a direction");
197 } 197 }
198 if (container_is_floating(container)) { 198 if (container_is_floating(container)) {
199 if (container->type == C_VIEW && container->sway_view->is_fullscreen) { 199 if (container->is_fullscreen) {
200 return cmd_results_new(CMD_FAILURE, "move", 200 return cmd_results_new(CMD_FAILURE, "move",
201 "Cannot move fullscreen floating container"); 201 "Cannot move fullscreen floating container");
202 } 202 }
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 1764b4e3..cecd300a 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -279,13 +279,15 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
279 279
280 struct sway_container *workspace = output_get_active_workspace(output); 280 struct sway_container *workspace = output_get_active_workspace(output);
281 if (workspace->current.ws_fullscreen) { 281 if (workspace->current.ws_fullscreen) {
282 send_frame_done_container_iterator( 282 if (workspace->current.ws_fullscreen->type == C_VIEW) {
283 workspace->current.ws_fullscreen->swayc, &data); 283 send_frame_done_container_iterator(
284#ifdef HAVE_XWAYLAND 284 workspace->current.ws_fullscreen, &data);
285 if (workspace->current.ws_fullscreen->type == SWAY_VIEW_XWAYLAND) { 285 } else {
286 send_frame_done_unmanaged(&data, 286 send_frame_done_container(&data, workspace->current.ws_fullscreen);
287 &root_container.sway_root->xwayland_unmanaged);
288 } 287 }
288#ifdef HAVE_XWAYLAND
289 send_frame_done_unmanaged(&data,
290 &root_container.sway_root->xwayland_unmanaged);
289#endif 291#endif
290 } else { 292 } else {
291 send_frame_done_layer(&data, 293 send_frame_done_layer(&data,
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 15c5b94c..3e7b1a62 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -836,13 +836,13 @@ void output_render(struct sway_output *output, struct timespec *when,
836 } 836 }
837 837
838 struct sway_container *workspace = output_get_active_workspace(output); 838 struct sway_container *workspace = output_get_active_workspace(output);
839 struct sway_view *fullscreen_view = workspace->current.ws_fullscreen; 839 struct sway_container *fullscreen_con = workspace->current.ws_fullscreen;
840 840
841 if (output_has_opaque_overlay_layer_surface(output)) { 841 if (output_has_opaque_overlay_layer_surface(output)) {
842 goto render_overlay; 842 goto render_overlay;
843 } 843 }
844 844
845 if (fullscreen_view) { 845 if (fullscreen_con) {
846 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 846 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
847 847
848 int nrects; 848 int nrects;
@@ -853,16 +853,21 @@ void output_render(struct sway_output *output, struct timespec *when,
853 } 853 }
854 854
855 // TODO: handle views smaller than the output 855 // TODO: handle views smaller than the output
856 if (fullscreen_view->swayc->instructions->length) { 856 if (fullscreen_con->type == C_VIEW) {
857 render_saved_view(fullscreen_view, output, damage, 1.0f); 857 if (fullscreen_con->instructions->length) {
858 render_saved_view(fullscreen_con->sway_view,
859 output, damage, 1.0f);
858 } else { 860 } else {
859 render_view_surfaces(fullscreen_view, output, damage, 1.0f); 861 render_view_surfaces(fullscreen_con->sway_view,
862 output, damage, 1.0f);
863 }
864 } else {
865 render_container(output, damage, fullscreen_con,
866 fullscreen_con->current.focused);
860 } 867 }
861#ifdef HAVE_XWAYLAND 868#ifdef HAVE_XWAYLAND
862 if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { 869 render_unmanaged(output, damage,
863 render_unmanaged(output, damage, 870 &root_container.sway_root->xwayland_unmanaged);
864 &root_container.sway_root->xwayland_unmanaged);
865 }
866#endif 871#endif
867 } else { 872 } else {
868 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; 873 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 2a89880a..ee7a0704 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -110,6 +110,7 @@ static void copy_pending_state(struct sway_container *container,
110 state->swayc_y = container->y; 110 state->swayc_y = container->y;
111 state->swayc_width = container->width; 111 state->swayc_width = container->width;
112 state->swayc_height = container->height; 112 state->swayc_height = container->height;
113 state->is_fullscreen = container->is_fullscreen;
113 state->has_gaps = container->has_gaps; 114 state->has_gaps = container->has_gaps;
114 state->current_gaps = container->current_gaps; 115 state->current_gaps = container->current_gaps;
115 state->gaps_inner = container->gaps_inner; 116 state->gaps_inner = container->gaps_inner;
@@ -122,7 +123,6 @@ static void copy_pending_state(struct sway_container *container,
122 state->view_y = view->y; 123 state->view_y = view->y;
123 state->view_width = view->width; 124 state->view_width = view->width;
124 state->view_height = view->height; 125 state->view_height = view->height;
125 state->is_fullscreen = view->is_fullscreen;
126 state->border = view->border; 126 state->border = view->border;
127 state->border_thickness = view->border_thickness; 127 state->border_thickness = view->border_thickness;
128 state->border_top = view->border_top; 128 state->border_top = view->border_top;
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index f3e4fef8..e6e1527e 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -267,7 +267,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
267 return; 267 return;
268 } 268 }
269 269
270 view_set_fullscreen(view, e->fullscreen); 270 container_set_fullscreen(view->swayc, e->fullscreen);
271 271
272 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 272 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
273 arrange_windows(output); 273 arrange_windows(output);
@@ -338,7 +338,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
338 view_map(view, view->wlr_xdg_surface->surface); 338 view_map(view, view->wlr_xdg_surface->surface);
339 339
340 if (xdg_surface->toplevel->client_pending.fullscreen) { 340 if (xdg_surface->toplevel->client_pending.fullscreen) {
341 view_set_fullscreen(view, true); 341 container_set_fullscreen(view->swayc, true);
342 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 342 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
343 arrange_windows(ws); 343 arrange_windows(ws);
344 } else { 344 } else {
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 46fd4769..5feee3e4 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -262,7 +262,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
262 return; 262 return;
263 } 263 }
264 264
265 view_set_fullscreen(view, e->fullscreen); 265 container_set_fullscreen(view->swayc, e->fullscreen);
266 266
267 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 267 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
268 arrange_windows(output); 268 arrange_windows(output);
@@ -333,7 +333,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
333 view_map(view, view->wlr_xdg_surface_v6->surface); 333 view_map(view, view->wlr_xdg_surface_v6->surface);
334 334
335 if (xdg_surface->toplevel->client_pending.fullscreen) { 335 if (xdg_surface->toplevel->client_pending.fullscreen) {
336 view_set_fullscreen(view, true); 336 container_set_fullscreen(view->swayc, true);
337 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 337 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
338 arrange_windows(ws); 338 arrange_windows(ws);
339 } else { 339 } else {
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 65d4fcd4..390ca580 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -357,7 +357,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
357 view_map(view, xsurface->surface); 357 view_map(view, xsurface->surface);
358 358
359 if (xsurface->fullscreen) { 359 if (xsurface->fullscreen) {
360 view_set_fullscreen(view, true); 360 container_set_fullscreen(view->swayc, true);
361 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 361 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
362 arrange_windows(ws); 362 arrange_windows(ws);
363 } else { 363 } else {
@@ -395,7 +395,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
395 if (!xsurface->mapped) { 395 if (!xsurface->mapped) {
396 return; 396 return;
397 } 397 }
398 view_set_fullscreen(view, xsurface->fullscreen); 398 container_set_fullscreen(view->swayc, xsurface->fullscreen);
399 399
400 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 400 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
401 arrange_windows(output); 401 arrange_windows(output);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 02bd2239..cc0dbe99 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -99,14 +99,8 @@ static struct sway_container *container_at_coords(
99 return ws; 99 return ws;
100 } 100 }
101 if (ws->sway_workspace->fullscreen) { 101 if (ws->sway_workspace->fullscreen) {
102 struct wlr_surface *wlr_surface = ws->sway_workspace->fullscreen->surface; 102 return container_at(ws->sway_workspace->fullscreen, lx, ly,
103 if (wlr_surface_point_accepts_input(wlr_surface, ox, oy)) { 103 surface, sx, sy);
104 *sx = ox;
105 *sy = oy;
106 *surface = wlr_surface;
107 return ws->sway_workspace->fullscreen->swayc;
108 }
109 return NULL;
110 } 104 }
111 if ((*surface = layer_surface_at(output, 105 if ((*surface = layer_surface_at(output,
112 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], 106 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
@@ -438,8 +432,8 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor,
438 struct sway_container *cont) { 432 struct sway_container *cont) {
439 struct sway_seat *seat = cursor->seat; 433 struct sway_seat *seat = cursor->seat;
440 434
441 // Deny moving or resizing a fullscreen view 435 // Deny moving or resizing a fullscreen container
442 if (cont->type == C_VIEW && cont->sway_view->is_fullscreen) { 436 if (container_is_fullscreen_or_child(cont)) {
443 seat_pointer_notify_button(seat, time_msec, button, state); 437 seat_pointer_notify_button(seat, time_msec, button, state);
444 return; 438 return;
445 } 439 }
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 8698d69e..e7b6e0c5 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -632,8 +632,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
632 632
633 if (last_workspace && last_workspace == new_workspace 633 if (last_workspace && last_workspace == new_workspace
634 && last_workspace->sway_workspace->fullscreen 634 && last_workspace->sway_workspace->fullscreen
635 && container && container->type == C_VIEW 635 && container && !container_is_fullscreen_or_child(container)) {
636 && !container->sway_view->is_fullscreen) {
637 return; 636 return;
638 } 637 }
639 638
diff --git a/sway/scratchpad.c b/sway/scratchpad.c
index 1e836e7d..64636c77 100644
--- a/sway/scratchpad.c
+++ b/sway/scratchpad.c
@@ -54,7 +54,7 @@ static void scratchpad_show(struct sway_container *con) {
54 // If the current con or any of its parents are in fullscreen mode, we 54 // If the current con or any of its parents are in fullscreen mode, we
55 // first need to disable it before showing the scratchpad con. 55 // first need to disable it before showing the scratchpad con.
56 if (ws->sway_workspace->fullscreen) { 56 if (ws->sway_workspace->fullscreen) {
57 view_set_fullscreen(ws->sway_workspace->fullscreen, false); 57 container_set_fullscreen(ws->sway_workspace->fullscreen, false);
58 } 58 }
59 59
60 // Show the container 60 // Show the container
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 533cf71c..5452b13c 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -220,8 +220,22 @@ static void arrange_workspace(struct sway_container *workspace) {
220 container_set_dirty(workspace); 220 container_set_dirty(workspace);
221 wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name, 221 wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name,
222 workspace->x, workspace->y); 222 workspace->x, workspace->y);
223 arrange_floating(workspace->sway_workspace->floating); 223 if (workspace->sway_workspace->fullscreen) {
224 arrange_children_of(workspace); 224 struct sway_container *fs = workspace->sway_workspace->fullscreen;
225 fs->x = workspace->parent->x;
226 fs->y = workspace->parent->y;
227 fs->width = workspace->parent->width;
228 fs->height = workspace->parent->height;
229 if (fs->type == C_VIEW) {
230 view_autoconfigure(fs->sway_view);
231 } else {
232 arrange_children_of(fs);
233 }
234 container_set_dirty(fs);
235 } else {
236 arrange_floating(workspace->sway_workspace->floating);
237 arrange_children_of(workspace);
238 }
225} 239}
226 240
227static void arrange_output(struct sway_container *output) { 241static void arrange_output(struct sway_container *output) {
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 237e1a35..6ebf2653 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -1130,3 +1130,90 @@ void container_end_mouse_operation(struct sway_container *container) {
1130 } 1130 }
1131 } 1131 }
1132} 1132}
1133
1134static void set_fullscreen_iterator(struct sway_container *con, void *data) {
1135 if (con->type != C_VIEW) {
1136 return;
1137 }
1138 if (con->sway_view->impl->set_fullscreen) {
1139 bool *enable = data;
1140 con->sway_view->impl->set_fullscreen(con->sway_view, *enable);
1141 }
1142}
1143
1144void container_set_fullscreen(struct sway_container *container, bool enable) {
1145 if (container->is_fullscreen == enable) {
1146 return;
1147 }
1148
1149 struct sway_container *workspace = container_parent(container, C_WORKSPACE);
1150 if (enable && workspace->sway_workspace->fullscreen) {
1151 container_set_fullscreen(workspace->sway_workspace->fullscreen, false);
1152 }
1153
1154 container_for_each_descendant_dfs(container,
1155 set_fullscreen_iterator, &enable);
1156
1157 container->is_fullscreen = enable;
1158
1159 if (enable) {
1160 workspace->sway_workspace->fullscreen = container;
1161 container->saved_x = container->x;
1162 container->saved_y = container->y;
1163 container->saved_width = container->width;
1164 container->saved_height = container->height;
1165
1166 struct sway_seat *seat;
1167 struct sway_container *focus, *focus_ws;
1168 wl_list_for_each(seat, &input_manager->seats, link) {
1169 focus = seat_get_focus(seat);
1170 if (focus) {
1171 focus_ws = focus;
1172 if (focus_ws->type != C_WORKSPACE) {
1173 focus_ws = container_parent(focus_ws, C_WORKSPACE);
1174 }
1175 if (focus_ws == workspace) {
1176 seat_set_focus(seat, container);
1177 }
1178 }
1179 }
1180 } else {
1181 workspace->sway_workspace->fullscreen = NULL;
1182 if (container_is_floating(container)) {
1183 container->x = container->saved_x;
1184 container->y = container->saved_y;
1185 container->width = container->saved_width;
1186 container->height = container->saved_height;
1187 } else {
1188 container->width = container->saved_width;
1189 container->height = container->saved_height;
1190 }
1191 }
1192
1193 container_end_mouse_operation(container);
1194
1195 ipc_event_window(container, "fullscreen_mode");
1196}
1197
1198bool container_is_fullscreen_or_child(struct sway_container *container) {
1199 do {
1200 if (container->is_fullscreen) {
1201 return true;
1202 }
1203 container = container->parent;
1204 } while (container && container->type != C_WORKSPACE);
1205
1206 return false;
1207}
1208
1209struct sway_container *container_wrap_children(struct sway_container *parent) {
1210 struct sway_container *middle = container_create(C_CONTAINER);
1211 middle->layout = parent->layout;
1212 while (parent->children->length) {
1213 struct sway_container *child = parent->children->items[0];
1214 container_remove_child(child);
1215 container_add_child(middle, child);
1216 }
1217 container_add_child(parent, middle);
1218 return middle;
1219}
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 2b3263f8..ab5acc16 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -66,10 +66,9 @@ static int index_child(const struct sway_container *child) {
66 66
67static void container_handle_fullscreen_reparent(struct sway_container *con, 67static void container_handle_fullscreen_reparent(struct sway_container *con,
68 struct sway_container *old_parent) { 68 struct sway_container *old_parent) {
69 if (con->type != C_VIEW || !con->sway_view->is_fullscreen) { 69 if (!con->is_fullscreen) {
70 return; 70 return;
71 } 71 }
72 struct sway_view *view = con->sway_view;
73 struct sway_container *old_workspace = old_parent; 72 struct sway_container *old_workspace = old_parent;
74 if (old_workspace && old_workspace->type != C_WORKSPACE) { 73 if (old_workspace && old_workspace->type != C_WORKSPACE) {
75 old_workspace = container_parent(old_workspace, C_WORKSPACE); 74 old_workspace = container_parent(old_workspace, C_WORKSPACE);
@@ -85,19 +84,27 @@ static void container_handle_fullscreen_reparent(struct sway_container *con,
85 84
86 // Mark the new workspace as fullscreen 85 // Mark the new workspace as fullscreen
87 if (new_workspace->sway_workspace->fullscreen) { 86 if (new_workspace->sway_workspace->fullscreen) {
88 view_set_fullscreen(new_workspace->sway_workspace->fullscreen, false); 87 container_set_fullscreen(
88 new_workspace->sway_workspace->fullscreen, false);
89 } 89 }
90 new_workspace->sway_workspace->fullscreen = view; 90 new_workspace->sway_workspace->fullscreen = con;
91 // Resize view to new output dimensions 91
92 // Resize container to new output dimensions
92 struct sway_container *output = new_workspace->parent; 93 struct sway_container *output = new_workspace->parent;
93 view->x = output->x;
94 view->y = output->y;
95 view->width = output->width;
96 view->height = output->height;
97 con->x = output->x; 94 con->x = output->x;
98 con->y = output->y; 95 con->y = output->y;
99 con->width = output->width; 96 con->width = output->width;
100 con->height = output->height; 97 con->height = output->height;
98
99 if (con->type == C_VIEW) {
100 struct sway_view *view = con->sway_view;
101 view->x = output->x;
102 view->y = output->y;
103 view->width = output->width;
104 view->height = output->height;
105 } else {
106 arrange_windows(new_workspace);
107 }
101} 108}
102 109
103void container_insert_child(struct sway_container *parent, 110void container_insert_child(struct sway_container *parent,
@@ -146,7 +153,7 @@ void container_add_child(struct sway_container *parent,
146} 153}
147 154
148struct sway_container *container_remove_child(struct sway_container *child) { 155struct sway_container *container_remove_child(struct sway_container *child) {
149 if (child->type == C_VIEW && child->sway_view->is_fullscreen) { 156 if (child->is_fullscreen) {
150 struct sway_container *workspace = container_parent(child, C_WORKSPACE); 157 struct sway_container *workspace = container_parent(child, C_WORKSPACE);
151 workspace->sway_workspace->fullscreen = NULL; 158 workspace->sway_workspace->fullscreen = NULL;
152 } 159 }
@@ -229,10 +236,10 @@ void container_move_to(struct sway_container *container,
229 if (focus_ws->type != C_WORKSPACE) { 236 if (focus_ws->type != C_WORKSPACE) {
230 focus_ws = container_parent(focus_ws, C_WORKSPACE); 237 focus_ws = container_parent(focus_ws, C_WORKSPACE);
231 } 238 }
232 seat_set_focus(seat, 239 if (focus_ws == new_workspace) {
233 new_workspace->sway_workspace->fullscreen->swayc); 240 struct sway_container *new_focus = seat_get_focus_inactive(seat,
234 if (focus_ws != new_workspace) { 241 new_workspace->sway_workspace->fullscreen);
235 seat_set_focus(seat, focus); 242 seat_set_focus(seat, new_focus);
236 } 243 }
237 } 244 }
238 } 245 }
@@ -375,10 +382,16 @@ void container_move(struct sway_container *container,
375 struct sway_container *sibling = NULL; 382 struct sway_container *sibling = NULL;
376 struct sway_container *current = container; 383 struct sway_container *current = container;
377 struct sway_container *parent = current->parent; 384 struct sway_container *parent = current->parent;
385 struct sway_container *top = &root_container;
378 386
379 // If moving a fullscreen view, only consider outputs 387 // If moving a fullscreen view, only consider outputs
380 if (container->type == C_VIEW && container->sway_view->is_fullscreen) { 388 if (container->is_fullscreen) {
381 current = container_parent(container, C_OUTPUT); 389 current = container_parent(container, C_OUTPUT);
390 } else if (container_is_fullscreen_or_child(container)) {
391 // If we've fullscreened a split container, only allow the child to move
392 // around within the fullscreen parent.
393 struct sway_container *ws = container_parent(container, C_WORKSPACE);
394 top = ws->sway_workspace->fullscreen;
382 } 395 }
383 396
384 struct sway_container *new_parent = container_flatten(parent); 397 struct sway_container *new_parent = container_flatten(parent);
@@ -388,7 +401,7 @@ void container_move(struct sway_container *container,
388 } 401 }
389 402
390 while (!sibling) { 403 while (!sibling) {
391 if (current->type == C_ROOT) { 404 if (current == top) {
392 return; 405 return;
393 } 406 }
394 407
@@ -452,8 +465,9 @@ void container_move(struct sway_container *container,
452 if ((index == parent->children->length - 1 && offs > 0) 465 if ((index == parent->children->length - 1 && offs > 0)
453 || (index == 0 && offs < 0)) { 466 || (index == 0 && offs < 0)) {
454 if (current->parent == container->parent) { 467 if (current->parent == container->parent) {
455 if (parent->layout == L_TABBED 468 if (!parent->is_fullscreen &&
456 || parent->layout == L_STACKED) { 469 (parent->layout == L_TABBED ||
470 parent->layout == L_STACKED)) {
457 move_out_of_tabs_stacks(container, current, 471 move_out_of_tabs_stacks(container, current,
458 move_dir, offs); 472 move_dir, offs);
459 return; 473 return;
@@ -474,8 +488,8 @@ void container_move(struct sway_container *container,
474 sibling = parent->children->items[index + offs]; 488 sibling = parent->children->items[index + offs];
475 wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id); 489 wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id);
476 } 490 }
477 } else if (parent->layout == L_TABBED 491 } else if (!parent->is_fullscreen && (parent->layout == L_TABBED ||
478 || parent->layout == L_STACKED) { 492 parent->layout == L_STACKED)) {
479 move_out_of_tabs_stacks(container, current, move_dir, offs); 493 move_out_of_tabs_stacks(container, current, move_dir, offs);
480 return; 494 return;
481 } else { 495 } else {
@@ -707,16 +721,16 @@ struct sway_container *container_get_in_direction(
707 return NULL; 721 return NULL;
708 } 722 }
709 723
710 if (container->type == C_VIEW && container->sway_view->is_fullscreen) { 724 if (dir == MOVE_CHILD) {
711 if (dir == MOVE_PARENT || dir == MOVE_CHILD) { 725 return seat_get_focus_inactive(seat, container);
726 }
727 if (container->is_fullscreen) {
728 if (dir == MOVE_PARENT) {
712 return NULL; 729 return NULL;
713 } 730 }
714 container = container_parent(container, C_OUTPUT); 731 container = container_parent(container, C_OUTPUT);
715 parent = container->parent; 732 parent = container->parent;
716 } else { 733 } else {
717 if (dir == MOVE_CHILD) {
718 return seat_get_focus_inactive(seat, container);
719 }
720 if (dir == MOVE_PARENT) { 734 if (dir == MOVE_PARENT) {
721 if (parent->type == C_OUTPUT) { 735 if (parent->type == C_OUTPUT) {
722 return NULL; 736 return NULL;
@@ -767,7 +781,8 @@ struct sway_container *container_get_in_direction(
767 } 781 }
768 sway_assert(next_workspace, "Next container has no workspace"); 782 sway_assert(next_workspace, "Next container has no workspace");
769 if (next_workspace->sway_workspace->fullscreen) { 783 if (next_workspace->sway_workspace->fullscreen) {
770 return next_workspace->sway_workspace->fullscreen->swayc; 784 return seat_get_focus_inactive(seat,
785 next_workspace->sway_workspace->fullscreen);
771 } 786 }
772 if (next->children && next->children->length) { 787 if (next->children && next->children->length) {
773 // TODO consider floating children as well 788 // TODO consider floating children as well
@@ -1014,13 +1029,13 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) {
1014 1029
1015 wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id); 1030 wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
1016 1031
1017 int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen; 1032 int fs1 = con1->is_fullscreen;
1018 int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen; 1033 int fs2 = con2->is_fullscreen;
1019 if (fs1) { 1034 if (fs1) {
1020 view_set_fullscreen(con1->sway_view, false); 1035 container_set_fullscreen(con1, false);
1021 } 1036 }
1022 if (fs2) { 1037 if (fs2) {
1023 view_set_fullscreen(con2->sway_view, false); 1038 container_set_fullscreen(con2, false);
1024 } 1039 }
1025 1040
1026 struct sway_seat *seat = input_manager_get_default_seat(input_manager); 1041 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
@@ -1053,10 +1068,10 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) {
1053 prev_workspace_name = stored_prev_name; 1068 prev_workspace_name = stored_prev_name;
1054 } 1069 }
1055 1070
1056 if (fs1 && con2->type == C_VIEW) { 1071 if (fs1) {
1057 view_set_fullscreen(con2->sway_view, true); 1072 container_set_fullscreen(con2, true);
1058 } 1073 }
1059 if (fs2 && con1->type == C_VIEW) { 1074 if (fs2) {
1060 view_set_fullscreen(con1->sway_view, true); 1075 container_set_fullscreen(con1, true);
1061 } 1076 }
1062} 1077}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index beeb8144..82c3ad4a 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -225,7 +225,7 @@ void view_autoconfigure(struct sway_view *view) {
225 225
226 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 226 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
227 227
228 if (view->is_fullscreen) { 228 if (view->swayc->is_fullscreen) {
229 view->x = output->x; 229 view->x = output->x;
230 view->y = output->y; 230 view->y = output->y;
231 view->width = output->width; 231 view->width = output->width;
@@ -233,10 +233,6 @@ void view_autoconfigure(struct sway_view *view) {
233 return; 233 return;
234 } 234 }
235 235
236 if (container_is_floating(view->swayc)) {
237 return;
238 }
239
240 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 236 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
241 237
242 int other_views = 0; 238 int other_views = 0;
@@ -349,68 +345,6 @@ void view_set_tiled(struct sway_view *view, bool tiled) {
349 } 345 }
350} 346}
351 347
352void view_set_fullscreen(struct sway_view *view, bool fullscreen) {
353 if (view->is_fullscreen == fullscreen) {
354 return;
355 }
356
357 struct sway_container *workspace =
358 container_parent(view->swayc, C_WORKSPACE);
359
360 if (view->impl->set_fullscreen) {
361 view->impl->set_fullscreen(view, fullscreen);
362 }
363
364 view->is_fullscreen = fullscreen;
365
366 if (fullscreen) {
367 if (workspace->sway_workspace->fullscreen) {
368 view_set_fullscreen(workspace->sway_workspace->fullscreen, false);
369 }
370 workspace->sway_workspace->fullscreen = view;
371 view->saved_x = view->x;
372 view->saved_y = view->y;
373 view->saved_width = view->width;
374 view->saved_height = view->height;
375 view->swayc->saved_x = view->swayc->x;
376 view->swayc->saved_y = view->swayc->y;
377 view->swayc->saved_width = view->swayc->width;
378 view->swayc->saved_height = view->swayc->height;
379
380 struct sway_seat *seat;
381 struct sway_container *focus, *focus_ws;
382 wl_list_for_each(seat, &input_manager->seats, link) {
383 focus = seat_get_focus(seat);
384 if (focus) {
385 focus_ws = focus;
386 if (focus && focus_ws->type != C_WORKSPACE) {
387 focus_ws = container_parent(focus_ws, C_WORKSPACE);
388 }
389 seat_set_focus(seat, view->swayc);
390 if (focus_ws != workspace) {
391 seat_set_focus(seat, focus);
392 }
393 }
394 }
395 } else {
396 workspace->sway_workspace->fullscreen = NULL;
397 if (container_is_floating(view->swayc)) {
398 view->x = view->saved_x;
399 view->y = view->saved_y;
400 view->width = view->saved_width;
401 view->height = view->saved_height;
402 container_set_geometry_from_floating_view(view->swayc);
403 } else {
404 view->swayc->width = view->swayc->saved_width;
405 view->swayc->height = view->swayc->saved_height;
406 }
407 }
408
409 container_end_mouse_operation(view->swayc);
410
411 ipc_event_window(view->swayc, "fullscreen_mode");
412}
413
414void view_close(struct sway_view *view) { 348void view_close(struct sway_view *view) {
415 if (view->impl->close) { 349 if (view->impl->close) {
416 view->impl->close(view); 350 view->impl->close(view);
@@ -680,7 +614,7 @@ void view_unmap(struct sway_view *view) {
680 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 614 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
681 615
682 struct sway_container *parent; 616 struct sway_container *parent;
683 if (view->is_fullscreen) { 617 if (view->swayc->is_fullscreen) {
684 ws->sway_workspace->fullscreen = NULL; 618 ws->sway_workspace->fullscreen = NULL;
685 parent = container_destroy(view->swayc); 619 parent = container_destroy(view->swayc);
686 620
@@ -1133,7 +1067,8 @@ bool view_is_visible(struct sway_view *view) {
1133 container = container->parent; 1067 container = container->parent;
1134 } 1068 }
1135 // Check view isn't hidden by another fullscreen view 1069 // Check view isn't hidden by another fullscreen view
1136 if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { 1070 if (workspace->sway_workspace->fullscreen &&
1071 !container_is_fullscreen_or_child(view->swayc)) {
1137 return false; 1072 return false;
1138 } 1073 }
1139 // Check the workspace is visible 1074 // Check the workspace is visible