aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/arrange.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-06-03 16:35:06 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-06-09 10:08:43 +1000
commit59c94887018bdfa578c4371c4275061ca6e71b3e (patch)
tree62bdaa6ac4777d1fcb292013bddd2043dad7765a /sway/tree/arrange.c
parentMerge pull request #2115 from RedSoxFan/restore-workspaces (diff)
downloadsway-59c94887018bdfa578c4371c4275061ca6e71b3e.tar.gz
sway-59c94887018bdfa578c4371c4275061ca6e71b3e.tar.zst
sway-59c94887018bdfa578c4371c4275061ca6e71b3e.zip
WIP: Atomic layout updates ground work
Diffstat (limited to 'sway/tree/arrange.c')
-rw-r--r--sway/tree/arrange.c321
1 files changed, 177 insertions, 144 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 721b557e..d8b3aec1 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -5,7 +5,6 @@
5#include <string.h> 5#include <string.h>
6#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
7#include <wlr/types/wlr_output_layout.h> 7#include <wlr/types/wlr_output_layout.h>
8#include "sway/debug.h"
9#include "sway/tree/arrange.h" 8#include "sway/tree/arrange.h"
10#include "sway/tree/container.h" 9#include "sway/tree/container.h"
11#include "sway/tree/layout.h" 10#include "sway/tree/layout.h"
@@ -17,116 +16,56 @@
17 16
18struct sway_container root_container; 17struct sway_container root_container;
19 18
20void arrange_root() {
21 if (config->reloading) {
22 return;
23 }
24 struct wlr_output_layout *output_layout =
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 for (int i = 0; i < root_container.children->length; ++i) {
33 struct sway_container *output = root_container.children->items[i];
34 arrange_output(output);
35 }
36}
37
38void arrange_output(struct sway_container *output) {
39 if (config->reloading) {
40 return;
41 }
42 if (!sway_assert(output->type == C_OUTPUT,
43 "called arrange_output() on non-output container")) {
44 return;
45 }
46 const struct wlr_box *output_box = wlr_output_layout_get_box(
47 root_container.sway_root->output_layout,
48 output->sway_output->wlr_output);
49 output->x = output_box->x;
50 output->y = output_box->y;
51 output->width = output_box->width;
52 output->height = output_box->height;
53 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
54 output->name, output->x, output->y);
55 for (int i = 0; i < output->children->length; ++i) {
56 struct sway_container *workspace = output->children->items[i];
57 arrange_workspace(workspace);
58 }
59 container_damage_whole(output);
60}
61
62void arrange_workspace(struct sway_container *workspace) {
63 if (config->reloading) {
64 return;
65 }
66 if (!sway_assert(workspace->type == C_WORKSPACE,
67 "called arrange_workspace() on non-workspace container")) {
68 return;
69 }
70 struct sway_container *output = workspace->parent;
71 struct wlr_box *area = &output->sway_output->usable_area;
72 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
73 area->width, area->height, area->x, area->y);
74 workspace->width = area->width;
75 workspace->height = area->height;
76 workspace->x = output->x + area->x;
77 workspace->y = output->y + area->y;
78 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
79 workspace->name, workspace->x, workspace->y);
80 arrange_children_of(workspace);
81 container_damage_whole(workspace);
82}
83
84static void apply_horiz_layout(struct sway_container *parent) { 19static void apply_horiz_layout(struct sway_container *parent) {
85 size_t num_children = parent->children->length; 20 size_t num_children = parent->children->length;
86 if (!num_children) { 21 if (!num_children) {
87 return; 22 return;
88 } 23 }
89 size_t parent_offset = 0; 24 size_t parent_offset = 0;
90 if (parent->parent->layout == L_TABBED) { 25 if (parent->parent->pending.layout == L_TABBED) {
91 parent_offset = container_titlebar_height(); 26 parent_offset = container_titlebar_height();
92 } else if (parent->parent->layout == L_STACKED) { 27 } else if (parent->parent->pending.layout == L_STACKED) {
93 parent_offset = 28 parent_offset = container_titlebar_height() *
94 container_titlebar_height() * parent->parent->children->length; 29 parent->parent->children->length;
95 } 30 }
96 size_t parent_height = parent->height - parent_offset; 31 size_t parent_height = parent->pending.swayc_height - parent_offset;
97 32
98 // Calculate total width of children 33 // Calculate total width of children
99 double total_width = 0; 34 double total_width = 0;
100 for (size_t i = 0; i < num_children; ++i) { 35 for (size_t i = 0; i < num_children; ++i) {
101 struct sway_container *child = parent->children->items[i]; 36 struct sway_container *child = parent->children->items[i];
102 if (child->width <= 0) { 37 if (child->pending.swayc_width <= 0) {
103 if (num_children > 1) { 38 if (num_children > 1) {
104 child->width = parent->width / (num_children - 1); 39 child->pending.swayc_width =
40 parent->pending.swayc_width / (num_children - 1);
105 } else { 41 } else {
106 child->width = parent->width; 42 child->pending.swayc_width = parent->pending.swayc_width;
107 } 43 }
108 } 44 }
109 total_width += child->width; 45 total_width += child->pending.swayc_width;
110 } 46 }
111 double scale = parent->width / total_width; 47 double scale = parent->pending.swayc_width / total_width;
112 48
113 // Resize windows 49 // Resize windows
114 wlr_log(L_DEBUG, "Arranging %p horizontally", parent); 50 wlr_log(L_DEBUG, "Arranging %p horizontally", parent);
115 double child_x = parent->x; 51 double child_x = parent->pending.swayc_x;
116 struct sway_container *child;
117 for (size_t i = 0; i < num_children; ++i) { 52 for (size_t i = 0; i < num_children; ++i) {
118 child = parent->children->items[i]; 53 struct sway_container *child = parent->children->items[i];
119 wlr_log(L_DEBUG, 54 wlr_log(L_DEBUG,
120 "Calculating arrangement for %p:%d (will scale %f by %f)", 55 "Calculating arrangement for %p:%d (will scale %f by %f)",
121 child, child->type, child->width, scale); 56 child, child->type, child->pending.swayc_width, scale);
122 child->x = child_x; 57 child->pending.swayc_x = child_x;
123 child->y = parent->y + parent_offset; 58 child->pending.swayc_y = parent->pending.swayc_y + parent_offset;
124 child->width = floor(child->width * scale); 59 child->pending.swayc_width = floor(child->pending.swayc_width * scale);
125 child->height = parent_height; 60 child->pending.swayc_height = parent_height;
126 child_x += child->width; 61 child_x += child->pending.swayc_width;
62
63 // Make last child use remaining width of parent
64 if (i == num_children - 1) {
65 child->pending.swayc_width = parent->pending.swayc_x +
66 parent->pending.swayc_width - child->pending.swayc_x;
67 }
127 } 68 }
128 // Make last child use remaining width of parent
129 child->width = parent->x + parent->width - child->x;
130} 69}
131 70
132static void apply_vert_layout(struct sway_container *parent) { 71static void apply_vert_layout(struct sway_container *parent) {
@@ -135,46 +74,51 @@ static void apply_vert_layout(struct sway_container *parent) {
135 return; 74 return;
136 } 75 }
137 size_t parent_offset = 0; 76 size_t parent_offset = 0;
138 if (parent->parent->layout == L_TABBED) { 77 if (parent->parent->pending.layout == L_TABBED) {
139 parent_offset = container_titlebar_height(); 78 parent_offset = container_titlebar_height();
140 } else if (parent->parent->layout == L_STACKED) { 79 } else if (parent->parent->pending.layout == L_STACKED) {
141 parent_offset = 80 parent_offset =
142 container_titlebar_height() * parent->parent->children->length; 81 container_titlebar_height() * parent->parent->children->length;
143 } 82 }
144 size_t parent_height = parent->height - parent_offset; 83 size_t parent_height = parent->pending.swayc_height - parent_offset;
145 84
146 // Calculate total height of children 85 // Calculate total height of children
147 double total_height = 0; 86 double total_height = 0;
148 for (size_t i = 0; i < num_children; ++i) { 87 for (size_t i = 0; i < num_children; ++i) {
149 struct sway_container *child = parent->children->items[i]; 88 struct sway_container *child = parent->children->items[i];
150 if (child->height <= 0) { 89 if (child->pending.swayc_height <= 0) {
151 if (num_children > 1) { 90 if (num_children > 1) {
152 child->height = parent_height / (num_children - 1); 91 child->pending.swayc_height =
92 parent_height / (num_children - 1);
153 } else { 93 } else {
154 child->height = parent_height; 94 child->pending.swayc_height = parent_height;
155 } 95 }
156 } 96 }
157 total_height += child->height; 97 total_height += child->pending.swayc_height;
158 } 98 }
159 double scale = parent_height / total_height; 99 double scale = parent_height / total_height;
160 100
161 // Resize 101 // Resize
162 wlr_log(L_DEBUG, "Arranging %p vertically", parent); 102 wlr_log(L_DEBUG, "Arranging %p vertically", parent);
163 double child_y = parent->y + parent_offset; 103 double child_y = parent->pending.swayc_y + parent_offset;
164 struct sway_container *child;
165 for (size_t i = 0; i < num_children; ++i) { 104 for (size_t i = 0; i < num_children; ++i) {
166 child = parent->children->items[i]; 105 struct sway_container *child = parent->children->items[i];
167 wlr_log(L_DEBUG, 106 wlr_log(L_DEBUG,
168 "Calculating arrangement for %p:%d (will scale %f by %f)", 107 "Calculating arrangement for %p:%d (will scale %f by %f)",
169 child, child->type, child->height, scale); 108 child, child->type, child->pending.swayc_height, scale);
170 child->x = parent->x; 109 child->pending.swayc_x = parent->pending.swayc_x;
171 child->y = child_y; 110 child->pending.swayc_y = child_y;
172 child->width = parent->width; 111 child->pending.swayc_width = parent->pending.swayc_width;
173 child->height = floor(child->height * scale); 112 child->pending.swayc_height =
174 child_y += child->height; 113 floor(child->pending.swayc_height * scale);
114 child_y += child->pending.swayc_height;
115
116 // Make last child use remaining height of parent
117 if (i == num_children - 1) {
118 child->pending.swayc_height = parent->pending.swayc_y +
119 parent_offset + parent_height - child->pending.swayc_y;
120 }
175 } 121 }
176 // Make last child use remaining height of parent
177 child->height = parent->y + parent_offset + parent_height - child->y;
178} 122}
179 123
180static void apply_tabbed_or_stacked_layout(struct sway_container *parent) { 124static void apply_tabbed_or_stacked_layout(struct sway_container *parent) {
@@ -182,46 +126,33 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) {
182 return; 126 return;
183 } 127 }
184 size_t parent_offset = 0; 128 size_t parent_offset = 0;
185 if (parent->parent->layout == L_TABBED) { 129 if (parent->parent->pending.layout == L_TABBED) {
186 parent_offset = container_titlebar_height(); 130 parent_offset = container_titlebar_height();
187 } else if (parent->parent->layout == L_STACKED) { 131 } else if (parent->parent->pending.layout == L_STACKED) {
188 parent_offset = 132 parent_offset =
189 container_titlebar_height() * parent->parent->children->length; 133 container_titlebar_height() * parent->parent->children->length;
190 } 134 }
191 size_t parent_height = parent->height - parent_offset; 135 size_t parent_height = parent->pending.swayc_height - parent_offset;
192 for (int i = 0; i < parent->children->length; ++i) { 136 for (int i = 0; i < parent->children->length; ++i) {
193 struct sway_container *child = parent->children->items[i]; 137 struct sway_container *child = parent->children->items[i];
194 child->x = parent->x; 138 child->pending.swayc_x = parent->pending.swayc_x;
195 child->y = parent->y + parent_offset; 139 child->pending.swayc_y = parent->pending.swayc_y + parent_offset;
196 child->width = parent->width; 140 child->pending.swayc_width = parent->pending.swayc_width;
197 child->height = parent_height; 141 child->pending.swayc_height = parent_height;
198 } 142 }
199} 143}
200 144
201void arrange_children_of(struct sway_container *parent) { 145static void _arrange_children_of(struct sway_container *parent,
146 struct sway_transaction *transaction) {
202 if (config->reloading) { 147 if (config->reloading) {
203 return; 148 return;
204 } 149 }
205 if (!sway_assert(parent->type == C_WORKSPACE || parent->type == C_CONTAINER,
206 "container is a %s", container_type_to_str(parent->type))) {
207 return;
208 }
209
210 struct sway_container *workspace = parent;
211 if (workspace->type != C_WORKSPACE) {
212 workspace = container_parent(workspace, C_WORKSPACE);
213 }
214 if (workspace->sway_workspace->fullscreen) {
215 // Just arrange the fullscreen view and jump out
216 view_autoconfigure(workspace->sway_workspace->fullscreen);
217 return;
218 }
219
220 wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent, 150 wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent,
221 parent->name, parent->width, parent->height, parent->x, parent->y); 151 parent->name, parent->pending.swayc_width, parent->pending.swayc_height,
152 parent->pending.swayc_x, parent->pending.swayc_y);
222 153
223 // Calculate x, y, width and height of children 154 // Calculate x, y, width and height of children
224 switch (parent->layout) { 155 switch (parent->pending.layout) {
225 case L_HORIZ: 156 case L_HORIZ:
226 apply_horiz_layout(parent); 157 apply_horiz_layout(parent);
227 break; 158 break;
@@ -232,33 +163,135 @@ void arrange_children_of(struct sway_container *parent) {
232 case L_STACKED: 163 case L_STACKED:
233 apply_tabbed_or_stacked_layout(parent); 164 apply_tabbed_or_stacked_layout(parent);
234 break; 165 break;
235 default: 166 case L_NONE:
236 wlr_log(L_DEBUG, "TODO: arrange layout type %d", parent->layout);
237 apply_horiz_layout(parent); 167 apply_horiz_layout(parent);
238 break; 168 break;
169 case L_FLOATING:
170 sway_assert(false, "Didn't expect to see floating here");
239 } 171 }
240 172
241 // Apply x, y, width and height to children and recurse if needed 173 // Recurse into child containers
242 for (int i = 0; i < parent->children->length; ++i) { 174 for (int i = 0; i < parent->children->length; ++i) {
243 struct sway_container *child = parent->children->items[i]; 175 struct sway_container *child = parent->children->items[i];
244 if (child->type == C_VIEW) { 176 if (child->type == C_VIEW) {
245 view_autoconfigure(child->sway_view); 177 view_autoconfigure(child->sway_view);
246 } else { 178 } else {
247 arrange_children_of(child); 179 _arrange_children_of(child, transaction);
248 } 180 }
181 transaction_add_container(transaction, child);
249 } 182 }
183}
250 184
251 // If container is a workspace, process floating containers too 185static void _arrange_workspace(struct sway_container *workspace,
252 if (parent->type == C_WORKSPACE) { 186 struct sway_transaction *transaction) {
253 struct sway_workspace *ws = workspace->sway_workspace; 187 if (config->reloading) {
254 for (int i = 0; i < ws->floating->children->length; ++i) { 188 return;
255 struct sway_container *child = ws->floating->children->items[i]; 189 }
256 if (child->type != C_VIEW) { 190 struct sway_container *output = workspace->parent;
257 arrange_children_of(child); 191 struct wlr_box *area = &output->sway_output->usable_area;
258 } 192 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
259 } 193 area->width, area->height, area->x, area->y);
194 workspace->pending.swayc_width = area->width;
195 workspace->pending.swayc_height = area->height;
196 workspace->pending.swayc_x = output->x + area->x;
197 workspace->pending.swayc_y = output->y + area->y;
198 transaction_add_container(transaction, workspace);
199 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name,
200 workspace->pending.swayc_x, workspace->pending.swayc_y);
201 _arrange_children_of(workspace, transaction);
202}
203
204static void _arrange_output(struct sway_container *output,
205 struct sway_transaction *transaction) {
206 if (config->reloading) {
207 return;
208 }
209 const struct wlr_box *output_box = wlr_output_layout_get_box(
210 root_container.sway_root->output_layout,
211 output->sway_output->wlr_output);
212 output->x = output_box->x;
213 output->y = output_box->y;
214 output->width = output_box->width;
215 output->height = output_box->height;
216 output->pending.swayc_x = output_box->x;
217 output->pending.swayc_y = output_box->y;
218 output->pending.swayc_width = output_box->width;
219 output->pending.swayc_height = output_box->height;
220 transaction_add_container(transaction, output);
221 wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
222 output->name, output->pending.swayc_x, output->pending.swayc_y);
223 for (int i = 0; i < output->children->length; ++i) {
224 struct sway_container *workspace = output->children->items[i];
225 _arrange_workspace(workspace, transaction);
226 }
227}
228
229static void _arrange_root(struct sway_transaction *transaction) {
230 if (config->reloading) {
231 return;
260 } 232 }
233 struct wlr_output_layout *output_layout =
234 root_container.sway_root->output_layout;
235 const struct wlr_box *layout_box =
236 wlr_output_layout_get_box(output_layout, NULL);
237 root_container.x = layout_box->x;
238 root_container.y = layout_box->y;
239 root_container.width = layout_box->width;
240 root_container.height = layout_box->height;
241 root_container.pending.swayc_x = layout_box->x;
242 root_container.pending.swayc_y = layout_box->y;
243 root_container.pending.swayc_width = layout_box->width;
244 root_container.pending.swayc_height = layout_box->height;
245 transaction_add_container(transaction, &root_container);
246 for (int i = 0; i < root_container.children->length; ++i) {
247 struct sway_container *output = root_container.children->items[i];
248 _arrange_output(output, transaction);
249 }
250}
251
252void arrange_windows(struct sway_container *container,
253 struct sway_transaction *transaction) {
254 switch (container->type) {
255 case C_ROOT:
256 _arrange_root(transaction);
257 break;
258 case C_OUTPUT:
259 _arrange_output(container, transaction);
260 break;
261 case C_WORKSPACE:
262 _arrange_workspace(container, transaction);
263 break;
264 case C_CONTAINER:
265 _arrange_children_of(container, transaction);
266 transaction_add_container(transaction, container);
267 break;
268 case C_VIEW:
269 break;
270 case C_TYPES:
271 break;
272 }
273 transaction_add_damage(transaction, container_get_box(container));
274}
275
276void arrange_and_commit(struct sway_container *container) {
277 struct sway_transaction *transaction = transaction_create();
278 arrange_windows(container, transaction);
279 transaction_commit(transaction);
280}
281
282// These functions are only temporary
283void arrange_root() {
284 arrange_and_commit(&root_container);
285}
286
287void arrange_output(struct sway_container *container) {
288 arrange_and_commit(container);
289}
290
291void arrange_workspace(struct sway_container *container) {
292 arrange_and_commit(container);
293}
261 294
262 container_damage_whole(parent); 295void arrange_children_of(struct sway_container *container) {
263 update_debug_tree(); 296 arrange_and_commit(container);
264} 297}