summaryrefslogtreecommitdiffstats
path: root/sway/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/container.c')
-rw-r--r--sway/container.c138
1 files changed, 94 insertions, 44 deletions
diff --git a/sway/container.c b/sway/container.c
index 4559a5f5..7ccc2e09 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -8,6 +8,8 @@
8#include "layout.h" 8#include "layout.h"
9#include "log.h" 9#include "log.h"
10 10
11#define ASSERT_NONNULL(PTR) \
12 sway_assert (PTR, "%s: " #PTR "must be non-null", __func__)
11 13
12static swayc_t *new_swayc(enum swayc_types type) { 14static swayc_t *new_swayc(enum swayc_types type) {
13 swayc_t *c = calloc(1, sizeof(swayc_t)); 15 swayc_t *c = calloc(1, sizeof(swayc_t));
@@ -20,37 +22,40 @@ static swayc_t *new_swayc(enum swayc_types type) {
20 return c; 22 return c;
21} 23}
22 24
23static void free_swayc(swayc_t *c) { 25static void free_swayc(swayc_t *cont) {
26 if (!ASSERT_NONNULL(cont)) {
27 return;
28 }
24 // TODO does not properly handle containers with children, 29 // TODO does not properly handle containers with children,
25 // TODO but functions that call this usually check for that 30 // TODO but functions that call this usually check for that
26 if (c->children) { 31 if (cont->children) {
27 if (c->children->length) { 32 if (cont->children->length) {
28 int i; 33 int i;
29 for (i = 0; i < c->children->length; ++i) { 34 for (i = 0; i < cont->children->length; ++i) {
30 free_swayc(c->children->items[i]); 35 free_swayc(cont->children->items[i]);
31 } 36 }
32 } 37 }
33 list_free(c->children); 38 list_free(cont->children);
34 } 39 }
35 if (c->floating) { 40 if (cont->floating) {
36 if (c->floating->length) { 41 if (cont->floating->length) {
37 int i; 42 int i;
38 for (i = 0; i < c->floating->length; ++i) { 43 for (i = 0; i < cont->floating->length; ++i) {
39 free_swayc(c->floating->items[i]); 44 free_swayc(cont->floating->items[i]);
40 } 45 }
41 } 46 }
42 list_free(c->floating); 47 list_free(cont->floating);
43 } 48 }
44 if (c->parent) { 49 if (cont->parent) {
45 remove_child(c); 50 remove_child(cont);
46 } 51 }
47 if (c->name) { 52 if (cont->name) {
48 free(c->name); 53 free(cont->name);
49 } 54 }
50 free(c); 55 free(cont);
51} 56}
52 57
53/* New containers */ 58// New containers
54 59
55static bool workspace_test(swayc_t *view, void *name) { 60static bool workspace_test(swayc_t *view, void *name) {
56 return strcasecmp(view->name, (char *)name) == 0; 61 return strcasecmp(view->name, (char *)name) == 0;
@@ -103,6 +108,9 @@ swayc_t *new_output(wlc_handle handle) {
103} 108}
104 109
105swayc_t *new_workspace(swayc_t *output, const char *name) { 110swayc_t *new_workspace(swayc_t *output, const char *name) {
111 if (!ASSERT_NONNULL(output)) {
112 return NULL;
113 }
106 sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); 114 sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle);
107 swayc_t *workspace = new_swayc(C_WORKSPACE); 115 swayc_t *workspace = new_swayc(C_WORKSPACE);
108 116
@@ -120,6 +128,9 @@ swayc_t *new_workspace(swayc_t *output, const char *name) {
120} 128}
121 129
122swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { 130swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
131 if (!ASSERT_NONNULL(child)) {
132 return NULL;
133 }
123 swayc_t *cont = new_swayc(C_CONTAINER); 134 swayc_t *cont = new_swayc(C_CONTAINER);
124 135
125 sway_log(L_DEBUG, "creating container %p around %p", cont, child); 136 sway_log(L_DEBUG, "creating container %p around %p", cont, child);
@@ -162,6 +173,9 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
162} 173}
163 174
164swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { 175swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
176 if (!ASSERT_NONNULL(sibling)) {
177 return NULL;
178 }
165 const char *title = wlc_view_get_title(handle); 179 const char *title = wlc_view_get_title(handle);
166 swayc_t *view = new_swayc(C_VIEW); 180 swayc_t *view = new_swayc(C_VIEW);
167 sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d", 181 sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d",
@@ -172,14 +186,14 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
172 view->visible = true; 186 view->visible = true;
173 view->is_focused = true; 187 view->is_focused = true;
174 // Setup geometry 188 // Setup geometry
189 const struct wlc_geometry* geometry = wlc_view_get_geometry(handle);
175 view->width = 0; 190 view->width = 0;
176 view->height = 0; 191 view->height = 0;
192 view->desired_width = geometry->size.w;
193 view->desired_height = geometry->size.h;
177 194
178 view->gaps = config->gaps_inner; 195 view->gaps = config->gaps_inner;
179 196
180 view->desired_width = -1;
181 view->desired_height = -1;
182
183 view->is_floating = false; 197 view->is_floating = false;
184 198
185 if (sibling->type == C_WORKSPACE) { 199 if (sibling->type == C_WORKSPACE) {
@@ -225,9 +239,12 @@ swayc_t *new_floating_view(wlc_handle handle) {
225 return view; 239 return view;
226} 240}
227 241
228/* Destroy container */ 242// Destroy container
229 243
230swayc_t *destroy_output(swayc_t *output) { 244swayc_t *destroy_output(swayc_t *output) {
245 if (!ASSERT_NONNULL(output)) {
246 return NULL;
247 }
231 if (output->children->length == 0) { 248 if (output->children->length == 0) {
232 // TODO move workspaces to other outputs 249 // TODO move workspaces to other outputs
233 } 250 }
@@ -237,23 +254,21 @@ swayc_t *destroy_output(swayc_t *output) {
237} 254}
238 255
239swayc_t *destroy_workspace(swayc_t *workspace) { 256swayc_t *destroy_workspace(swayc_t *workspace) {
257 if (!ASSERT_NONNULL(workspace)) {
258 return NULL;
259 }
240 // NOTE: This is called from elsewhere without checking children length 260 // NOTE: This is called from elsewhere without checking children length
241 // TODO move containers to other workspaces? 261 // TODO move containers to other workspaces?
242 // for now just dont delete 262 // for now just dont delete
243 263
244 // Do not destroy this if it's the last workspace on this output 264 // Do not destroy this if it's the last workspace on this output
245 swayc_t *output = workspace->parent; 265 swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT);
246 while (output && output->type != C_OUTPUT) { 266 if (output && output->children->length == 1) {
247 output = output->parent; 267 return NULL;
248 }
249 if (output) {
250 if (output->children->length == 1) {
251 return NULL;
252 }
253 } 268 }
254 269
255 if (workspace->children->length == 0) { 270 if (workspace->children->length == 0) {
256 sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); 271 sway_log(L_DEBUG, "%s: '%s'", __func__, workspace->name);
257 swayc_t *parent = workspace->parent; 272 swayc_t *parent = workspace->parent;
258 free_swayc(workspace); 273 free_swayc(workspace);
259 return parent; 274 return parent;
@@ -262,6 +277,9 @@ swayc_t *destroy_workspace(swayc_t *workspace) {
262} 277}
263 278
264swayc_t *destroy_container(swayc_t *container) { 279swayc_t *destroy_container(swayc_t *container) {
280 if (!ASSERT_NONNULL(container)) {
281 return NULL;
282 }
265 while (container->children->length == 0 && container->type == C_CONTAINER) { 283 while (container->children->length == 0 && container->type == C_CONTAINER) {
266 sway_log(L_DEBUG, "Container: Destroying container '%p'", container); 284 sway_log(L_DEBUG, "Container: Destroying container '%p'", container);
267 swayc_t *parent = container->parent; 285 swayc_t *parent = container->parent;
@@ -272,8 +290,7 @@ swayc_t *destroy_container(swayc_t *container) {
272} 290}
273 291
274swayc_t *destroy_view(swayc_t *view) { 292swayc_t *destroy_view(swayc_t *view) {
275 if (view == NULL) { 293 if (!ASSERT_NONNULL(view)) {
276 sway_log(L_DEBUG, "Warning: NULL passed into destroy_view");
277 return NULL; 294 return NULL;
278 } 295 }
279 sway_log(L_DEBUG, "Destroying view '%p'", view); 296 sway_log(L_DEBUG, "Destroying view '%p'", view);
@@ -287,6 +304,34 @@ swayc_t *destroy_view(swayc_t *view) {
287 return parent; 304 return parent;
288} 305}
289 306
307// Container lookup
308
309swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) {
310 if (!ASSERT_NONNULL(container)) {
311 return NULL;
312 }
313 if (!sway_assert(type < C_TYPES && type >= C_ROOT, "%s: invalid type", __func__)) {
314 return NULL;
315 }
316 do {
317 container = container->parent;
318 } while(container && container->type != type);
319 return container;
320}
321
322swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) {
323 if (!ASSERT_NONNULL(container)) {
324 return NULL;
325 }
326 if (!sway_assert(layout < L_LAYOUTS && layout >= L_NONE, "%s: invalid layout", __func__)) {
327 return NULL;
328 }
329 do {
330 container = container->parent;
331 } while (container && container->layout != layout);
332 return container;
333}
334
290swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { 335swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
291 if (!container->children) { 336 if (!container->children) {
292 return NULL; 337 return NULL;
@@ -316,25 +361,27 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da
316} 361}
317 362
318void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { 363void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) {
319 if (!container || !container->children || !container->children->length) { 364 if (container && container->children && container->children->length) {
320 return; 365 int i;
321 } 366 for (i = 0; i < container->children->length; ++i) {
322 int i; 367 swayc_t *child = container->children->items[i];
323 for (i = 0; i < container->children->length; ++i) {
324 swayc_t *child = container->children->items[i];
325 f(child, data);
326 container_map(child, f, data);
327 }
328 if (container->type == C_WORKSPACE) {
329 for (i = 0; i < container->floating->length; ++i) {
330 swayc_t *child = container->floating->items[i];
331 f(child, data); 368 f(child, data);
332 container_map(child, f, data); 369 container_map(child, f, data);
333 } 370 }
371 if (container->type == C_WORKSPACE) {
372 for (i = 0; i < container->floating->length; ++i) {
373 swayc_t *child = container->floating->items[i];
374 f(child, data);
375 container_map(child, f, data);
376 }
377 }
334 } 378 }
335} 379}
336 380
337void set_view_visibility(swayc_t *view, void *data) { 381void set_view_visibility(swayc_t *view, void *data) {
382 if (!ASSERT_NONNULL(view)) {
383 return;
384 }
338 uint32_t *p = data; 385 uint32_t *p = data;
339 if (view->type == C_VIEW) { 386 if (view->type == C_VIEW) {
340 wlc_view_set_mask(view->handle, *p); 387 wlc_view_set_mask(view->handle, *p);
@@ -348,6 +395,9 @@ void set_view_visibility(swayc_t *view, void *data) {
348} 395}
349 396
350void reset_gaps(swayc_t *view, void *data) { 397void reset_gaps(swayc_t *view, void *data) {
398 if (!ASSERT_NONNULL(view)) {
399 return;
400 }
351 if (view->type == C_OUTPUT) { 401 if (view->type == C_OUTPUT) {
352 view->gaps = config->gaps_outer; 402 view->gaps = config->gaps_outer;
353 } 403 }