diff options
Diffstat (limited to 'sway/container.c')
-rw-r--r-- | sway/container.c | 138 |
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 | ||
12 | static swayc_t *new_swayc(enum swayc_types type) { | 14 | static 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 | ||
23 | static void free_swayc(swayc_t *c) { | 25 | static 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 | ||
55 | static bool workspace_test(swayc_t *view, void *name) { | 60 | static 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 | ||
105 | swayc_t *new_workspace(swayc_t *output, const char *name) { | 110 | swayc_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 | ||
122 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | 130 | swayc_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 | ||
164 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | 175 | swayc_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 | ||
230 | swayc_t *destroy_output(swayc_t *output) { | 244 | swayc_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 | ||
239 | swayc_t *destroy_workspace(swayc_t *workspace) { | 256 | swayc_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 | ||
264 | swayc_t *destroy_container(swayc_t *container) { | 279 | swayc_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 | ||
274 | swayc_t *destroy_view(swayc_t *view) { | 292 | swayc_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 | |||
309 | swayc_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 | |||
322 | swayc_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 | |||
290 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | 335 | swayc_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 | ||
318 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | 363 | void 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 | ||
337 | void set_view_visibility(swayc_t *view, void *data) { | 381 | void 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 | ||
350 | void reset_gaps(swayc_t *view, void *data) { | 397 | void 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 | } |