aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/util.c21
-rw-r--r--include/sway/config.h2
-rw-r--r--include/sway/tree/container.h28
-rw-r--r--include/sway/tree/layout.h52
-rw-r--r--include/util.h14
-rw-r--r--sway/commands/exec_always.c1
-rw-r--r--sway/commands/floating.c1
-rw-r--r--sway/commands/focus.c2
-rw-r--r--sway/commands/fullscreen.c1
-rw-r--r--sway/commands/hide_edge_borders.c1
-rw-r--r--sway/commands/move.c1
-rw-r--r--sway/commands/output.c1
-rw-r--r--sway/commands/resize.c21
-rw-r--r--sway/commands/show_marks.c1
-rw-r--r--sway/commands/sticky.c1
-rw-r--r--sway/commands/swap.c128
-rw-r--r--sway/commands/unmark.c1
-rw-r--r--sway/commands/urgent.c1
-rw-r--r--sway/config.c2
-rw-r--r--sway/config/output.c1
-rw-r--r--sway/criteria.c1
-rw-r--r--sway/debug-tree.c2
-rw-r--r--sway/desktop/layer_shell.c1
-rw-r--r--sway/desktop/output.c2
-rw-r--r--sway/desktop/render.c2
-rw-r--r--sway/desktop/xdg_shell.c1
-rw-r--r--sway/desktop/xdg_shell_v6.c1
-rw-r--r--sway/desktop/xwayland.c1
-rw-r--r--sway/input/cursor.c1
-rw-r--r--sway/input/seat.c3
-rw-r--r--sway/ipc-server.c1
-rw-r--r--sway/main.c2
-rw-r--r--sway/meson.build1
-rw-r--r--sway/server.c2
-rw-r--r--sway/tree/arrange.c1
-rw-r--r--sway/tree/container.c221
-rw-r--r--sway/tree/layout.c403
-rw-r--r--sway/tree/view.c1
38 files changed, 449 insertions, 479 deletions
diff --git a/common/util.c b/common/util.c
index 467aa4b5..561b3804 100644
--- a/common/util.c
+++ b/common/util.c
@@ -175,3 +175,24 @@ failed:
175 free(current); 175 free(current);
176 return NULL; 176 return NULL;
177} 177}
178
179bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) {
180 switch (dir) {
181 case MOVE_UP:
182 *out = WLR_DIRECTION_UP;
183 break;
184 case MOVE_DOWN:
185 *out = WLR_DIRECTION_DOWN;
186 break;
187 case MOVE_LEFT:
188 *out = WLR_DIRECTION_LEFT;
189 break;
190 case MOVE_RIGHT:
191 *out = WLR_DIRECTION_RIGHT;
192 break;
193 default:
194 return false;
195 }
196
197 return true;
198}
diff --git a/include/sway/config.h b/include/sway/config.h
index c2eaea1b..18d10faa 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -8,8 +8,8 @@
8#include <xkbcommon/xkbcommon.h> 8#include <xkbcommon/xkbcommon.h>
9#include "list.h" 9#include "list.h"
10#include "swaynag.h" 10#include "swaynag.h"
11#include "tree/layout.h"
12#include "tree/container.h" 11#include "tree/container.h"
12#include "sway/tree/root.h"
13#include "wlr-layer-shell-unstable-v1-protocol.h" 13#include "wlr-layer-shell-unstable-v1-protocol.h"
14 14
15// TODO: Refactor this shit 15// TODO: Refactor this shit
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 2b6e6e0c..e4071cfe 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -53,6 +53,9 @@ struct sway_output;
53struct sway_workspace; 53struct sway_workspace;
54struct sway_view; 54struct sway_view;
55 55
56enum movement_direction;
57enum wlr_direction;
58
56struct sway_container_state { 59struct sway_container_state {
57 // Container/swayc properties 60 // Container/swayc properties
58 enum sway_container_layout layout; 61 enum sway_container_layout layout;
@@ -341,4 +344,29 @@ void container_add_gaps(struct sway_container *container);
341 344
342int container_sibling_index(const struct sway_container *child); 345int container_sibling_index(const struct sway_container *child);
343 346
347void container_handle_fullscreen_reparent(struct sway_container *con,
348 struct sway_container *old_parent);
349
350void container_add_child(struct sway_container *parent,
351 struct sway_container *child);
352
353void container_insert_child(struct sway_container *parent,
354 struct sway_container *child, int i);
355
356struct sway_container *container_add_sibling(struct sway_container *parent,
357 struct sway_container *child);
358
359struct sway_container *container_remove_child(struct sway_container *child);
360
361struct sway_container *container_replace_child(struct sway_container *child,
362 struct sway_container *new_child);
363
364bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out);
365
366enum sway_container_layout container_get_default_layout(
367 struct sway_container *con);
368
369struct sway_container *container_split(struct sway_container *child,
370 enum sway_container_layout layout);
371
344#endif 372#endif
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h
deleted file mode 100644
index 5c834ad2..00000000
--- a/include/sway/tree/layout.h
+++ /dev/null
@@ -1,52 +0,0 @@
1#ifndef _SWAY_LAYOUT_H
2#define _SWAY_LAYOUT_H
3#include <wlr/types/wlr_output_layout.h>
4#include <wlr/render/wlr_texture.h>
5#include "sway/tree/container.h"
6#include "sway/tree/root.h"
7#include "config.h"
8
9enum movement_direction {
10 MOVE_LEFT,
11 MOVE_RIGHT,
12 MOVE_UP,
13 MOVE_DOWN,
14 MOVE_PARENT,
15 MOVE_CHILD,
16};
17
18enum wlr_edges;
19
20struct sway_container;
21
22void container_handle_fullscreen_reparent(struct sway_container *con,
23 struct sway_container *old_parent);
24
25void container_add_child(struct sway_container *parent,
26 struct sway_container *child);
27
28void container_insert_child(struct sway_container *parent,
29 struct sway_container *child, int i);
30
31struct sway_container *container_add_sibling(struct sway_container *parent,
32 struct sway_container *child);
33
34struct sway_container *container_remove_child(struct sway_container *child);
35
36struct sway_container *container_replace_child(struct sway_container *child,
37 struct sway_container *new_child);
38
39bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out);
40
41enum sway_container_layout container_get_default_layout(
42 struct sway_container *con);
43
44struct sway_container *container_split(struct sway_container *child,
45 enum sway_container_layout layout);
46
47void container_recursive_resize(struct sway_container *container,
48 double amount, enum wlr_edges edge);
49
50void container_swap(struct sway_container *con1, struct sway_container *con2);
51
52#endif
diff --git a/include/util.h b/include/util.h
index 9277fa6e..46ed1533 100644
--- a/include/util.h
+++ b/include/util.h
@@ -4,9 +4,19 @@
4#include <stdint.h> 4#include <stdint.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include <unistd.h> 6#include <unistd.h>
7#include <sys/types.h> 7#include <sys/types.h>
8#include <wlr/types/wlr_output_layout.h>
8#include <xkbcommon/xkbcommon.h> 9#include <xkbcommon/xkbcommon.h>
9 10
11enum movement_direction {
12 MOVE_LEFT,
13 MOVE_RIGHT,
14 MOVE_UP,
15 MOVE_DOWN,
16 MOVE_PARENT,
17 MOVE_CHILD,
18};
19
10/** 20/**
11 * Wrap i into the range [0, max[ 21 * Wrap i into the range [0, max[
12 */ 22 */
@@ -71,4 +81,6 @@ char* resolve_path(const char* path);
71char *b64_encode(const char* binaryData, size_t len, size_t *flen); 81char *b64_encode(const char* binaryData, size_t len, size_t *flen);
72unsigned char *b64_decode(const char *ascii, size_t len, size_t *flen); 82unsigned char *b64_decode(const char *ascii, size_t len, size_t *flen);
73 83
84bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out);
85
74#endif 86#endif
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c
index 5ce7919b..bc07c2aa 100644
--- a/sway/commands/exec_always.c
+++ b/sway/commands/exec_always.c
@@ -8,6 +8,7 @@
8#include "sway/commands.h" 8#include "sway/commands.h"
9#include "sway/config.h" 9#include "sway/config.h"
10#include "sway/tree/container.h" 10#include "sway/tree/container.h"
11#include "sway/tree/root.h"
11#include "sway/tree/workspace.h" 12#include "sway/tree/workspace.h"
12#include "log.h" 13#include "log.h"
13#include "stringop.h" 14#include "stringop.h"
diff --git a/sway/commands/floating.c b/sway/commands/floating.c
index beafd9fb..436376e3 100644
--- a/sway/commands/floating.c
+++ b/sway/commands/floating.c
@@ -6,7 +6,6 @@
6#include "sway/output.h" 6#include "sway/output.h"
7#include "sway/tree/arrange.h" 7#include "sway/tree/arrange.h"
8#include "sway/tree/container.h" 8#include "sway/tree/container.h"
9#include "sway/tree/layout.h"
10#include "sway/tree/view.h" 9#include "sway/tree/view.h"
11#include "sway/tree/workspace.h" 10#include "sway/tree/workspace.h"
12#include "list.h" 11#include "list.h"
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index a9fa9a0f..f342e524 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -6,9 +6,11 @@
6#include "sway/input/seat.h" 6#include "sway/input/seat.h"
7#include "sway/output.h" 7#include "sway/output.h"
8#include "sway/tree/arrange.h" 8#include "sway/tree/arrange.h"
9#include "sway/tree/root.h"
9#include "sway/tree/view.h" 10#include "sway/tree/view.h"
10#include "sway/tree/workspace.h" 11#include "sway/tree/workspace.h"
11#include "stringop.h" 12#include "stringop.h"
13#include "util.h"
12 14
13static bool parse_movement_direction(const char *name, 15static bool parse_movement_direction(const char *name,
14 enum movement_direction *out) { 16 enum movement_direction *out) {
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c
index a0661200..ac65dffb 100644
--- a/sway/commands/fullscreen.c
+++ b/sway/commands/fullscreen.c
@@ -5,7 +5,6 @@
5#include "sway/tree/container.h" 5#include "sway/tree/container.h"
6#include "sway/tree/view.h" 6#include "sway/tree/view.h"
7#include "sway/tree/workspace.h" 7#include "sway/tree/workspace.h"
8#include "sway/tree/layout.h"
9#include "util.h" 8#include "util.h"
10 9
11struct cmd_results *cmd_fullscreen(int argc, char **argv) { 10struct cmd_results *cmd_fullscreen(int argc, char **argv) {
diff --git a/sway/commands/hide_edge_borders.c b/sway/commands/hide_edge_borders.c
index d59c9fdb..e494f6aa 100644
--- a/sway/commands/hide_edge_borders.c
+++ b/sway/commands/hide_edge_borders.c
@@ -1,6 +1,7 @@
1#include "sway/commands.h" 1#include "sway/commands.h"
2#include "sway/config.h" 2#include "sway/config.h"
3#include "sway/tree/container.h" 3#include "sway/tree/container.h"
4#include "sway/tree/root.h"
4#include "sway/tree/view.h" 5#include "sway/tree/view.h"
5 6
6static void _configure_view(struct sway_container *con, void *data) { 7static void _configure_view(struct sway_container *con, void *data) {
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 2744b354..d0f6b9ea 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -19,6 +19,7 @@
19#include "stringop.h" 19#include "stringop.h"
20#include "list.h" 20#include "list.h"
21#include "log.h" 21#include "log.h"
22#include "util.h"
22 23
23static const char *expected_syntax = 24static const char *expected_syntax =
24 "Expected 'move <left|right|up|down> <[px] px>' or " 25 "Expected 'move <left|right|up|down> <[px] px>' or "
diff --git a/sway/commands/output.c b/sway/commands/output.c
index ef1b7a69..00910843 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -1,7 +1,6 @@
1#include "sway/commands.h" 1#include "sway/commands.h"
2#include "sway/config.h" 2#include "sway/config.h"
3#include "sway/output.h" 3#include "sway/output.h"
4#include "sway/tree/layout.h"
5#include "list.h" 4#include "list.h"
6#include "log.h" 5#include "log.h"
7 6
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index ea1e36ff..ad659ef5 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -159,6 +159,27 @@ static int parallel_size(struct sway_container *c, enum resize_axis a) {
159 return normalize_axis(a) == RESIZE_AXIS_HORIZONTAL ? c->width : c->height; 159 return normalize_axis(a) == RESIZE_AXIS_HORIZONTAL ? c->width : c->height;
160} 160}
161 161
162static void container_recursive_resize(struct sway_container *container,
163 double amount, enum wlr_edges edge) {
164 bool layout_match = true;
165 wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount);
166 if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) {
167 container->width += amount;
168 layout_match = container->layout == L_HORIZ;
169 } else if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) {
170 container->height += amount;
171 layout_match = container->layout == L_VERT;
172 }
173 if (container->children) {
174 for (int i = 0; i < container->children->length; i++) {
175 struct sway_container *child = container->children->items[i];
176 double amt = layout_match ?
177 amount / container->children->length : amount;
178 container_recursive_resize(child, amt, edge);
179 }
180 }
181}
182
162static void resize_tiled(struct sway_container *parent, int amount, 183static void resize_tiled(struct sway_container *parent, int amount,
163 enum resize_axis axis) { 184 enum resize_axis axis) {
164 struct sway_container *focused = parent; 185 struct sway_container *focused = parent;
diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c
index dd7d170c..1844e917 100644
--- a/sway/commands/show_marks.c
+++ b/sway/commands/show_marks.c
@@ -2,6 +2,7 @@
2#include <string.h> 2#include <string.h>
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/config.h" 4#include "sway/config.h"
5#include "sway/tree/root.h"
5#include "sway/tree/view.h" 6#include "sway/tree/view.h"
6#include "sway/output.h" 7#include "sway/output.h"
7#include "list.h" 8#include "list.h"
diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c
index 72ef4282..8692e08d 100644
--- a/sway/commands/sticky.c
+++ b/sway/commands/sticky.c
@@ -6,7 +6,6 @@
6#include "sway/output.h" 6#include "sway/output.h"
7#include "sway/tree/arrange.h" 7#include "sway/tree/arrange.h"
8#include "sway/tree/container.h" 8#include "sway/tree/container.h"
9#include "sway/tree/layout.h"
10#include "sway/tree/view.h" 9#include "sway/tree/view.h"
11#include "sway/tree/workspace.h" 10#include "sway/tree/workspace.h"
12#include "list.h" 11#include "list.h"
diff --git a/sway/commands/swap.c b/sway/commands/swap.c
index f881a002..f25c43a1 100644
--- a/sway/commands/swap.c
+++ b/sway/commands/swap.c
@@ -1,15 +1,141 @@
1#define _POSIX_C_SOURCE 200809L
1#include <strings.h> 2#include <strings.h>
2#include <wlr/util/log.h> 3#include <wlr/util/log.h>
3#include "config.h" 4#include "config.h"
5#include "log.h"
4#include "sway/commands.h" 6#include "sway/commands.h"
5#include "sway/tree/arrange.h" 7#include "sway/tree/arrange.h"
6#include "sway/tree/layout.h" 8#include "sway/tree/root.h"
7#include "sway/tree/view.h" 9#include "sway/tree/view.h"
10#include "sway/tree/workspace.h"
8#include "stringop.h" 11#include "stringop.h"
9 12
10static const char* EXPECTED_SYNTAX = 13static const char* EXPECTED_SYNTAX =
11 "Expected 'swap container with id|con_id|mark <arg>'"; 14 "Expected 'swap container with id|con_id|mark <arg>'";
12 15
16static void swap_places(struct sway_container *con1,
17 struct sway_container *con2) {
18 struct sway_container *temp = malloc(sizeof(struct sway_container));
19 temp->x = con1->x;
20 temp->y = con1->y;
21 temp->width = con1->width;
22 temp->height = con1->height;
23 temp->parent = con1->parent;
24
25 con1->x = con2->x;
26 con1->y = con2->y;
27 con1->width = con2->width;
28 con1->height = con2->height;
29
30 con2->x = temp->x;
31 con2->y = temp->y;
32 con2->width = temp->width;
33 con2->height = temp->height;
34
35 int temp_index = container_sibling_index(con1);
36 container_insert_child(con2->parent, con1, container_sibling_index(con2));
37 container_insert_child(temp->parent, con2, temp_index);
38
39 free(temp);
40}
41
42static void swap_focus(struct sway_container *con1,
43 struct sway_container *con2, struct sway_seat *seat,
44 struct sway_container *focus) {
45 if (focus == con1 || focus == con2) {
46 struct sway_container *ws1 = container_parent(con1, C_WORKSPACE);
47 struct sway_container *ws2 = container_parent(con2, C_WORKSPACE);
48 if (focus == con1 && (con2->parent->layout == L_TABBED
49 || con2->parent->layout == L_STACKED)) {
50 if (workspace_is_visible(ws2)) {
51 seat_set_focus_warp(seat, con2, false, true);
52 }
53 seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
54 } else if (focus == con2 && (con1->parent->layout == L_TABBED
55 || con1->parent->layout == L_STACKED)) {
56 if (workspace_is_visible(ws1)) {
57 seat_set_focus_warp(seat, con1, false, true);
58 }
59 seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
60 } else if (ws1 != ws2) {
61 seat_set_focus(seat, focus == con1 ? con2 : con1);
62 } else {
63 seat_set_focus(seat, focus);
64 }
65 } else {
66 seat_set_focus(seat, focus);
67 }
68}
69
70static void container_swap(struct sway_container *con1,
71 struct sway_container *con2) {
72 if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
73 return;
74 }
75 if (!sway_assert(con1->type >= C_CONTAINER && con2->type >= C_CONTAINER,
76 "Can only swap containers and views")) {
77 return;
78 }
79 if (!sway_assert(!container_has_ancestor(con1, con2)
80 && !container_has_ancestor(con2, con1),
81 "Cannot swap ancestor and descendant")) {
82 return;
83 }
84 if (!sway_assert(!container_is_floating(con1)
85 && !container_is_floating(con2),
86 "Swapping with floating containers is not supported")) {
87 return;
88 }
89
90 wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
91
92 int fs1 = con1->is_fullscreen;
93 int fs2 = con2->is_fullscreen;
94 if (fs1) {
95 container_set_fullscreen(con1, false);
96 }
97 if (fs2) {
98 container_set_fullscreen(con2, false);
99 }
100
101 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
102 struct sway_container *focus = seat_get_focus(seat);
103 struct sway_container *vis1 = container_parent(
104 seat_get_focus_inactive(seat, container_parent(con1, C_OUTPUT)),
105 C_WORKSPACE);
106 struct sway_container *vis2 = container_parent(
107 seat_get_focus_inactive(seat, container_parent(con2, C_OUTPUT)),
108 C_WORKSPACE);
109
110 char *stored_prev_name = NULL;
111 if (prev_workspace_name) {
112 stored_prev_name = strdup(prev_workspace_name);
113 }
114
115 swap_places(con1, con2);
116
117 if (!workspace_is_visible(vis1)) {
118 seat_set_focus(seat, seat_get_focus_inactive(seat, vis1));
119 }
120 if (!workspace_is_visible(vis2)) {
121 seat_set_focus(seat, seat_get_focus_inactive(seat, vis2));
122 }
123
124 swap_focus(con1, con2, seat, focus);
125
126 if (stored_prev_name) {
127 free(prev_workspace_name);
128 prev_workspace_name = stored_prev_name;
129 }
130
131 if (fs1) {
132 container_set_fullscreen(con2, true);
133 }
134 if (fs2) {
135 container_set_fullscreen(con1, true);
136 }
137}
138
13static bool test_con_id(struct sway_container *container, void *con_id) { 139static bool test_con_id(struct sway_container *container, void *con_id) {
14 return container->id == (size_t)con_id; 140 return container->id == (size_t)con_id;
15} 141}
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c
index c183785b..62127c97 100644
--- a/sway/commands/unmark.c
+++ b/sway/commands/unmark.c
@@ -2,6 +2,7 @@
2#include <string.h> 2#include <string.h>
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/config.h" 4#include "sway/config.h"
5#include "sway/tree/root.h"
5#include "sway/tree/view.h" 6#include "sway/tree/view.h"
6#include "list.h" 7#include "list.h"
7#include "log.h" 8#include "log.h"
diff --git a/sway/commands/urgent.c b/sway/commands/urgent.c
index 51c497c4..bccb33fe 100644
--- a/sway/commands/urgent.c
+++ b/sway/commands/urgent.c
@@ -4,7 +4,6 @@
4#include "sway/tree/arrange.h" 4#include "sway/tree/arrange.h"
5#include "sway/tree/container.h" 5#include "sway/tree/container.h"
6#include "sway/tree/view.h" 6#include "sway/tree/view.h"
7#include "sway/tree/layout.h"
8#include "util.h" 7#include "util.h"
9 8
10struct cmd_results *cmd_urgent(int argc, char **argv) { 9struct cmd_results *cmd_urgent(int argc, char **argv) {
diff --git a/sway/config.c b/sway/config.c
index 642abbac..8105722a 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -27,7 +27,7 @@
27#include "sway/criteria.h" 27#include "sway/criteria.h"
28#include "sway/swaynag.h" 28#include "sway/swaynag.h"
29#include "sway/tree/arrange.h" 29#include "sway/tree/arrange.h"
30#include "sway/tree/layout.h" 30#include "sway/tree/root.h"
31#include "sway/tree/workspace.h" 31#include "sway/tree/workspace.h"
32#include "cairo.h" 32#include "cairo.h"
33#include "pango.h" 33#include "pango.h"
diff --git a/sway/config/output.c b/sway/config/output.c
index 7f9b1007..199267bf 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -9,6 +9,7 @@
9#include <wlr/types/wlr_output_layout.h> 9#include <wlr/types/wlr_output_layout.h>
10#include "sway/config.h" 10#include "sway/config.h"
11#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/tree/root.h"
12#include "log.h" 13#include "log.h"
13 14
14int output_name_cmp(const void *item, const void *data) { 15int output_name_cmp(const void *item, const void *data) {
diff --git a/sway/criteria.c b/sway/criteria.c
index 81c2325a..5452c4ee 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -6,6 +6,7 @@
6#include "sway/criteria.h" 6#include "sway/criteria.h"
7#include "sway/tree/container.h" 7#include "sway/tree/container.h"
8#include "sway/config.h" 8#include "sway/config.h"
9#include "sway/tree/root.h"
9#include "sway/tree/view.h" 10#include "sway/tree/view.h"
10#include "stringop.h" 11#include "stringop.h"
11#include "list.h" 12#include "list.h"
diff --git a/sway/debug-tree.c b/sway/debug-tree.c
index ea0826b9..2768cf58 100644
--- a/sway/debug-tree.c
+++ b/sway/debug-tree.c
@@ -9,7 +9,7 @@
9#include "sway/output.h" 9#include "sway/output.h"
10#include "sway/server.h" 10#include "sway/server.h"
11#include "sway/tree/container.h" 11#include "sway/tree/container.h"
12#include "sway/tree/layout.h" 12#include "sway/tree/root.h"
13#include "cairo.h" 13#include "cairo.h"
14#include "config.h" 14#include "config.h"
15#include "pango.h" 15#include "pango.h"
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index a2935883..1fae5db2 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -14,7 +14,6 @@
14#include "sway/output.h" 14#include "sway/output.h"
15#include "sway/server.h" 15#include "sway/server.h"
16#include "sway/tree/arrange.h" 16#include "sway/tree/arrange.h"
17#include "sway/tree/layout.h"
18#include "log.h" 17#include "log.h"
19 18
20static void apply_exclusive(struct wlr_box *usable_area, 19static void apply_exclusive(struct wlr_box *usable_area,
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 401d3c44..35fce1a6 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -23,7 +23,7 @@
23#include "sway/server.h" 23#include "sway/server.h"
24#include "sway/tree/arrange.h" 24#include "sway/tree/arrange.h"
25#include "sway/tree/container.h" 25#include "sway/tree/container.h"
26#include "sway/tree/layout.h" 26#include "sway/tree/root.h"
27#include "sway/tree/view.h" 27#include "sway/tree/view.h"
28#include "sway/tree/workspace.h" 28#include "sway/tree/workspace.h"
29 29
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 5cf8abc0..b5a10370 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -24,7 +24,7 @@
24#include "sway/server.h" 24#include "sway/server.h"
25#include "sway/tree/arrange.h" 25#include "sway/tree/arrange.h"
26#include "sway/tree/container.h" 26#include "sway/tree/container.h"
27#include "sway/tree/layout.h" 27#include "sway/tree/root.h"
28#include "sway/tree/view.h" 28#include "sway/tree/view.h"
29#include "sway/tree/workspace.h" 29#include "sway/tree/workspace.h"
30 30
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index f5aaa575..7d1824f1 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -13,7 +13,6 @@
13#include "sway/server.h" 13#include "sway/server.h"
14#include "sway/tree/arrange.h" 14#include "sway/tree/arrange.h"
15#include "sway/tree/container.h" 15#include "sway/tree/container.h"
16#include "sway/tree/layout.h"
17#include "sway/tree/view.h" 16#include "sway/tree/view.h"
18 17
19static const struct sway_view_child_impl popup_impl; 18static const struct sway_view_child_impl popup_impl;
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index f623b77b..522fddca 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -12,7 +12,6 @@
12#include "sway/server.h" 12#include "sway/server.h"
13#include "sway/tree/arrange.h" 13#include "sway/tree/arrange.h"
14#include "sway/tree/container.h" 14#include "sway/tree/container.h"
15#include "sway/tree/layout.h"
16#include "sway/tree/view.h" 15#include "sway/tree/view.h"
17 16
18static const struct sway_view_child_impl popup_impl; 17static const struct sway_view_child_impl popup_impl;
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 6fcc850d..4e401008 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -14,7 +14,6 @@
14#include "sway/server.h" 14#include "sway/server.h"
15#include "sway/tree/arrange.h" 15#include "sway/tree/arrange.h"
16#include "sway/tree/container.h" 16#include "sway/tree/container.h"
17#include "sway/tree/layout.h"
18#include "sway/tree/view.h" 17#include "sway/tree/view.h"
19 18
20static const char *atom_map[ATOM_LAST] = { 19static const char *atom_map[ATOM_LAST] = {
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index ba5e0400..00240e84 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -20,6 +20,7 @@
20#include "sway/layers.h" 20#include "sway/layers.h"
21#include "sway/output.h" 21#include "sway/output.h"
22#include "sway/tree/arrange.h" 22#include "sway/tree/arrange.h"
23#include "sway/tree/root.h"
23#include "sway/tree/view.h" 24#include "sway/tree/view.h"
24#include "sway/tree/workspace.h" 25#include "sway/tree/workspace.h"
25#include "wlr-layer-shell-unstable-v1-protocol.h" 26#include "wlr-layer-shell-unstable-v1-protocol.h"
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 997d7815..269823ee 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -25,10 +25,9 @@
25#include "sway/output.h" 25#include "sway/output.h"
26#include "sway/tree/arrange.h" 26#include "sway/tree/arrange.h"
27#include "sway/tree/container.h" 27#include "sway/tree/container.h"
28#include "sway/tree/container.h" 28#include "sway/tree/root.h"
29#include "sway/tree/view.h" 29#include "sway/tree/view.h"
30#include "sway/tree/workspace.h" 30#include "sway/tree/workspace.h"
31#include "sway/tree/workspace.h"
32 31
33static void seat_device_destroy(struct sway_seat_device *seat_device) { 32static void seat_device_destroy(struct sway_seat_device *seat_device) {
34 if (!seat_device) { 33 if (!seat_device) {
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 34e940ad..1ac0521e 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -31,6 +31,7 @@
31#include "sway/server.h" 31#include "sway/server.h"
32#include "sway/input/input-manager.h" 32#include "sway/input/input-manager.h"
33#include "sway/input/seat.h" 33#include "sway/input/seat.h"
34#include "sway/tree/root.h"
34#include "sway/tree/view.h" 35#include "sway/tree/view.h"
35#include "list.h" 36#include "list.h"
36#include "log.h" 37#include "log.h"
diff --git a/sway/main.c b/sway/main.c
index 3ba4ba75..7ed10c86 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -23,7 +23,7 @@
23#include "sway/desktop/transaction.h" 23#include "sway/desktop/transaction.h"
24#include "sway/server.h" 24#include "sway/server.h"
25#include "sway/swaynag.h" 25#include "sway/swaynag.h"
26#include "sway/tree/layout.h" 26#include "sway/tree/root.h"
27#include "sway/ipc-server.h" 27#include "sway/ipc-server.h"
28#include "ipc-client.h" 28#include "ipc-client.h"
29#include "readline.h" 29#include "readline.h"
diff --git a/sway/meson.build b/sway/meson.build
index 676422d0..bcb44e8b 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -150,7 +150,6 @@ sway_sources = files(
150 150
151 'tree/arrange.c', 151 'tree/arrange.c',
152 'tree/container.c', 152 'tree/container.c',
153 'tree/layout.c',
154 'tree/root.c', 153 'tree/root.c',
155 'tree/view.c', 154 'tree/view.c',
156 'tree/workspace.c', 155 'tree/workspace.c',
diff --git a/sway/server.c b/sway/server.c
index 00acaa01..7fa6007e 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -24,7 +24,7 @@
24#include "sway/desktop/idle_inhibit_v1.h" 24#include "sway/desktop/idle_inhibit_v1.h"
25#include "sway/input/input-manager.h" 25#include "sway/input/input-manager.h"
26#include "sway/server.h" 26#include "sway/server.h"
27#include "sway/tree/layout.h" 27#include "sway/tree/root.h"
28#include "config.h" 28#include "config.h"
29#ifdef HAVE_XWAYLAND 29#ifdef HAVE_XWAYLAND
30#include "sway/xwayland.h" 30#include "sway/xwayland.h"
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 0da61a4c..60e5b951 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -7,7 +7,6 @@
7#include <wlr/types/wlr_output_layout.h> 7#include <wlr/types/wlr_output_layout.h>
8#include "sway/tree/arrange.h" 8#include "sway/tree/arrange.h"
9#include "sway/tree/container.h" 9#include "sway/tree/container.h"
10#include "sway/tree/layout.h"
11#include "sway/output.h" 10#include "sway/output.h"
12#include "sway/tree/workspace.h" 11#include "sway/tree/workspace.h"
13#include "sway/tree/view.h" 12#include "sway/tree/view.h"
diff --git a/sway/tree/container.c b/sway/tree/container.c
index f9611342..f13e2e96 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -19,7 +19,6 @@
19#include "sway/output.h" 19#include "sway/output.h"
20#include "sway/server.h" 20#include "sway/server.h"
21#include "sway/tree/arrange.h" 21#include "sway/tree/arrange.h"
22#include "sway/tree/layout.h"
23#include "sway/tree/view.h" 22#include "sway/tree/view.h"
24#include "sway/tree/workspace.h" 23#include "sway/tree/workspace.h"
25#include "log.h" 24#include "log.h"
@@ -1159,3 +1158,223 @@ void container_add_gaps(struct sway_container *c) {
1159int container_sibling_index(const struct sway_container *child) { 1158int container_sibling_index(const struct sway_container *child) {
1160 return list_find(child->parent->children, child); 1159 return list_find(child->parent->children, child);
1161} 1160}
1161
1162void container_handle_fullscreen_reparent(struct sway_container *con,
1163 struct sway_container *old_parent) {
1164 if (!con->is_fullscreen) {
1165 return;
1166 }
1167 struct sway_container *old_workspace = old_parent;
1168 if (old_workspace && old_workspace->type != C_WORKSPACE) {
1169 old_workspace = container_parent(old_workspace, C_WORKSPACE);
1170 }
1171 struct sway_container *new_workspace = container_parent(con, C_WORKSPACE);
1172 if (old_workspace == new_workspace) {
1173 return;
1174 }
1175 // Unmark the old workspace as fullscreen
1176 if (old_workspace) {
1177 old_workspace->sway_workspace->fullscreen = NULL;
1178 }
1179
1180 // Mark the new workspace as fullscreen
1181 if (new_workspace->sway_workspace->fullscreen) {
1182 container_set_fullscreen(
1183 new_workspace->sway_workspace->fullscreen, false);
1184 }
1185 new_workspace->sway_workspace->fullscreen = con;
1186
1187 // Resize container to new output dimensions
1188 struct sway_container *output = new_workspace->parent;
1189 con->x = output->x;
1190 con->y = output->y;
1191 con->width = output->width;
1192 con->height = output->height;
1193
1194 if (con->type == C_VIEW) {
1195 struct sway_view *view = con->sway_view;
1196 view->x = output->x;
1197 view->y = output->y;
1198 view->width = output->width;
1199 view->height = output->height;
1200 } else {
1201 arrange_windows(new_workspace);
1202 }
1203}
1204
1205void container_insert_child(struct sway_container *parent,
1206 struct sway_container *child, int i) {
1207 struct sway_container *old_parent = child->parent;
1208 if (old_parent) {
1209 container_remove_child(child);
1210 }
1211 wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
1212 list_insert(parent->children, i, child);
1213 child->parent = parent;
1214 container_handle_fullscreen_reparent(child, old_parent);
1215}
1216
1217struct sway_container *container_add_sibling(struct sway_container *fixed,
1218 struct sway_container *active) {
1219 // TODO handle floating
1220 struct sway_container *old_parent = NULL;
1221 if (active->parent) {
1222 old_parent = active->parent;
1223 container_remove_child(active);
1224 }
1225 struct sway_container *parent = fixed->parent;
1226 int i = container_sibling_index(fixed);
1227 list_insert(parent->children, i + 1, active);
1228 active->parent = parent;
1229 container_handle_fullscreen_reparent(active, old_parent);
1230 return active->parent;
1231}
1232
1233void container_add_child(struct sway_container *parent,
1234 struct sway_container *child) {
1235 wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
1236 child, child->type, child->width, child->height,
1237 parent, parent->type, parent->width, parent->height);
1238 struct sway_container *old_parent = child->parent;
1239 list_add(parent->children, child);
1240 child->parent = parent;
1241 container_handle_fullscreen_reparent(child, old_parent);
1242 if (old_parent) {
1243 container_set_dirty(old_parent);
1244 }
1245 container_set_dirty(child);
1246}
1247
1248struct sway_container *container_remove_child(struct sway_container *child) {
1249 if (child->is_fullscreen) {
1250 struct sway_container *workspace = container_parent(child, C_WORKSPACE);
1251 workspace->sway_workspace->fullscreen = NULL;
1252 }
1253
1254 struct sway_container *parent = child->parent;
1255 list_t *list = container_is_floating(child) ?
1256 parent->sway_workspace->floating : parent->children;
1257 int index = list_find(list, child);
1258 if (index != -1) {
1259 list_del(list, index);
1260 }
1261 child->parent = NULL;
1262 container_notify_subtree_changed(parent);
1263
1264 container_set_dirty(parent);
1265 container_set_dirty(child);
1266
1267 return parent;
1268}
1269
1270enum sway_container_layout container_get_default_layout(
1271 struct sway_container *con) {
1272 if (con->type != C_OUTPUT) {
1273 con = container_parent(con, C_OUTPUT);
1274 }
1275
1276 if (!sway_assert(con != NULL,
1277 "container_get_default_layout must be called on an attached"
1278 " container below the root container")) {
1279 return 0;
1280 }
1281
1282 if (config->default_layout != L_NONE) {
1283 return config->default_layout;
1284 } else if (config->default_orientation != L_NONE) {
1285 return config->default_orientation;
1286 } else if (con->width >= con->height) {
1287 return L_HORIZ;
1288 } else {
1289 return L_VERT;
1290 }
1291}
1292
1293struct sway_container *container_replace_child(struct sway_container *child,
1294 struct sway_container *new_child) {
1295 struct sway_container *parent = child->parent;
1296 if (parent == NULL) {
1297 return NULL;
1298 }
1299
1300 list_t *list = container_is_floating(child) ?
1301 parent->sway_workspace->floating : parent->children;
1302 int i = list_find(list, child);
1303
1304 if (new_child->parent) {
1305 container_remove_child(new_child);
1306 }
1307 list->items[i] = new_child;
1308 new_child->parent = parent;
1309 child->parent = NULL;
1310
1311 // Set geometry for new child
1312 new_child->x = child->x;
1313 new_child->y = child->y;
1314 new_child->width = child->width;
1315 new_child->height = child->height;
1316
1317 // reset geometry for child
1318 child->width = 0;
1319 child->height = 0;
1320
1321 return parent;
1322}
1323
1324struct sway_container *container_split(struct sway_container *child,
1325 enum sway_container_layout layout) {
1326 // TODO floating: cannot split a floating container
1327 if (!sway_assert(child, "child cannot be null")) {
1328 return NULL;
1329 }
1330 if (child->type == C_WORKSPACE && child->children->length == 0) {
1331 // Special case: this just behaves like splitt
1332 child->prev_split_layout = child->layout;
1333 child->layout = layout;
1334 return child;
1335 }
1336
1337 struct sway_container *cont = container_create(C_CONTAINER);
1338
1339 wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
1340
1341 child->type == C_WORKSPACE ? workspace_remove_gaps(child)
1342 : container_remove_gaps(child);
1343
1344 cont->prev_split_layout = L_NONE;
1345 cont->width = child->width;
1346 cont->height = child->height;
1347 cont->x = child->x;
1348 cont->y = child->y;
1349
1350 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
1351 bool set_focus = (seat_get_focus(seat) == child);
1352
1353 container_add_gaps(cont);
1354
1355 if (child->type == C_WORKSPACE) {
1356 struct sway_container *workspace = child;
1357 while (workspace->children->length) {
1358 struct sway_container *ws_child = workspace->children->items[0];
1359 container_remove_child(ws_child);
1360 container_add_child(cont, ws_child);
1361 }
1362
1363 container_add_child(workspace, cont);
1364 enum sway_container_layout old_layout = workspace->layout;
1365 workspace->layout = layout;
1366 cont->layout = old_layout;
1367 } else {
1368 cont->layout = layout;
1369 container_replace_child(child, cont);
1370 container_add_child(cont, child);
1371 }
1372
1373 if (set_focus) {
1374 seat_set_focus(seat, cont);
1375 seat_set_focus(seat, child);
1376 }
1377
1378 container_notify_subtree_changed(cont);
1379 return cont;
1380}
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
deleted file mode 100644
index 85fe7643..00000000
--- a/sway/tree/layout.c
+++ /dev/null
@@ -1,403 +0,0 @@
1#define _POSIX_C_SOURCE 200809L
2#include <math.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <string.h>
6#include <wlr/types/wlr_output.h>
7#include <wlr/types/wlr_output_layout.h>
8#include "config.h"
9#include "sway/debug.h"
10#include "sway/tree/arrange.h"
11#include "sway/tree/container.h"
12#include "sway/tree/layout.h"
13#include "sway/output.h"
14#include "sway/tree/workspace.h"
15#include "sway/tree/view.h"
16#include "sway/input/seat.h"
17#include "sway/ipc-server.h"
18#include "list.h"
19#include "log.h"
20
21void container_handle_fullscreen_reparent(struct sway_container *con,
22 struct sway_container *old_parent) {
23 if (!con->is_fullscreen) {
24 return;
25 }
26 struct sway_container *old_workspace = old_parent;
27 if (old_workspace && old_workspace->type != C_WORKSPACE) {
28 old_workspace = container_parent(old_workspace, C_WORKSPACE);
29 }
30 struct sway_container *new_workspace = container_parent(con, C_WORKSPACE);
31 if (old_workspace == new_workspace) {
32 return;
33 }
34 // Unmark the old workspace as fullscreen
35 if (old_workspace) {
36 old_workspace->sway_workspace->fullscreen = NULL;
37 }
38
39 // Mark the new workspace as fullscreen
40 if (new_workspace->sway_workspace->fullscreen) {
41 container_set_fullscreen(
42 new_workspace->sway_workspace->fullscreen, false);
43 }
44 new_workspace->sway_workspace->fullscreen = con;
45
46 // Resize container to new output dimensions
47 struct sway_container *output = new_workspace->parent;
48 con->x = output->x;
49 con->y = output->y;
50 con->width = output->width;
51 con->height = output->height;
52
53 if (con->type == C_VIEW) {
54 struct sway_view *view = con->sway_view;
55 view->x = output->x;
56 view->y = output->y;
57 view->width = output->width;
58 view->height = output->height;
59 } else {
60 arrange_windows(new_workspace);
61 }
62}
63
64void container_insert_child(struct sway_container *parent,
65 struct sway_container *child, int i) {
66 struct sway_container *old_parent = child->parent;
67 if (old_parent) {
68 container_remove_child(child);
69 }
70 wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
71 list_insert(parent->children, i, child);
72 child->parent = parent;
73 container_handle_fullscreen_reparent(child, old_parent);
74}
75
76struct sway_container *container_add_sibling(struct sway_container *fixed,
77 struct sway_container *active) {
78 // TODO handle floating
79 struct sway_container *old_parent = NULL;
80 if (active->parent) {
81 old_parent = active->parent;
82 container_remove_child(active);
83 }
84 struct sway_container *parent = fixed->parent;
85 int i = container_sibling_index(fixed);
86 list_insert(parent->children, i + 1, active);
87 active->parent = parent;
88 container_handle_fullscreen_reparent(active, old_parent);
89 return active->parent;
90}
91
92void container_add_child(struct sway_container *parent,
93 struct sway_container *child) {
94 wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
95 child, child->type, child->width, child->height,
96 parent, parent->type, parent->width, parent->height);
97 struct sway_container *old_parent = child->parent;
98 list_add(parent->children, child);
99 child->parent = parent;
100 container_handle_fullscreen_reparent(child, old_parent);
101 if (old_parent) {
102 container_set_dirty(old_parent);
103 }
104 container_set_dirty(child);
105}
106
107struct sway_container *container_remove_child(struct sway_container *child) {
108 if (child->is_fullscreen) {
109 struct sway_container *workspace = container_parent(child, C_WORKSPACE);
110 workspace->sway_workspace->fullscreen = NULL;
111 }
112
113 struct sway_container *parent = child->parent;
114 list_t *list = container_is_floating(child) ?
115 parent->sway_workspace->floating : parent->children;
116 int index = list_find(list, child);
117 if (index != -1) {
118 list_del(list, index);
119 }
120 child->parent = NULL;
121 container_notify_subtree_changed(parent);
122
123 container_set_dirty(parent);
124 container_set_dirty(child);
125
126 return parent;
127}
128
129bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) {
130 switch (dir) {
131 case MOVE_UP:
132 *out = WLR_DIRECTION_UP;
133 break;
134 case MOVE_DOWN:
135 *out = WLR_DIRECTION_DOWN;
136 break;
137 case MOVE_LEFT:
138 *out = WLR_DIRECTION_LEFT;
139 break;
140 case MOVE_RIGHT:
141 *out = WLR_DIRECTION_RIGHT;
142 break;
143 default:
144 return false;
145 }
146
147 return true;
148}
149
150enum sway_container_layout container_get_default_layout(
151 struct sway_container *con) {
152 if (con->type != C_OUTPUT) {
153 con = container_parent(con, C_OUTPUT);
154 }
155
156 if (!sway_assert(con != NULL,
157 "container_get_default_layout must be called on an attached"
158 " container below the root container")) {
159 return 0;
160 }
161
162 if (config->default_layout != L_NONE) {
163 return config->default_layout;
164 } else if (config->default_orientation != L_NONE) {
165 return config->default_orientation;
166 } else if (con->width >= con->height) {
167 return L_HORIZ;
168 } else {
169 return L_VERT;
170 }
171}
172
173struct sway_container *container_replace_child(struct sway_container *child,
174 struct sway_container *new_child) {
175 struct sway_container *parent = child->parent;
176 if (parent == NULL) {
177 return NULL;
178 }
179
180 list_t *list = container_is_floating(child) ?
181 parent->sway_workspace->floating : parent->children;
182 int i = list_find(list, child);
183
184 if (new_child->parent) {
185 container_remove_child(new_child);
186 }
187 list->items[i] = new_child;
188 new_child->parent = parent;
189 child->parent = NULL;
190
191 // Set geometry for new child
192 new_child->x = child->x;
193 new_child->y = child->y;
194 new_child->width = child->width;
195 new_child->height = child->height;
196
197 // reset geometry for child
198 child->width = 0;
199 child->height = 0;
200
201 return parent;
202}
203
204struct sway_container *container_split(struct sway_container *child,
205 enum sway_container_layout layout) {
206 // TODO floating: cannot split a floating container
207 if (!sway_assert(child, "child cannot be null")) {
208 return NULL;
209 }
210 if (child->type == C_WORKSPACE && child->children->length == 0) {
211 // Special case: this just behaves like splitt
212 child->prev_split_layout = child->layout;
213 child->layout = layout;
214 return child;
215 }
216
217 struct sway_container *cont = container_create(C_CONTAINER);
218
219 wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
220
221 child->type == C_WORKSPACE ? workspace_remove_gaps(child)
222 : container_remove_gaps(child);
223
224 cont->prev_split_layout = L_NONE;
225 cont->width = child->width;
226 cont->height = child->height;
227 cont->x = child->x;
228 cont->y = child->y;
229
230 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
231 bool set_focus = (seat_get_focus(seat) == child);
232
233 container_add_gaps(cont);
234
235 if (child->type == C_WORKSPACE) {
236 struct sway_container *workspace = child;
237 while (workspace->children->length) {
238 struct sway_container *ws_child = workspace->children->items[0];
239 container_remove_child(ws_child);
240 container_add_child(cont, ws_child);
241 }
242
243 container_add_child(workspace, cont);
244 enum sway_container_layout old_layout = workspace->layout;
245 workspace->layout = layout;
246 cont->layout = old_layout;
247 } else {
248 cont->layout = layout;
249 container_replace_child(child, cont);
250 container_add_child(cont, child);
251 }
252
253 if (set_focus) {
254 seat_set_focus(seat, cont);
255 seat_set_focus(seat, child);
256 }
257
258 container_notify_subtree_changed(cont);
259 return cont;
260}
261
262void container_recursive_resize(struct sway_container *container,
263 double amount, enum wlr_edges edge) {
264 bool layout_match = true;
265 wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount);
266 if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) {
267 container->width += amount;
268 layout_match = container->layout == L_HORIZ;
269 } else if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) {
270 container->height += amount;
271 layout_match = container->layout == L_VERT;
272 }
273 if (container->children) {
274 for (int i = 0; i < container->children->length; i++) {
275 struct sway_container *child = container->children->items[i];
276 double amt = layout_match ?
277 amount / container->children->length : amount;
278 container_recursive_resize(child, amt, edge);
279 }
280 }
281}
282
283static void swap_places(struct sway_container *con1,
284 struct sway_container *con2) {
285 struct sway_container *temp = malloc(sizeof(struct sway_container));
286 temp->x = con1->x;
287 temp->y = con1->y;
288 temp->width = con1->width;
289 temp->height = con1->height;
290 temp->parent = con1->parent;
291
292 con1->x = con2->x;
293 con1->y = con2->y;
294 con1->width = con2->width;
295 con1->height = con2->height;
296
297 con2->x = temp->x;
298 con2->y = temp->y;
299 con2->width = temp->width;
300 con2->height = temp->height;
301
302 int temp_index = container_sibling_index(con1);
303 container_insert_child(con2->parent, con1, container_sibling_index(con2));
304 container_insert_child(temp->parent, con2, temp_index);
305
306 free(temp);
307}
308
309static void swap_focus(struct sway_container *con1,
310 struct sway_container *con2, struct sway_seat *seat,
311 struct sway_container *focus) {
312 if (focus == con1 || focus == con2) {
313 struct sway_container *ws1 = container_parent(con1, C_WORKSPACE);
314 struct sway_container *ws2 = container_parent(con2, C_WORKSPACE);
315 if (focus == con1 && (con2->parent->layout == L_TABBED
316 || con2->parent->layout == L_STACKED)) {
317 if (workspace_is_visible(ws2)) {
318 seat_set_focus_warp(seat, con2, false, true);
319 }
320 seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
321 } else if (focus == con2 && (con1->parent->layout == L_TABBED
322 || con1->parent->layout == L_STACKED)) {
323 if (workspace_is_visible(ws1)) {
324 seat_set_focus_warp(seat, con1, false, true);
325 }
326 seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
327 } else if (ws1 != ws2) {
328 seat_set_focus(seat, focus == con1 ? con2 : con1);
329 } else {
330 seat_set_focus(seat, focus);
331 }
332 } else {
333 seat_set_focus(seat, focus);
334 }
335}
336
337void container_swap(struct sway_container *con1, struct sway_container *con2) {
338 if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
339 return;
340 }
341 if (!sway_assert(con1->type >= C_CONTAINER && con2->type >= C_CONTAINER,
342 "Can only swap containers and views")) {
343 return;
344 }
345 if (!sway_assert(!container_has_ancestor(con1, con2)
346 && !container_has_ancestor(con2, con1),
347 "Cannot swap ancestor and descendant")) {
348 return;
349 }
350 if (!sway_assert(!container_is_floating(con1)
351 && !container_is_floating(con2),
352 "Swapping with floating containers is not supported")) {
353 return;
354 }
355
356 wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
357
358 int fs1 = con1->is_fullscreen;
359 int fs2 = con2->is_fullscreen;
360 if (fs1) {
361 container_set_fullscreen(con1, false);
362 }
363 if (fs2) {
364 container_set_fullscreen(con2, false);
365 }
366
367 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
368 struct sway_container *focus = seat_get_focus(seat);
369 struct sway_container *vis1 = container_parent(
370 seat_get_focus_inactive(seat, container_parent(con1, C_OUTPUT)),
371 C_WORKSPACE);
372 struct sway_container *vis2 = container_parent(
373 seat_get_focus_inactive(seat, container_parent(con2, C_OUTPUT)),
374 C_WORKSPACE);
375
376 char *stored_prev_name = NULL;
377 if (prev_workspace_name) {
378 stored_prev_name = strdup(prev_workspace_name);
379 }
380
381 swap_places(con1, con2);
382
383 if (!workspace_is_visible(vis1)) {
384 seat_set_focus(seat, seat_get_focus_inactive(seat, vis1));
385 }
386 if (!workspace_is_visible(vis2)) {
387 seat_set_focus(seat, seat_get_focus_inactive(seat, vis2));
388 }
389
390 swap_focus(con1, con2, seat, focus);
391
392 if (stored_prev_name) {
393 free(prev_workspace_name);
394 prev_workspace_name = stored_prev_name;
395 }
396
397 if (fs1) {
398 container_set_fullscreen(con2, true);
399 }
400 if (fs2) {
401 container_set_fullscreen(con1, true);
402 }
403}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index ba4a880f..2870d4f5 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -18,7 +18,6 @@
18#include "sway/input/seat.h" 18#include "sway/input/seat.h"
19#include "sway/tree/arrange.h" 19#include "sway/tree/arrange.h"
20#include "sway/tree/container.h" 20#include "sway/tree/container.h"
21#include "sway/tree/layout.h"
22#include "sway/tree/view.h" 21#include "sway/tree/view.h"
23#include "sway/tree/workspace.h" 22#include "sway/tree/workspace.h"
24#include "sway/config.h" 23#include "sway/config.h"