summaryrefslogtreecommitdiffstats
path: root/sway/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/layout.c')
-rw-r--r--sway/layout.c275
1 files changed, 72 insertions, 203 deletions
diff --git a/sway/layout.c b/sway/layout.c
index ccf29f34..8b9315b4 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -9,25 +9,75 @@
9 9
10swayc_t root_container; 10swayc_t root_container;
11 11
12swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { 12void init_layout(void) {
13 if (!container->children) { 13 root_container.type = C_ROOT;
14 root_container.layout = L_NONE;
15 root_container.children = create_list();
16 root_container.handle = -1;
17}
18
19static int index_child(swayc_t *parent, swayc_t *child) {
20 int i;
21 for (i = 0; i < parent->children->length; ++i) {
22 if (parent->children->items[i] == child) {
23 break;
24 }
25 }
26 return i;
27}
28
29void add_child(swayc_t *parent, swayc_t *child) {
30 sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type,
31 child->width, child->height, parent, parent->type, parent->width, parent->height);
32 list_add(parent->children, child);
33 child->parent = parent;
34 if (parent->focused == NULL) {
35 parent->focused = child;
36 }
37}
38
39swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) {
40 swayc_t *parent = sibling->parent;
41 int i = index_child(parent, sibling);
42 if (i == parent->children->length) {
43 --i;
44 }
45 list_insert(parent->children, i+1, child);
46 child->parent = parent;
47 return child->parent;
48}
49
50swayc_t *replace_child(swayc_t *child, swayc_t *new_child) {
51 swayc_t *parent = child->parent;
52 if (parent == NULL) {
14 return NULL; 53 return NULL;
15 } 54 }
55 int i = index_child(parent, child);
56 parent->children->items[i] = new_child;
57 new_child->parent = child->parent;
58
59 if (child->parent->focused == child) {
60 child->parent->focused = new_child;
61 }
62 child->parent = NULL;
63 return parent;
64}
65
66swayc_t *remove_child(swayc_t *parent, swayc_t *child) {
16 int i; 67 int i;
17 for (i = 0; i < container->children->length; ++i) { 68 for (i = 0; i < parent->children->length; ++i) {
18 swayc_t *child = container->children->items[i]; 69 if (parent->children->items[i] == child) {
19 if (test(child, data)) { 70 list_del(parent->children, i);
20 return child; 71 break;
21 } else {
22 swayc_t *_ = find_container(child, test, data);
23 if (_) {
24 return _;
25 }
26 } 72 }
27 } 73 }
28 return NULL; 74 if (parent->focused == child) {
75 parent->focused = NULL;
76 }
77 return parent;
29} 78}
30 79
80
31void arrange_windows(swayc_t *container, int width, int height) { 81void arrange_windows(swayc_t *container, int width, int height) {
32 int i; 82 int i;
33 if (width == -1 || height == -1) { 83 if (width == -1 || height == -1) {
@@ -68,7 +118,7 @@ void arrange_windows(swayc_t *container, int width, int height) {
68 }; 118 };
69 if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { 119 if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) {
70 swayc_t *parent = container; 120 swayc_t *parent = container;
71 while(parent->type != C_OUTPUT) { 121 while (parent->type != C_OUTPUT) {
72 parent = parent->parent; 122 parent = parent->parent;
73 } 123 }
74 geometry.origin.x = 0; 124 geometry.origin.x = 0;
@@ -131,25 +181,6 @@ void arrange_windows(swayc_t *container, int width, int height) {
131 } 181 }
132} 182}
133 183
134void init_layout(void) {
135 root_container.type = C_ROOT;
136 root_container.layout = L_NONE;
137 root_container.children = create_list();
138 root_container.handle = -1;
139}
140
141void free_swayc(swayc_t *container) {
142 // NOTE: Does not handle moving children into a different container
143 if (container->parent) {
144 remove_container_from_parent(container->parent, container);
145 }
146 list_free(container->children);
147 if (container->name) {
148 free(container->name);
149 }
150 free(container);
151}
152
153swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { 184swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) {
154 if (parent->children == NULL) { 185 if (parent->children == NULL) {
155 return NULL; 186 return NULL;
@@ -176,99 +207,6 @@ swayc_t *get_focused_container(swayc_t *parent) {
176 return get_focused_container(parent->focused); 207 return get_focused_container(parent->focused);
177} 208}
178 209
179void add_view(wlc_handle view_handle) {
180 const uint32_t type = wlc_view_get_type(view_handle);
181 const char *title = wlc_view_get_title(view_handle);
182 if ((type & WLC_BIT_OVERRIDE_REDIRECT) || (type & WLC_BIT_UNMANAGED) || (type &
183 WLC_BIT_POPUP) || (type & WLC_BIT_MODAL) || (type & WLC_BIT_SPLASH)) {
184 sway_log(L_DEBUG, "Leaving view %d:%s alone (unmanaged)", view_handle, title);
185 unfocus_all(&root_container);
186 wlc_view_set_state(view_handle, WLC_BIT_ACTIVATED, true);
187 wlc_view_focus(view_handle);
188 return;
189 }
190
191 swayc_t *parent = get_focused_container(&root_container);
192 sway_log(L_DEBUG, "Adding new view %d:%s:%d under container %p %d", view_handle, title, type, parent, parent->type);
193
194 while (parent->type == C_VIEW) {
195 parent = parent->parent;
196 }
197
198 swayc_t *view = calloc(1, sizeof(swayc_t));
199 view->weight = 1;
200 view->layout = L_NONE;
201 view->handle = view_handle;
202 view->parent = parent;
203 view->type = C_VIEW;
204 view->visible = true;
205 if (title) {
206 view->name = malloc(strlen(title) + 1);
207 strcpy(view->name, title);
208 }
209 add_child(parent, view);
210
211 unfocus_all(&root_container);
212 focus_view(view);
213
214 arrange_windows(parent, -1, -1);
215}
216
217int remove_container_from_parent(swayc_t *parent, swayc_t *container) {
218 int i;
219 for (i = 0; i < parent->children->length; ++i) {
220 if (parent->children->items[i] == container) {
221 list_del(parent->children, i);
222 break;
223 }
224 }
225
226 if (parent->focused == container) {
227 parent->focused = NULL;
228 }
229
230 return i;
231}
232
233void destroy_view(swayc_t *view) {
234 if (view == NULL) {
235 sway_log(L_DEBUG, "Warning: NULL passed into destroy_view");
236 return;
237 }
238 sway_log(L_DEBUG, "Destroying container %p", view);
239 swayc_t *parent = view->parent;
240 if (!parent) {
241 return;
242 }
243
244 int i;
245 for (i = 0; i < parent->children->length; ++i) {
246 if (parent->children->items[i] == view) {
247 list_del(parent->children, i);
248 break;
249 }
250 }
251
252 free_swayc(view);
253
254 if (parent->focused == view) {
255 parent->focused = NULL;
256 }
257
258 unfocus_all(&root_container);
259 if (parent->children->length != 0) {
260 focus_view(parent->children->items[0]);
261 } else {
262 focus_view(parent);
263 }
264
265 arrange_windows(parent, -1, -1);
266
267 if (parent->children->length == 0 && parent->type == C_CONTAINER) {
268 destroy_view(parent);
269 }
270}
271
272void unfocus_all(swayc_t *container) { 210void unfocus_all(swayc_t *container) {
273 if (container->children == NULL) { 211 if (container->children == NULL) {
274 return; 212 return;
@@ -285,85 +223,16 @@ void unfocus_all(swayc_t *container) {
285} 223}
286 224
287void focus_view(swayc_t *view) { 225void focus_view(swayc_t *view) {
288 sway_log(L_DEBUG, "Setting focus for %p", view); 226 sway_log(L_DEBUG, "Setting focus to %p", view);
289 if (view == &root_container) { 227 if (view->type == C_VIEW) {
290 // Propegate wayland focus down 228 wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, true);
291 swayc_t *child = view->focused; 229 wlc_view_bring_to_front(view->handle);
292 while (child && child->type != C_VIEW) { 230 wlc_view_focus(view->handle);
293 child = child->focused;
294 }
295 if (child) {
296 wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, true);
297 wlc_view_focus(child->handle);
298 }
299 return;
300 }
301 view->parent->focused = view;
302 focus_view(view->parent);
303}
304
305void add_child(swayc_t *parent, swayc_t *child) {
306 sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type,
307 child->width, child->height, parent, parent->type, parent->width, parent->height);
308 list_add(parent->children, child);
309}
310
311swayc_t *create_container(swayc_t *parent, wlc_handle handle) {
312 swayc_t *c = calloc(1, sizeof(swayc_t));
313 c->weight = 1;
314 c->handle = handle;
315 c->parent = parent;
316 c->layout = L_NONE;
317 c->type = C_CONTAINER;
318 c->children = create_list();
319 return c;
320}
321
322void add_output_widths(swayc_t *container, void *_width) {
323 int *width = _width;
324 if (container->type == C_OUTPUT) {
325 *width += container->width;
326 } 231 }
327} 232 // Propagete focus up
328 233 while (view != &root_container) {
329void add_output(wlc_handle output) { 234 view->parent->focused = view;
330 sway_log(L_DEBUG, "Adding output %d", output); 235 view = view->parent;
331 const struct wlc_size* size = wlc_output_get_resolution(output);
332
333 swayc_t *container = create_container(&root_container, output);
334 container->type = C_OUTPUT;
335 container->width = size->w;
336 container->height = size->h;
337 add_child(&root_container, container);
338
339 int total_width = 0;
340 container_map(&root_container, add_output_widths, &total_width);
341
342 swayc_t *workspace = create_container(container, -1);
343 workspace->type = C_WORKSPACE;
344 workspace->name = workspace_next_name();
345 workspace->width = size->w; // TODO: gaps
346 workspace->height = size->h;
347 workspace->layout = L_HORIZ; // TODO: Get default layout from config
348 add_child(container, workspace);
349 sway_log(L_DEBUG, "Added workspace %s for output %d", workspace->name, output);
350
351 if (root_container.focused == NULL) {
352 workspace_switch(workspace);
353 unfocus_all(&root_container);
354 focus_view(workspace);
355 } 236 }
356} 237}
357 238
358void destroy_output(wlc_handle output) {
359 sway_log(L_DEBUG, "Destroying output %d", output);
360 int i;
361 for (i = 0; i < root_container.children->length; ++i) {
362 swayc_t *c = root_container.children->items[i];
363 if (c->handle == output) {
364 list_del(root_container.children, i);
365 free_swayc(c);
366 return;
367 }
368 }
369}