aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-04-28 11:26:14 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-04-28 11:26:14 +1000
commit167c2e1aa99aa8011e169b0fb61c47953cc9a5f6 (patch)
treef312cac40cd542964f62d8b7ed53d44bb13dea37 /sway
parentMerge pull request #1866 from ggreer/swaybar-cmd-sh (diff)
downloadsway-167c2e1aa99aa8011e169b0fb61c47953cc9a5f6.tar.gz
sway-167c2e1aa99aa8011e169b0fb61c47953cc9a5f6.tar.zst
sway-167c2e1aa99aa8011e169b0fb61c47953cc9a5f6.zip
Refactor arrange_windows()
Replaces arrange_windows() with arrange_root(), arrange_output(), arrange_workspace() and arrange_children_of(). Also makes fullscreen views save and restore their dimensions, which allows it to preserve any custom resize and is also a requirement for floating views once they are implemented.
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/layout.c4
-rw-r--r--sway/commands/reload.c4
-rw-r--r--sway/commands/resize.c4
-rw-r--r--sway/commands/split.c4
-rw-r--r--sway/desktop/layer_shell.c3
-rw-r--r--sway/desktop/output.c9
-rw-r--r--sway/input/seat.c1
-rw-r--r--sway/meson.build1
-rw-r--r--sway/tree/arrange.c239
-rw-r--r--sway/tree/container.c4
-rw-r--r--sway/tree/layout.c279
-rw-r--r--sway/tree/view.c30
-rw-r--r--sway/tree/workspace.c3
13 files changed, 305 insertions, 280 deletions
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index ca45a6c8..bb36bb18 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -1,8 +1,8 @@
1#include <string.h> 1#include <string.h>
2#include <strings.h> 2#include <strings.h>
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/tree/arrange.h"
4#include "sway/tree/container.h" 5#include "sway/tree/container.h"
5#include "sway/tree/layout.h"
6#include "log.h" 6#include "log.h"
7 7
8struct cmd_results *cmd_layout(int argc, char **argv) { 8struct cmd_results *cmd_layout(int argc, char **argv) {
@@ -48,7 +48,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
48 } 48 }
49 } 49 }
50 50
51 arrange_windows(parent, parent->width, parent->height); 51 arrange_children_of(parent);
52 52
53 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 53 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
54} 54}
diff --git a/sway/commands/reload.c b/sway/commands/reload.c
index 5bca6cde..092dd46f 100644
--- a/sway/commands/reload.c
+++ b/sway/commands/reload.c
@@ -1,6 +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/tree/layout.h" 3#include "sway/tree/arrange.h"
4 4
5struct cmd_results *cmd_reload(int argc, char **argv) { 5struct cmd_results *cmd_reload(int argc, char **argv) {
6 struct cmd_results *error = NULL; 6 struct cmd_results *error = NULL;
@@ -12,6 +12,6 @@ struct cmd_results *cmd_reload(int argc, char **argv) {
12 } 12 }
13 13
14 load_swaybars(); 14 load_swaybars();
15 arrange_windows(&root_container, -1, -1); 15 arrange_root();
16 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 16 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
17} 17}
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 93c1fe7d..d1f9e019 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -6,7 +6,7 @@
6#include <strings.h> 6#include <strings.h>
7#include <wlr/util/log.h> 7#include <wlr/util/log.h>
8#include "sway/commands.h" 8#include "sway/commands.h"
9#include "sway/tree/layout.h" 9#include "sway/tree/arrange.h"
10#include "log.h" 10#include "log.h"
11 11
12static const int MIN_SANE_W = 100, MIN_SANE_H = 60; 12static const int MIN_SANE_W = 100, MIN_SANE_H = 60;
@@ -182,7 +182,7 @@ static void resize_tiled(int amount, enum resize_axis axis) {
182 } 182 }
183 } 183 }
184 184
185 arrange_windows(parent->parent, -1, -1); 185 arrange_children_of(parent->parent);
186} 186}
187 187
188static void resize(int amount, enum resize_axis axis, enum resize_unit unit) { 188static void resize(int amount, enum resize_axis axis, enum resize_unit unit) {
diff --git a/sway/commands/split.c b/sway/commands/split.c
index 130ed31f..0a61ac8d 100644
--- a/sway/commands/split.c
+++ b/sway/commands/split.c
@@ -1,8 +1,8 @@
1#include <string.h> 1#include <string.h>
2#include <strings.h> 2#include <strings.h>
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/tree/arrange.h"
4#include "sway/tree/container.h" 5#include "sway/tree/container.h"
5#include "sway/tree/layout.h"
6#include "sway/tree/view.h" 6#include "sway/tree/view.h"
7#include "sway/input/input-manager.h" 7#include "sway/input/input-manager.h"
8#include "sway/input/seat.h" 8#include "sway/input/seat.h"
@@ -12,7 +12,7 @@ static struct cmd_results *do_split(int layout) {
12 struct sway_container *con = config->handler_context.current_container; 12 struct sway_container *con = config->handler_context.current_container;
13 struct sway_container *parent = container_split(con, layout); 13 struct sway_container *parent = container_split(con, layout);
14 container_create_notify(parent); 14 container_create_notify(parent);
15 arrange_windows(parent, -1, -1); 15 arrange_children_of(parent);
16 16
17 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 17 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
18} 18}
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index f9a1a8bd..03419ac1 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -12,6 +12,7 @@
12#include "sway/layers.h" 12#include "sway/layers.h"
13#include "sway/output.h" 13#include "sway/output.h"
14#include "sway/server.h" 14#include "sway/server.h"
15#include "sway/tree/arrange.h"
15#include "sway/tree/layout.h" 16#include "sway/tree/layout.h"
16#include "log.h" 17#include "log.h"
17 18
@@ -175,7 +176,7 @@ void arrange_layers(struct sway_output *output) {
175 sizeof(struct wlr_box)) != 0) { 176 sizeof(struct wlr_box)) != 0) {
176 wlr_log(L_DEBUG, "Usable area changed, rearranging output"); 177 wlr_log(L_DEBUG, "Usable area changed, rearranging output");
177 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); 178 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
178 arrange_windows(output->swayc, -1, -1); 179 arrange_output(output->swayc);
179 } 180 }
180 181
181 // Arrange non-exlusive surfaces from top->bottom 182 // Arrange non-exlusive surfaces from top->bottom
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index b19b72df..d9ae890f 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -19,6 +19,7 @@
19#include "sway/layers.h" 19#include "sway/layers.h"
20#include "sway/output.h" 20#include "sway/output.h"
21#include "sway/server.h" 21#include "sway/server.h"
22#include "sway/tree/arrange.h"
22#include "sway/tree/container.h" 23#include "sway/tree/container.h"
23#include "sway/tree/layout.h" 24#include "sway/tree/layout.h"
24#include "sway/tree/view.h" 25#include "sway/tree/view.h"
@@ -534,19 +535,19 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
534static void handle_mode(struct wl_listener *listener, void *data) { 535static void handle_mode(struct wl_listener *listener, void *data) {
535 struct sway_output *output = wl_container_of(listener, output, mode); 536 struct sway_output *output = wl_container_of(listener, output, mode);
536 arrange_layers(output); 537 arrange_layers(output);
537 arrange_windows(output->swayc, -1, -1); 538 arrange_output(output->swayc);
538} 539}
539 540
540static void handle_transform(struct wl_listener *listener, void *data) { 541static void handle_transform(struct wl_listener *listener, void *data) {
541 struct sway_output *output = wl_container_of(listener, output, transform); 542 struct sway_output *output = wl_container_of(listener, output, transform);
542 arrange_layers(output); 543 arrange_layers(output);
543 arrange_windows(output->swayc, -1, -1); 544 arrange_output(output->swayc);
544} 545}
545 546
546static void handle_scale(struct wl_listener *listener, void *data) { 547static void handle_scale(struct wl_listener *listener, void *data) {
547 struct sway_output *output = wl_container_of(listener, output, scale); 548 struct sway_output *output = wl_container_of(listener, output, scale);
548 arrange_layers(output); 549 arrange_layers(output);
549 arrange_windows(output->swayc, -1, -1); 550 arrange_output(output->swayc);
550} 551}
551 552
552void handle_new_output(struct wl_listener *listener, void *data) { 553void handle_new_output(struct wl_listener *listener, void *data) {
@@ -598,5 +599,5 @@ void handle_new_output(struct wl_listener *listener, void *data) {
598 output->damage_destroy.notify = damage_handle_destroy; 599 output->damage_destroy.notify = damage_handle_destroy;
599 600
600 arrange_layers(output); 601 arrange_layers(output);
601 arrange_windows(&root_container, -1, -1); 602 arrange_root();
602} 603}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 963d38b2..8b9817da 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -16,6 +16,7 @@
16#include "sway/ipc-server.h" 16#include "sway/ipc-server.h"
17#include "sway/layers.h" 17#include "sway/layers.h"
18#include "sway/output.h" 18#include "sway/output.h"
19#include "sway/tree/arrange.h"
19#include "sway/tree/container.h" 20#include "sway/tree/container.h"
20#include "sway/tree/view.h" 21#include "sway/tree/view.h"
21#include "sway/tree/workspace.h" 22#include "sway/tree/workspace.h"
diff --git a/sway/meson.build b/sway/meson.build
index c9bb8f83..146ad4b8 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -105,6 +105,7 @@ sway_sources = files(
105 'commands/input/xkb_rules.c', 105 'commands/input/xkb_rules.c',
106 'commands/input/xkb_variant.c', 106 'commands/input/xkb_variant.c',
107 107
108 'tree/arrange.c',
108 'tree/container.c', 109 'tree/container.c',
109 'tree/layout.c', 110 'tree/layout.c',
110 'tree/view.c', 111 'tree/view.c',
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
new file mode 100644
index 00000000..dd87ce7c
--- /dev/null
+++ b/sway/tree/arrange.c
@@ -0,0 +1,239 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.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 "sway/debug.h"
9#include "sway/tree/arrange.h"
10#include "sway/tree/container.h"
11#include "sway/tree/layout.h"
12#include "sway/output.h"
13#include "sway/tree/workspace.h"
14#include "sway/tree/view.h"
15#include "list.h"
16#include "log.h"
17
18struct sway_container root_container;
19
20void arrange_windows(struct sway_container *container) {
21 switch (container->type) {
22 case C_ROOT:
23 arrange_root();
24 break;
25 case C_OUTPUT:
26 arrange_output(container);
27 break;
28 case C_WORKSPACE:
29 arrange_workspace(container);
30 break;
31 case C_CONTAINER:
32 arrange_children_of(container);
33 break;
34 case C_VIEW:
35 // ignore
36 break;
37 case C_TYPES:
38 sway_assert(
39 false, "Called arrange_windows() with container type C_TYPES");
40 break;
41 }
42}
43
44void arrange_root() {
45 if (config->reloading) {
46 return;
47 }
48 struct wlr_output_layout *output_layout =
49 root_container.sway_root->output_layout;
50 const struct wlr_box *layout_box =
51 wlr_output_layout_get_box(output_layout, NULL);
52 root_container.x = layout_box->x;
53 root_container.y = layout_box->y;
54 root_container.width = layout_box->width;
55 root_container.height = layout_box->height;
56 for (int i = 0; i < root_container.children->length; ++i) {
57 struct sway_container *output = root_container.children->items[i];
58 arrange_output(output);
59 }
60}
61
62void arrange_output(struct sway_container *output) {
63 if (config->reloading) {
64 return;
65 }
66 if (!sway_assert(output->type == C_OUTPUT,
67 "called arrange_output() on non-output container")) {
68 return;
69 }
70 const struct wlr_box *output_box = wlr_output_layout_get_box(
71 root_container.sway_root->output_layout,
72 output->sway_output->wlr_output);
73 output->x = output_box->x;
74 output->y = output_box->y;
75 output->width = output_box->width;
76 output->height = output_box->height;
77 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
78 output->name, output->x, output->y);
79 for (int i = 0; i < output->children->length; ++i) {
80 struct sway_container *workspace = output->children->items[i];
81 arrange_workspace(workspace);
82 }
83 container_damage_whole(output);
84}
85
86void arrange_workspace(struct sway_container *workspace) {
87 if (config->reloading) {
88 return;
89 }
90 if (!sway_assert(workspace->type == C_WORKSPACE,
91 "called arrange_workspace() on non-workspace container")) {
92 return;
93 }
94 struct sway_container *output = workspace->parent;
95 struct wlr_box *area = &output->sway_output->usable_area;
96 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
97 area->width, area->height, area->x, area->y);
98 workspace->width = area->width;
99 workspace->height = area->height;
100 workspace->x = area->x;
101 workspace->y = area->y;
102 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
103 workspace->name, workspace->x, workspace->y);
104 arrange_children_of(workspace);
105 container_damage_whole(workspace);
106}
107
108static void apply_horiz_layout(struct sway_container *parent) {
109 size_t num_children = parent->children->length;
110 if (!num_children) {
111 return;
112 }
113 // Calculate total width of children
114 double total_width = 0;
115 for (size_t i = 0; i < num_children; ++i) {
116 struct sway_container *child = parent->children->items[i];
117 if (child->width <= 0) {
118 if (num_children > 1) {
119 child->width = parent->width / (num_children - 1);
120 } else {
121 child->width = parent->width;
122 }
123 }
124 total_width += child->width;
125 }
126 double scale = parent->width / total_width;
127
128 // Resize windows
129 wlr_log(L_DEBUG, "Arranging %p horizontally", parent);
130 double child_x = parent->x;
131 struct sway_container *child;
132 for (size_t i = 0; i < num_children; ++i) {
133 child = parent->children->items[i];
134 wlr_log(L_DEBUG,
135 "Calculating arrangement for %p:%d (will scale %f by %f)",
136 child, child->type, child->width, scale);
137 child->x = child_x;
138 child->y = parent->y;
139 child->width = floor(child->width * scale);
140 child->height = parent->height;
141 child_x += child->width;
142 }
143 // Make last child use remaining width of parent
144 child->width = parent->x + parent->width - child->x;
145}
146
147static void apply_vert_layout(struct sway_container *parent) {
148 size_t num_children = parent->children->length;
149 if (!num_children) {
150 return;
151 }
152 // Calculate total height of children
153 double total_height = 0;
154 for (size_t i = 0; i < num_children; ++i) {
155 struct sway_container *child = parent->children->items[i];
156 if (child->height <= 0) {
157 if (num_children > 1) {
158 child->height = parent->height / (num_children - 1);
159 } else {
160 child->height = parent->height;
161 }
162 }
163 total_height += child->height;
164 }
165 double scale = parent->height / total_height;
166
167 // Resize
168 wlr_log(L_DEBUG, "Arranging %p vertically", parent);
169 double child_y = parent->y;
170 struct sway_container *child;
171 for (size_t i = 0; i < num_children; ++i) {
172 child = parent->children->items[i];
173 wlr_log(L_DEBUG,
174 "Calculating arrangement for %p:%d (will scale %f by %f)",
175 child, child->type, child->height, scale);
176 child->x = parent->x;
177 child->y = child_y;
178 child->width = parent->width;
179 child->height = floor(child->height * scale);
180 child_y += child->height;
181 }
182 // Make last child use remaining height of parent
183 child->height = parent->y + parent->height - child->y;
184}
185
186void arrange_children_of(struct sway_container *parent) {
187 if (config->reloading) {
188 return;
189 }
190 if (!sway_assert(parent->type == C_WORKSPACE || parent->type == C_CONTAINER,
191 "container is a %s", container_type_to_str(parent->type))) {
192 return;
193 }
194
195 struct sway_container *workspace = parent;
196 if (workspace->type != C_WORKSPACE) {
197 workspace = container_parent(workspace, C_WORKSPACE);
198 }
199 if (workspace->sway_workspace->fullscreen) {
200 // Just arrange the fullscreen view and jump out
201 struct sway_container *view =
202 workspace->sway_workspace->fullscreen->swayc;
203 view_configure(view->sway_view, 0, 0,
204 workspace->parent->width, workspace->parent->height);
205 view->width = workspace->parent->width;
206 view->height = workspace->parent->height;
207 return;
208 }
209
210 wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent,
211 parent->name, parent->width, parent->height, parent->x, parent->y);
212
213 // Calculate x, y, width and height of children
214 switch (parent->layout) {
215 case L_HORIZ:
216 apply_horiz_layout(parent);
217 break;
218 case L_VERT:
219 apply_vert_layout(parent);
220 break;
221 default:
222 wlr_log(L_DEBUG, "TODO: arrange layout type %d", parent->layout);
223 apply_horiz_layout(parent);
224 break;
225 }
226
227 // Apply x, y, width and height to children and recurse if needed
228 for (int i = 0; i < parent->children->length; ++i) {
229 struct sway_container *child = parent->children->items[i];
230 if (child->type == C_VIEW) {
231 view_configure(child->sway_view, child->x, child->y,
232 child->width, child->height);
233 } else {
234 arrange_children_of(child);
235 }
236 }
237 container_damage_whole(parent);
238 update_debug_tree();
239}
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 09a6b7ce..03d7e49c 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -13,6 +13,7 @@
13#include "sway/ipc-server.h" 13#include "sway/ipc-server.h"
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/layout.h" 17#include "sway/tree/layout.h"
17#include "sway/tree/view.h" 18#include "sway/tree/view.h"
18#include "sway/tree/workspace.h" 19#include "sway/tree/workspace.h"
@@ -143,8 +144,7 @@ static struct sway_container *container_output_destroy(
143 container_add_child(root_container.children->items[p], child); 144 container_add_child(root_container.children->items[p], child);
144 } 145 }
145 container_sort_workspaces(root_container.children->items[p]); 146 container_sort_workspaces(root_container.children->items[p]);
146 arrange_windows(root_container.children->items[p], 147 arrange_output(root_container.children->items[p]);
147 -1, -1);
148 } 148 }
149 } 149 }
150 150
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index a64cc9a9..ec1c6fe5 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -7,6 +7,7 @@
7#include <wlr/types/wlr_output.h> 7#include <wlr/types/wlr_output.h>
8#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
9#include "sway/debug.h" 9#include "sway/debug.h"
10#include "sway/tree/arrange.h"
10#include "sway/tree/container.h" 11#include "sway/tree/container.h"
11#include "sway/tree/layout.h" 12#include "sway/tree/layout.h"
12#include "sway/output.h" 13#include "sway/output.h"
@@ -21,16 +22,7 @@ struct sway_container root_container;
21 22
22static void output_layout_handle_change(struct wl_listener *listener, 23static void output_layout_handle_change(struct wl_listener *listener,
23 void *data) { 24 void *data) {
24 struct wlr_output_layout *output_layout = 25 arrange_root();
25 root_container.sway_root->output_layout;
26 const struct wlr_box *layout_box =
27 wlr_output_layout_get_box(output_layout, NULL);
28 root_container.x = layout_box->x;
29 root_container.y = layout_box->y;
30 root_container.width = layout_box->width;
31 root_container.height = layout_box->height;
32
33 arrange_windows(&root_container, layout_box->width, layout_box->height);
34} 26}
35 27
36void layout_init(void) { 28void layout_init(void) {
@@ -91,13 +83,15 @@ static void container_handle_fullscreen_reparent(struct sway_container *viewcon,
91 83
92 // Mark the new workspace as fullscreen 84 // Mark the new workspace as fullscreen
93 if (new_workspace->sway_workspace->fullscreen) { 85 if (new_workspace->sway_workspace->fullscreen) {
94 view_set_fullscreen(new_workspace->sway_workspace->fullscreen, false); 86 view_set_fullscreen_raw(
87 new_workspace->sway_workspace->fullscreen, false);
95 } 88 }
96 new_workspace->sway_workspace->fullscreen = view; 89 new_workspace->sway_workspace->fullscreen = view;
97 // Resize view to new output dimensions 90 // Resize view to new output dimensions
98 struct sway_output *output = new_workspace->parent->sway_output; 91 struct sway_container *output = new_workspace->parent;
99 view_configure(view, 0, 0, 92 view_configure(view, 0, 0, output->width, output->height);
100 output->wlr_output->width, output->wlr_output->height); 93 view->swayc->width = output->width;
94 view->swayc->height = output->height;
101} 95}
102 96
103void container_insert_child(struct sway_container *parent, 97void container_insert_child(struct sway_container *parent,
@@ -166,6 +160,7 @@ void container_move_to(struct sway_container *container,
166 } 160 }
167 struct sway_container *old_parent = container_remove_child(container); 161 struct sway_container *old_parent = container_remove_child(container);
168 container->width = container->height = 0; 162 container->width = container->height = 0;
163 container->saved_width = container->saved_height = 0;
169 struct sway_container *new_parent; 164 struct sway_container *new_parent;
170 if (destination->type == C_VIEW) { 165 if (destination->type == C_VIEW) {
171 new_parent = container_add_sibling(destination, container); 166 new_parent = container_add_sibling(destination, container);
@@ -188,9 +183,9 @@ void container_move_to(struct sway_container *container,
188 seat_set_focus(seat, new_parent); 183 seat_set_focus(seat, new_parent);
189 } 184 }
190 if (old_parent) { 185 if (old_parent) {
191 arrange_windows(old_parent, -1, -1); 186 arrange_children_of(old_parent);
192 } 187 }
193 arrange_windows(new_parent, -1, -1); 188 arrange_children_of(new_parent);
194 // If view was moved to a fullscreen workspace, refocus the fullscreen view 189 // If view was moved to a fullscreen workspace, refocus the fullscreen view
195 struct sway_container *new_workspace = container; 190 struct sway_container *new_workspace = container;
196 if (new_workspace->type != C_WORKSPACE) { 191 if (new_workspace->type != C_WORKSPACE) {
@@ -299,7 +294,7 @@ static void workspace_rejigger(struct sway_container *ws,
299 container_reap_empty_recursive(original_parent); 294 container_reap_empty_recursive(original_parent);
300 wl_signal_emit(&child->events.reparent, original_parent); 295 wl_signal_emit(&child->events.reparent, original_parent);
301 container_create_notify(new_parent); 296 container_create_notify(new_parent);
302 arrange_windows(ws, -1, -1); 297 arrange_workspace(ws);
303} 298}
304 299
305void container_move(struct sway_container *container, 300void container_move(struct sway_container *container,
@@ -378,7 +373,7 @@ void container_move(struct sway_container *container,
378 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? 373 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ?
379 L_HORIZ : L_VERT; 374 L_HORIZ : L_VERT;
380 container_insert_child(current, container, offs < 0 ? 0 : 1); 375 container_insert_child(current, container, offs < 0 ? 0 : 1);
381 arrange_windows(current, -1, -1); 376 arrange_workspace(current);
382 } 377 }
383 return; 378 return;
384 } else { 379 } else {
@@ -402,8 +397,8 @@ void container_move(struct sway_container *container,
402 container_insert_child(current->parent, container, 397 container_insert_child(current->parent, container,
403 index + (offs < 0 ? 0 : 1)); 398 index + (offs < 0 ? 0 : 1));
404 container->width = container->height = 0; 399 container->width = container->height = 0;
405 arrange_windows(current->parent, -1, -1); 400 arrange_children_of(current->parent);
406 arrange_windows(old_parent, -1, -1); 401 arrange_children_of(old_parent);
407 return; 402 return;
408 } 403 }
409 } else { 404 } else {
@@ -433,14 +428,14 @@ void container_move(struct sway_container *container,
433 wlr_log(L_DEBUG, "Swapping siblings"); 428 wlr_log(L_DEBUG, "Swapping siblings");
434 sibling->parent->children->items[index + offs] = container; 429 sibling->parent->children->items[index + offs] = container;
435 sibling->parent->children->items[index] = sibling; 430 sibling->parent->children->items[index] = sibling;
436 arrange_windows(sibling->parent, -1, -1); 431 arrange_children_of(sibling->parent);
437 } else { 432 } else {
438 wlr_log(L_DEBUG, "Promoting to sibling of cousin"); 433 wlr_log(L_DEBUG, "Promoting to sibling of cousin");
439 container_insert_child(sibling->parent, container, 434 container_insert_child(sibling->parent, container,
440 index_child(sibling) + (offs > 0 ? 0 : 1)); 435 index_child(sibling) + (offs > 0 ? 0 : 1));
441 container->width = container->height = 0; 436 container->width = container->height = 0;
442 arrange_windows(sibling->parent, -1, -1); 437 arrange_children_of(sibling->parent);
443 arrange_windows(old_parent, -1, -1); 438 arrange_children_of(old_parent);
444 } 439 }
445 sibling = NULL; 440 sibling = NULL;
446 break; 441 break;
@@ -454,8 +449,8 @@ void container_move(struct sway_container *container,
454 "(move dir: %d)", limit, move_dir); 449 "(move dir: %d)", limit, move_dir);
455 container_insert_child(sibling, container, limit); 450 container_insert_child(sibling, container, limit);
456 container->width = container->height = 0; 451 container->width = container->height = 0;
457 arrange_windows(sibling, -1, -1); 452 arrange_children_of(sibling);
458 arrange_windows(old_parent, -1, -1); 453 arrange_children_of(old_parent);
459 sibling = NULL; 454 sibling = NULL;
460 } else { 455 } else {
461 wlr_log(L_DEBUG, "Reparenting container (perpendicular)"); 456 wlr_log(L_DEBUG, "Reparenting container (perpendicular)");
@@ -478,8 +473,8 @@ void container_move(struct sway_container *container,
478 container_add_child(sibling, container); 473 container_add_child(sibling, container);
479 } 474 }
480 container->width = container->height = 0; 475 container->width = container->height = 0;
481 arrange_windows(sibling, -1, -1); 476 arrange_children_of(sibling);
482 arrange_windows(old_parent, -1, -1); 477 arrange_children_of(old_parent);
483 sibling = NULL; 478 sibling = NULL;
484 } 479 }
485 break; 480 break;
@@ -553,234 +548,6 @@ void container_sort_workspaces(struct sway_container *output) {
553 list_stable_sort(output->children, sort_workspace_cmp_qsort); 548 list_stable_sort(output->children, sort_workspace_cmp_qsort);
554} 549}
555 550
556static void apply_horiz_layout(struct sway_container *container, const double x,
557 const double y, const double width,
558 const double height, const int start,
559 const int end);
560
561static void apply_vert_layout(struct sway_container *container, const double x,
562 const double y, const double width,
563 const double height, const int start,
564 const int end);
565
566void arrange_windows(struct sway_container *container,
567 double width, double height) {
568 if (config->reloading) {
569 return;
570 }
571 int i;
572 if (width == -1 || height == -1) {
573 width = container->width;
574 height = container->height;
575 }
576 // pixels are indivisible. if we don't round the pixels, then the view
577 // calculations will be off (e.g. 50.5 + 50.5 = 101, but in reality it's
578 // 50 + 50 = 100). doing it here cascades properly to all width/height/x/y.
579 width = floor(width);
580 height = floor(height);
581
582 wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container,
583 container->name, container->width, container->height, container->x,
584 container->y);
585
586 double x = 0, y = 0;
587 switch (container->type) {
588 case C_ROOT:
589 for (i = 0; i < container->children->length; ++i) {
590 struct sway_container *output = container->children->items[i];
591 const struct wlr_box *output_box = wlr_output_layout_get_box(
592 container->sway_root->output_layout,
593 output->sway_output->wlr_output);
594 output->x = output_box->x;
595 output->y = output_box->y;
596 output->width = output_box->width;
597 output->height = output_box->height;
598 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
599 output->name, output->x, output->y);
600 arrange_windows(output, output_box->width, output_box->height);
601 }
602 return;
603 case C_OUTPUT:
604 // arrange all workspaces:
605 for (i = 0; i < container->children->length; ++i) {
606 struct sway_container *child = container->children->items[i];
607 arrange_windows(child, -1, -1);
608 }
609 return;
610 case C_WORKSPACE:
611 {
612 struct sway_container *output =
613 container_parent(container, C_OUTPUT);
614 struct wlr_box *area = &output->sway_output->usable_area;
615 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
616 area->width, area->height, area->x, area->y);
617 container->width = width = area->width;
618 container->height = height = area->height;
619 container->x = x = area->x;
620 container->y = y = area->y;
621 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
622 container->name, container->x, container->y);
623 if (container->sway_workspace->fullscreen) {
624 view_configure(container->sway_workspace->fullscreen, 0, 0,
625 output->width, output->height);
626 return;
627 }
628 }
629 // children are properly handled below
630 break;
631 case C_VIEW:
632 {
633 container->width = width;
634 container->height = height;
635 view_configure(container->sway_view, container->x, container->y,
636 container->width, container->height);
637 wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f",
638 container->width, container->height,
639 container->x, container->y);
640 }
641 return;
642 default:
643 container->width = width;
644 container->height = height;
645 x = container->x;
646 y = container->y;
647 break;
648 }
649
650 switch (container->layout) {
651 case L_HORIZ:
652 apply_horiz_layout(container, x, y, width, height, 0,
653 container->children->length);
654 break;
655 case L_VERT:
656 apply_vert_layout(container, x, y, width, height, 0,
657 container->children->length);
658 break;
659 default:
660 wlr_log(L_DEBUG, "TODO: arrange layout type %d", container->layout);
661 apply_horiz_layout(container, x, y, width, height, 0,
662 container->children->length);
663 break;
664 }
665 container_damage_whole(container);
666 // TODO: Make this less shitty
667 update_debug_tree();
668}
669
670static void apply_horiz_layout(struct sway_container *container,
671 const double x, const double y,
672 const double width, const double height,
673 const int start, const int end) {
674 double scale = 0;
675 // Calculate total width
676 for (int i = start; i < end; ++i) {
677 double *old_width =
678 &((struct sway_container *)container->children->items[i])->width;
679 if (*old_width <= 0) {
680 if (end - start > 1) {
681 *old_width = width / (end - start - 1);
682 } else {
683 *old_width = width;
684 }
685 }
686 scale += *old_width;
687 }
688 scale = width / scale;
689
690 // Resize windows
691 double child_x = x;
692 if (scale > 0.1) {
693 wlr_log(L_DEBUG, "Arranging %p horizontally", container);
694 for (int i = start; i < end; ++i) {
695 struct sway_container *child = container->children->items[i];
696 wlr_log(L_DEBUG,
697 "Calculating arrangement for %p:%d (will scale %f by %f)",
698 child, child->type, width, scale);
699
700 if (child->type == C_VIEW) {
701 view_configure(child->sway_view, child_x, y, child->width,
702 child->height);
703 } else {
704 child->x = child_x;
705 child->y = y;
706 }
707
708 if (i == end - 1) {
709 double remaining_width = x + width - child_x;
710 arrange_windows(child, remaining_width, height);
711 } else {
712 arrange_windows(child, child->width * scale, height);
713 }
714 child_x += child->width;
715 }
716
717 // update focused view border last because it may
718 // depend on the title bar geometry of its siblings.
719 /* TODO WLR
720 if (focused && container->children->length > 1) {
721 update_container_border(focused);
722 }
723 */
724 }
725}
726
727void apply_vert_layout(struct sway_container *container,
728 const double x, const double y,
729 const double width, const double height, const int start,
730 const int end) {
731 int i;
732 double scale = 0;
733 // Calculate total height
734 for (i = start; i < end; ++i) {
735 double *old_height =
736 &((struct sway_container *)container->children->items[i])->height;
737 if (*old_height <= 0) {
738 if (end - start > 1) {
739 *old_height = height / (end - start - 1);
740 } else {
741 *old_height = height;
742 }
743 }
744 scale += *old_height;
745 }
746 scale = height / scale;
747
748 // Resize
749 double child_y = y;
750 if (scale > 0.1) {
751 wlr_log(L_DEBUG, "Arranging %p vertically", container);
752 for (i = start; i < end; ++i) {
753 struct sway_container *child = container->children->items[i];
754 wlr_log(L_DEBUG,
755 "Calculating arrangement for %p:%d (will scale %f by %f)",
756 child, child->type, height, scale);
757 if (child->type == C_VIEW) {
758 view_configure(child->sway_view, x, child_y, child->width,
759 child->height);
760 } else {
761 child->x = x;
762 child->y = child_y;
763 }
764
765 if (i == end - 1) {
766 double remaining_height = y + height - child_y;
767 arrange_windows(child, width, remaining_height);
768 } else {
769 arrange_windows(child, width, child->height * scale);
770 }
771 child_y += child->height;
772 }
773
774 // update focused view border last because it may
775 // depend on the title bar geometry of its siblings.
776 /* TODO WLR
777 if (focused && container->children->length > 1) {
778 update_container_border(focused);
779 }
780 */
781 }
782}
783
784/** 551/**
785 * Get swayc in the direction of newly entered output. 552 * Get swayc in the direction of newly entered output.
786 */ 553 */
@@ -1026,7 +793,7 @@ struct sway_container *container_split(struct sway_container *child,
1026 // Special case: this just behaves like splitt 793 // Special case: this just behaves like splitt
1027 child->prev_layout = child->layout; 794 child->prev_layout = child->layout;
1028 child->layout = layout; 795 child->layout = layout;
1029 arrange_windows(child, -1, -1); 796 arrange_children_of(child);
1030 return child; 797 return child;
1031 } 798 }
1032 799
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 3eeb1d97..e0aa6c0c 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -7,6 +7,7 @@
7#include "sway/ipc-server.h" 7#include "sway/ipc-server.h"
8#include "sway/output.h" 8#include "sway/output.h"
9#include "sway/input/seat.h" 9#include "sway/input/seat.h"
10#include "sway/tree/arrange.h"
10#include "sway/tree/container.h" 11#include "sway/tree/container.h"
11#include "sway/tree/layout.h" 12#include "sway/tree/layout.h"
12#include "sway/tree/view.h" 13#include "sway/tree/view.h"
@@ -78,14 +79,14 @@ void view_set_activated(struct sway_view *view, bool activated) {
78 } 79 }
79} 80}
80 81
81void view_set_fullscreen(struct sway_view *view, bool fullscreen) { 82// Set fullscreen, but without IPC events or arranging windows.
83void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen) {
82 if (view->is_fullscreen == fullscreen) { 84 if (view->is_fullscreen == fullscreen) {
83 return; 85 return;
84 } 86 }
85 87
86 struct sway_container *workspace = container_parent(view->swayc, C_WORKSPACE); 88 struct sway_container *workspace =
87 struct sway_container *container = container_parent(workspace, C_OUTPUT); 89 container_parent(view->swayc, C_WORKSPACE);
88 struct sway_output *output = container->sway_output;
89 90
90 if (view->impl->set_fullscreen) { 91 if (view->impl->set_fullscreen) {
91 view->impl->set_fullscreen(view, fullscreen); 92 view->impl->set_fullscreen(view, fullscreen);
@@ -98,6 +99,8 @@ void view_set_fullscreen(struct sway_view *view, bool fullscreen) {
98 view_set_fullscreen(workspace->sway_workspace->fullscreen, false); 99 view_set_fullscreen(workspace->sway_workspace->fullscreen, false);
99 } 100 }
100 workspace->sway_workspace->fullscreen = view; 101 workspace->sway_workspace->fullscreen = view;
102 view->swayc->saved_width = view->swayc->width;
103 view->swayc->saved_height = view->swayc->height;
101 104
102 struct sway_seat *seat; 105 struct sway_seat *seat;
103 struct sway_container *focus, *focus_ws; 106 struct sway_container *focus, *focus_ws;
@@ -114,11 +117,22 @@ void view_set_fullscreen(struct sway_view *view, bool fullscreen) {
114 } 117 }
115 } else { 118 } else {
116 workspace->sway_workspace->fullscreen = NULL; 119 workspace->sway_workspace->fullscreen = NULL;
120 view->swayc->width = view->swayc->saved_width;
121 view->swayc->height = view->swayc->saved_height;
117 } 122 }
123}
118 124
119 arrange_windows(workspace, -1, -1); 125void view_set_fullscreen(struct sway_view *view, bool fullscreen) {
120 output_damage_whole(output); 126 if (view->is_fullscreen == fullscreen) {
127 return;
128 }
121 129
130 view_set_fullscreen_raw(view, fullscreen);
131
132 struct sway_container *workspace =
133 container_parent(view->swayc, C_WORKSPACE);
134 arrange_workspace(workspace);
135 output_damage_whole(workspace->parent->sway_output);
122 ipc_event_window(view->swayc, "fullscreen_mode"); 136 ipc_event_window(view->swayc, "fullscreen_mode");
123} 137}
124 138
@@ -257,7 +271,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
257 wl_signal_add(&view->swayc->events.reparent, &view->container_reparent); 271 wl_signal_add(&view->swayc->events.reparent, &view->container_reparent);
258 view->container_reparent.notify = view_handle_container_reparent; 272 view->container_reparent.notify = view_handle_container_reparent;
259 273
260 arrange_windows(cont->parent, -1, -1); 274 arrange_children_of(cont->parent);
261 input_manager_set_focus(input_manager, cont); 275 input_manager_set_focus(input_manager, cont);
262 276
263 view_damage(view, true); 277 view_damage(view, true);
@@ -288,7 +302,7 @@ void view_unmap(struct sway_view *view) {
288 view->swayc = NULL; 302 view->swayc = NULL;
289 view->surface = NULL; 303 view->surface = NULL;
290 304
291 arrange_windows(parent, -1, -1); 305 arrange_children_of(parent);
292} 306}
293 307
294void view_update_position(struct sway_view *view, double ox, double oy) { 308void view_update_position(struct sway_view *view, double ox, double oy) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 66e1f7b9..f34baa9e 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -9,6 +9,7 @@
9#include "sway/input/input-manager.h" 9#include "sway/input/input-manager.h"
10#include "sway/input/seat.h" 10#include "sway/input/seat.h"
11#include "sway/ipc-server.h" 11#include "sway/ipc-server.h"
12#include "sway/tree/arrange.h"
12#include "sway/tree/container.h" 13#include "sway/tree/container.h"
13#include "sway/tree/workspace.h" 14#include "sway/tree/workspace.h"
14#include "log.h" 15#include "log.h"
@@ -392,7 +393,7 @@ bool workspace_switch(struct sway_container *workspace) {
392 } 393 }
393 seat_set_focus(seat, next); 394 seat_set_focus(seat, next);
394 struct sway_container *output = container_parent(workspace, C_OUTPUT); 395 struct sway_container *output = container_parent(workspace, C_OUTPUT);
395 arrange_windows(output, -1, -1); 396 arrange_output(output);
396 return true; 397 return true;
397} 398}
398 399