diff options
Diffstat (limited to 'sway/container.c')
-rw-r--r-- | sway/container.c | 140 |
1 files changed, 105 insertions, 35 deletions
diff --git a/sway/container.c b/sway/container.c index 7ccc2e09..62ff1c4a 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -26,14 +26,11 @@ static void free_swayc(swayc_t *cont) { | |||
26 | if (!ASSERT_NONNULL(cont)) { | 26 | if (!ASSERT_NONNULL(cont)) { |
27 | return; | 27 | return; |
28 | } | 28 | } |
29 | // TODO does not properly handle containers with children, | ||
30 | // TODO but functions that call this usually check for that | ||
31 | if (cont->children) { | 29 | if (cont->children) { |
32 | if (cont->children->length) { | 30 | // remove children until there are no more, free_swayc calls |
33 | int i; | 31 | // remove_child, which removes child from this container |
34 | for (i = 0; i < cont->children->length; ++i) { | 32 | while (cont->children->length) { |
35 | free_swayc(cont->children->items[i]); | 33 | free_swayc(cont->children->items[0]); |
36 | } | ||
37 | } | 34 | } |
38 | list_free(cont->children); | 35 | list_free(cont->children); |
39 | } | 36 | } |
@@ -57,10 +54,6 @@ static void free_swayc(swayc_t *cont) { | |||
57 | 54 | ||
58 | // New containers | 55 | // New containers |
59 | 56 | ||
60 | static bool workspace_test(swayc_t *view, void *name) { | ||
61 | return strcasecmp(view->name, (char *)name) == 0; | ||
62 | } | ||
63 | |||
64 | swayc_t *new_output(wlc_handle handle) { | 57 | swayc_t *new_output(wlc_handle handle) { |
65 | const struct wlc_size* size = wlc_output_get_resolution(handle); | 58 | const struct wlc_size* size = wlc_output_get_resolution(handle); |
66 | const char *name = wlc_output_get_name(handle); | 59 | const char *name = wlc_output_get_name(handle); |
@@ -84,7 +77,7 @@ swayc_t *new_output(wlc_handle handle) { | |||
84 | if (strcasecmp(wso->output, name) == 0) { | 77 | if (strcasecmp(wso->output, name) == 0) { |
85 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); | 78 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); |
86 | // Check if any other workspaces are using this name | 79 | // Check if any other workspaces are using this name |
87 | if (find_container(&root_container, workspace_test, wso->workspace)) { | 80 | if (workspace_by_name(wso->workspace)) { |
88 | sway_log(L_DEBUG, "But it's already taken"); | 81 | sway_log(L_DEBUG, "But it's already taken"); |
89 | break; | 82 | break; |
90 | } | 83 | } |
@@ -128,7 +121,8 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { | |||
128 | } | 121 | } |
129 | 122 | ||
130 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | 123 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { |
131 | if (!ASSERT_NONNULL(child)) { | 124 | if (!ASSERT_NONNULL(child) |
125 | && !sway_assert(!child->is_floating, "cannot create container around floating window")) { | ||
132 | return NULL; | 126 | return NULL; |
133 | } | 127 | } |
134 | swayc_t *cont = new_swayc(C_CONTAINER); | 128 | swayc_t *cont = new_swayc(C_CONTAINER); |
@@ -207,6 +201,9 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
207 | } | 201 | } |
208 | 202 | ||
209 | swayc_t *new_floating_view(wlc_handle handle) { | 203 | swayc_t *new_floating_view(wlc_handle handle) { |
204 | if (swayc_active_workspace() == NULL) { | ||
205 | return NULL; | ||
206 | } | ||
210 | const char *title = wlc_view_get_title(handle); | 207 | const char *title = wlc_view_get_title(handle); |
211 | swayc_t *view = new_swayc(C_VIEW); | 208 | swayc_t *view = new_swayc(C_VIEW); |
212 | sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view", | 209 | sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view", |
@@ -220,8 +217,8 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
220 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | 217 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); |
221 | 218 | ||
222 | // give it requested geometry, but place in center | 219 | // give it requested geometry, but place in center |
223 | view->x = (active_workspace->width - geometry->size.w) / 2; | 220 | view->x = (swayc_active_workspace()->width - geometry->size.w) / 2; |
224 | view->y = (active_workspace->height- geometry->size.h) / 2; | 221 | view->y = (swayc_active_workspace()->height- geometry->size.h) / 2; |
225 | view->width = geometry->size.w; | 222 | view->width = geometry->size.w; |
226 | view->height = geometry->size.h; | 223 | view->height = geometry->size.h; |
227 | 224 | ||
@@ -231,10 +228,10 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
231 | view->is_floating = true; | 228 | view->is_floating = true; |
232 | 229 | ||
233 | // Case of focused workspace, just create as child of it | 230 | // Case of focused workspace, just create as child of it |
234 | list_add(active_workspace->floating, view); | 231 | list_add(swayc_active_workspace()->floating, view); |
235 | view->parent = active_workspace; | 232 | view->parent = swayc_active_workspace(); |
236 | if (active_workspace->focused == NULL) { | 233 | if (swayc_active_workspace()->focused == NULL) { |
237 | set_focused_container_for(active_workspace, view); | 234 | set_focused_container_for(swayc_active_workspace(), view); |
238 | } | 235 | } |
239 | return view; | 236 | return view; |
240 | } | 237 | } |
@@ -306,6 +303,35 @@ swayc_t *destroy_view(swayc_t *view) { | |||
306 | 303 | ||
307 | // Container lookup | 304 | // Container lookup |
308 | 305 | ||
306 | |||
307 | swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | ||
308 | if (!container->children) { | ||
309 | return NULL; | ||
310 | } | ||
311 | // Special case for checking floating stuff | ||
312 | int i; | ||
313 | if (container->type == C_WORKSPACE) { | ||
314 | for (i = 0; i < container->floating->length; ++i) { | ||
315 | swayc_t *child = container->floating->items[i]; | ||
316 | if (test(child, data)) { | ||
317 | return child; | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | for (i = 0; i < container->children->length; ++i) { | ||
322 | swayc_t *child = container->children->items[i]; | ||
323 | if (test(child, data)) { | ||
324 | return child; | ||
325 | } else { | ||
326 | swayc_t *res = swayc_by_test(child, test, data); | ||
327 | if (res) { | ||
328 | return res; | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | return NULL; | ||
333 | } | ||
334 | |||
309 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | 335 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { |
310 | if (!ASSERT_NONNULL(container)) { | 336 | if (!ASSERT_NONNULL(container)) { |
311 | return NULL; | 337 | return NULL; |
@@ -315,7 +341,7 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | |||
315 | } | 341 | } |
316 | do { | 342 | do { |
317 | container = container->parent; | 343 | container = container->parent; |
318 | } while(container && container->type != type); | 344 | } while (container && container->type != type); |
319 | return container; | 345 | return container; |
320 | } | 346 | } |
321 | 347 | ||
@@ -332,27 +358,30 @@ swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) { | |||
332 | return container; | 358 | return container; |
333 | } | 359 | } |
334 | 360 | ||
335 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | 361 | static swayc_t *_swayc_by_handle_helper(wlc_handle handle, swayc_t *parent) { |
336 | if (!container->children) { | 362 | if (!parent || !parent->children) { |
337 | return NULL; | 363 | return NULL; |
338 | } | 364 | } |
339 | // Special case for checking floating stuff | 365 | int i, len; |
340 | int i; | 366 | swayc_t **child; |
341 | if (container->type == C_WORKSPACE) { | 367 | if (parent->type == C_WORKSPACE) { |
342 | for (i = 0; i < container->floating->length; ++i) { | 368 | len = parent->floating->length; |
343 | swayc_t *child = container->floating->items[i]; | 369 | child = (swayc_t **)parent->floating->items; |
344 | if (test(child, data)) { | 370 | for (i = 0; i < len; ++i, ++child) { |
345 | return child; | 371 | if ((*child)->handle == handle) { |
372 | return *child; | ||
346 | } | 373 | } |
347 | } | 374 | } |
348 | } | 375 | } |
349 | for (i = 0; i < container->children->length; ++i) { | 376 | |
350 | swayc_t *child = container->children->items[i]; | 377 | len = parent->children->length; |
351 | if (test(child, data)) { | 378 | child = (swayc_t**)parent->children->items; |
352 | return child; | 379 | for (i = 0; i < len; ++i, ++child) { |
380 | if ((*child)->handle == handle) { | ||
381 | return *child; | ||
353 | } else { | 382 | } else { |
354 | swayc_t *res = find_container(child, test, data); | 383 | swayc_t *res; |
355 | if (res) { | 384 | if ((res = _swayc_by_handle_helper(handle, *child))) { |
356 | return res; | 385 | return res; |
357 | } | 386 | } |
358 | } | 387 | } |
@@ -360,6 +389,47 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da | |||
360 | return NULL; | 389 | return NULL; |
361 | } | 390 | } |
362 | 391 | ||
392 | swayc_t *swayc_by_handle(wlc_handle handle) { | ||
393 | return _swayc_by_handle_helper(handle, &root_container); | ||
394 | } | ||
395 | |||
396 | swayc_t *swayc_active_output(void) { | ||
397 | return root_container.focused; | ||
398 | } | ||
399 | |||
400 | swayc_t *swayc_active_workspace(void) { | ||
401 | return root_container.focused ? root_container.focused->focused : NULL; | ||
402 | } | ||
403 | |||
404 | swayc_t *swayc_active_workspace_for(swayc_t *cont) { | ||
405 | if (!cont) { | ||
406 | return NULL; | ||
407 | } | ||
408 | switch (cont->type) { | ||
409 | case C_ROOT: | ||
410 | cont = cont->focused; | ||
411 | /* Fallthrough */ | ||
412 | |||
413 | case C_OUTPUT: | ||
414 | cont = cont->focused; | ||
415 | /* Fallthrough */ | ||
416 | |||
417 | case C_WORKSPACE: | ||
418 | return cont; | ||
419 | |||
420 | default: | ||
421 | return swayc_parent_by_type(cont, C_WORKSPACE); | ||
422 | } | ||
423 | } | ||
424 | |||
425 | // Container information | ||
426 | |||
427 | bool swayc_is_fullscreen(swayc_t *view) { | ||
428 | return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN); | ||
429 | } | ||
430 | |||
431 | // Mapping | ||
432 | |||
363 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | 433 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { |
364 | if (container && container->children && container->children->length) { | 434 | if (container && container->children && container->children->length) { |
365 | int i; | 435 | int i; |