aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-26 12:05:16 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-26 12:05:16 +1000
commit5dbbab7bdc56fc513eea2f9a39d722859a3b0c2e (patch)
tree2aad57ba7f7eec9fdb51b98859f6da826a4d39a1 /sway/tree/layout.c
parentMerge pull request #2488 from RyanDwyer/separate-gaps-functions (diff)
downloadsway-5dbbab7bdc56fc513eea2f9a39d722859a3b0c2e.tar.gz
sway-5dbbab7bdc56fc513eea2f9a39d722859a3b0c2e.tar.zst
sway-5dbbab7bdc56fc513eea2f9a39d722859a3b0c2e.zip
Remove layout.c
When we have type safety we'll need to have functions for workspace_add_tiling and so on. This means the existing container functions will be just for containers, so they are being moved to container.c. At this point layout.c doesn't contain much else, so I've relocated everything and removed the file. * container_swap and its static functions have been moved to the swap command and made static. * container_recursive_resize has been moved to the resize command and made static. * The following have been moved to container.c: * container_handle_fullscreen_reparent * container_insert_child * container_add_sibling * container_add_child * container_remove_child * container_replace_child * container_split * enum movement_direction and sway_dir_to_wlr have been moved to util.c. Side note: Several commands included layout.h which then included root.h. With layout.h gone, root.h has to be included by those commands.
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c403
1 files changed, 0 insertions, 403 deletions
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}