diff options
Diffstat (limited to 'sway/container.c')
-rw-r--r-- | sway/container.c | 166 |
1 files changed, 117 insertions, 49 deletions
diff --git a/sway/container.c b/sway/container.c index 62c5bda0..7ccc2e09 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -8,53 +8,57 @@ | |||
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)); |
14 | c->handle = -1; | 16 | c->handle = -1; |
15 | c->layout = L_NONE; | 17 | c->layout = L_NONE; |
16 | c->type = type; | 18 | c->type = type; |
17 | c->weight = 1; | ||
18 | if (type != C_VIEW) { | 19 | if (type != C_VIEW) { |
19 | c->children = create_list(); | 20 | c->children = create_list(); |
20 | } | 21 | } |
21 | return c; | 22 | return c; |
22 | } | 23 | } |
23 | 24 | ||
24 | static void free_swayc(swayc_t *c) { | 25 | static void free_swayc(swayc_t *cont) { |
26 | if (!ASSERT_NONNULL(cont)) { | ||
27 | return; | ||
28 | } | ||
25 | // TODO does not properly handle containers with children, | 29 | // TODO does not properly handle containers with children, |
26 | // TODO but functions that call this usually check for that | 30 | // TODO but functions that call this usually check for that |
27 | if (c->children) { | 31 | if (cont->children) { |
28 | if (c->children->length) { | 32 | if (cont->children->length) { |
29 | int i; | 33 | int i; |
30 | for (i = 0; i < c->children->length; ++i) { | 34 | for (i = 0; i < cont->children->length; ++i) { |
31 | free_swayc(c->children->items[i]); | 35 | free_swayc(cont->children->items[i]); |
32 | } | 36 | } |
33 | } | 37 | } |
34 | list_free(c->children); | 38 | list_free(cont->children); |
35 | } | 39 | } |
36 | if (c->floating) { | 40 | if (cont->floating) { |
37 | if (c->floating->length) { | 41 | if (cont->floating->length) { |
38 | int i; | 42 | int i; |
39 | for (i = 0; i < c->floating->length; ++i) { | 43 | for (i = 0; i < cont->floating->length; ++i) { |
40 | free_swayc(c->floating->items[i]); | 44 | free_swayc(cont->floating->items[i]); |
41 | } | 45 | } |
42 | } | 46 | } |
43 | list_free(c->floating); | 47 | list_free(cont->floating); |
44 | } | 48 | } |
45 | if (c->parent) { | 49 | if (cont->parent) { |
46 | remove_child(c); | 50 | remove_child(cont); |
47 | } | 51 | } |
48 | if (c->name) { | 52 | if (cont->name) { |
49 | free(c->name); | 53 | free(cont->name); |
50 | } | 54 | } |
51 | free(c); | 55 | free(cont); |
52 | } | 56 | } |
53 | 57 | ||
54 | /* New containers */ | 58 | // New containers |
55 | 59 | ||
56 | static bool workspace_test(swayc_t *view, void *name) { | 60 | static bool workspace_test(swayc_t *view, void *name) { |
57 | return strcasecmp(view->name, (char *)name); | 61 | return strcasecmp(view->name, (char *)name) == 0; |
58 | } | 62 | } |
59 | 63 | ||
60 | swayc_t *new_output(wlc_handle handle) { | 64 | swayc_t *new_output(wlc_handle handle) { |
@@ -67,6 +71,7 @@ swayc_t *new_output(wlc_handle handle) { | |||
67 | output->height = size->h; | 71 | output->height = size->h; |
68 | output->handle = handle; | 72 | output->handle = handle; |
69 | output->name = name ? strdup(name) : NULL; | 73 | output->name = name ? strdup(name) : NULL; |
74 | output->gaps = config->gaps_outer + config->gaps_inner / 2; | ||
70 | 75 | ||
71 | add_child(&root_container, output); | 76 | add_child(&root_container, output); |
72 | 77 | ||
@@ -80,8 +85,10 @@ swayc_t *new_output(wlc_handle handle) { | |||
80 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); | 85 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); |
81 | // Check if any other workspaces are using this name | 86 | // Check if any other workspaces are using this name |
82 | if (find_container(&root_container, workspace_test, wso->workspace)) { | 87 | if (find_container(&root_container, workspace_test, wso->workspace)) { |
88 | sway_log(L_DEBUG, "But it's already taken"); | ||
83 | break; | 89 | break; |
84 | } | 90 | } |
91 | sway_log(L_DEBUG, "So we're going to use it"); | ||
85 | ws_name = strdup(wso->workspace); | 92 | ws_name = strdup(wso->workspace); |
86 | break; | 93 | break; |
87 | } | 94 | } |
@@ -101,10 +108,15 @@ swayc_t *new_output(wlc_handle handle) { | |||
101 | } | 108 | } |
102 | 109 | ||
103 | 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 | } | ||
104 | 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); |
105 | swayc_t *workspace = new_swayc(C_WORKSPACE); | 115 | swayc_t *workspace = new_swayc(C_WORKSPACE); |
106 | 116 | ||
107 | workspace->layout = L_HORIZ; // TODO: default layout | 117 | workspace->layout = L_HORIZ; // TODO: default layout |
118 | workspace->x = output->x; | ||
119 | workspace->y = output->y; | ||
108 | workspace->width = output->width; | 120 | workspace->width = output->width; |
109 | workspace->height = output->height; | 121 | workspace->height = output->height; |
110 | workspace->name = strdup(name); | 122 | workspace->name = strdup(name); |
@@ -116,6 +128,9 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { | |||
116 | } | 128 | } |
117 | 129 | ||
118 | 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 | } | ||
119 | swayc_t *cont = new_swayc(C_CONTAINER); | 134 | swayc_t *cont = new_swayc(C_CONTAINER); |
120 | 135 | ||
121 | sway_log(L_DEBUG, "creating container %p around %p", cont, child); | 136 | sway_log(L_DEBUG, "creating container %p around %p", cont, child); |
@@ -147,6 +162,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | |||
147 | // give them proper layouts | 162 | // give them proper layouts |
148 | cont->layout = workspace->layout; | 163 | cont->layout = workspace->layout; |
149 | workspace->layout = layout; | 164 | workspace->layout = layout; |
165 | set_focused_container_for(workspace, get_focused_view(workspace)); | ||
150 | } else { // Or is built around container | 166 | } else { // Or is built around container |
151 | swayc_t *parent = replace_child(child, cont); | 167 | swayc_t *parent = replace_child(child, cont); |
152 | if (parent) { | 168 | if (parent) { |
@@ -157,6 +173,9 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | |||
157 | } | 173 | } |
158 | 174 | ||
159 | 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 | } | ||
160 | const char *title = wlc_view_get_title(handle); | 179 | const char *title = wlc_view_get_title(handle); |
161 | swayc_t *view = new_swayc(C_VIEW); | 180 | swayc_t *view = new_swayc(C_VIEW); |
162 | 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", |
@@ -166,11 +185,15 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
166 | view->name = title ? strdup(title) : NULL; | 185 | view->name = title ? strdup(title) : NULL; |
167 | view->visible = true; | 186 | view->visible = true; |
168 | view->is_focused = true; | 187 | view->is_focused = true; |
188 | // Setup geometry | ||
189 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | ||
190 | view->width = 0; | ||
191 | view->height = 0; | ||
192 | view->desired_width = geometry->size.w; | ||
193 | view->desired_height = geometry->size.h; | ||
169 | 194 | ||
170 | view->desired_width = -1; | 195 | view->gaps = config->gaps_inner; |
171 | view->desired_height = -1; | ||
172 | 196 | ||
173 | // TODO: properly set this | ||
174 | view->is_floating = false; | 197 | view->is_floating = false; |
175 | 198 | ||
176 | if (sibling->type == C_WORKSPACE) { | 199 | if (sibling->type == C_WORKSPACE) { |
@@ -196,8 +219,9 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
196 | // Set the geometry of the floating view | 219 | // Set the geometry of the floating view |
197 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | 220 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); |
198 | 221 | ||
199 | view->x = geometry->origin.x; | 222 | // give it requested geometry, but place in center |
200 | view->y = geometry->origin.y; | 223 | view->x = (active_workspace->width - geometry->size.w) / 2; |
224 | view->y = (active_workspace->height- geometry->size.h) / 2; | ||
201 | view->width = geometry->size.w; | 225 | view->width = geometry->size.w; |
202 | view->height = geometry->size.h; | 226 | view->height = geometry->size.h; |
203 | 227 | ||
@@ -215,9 +239,12 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
215 | return view; | 239 | return view; |
216 | } | 240 | } |
217 | 241 | ||
218 | /* Destroy container */ | 242 | // Destroy container |
219 | 243 | ||
220 | swayc_t *destroy_output(swayc_t *output) { | 244 | swayc_t *destroy_output(swayc_t *output) { |
245 | if (!ASSERT_NONNULL(output)) { | ||
246 | return NULL; | ||
247 | } | ||
221 | if (output->children->length == 0) { | 248 | if (output->children->length == 0) { |
222 | // TODO move workspaces to other outputs | 249 | // TODO move workspaces to other outputs |
223 | } | 250 | } |
@@ -227,23 +254,21 @@ swayc_t *destroy_output(swayc_t *output) { | |||
227 | } | 254 | } |
228 | 255 | ||
229 | swayc_t *destroy_workspace(swayc_t *workspace) { | 256 | swayc_t *destroy_workspace(swayc_t *workspace) { |
257 | if (!ASSERT_NONNULL(workspace)) { | ||
258 | return NULL; | ||
259 | } | ||
230 | // NOTE: This is called from elsewhere without checking children length | 260 | // NOTE: This is called from elsewhere without checking children length |
231 | // TODO move containers to other workspaces? | 261 | // TODO move containers to other workspaces? |
232 | // for now just dont delete | 262 | // for now just dont delete |
233 | 263 | ||
234 | // 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 |
235 | swayc_t *output = workspace->parent; | 265 | swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); |
236 | while (output && output->type != C_OUTPUT) { | 266 | if (output && output->children->length == 1) { |
237 | output = output->parent; | 267 | return NULL; |
238 | } | ||
239 | if (output) { | ||
240 | if (output->children->length == 1) { | ||
241 | return NULL; | ||
242 | } | ||
243 | } | 268 | } |
244 | 269 | ||
245 | if (workspace->children->length == 0) { | 270 | if (workspace->children->length == 0) { |
246 | sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); | 271 | sway_log(L_DEBUG, "%s: '%s'", __func__, workspace->name); |
247 | swayc_t *parent = workspace->parent; | 272 | swayc_t *parent = workspace->parent; |
248 | free_swayc(workspace); | 273 | free_swayc(workspace); |
249 | return parent; | 274 | return parent; |
@@ -252,19 +277,20 @@ swayc_t *destroy_workspace(swayc_t *workspace) { | |||
252 | } | 277 | } |
253 | 278 | ||
254 | swayc_t *destroy_container(swayc_t *container) { | 279 | swayc_t *destroy_container(swayc_t *container) { |
280 | if (!ASSERT_NONNULL(container)) { | ||
281 | return NULL; | ||
282 | } | ||
255 | while (container->children->length == 0 && container->type == C_CONTAINER) { | 283 | while (container->children->length == 0 && container->type == C_CONTAINER) { |
256 | sway_log(L_DEBUG, "Container: Destroying container '%p'", container); | 284 | sway_log(L_DEBUG, "Container: Destroying container '%p'", container); |
257 | swayc_t *parent = container->parent; | 285 | swayc_t *parent = container->parent; |
258 | free_swayc(container); | 286 | free_swayc(container); |
259 | |||
260 | container = parent; | 287 | container = parent; |
261 | } | 288 | } |
262 | return container; | 289 | return container; |
263 | } | 290 | } |
264 | 291 | ||
265 | swayc_t *destroy_view(swayc_t *view) { | 292 | swayc_t *destroy_view(swayc_t *view) { |
266 | if (view == NULL) { | 293 | if (!ASSERT_NONNULL(view)) { |
267 | sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); | ||
268 | return NULL; | 294 | return NULL; |
269 | } | 295 | } |
270 | sway_log(L_DEBUG, "Destroying view '%p'", view); | 296 | sway_log(L_DEBUG, "Destroying view '%p'", view); |
@@ -278,6 +304,34 @@ swayc_t *destroy_view(swayc_t *view) { | |||
278 | return parent; | 304 | return parent; |
279 | } | 305 | } |
280 | 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 | |||
281 | 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) { |
282 | if (!container->children) { | 336 | if (!container->children) { |
283 | return NULL; | 337 | return NULL; |
@@ -307,25 +361,27 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da | |||
307 | } | 361 | } |
308 | 362 | ||
309 | 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) { |
310 | if (!container || !container->children || !container->children->length) { | 364 | if (container && container->children && container->children->length) { |
311 | return; | 365 | int i; |
312 | } | 366 | for (i = 0; i < container->children->length; ++i) { |
313 | int i; | 367 | swayc_t *child = container->children->items[i]; |
314 | for (i = 0; i < container->children->length; ++i) { | ||
315 | swayc_t *child = container->children->items[i]; | ||
316 | f(child, data); | ||
317 | container_map(child, f, data); | ||
318 | } | ||
319 | if (container->type == C_WORKSPACE) { | ||
320 | for (i = 0; i < container->floating->length; ++i) { | ||
321 | swayc_t *child = container->floating->items[i]; | ||
322 | f(child, data); | 368 | f(child, data); |
323 | container_map(child, f, data); | 369 | container_map(child, f, data); |
324 | } | 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 | } | ||
325 | } | 378 | } |
326 | } | 379 | } |
327 | 380 | ||
328 | 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 | } | ||
329 | uint32_t *p = data; | 385 | uint32_t *p = data; |
330 | if (view->type == C_VIEW) { | 386 | if (view->type == C_VIEW) { |
331 | wlc_view_set_mask(view->handle, *p); | 387 | wlc_view_set_mask(view->handle, *p); |
@@ -337,3 +393,15 @@ void set_view_visibility(swayc_t *view, void *data) { | |||
337 | } | 393 | } |
338 | view->visible = (*p == 2); | 394 | view->visible = (*p == 2); |
339 | } | 395 | } |
396 | |||
397 | void reset_gaps(swayc_t *view, void *data) { | ||
398 | if (!ASSERT_NONNULL(view)) { | ||
399 | return; | ||
400 | } | ||
401 | if (view->type == C_OUTPUT) { | ||
402 | view->gaps = config->gaps_outer; | ||
403 | } | ||
404 | if (view->type == C_VIEW) { | ||
405 | view->gaps = config->gaps_inner; | ||
406 | } | ||
407 | } | ||