diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 221 |
1 files changed, 117 insertions, 104 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index 40047dcf..bbafe9ec 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -7,14 +7,14 @@ | |||
7 | #include <wlr/types/wlr_output_layout.h> | 7 | #include <wlr/types/wlr_output_layout.h> |
8 | #include <wlr/types/wlr_wl_shell.h> | 8 | #include <wlr/types/wlr_wl_shell.h> |
9 | #include "sway/config.h" | 9 | #include "sway/config.h" |
10 | #include "sway/tree/container.h" | 10 | #include "sway/container.h" |
11 | #include "sway/input/input-manager.h" | 11 | #include "sway/input/input-manager.h" |
12 | #include "sway/input/seat.h" | 12 | #include "sway/input/seat.h" |
13 | #include "sway/tree/layout.h" | 13 | #include "sway/layout.h" |
14 | #include "sway/output.h" | 14 | #include "sway/output.h" |
15 | #include "sway/server.h" | 15 | #include "sway/server.h" |
16 | #include "sway/tree/view.h" | 16 | #include "sway/view.h" |
17 | #include "sway/tree/workspace.h" | 17 | #include "sway/workspace.h" |
18 | #include "sway/ipc-server.h" | 18 | #include "sway/ipc-server.h" |
19 | #include "log.h" | 19 | #include "log.h" |
20 | 20 | ||
@@ -33,15 +33,48 @@ static list_t *get_bfs_queue() { | |||
33 | return bfs_queue; | 33 | return bfs_queue; |
34 | } | 34 | } |
35 | 35 | ||
36 | static void notify_new_container(struct sway_container *container) { | 36 | static void notify_new_container(swayc_t *container) { |
37 | wl_signal_emit(&root_container.sway_root->events.new_container, container); | 37 | wl_signal_emit(&root_container.sway_root->events.new_container, container); |
38 | ipc_event_window(container, "new"); | 38 | ipc_event_window(container, "new"); |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct sway_container *container_create(enum sway_container_type type) { | 41 | swayc_t *swayc_by_test(swayc_t *container, |
42 | bool (*test)(swayc_t *view, void *data), void *data) { | ||
43 | if (!container->children) { | ||
44 | return NULL; | ||
45 | } | ||
46 | // TODO: floating windows | ||
47 | for (int i = 0; i < container->children->length; ++i) { | ||
48 | swayc_t *child = container->children->items[i]; | ||
49 | if (test(child, data)) { | ||
50 | return child; | ||
51 | } else { | ||
52 | swayc_t *res = swayc_by_test(child, test, data); | ||
53 | if (res) { | ||
54 | return res; | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, | ||
62 | void (*func)(swayc_t *item, void *data), void *data) { | ||
63 | for (int i = 0; i < root->children->length; ++i) { | ||
64 | swayc_t *item = root->children->items[i]; | ||
65 | if (item->type == type) { | ||
66 | func(item, data); | ||
67 | } | ||
68 | if (item->children && item->children->length) { | ||
69 | swayc_descendants_of_type(item, type, func, data); | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static swayc_t *new_swayc(enum swayc_types type) { | ||
42 | // next id starts at 1 because 0 is assigned to root_container in layout.c | 75 | // next id starts at 1 because 0 is assigned to root_container in layout.c |
43 | static size_t next_id = 1; | 76 | static size_t next_id = 1; |
44 | struct sway_container *c = calloc(1, sizeof(struct sway_container)); | 77 | swayc_t *c = calloc(1, sizeof(swayc_t)); |
45 | if (!c) { | 78 | if (!c) { |
46 | return NULL; | 79 | return NULL; |
47 | } | 80 | } |
@@ -49,6 +82,8 @@ static struct sway_container *container_create(enum sway_container_type type) { | |||
49 | c->layout = L_NONE; | 82 | c->layout = L_NONE; |
50 | c->workspace_layout = L_NONE; | 83 | c->workspace_layout = L_NONE; |
51 | c->type = type; | 84 | c->type = type; |
85 | c->nb_master = 1; | ||
86 | c->nb_slave_groups = 1; | ||
52 | if (type != C_VIEW) { | 87 | if (type != C_VIEW) { |
53 | c->children = create_list(); | 88 | c->children = create_list(); |
54 | } | 89 | } |
@@ -58,18 +93,18 @@ static struct sway_container *container_create(enum sway_container_type type) { | |||
58 | return c; | 93 | return c; |
59 | } | 94 | } |
60 | 95 | ||
61 | static void container_destroy(struct sway_container *cont) { | 96 | static void free_swayc(swayc_t *cont) { |
62 | if (cont == NULL) { | 97 | if (!sway_assert(cont, "free_swayc passed NULL")) { |
63 | return; | 98 | return; |
64 | } | 99 | } |
65 | 100 | ||
66 | wl_signal_emit(&cont->events.destroy, cont); | 101 | wl_signal_emit(&cont->events.destroy, cont); |
67 | 102 | ||
68 | if (cont->children) { | 103 | if (cont->children) { |
69 | // remove children until there are no more, container_destroy calls | 104 | // remove children until there are no more, free_swayc calls |
70 | // container_remove_child, which removes child from this container | 105 | // remove_child, which removes child from this container |
71 | while (cont->children->length) { | 106 | while (cont->children->length) { |
72 | container_destroy(cont->children->items[0]); | 107 | free_swayc(cont->children->items[0]); |
73 | } | 108 | } |
74 | list_free(cont->children); | 109 | list_free(cont->children); |
75 | } | 110 | } |
@@ -78,7 +113,7 @@ static void container_destroy(struct sway_container *cont) { | |||
78 | list_free(cont->marks); | 113 | list_free(cont->marks); |
79 | } | 114 | } |
80 | if (cont->parent) { | 115 | if (cont->parent) { |
81 | container_remove_child(cont); | 116 | remove_child(cont); |
82 | } | 117 | } |
83 | if (cont->name) { | 118 | if (cont->name) { |
84 | free(cont->name); | 119 | free(cont->name); |
@@ -86,8 +121,7 @@ static void container_destroy(struct sway_container *cont) { | |||
86 | free(cont); | 121 | free(cont); |
87 | } | 122 | } |
88 | 123 | ||
89 | struct sway_container *container_output_create( | 124 | swayc_t *new_output(struct sway_output *sway_output) { |
90 | struct sway_output *sway_output) { | ||
91 | struct wlr_box size; | 125 | struct wlr_box size; |
92 | wlr_output_effective_resolution(sway_output->wlr_output, &size.width, | 126 | wlr_output_effective_resolution(sway_output->wlr_output, &size.width, |
93 | &size.height); | 127 | &size.height); |
@@ -122,22 +156,22 @@ struct sway_container *container_output_create( | |||
122 | return NULL; | 156 | return NULL; |
123 | } | 157 | } |
124 | 158 | ||
125 | struct sway_container *output = container_create(C_OUTPUT); | 159 | swayc_t *output = new_swayc(C_OUTPUT); |
126 | output->sway_output = sway_output; | 160 | output->sway_output = sway_output; |
127 | output->name = strdup(name); | 161 | output->name = strdup(name); |
128 | if (output->name == NULL) { | 162 | if (output->name == NULL) { |
129 | container_destroy(output); | 163 | free_swayc(output); |
130 | return NULL; | 164 | return NULL; |
131 | } | 165 | } |
132 | 166 | ||
133 | apply_output_config(oc, output); | 167 | apply_output_config(oc, output); |
134 | 168 | ||
135 | container_add_child(&root_container, output); | 169 | add_child(&root_container, output); |
136 | 170 | ||
137 | // Create workspace | 171 | // Create workspace |
138 | char *ws_name = workspace_next_name(output->name); | 172 | char *ws_name = workspace_next_name(output->name); |
139 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); | 173 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); |
140 | struct sway_container *ws = container_workspace_create(output, ws_name); | 174 | swayc_t *ws = new_workspace(output, ws_name); |
141 | // Set each seat's focus if not already set | 175 | // Set each seat's focus if not already set |
142 | struct sway_seat *seat = NULL; | 176 | struct sway_seat *seat = NULL; |
143 | wl_list_for_each(seat, &input_manager->seats, link) { | 177 | wl_list_for_each(seat, &input_manager->seats, link) { |
@@ -151,14 +185,12 @@ struct sway_container *container_output_create( | |||
151 | return output; | 185 | return output; |
152 | } | 186 | } |
153 | 187 | ||
154 | struct sway_container *container_workspace_create( | 188 | swayc_t *new_workspace(swayc_t *output, const char *name) { |
155 | struct sway_container *output, const char *name) { | 189 | if (!sway_assert(output, "new_workspace called with null output")) { |
156 | if (!sway_assert(output, | ||
157 | "container_workspace_create called with null output")) { | ||
158 | return NULL; | 190 | return NULL; |
159 | } | 191 | } |
160 | wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); | 192 | wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); |
161 | struct sway_container *workspace = container_create(C_WORKSPACE); | 193 | swayc_t *workspace = new_swayc(C_WORKSPACE); |
162 | 194 | ||
163 | workspace->x = output->x; | 195 | workspace->x = output->x; |
164 | workspace->y = output->y; | 196 | workspace->y = output->y; |
@@ -166,23 +198,21 @@ struct sway_container *container_workspace_create( | |||
166 | workspace->height = output->height; | 198 | workspace->height = output->height; |
167 | workspace->name = !name ? NULL : strdup(name); | 199 | workspace->name = !name ? NULL : strdup(name); |
168 | workspace->prev_layout = L_NONE; | 200 | workspace->prev_layout = L_NONE; |
169 | workspace->layout = container_get_default_layout(output); | 201 | workspace->layout = default_layout(output); |
170 | workspace->workspace_layout = container_get_default_layout(output); | 202 | workspace->workspace_layout = default_layout(output); |
171 | 203 | ||
172 | container_add_child(output, workspace); | 204 | add_child(output, workspace); |
173 | container_sort_workspaces(output); | 205 | sort_workspaces(output); |
174 | notify_new_container(workspace); | 206 | notify_new_container(workspace); |
175 | return workspace; | 207 | return workspace; |
176 | } | 208 | } |
177 | 209 | ||
178 | struct sway_container *container_view_create(struct sway_container *sibling, | 210 | swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { |
179 | struct sway_view *sway_view) { | 211 | if (!sway_assert(sibling, "new_view called with NULL sibling/parent")) { |
180 | if (!sway_assert(sibling, | ||
181 | "container_view_create called with NULL sibling/parent")) { | ||
182 | return NULL; | 212 | return NULL; |
183 | } | 213 | } |
184 | const char *title = view_get_title(sway_view); | 214 | const char *title = view_get_title(sway_view); |
185 | struct sway_container *swayc = container_create(C_VIEW); | 215 | swayc_t *swayc = new_swayc(C_VIEW); |
186 | wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s", | 216 | wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s", |
187 | swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); | 217 | swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); |
188 | // Setup values | 218 | // Setup values |
@@ -193,18 +223,17 @@ struct sway_container *container_view_create(struct sway_container *sibling, | |||
193 | 223 | ||
194 | if (sibling->type == C_WORKSPACE) { | 224 | if (sibling->type == C_WORKSPACE) { |
195 | // Case of focused workspace, just create as child of it | 225 | // Case of focused workspace, just create as child of it |
196 | container_add_child(sibling, swayc); | 226 | add_child(sibling, swayc); |
197 | } else { | 227 | } else { |
198 | // Regular case, create as sibling of current container | 228 | // Regular case, create as sibling of current container |
199 | container_add_sibling(sibling, swayc); | 229 | add_sibling(sibling, swayc); |
200 | } | 230 | } |
201 | notify_new_container(swayc); | 231 | notify_new_container(swayc); |
202 | return swayc; | 232 | return swayc; |
203 | } | 233 | } |
204 | 234 | ||
205 | struct sway_container *container_output_destroy(struct sway_container *output) { | 235 | swayc_t *destroy_output(swayc_t *output) { |
206 | if (!sway_assert(output, | 236 | if (!sway_assert(output, "null output passed to destroy_output")) { |
207 | "null output passed to container_output_destroy")) { | ||
208 | return NULL; | 237 | return NULL; |
209 | } | 238 | } |
210 | 239 | ||
@@ -216,13 +245,12 @@ struct sway_container *container_output_destroy(struct sway_container *output) { | |||
216 | int p = root_container.children->items[0] == output; | 245 | int p = root_container.children->items[0] == output; |
217 | // Move workspace from this output to another output | 246 | // Move workspace from this output to another output |
218 | while (output->children->length) { | 247 | while (output->children->length) { |
219 | struct sway_container *child = output->children->items[0]; | 248 | swayc_t *child = output->children->items[0]; |
220 | container_remove_child(child); | 249 | remove_child(child); |
221 | container_add_child(root_container.children->items[p], child); | 250 | add_child(root_container.children->items[p], child); |
222 | } | 251 | } |
223 | container_sort_workspaces(root_container.children->items[p]); | 252 | sort_workspaces(root_container.children->items[p]); |
224 | arrange_windows(root_container.children->items[p], | 253 | arrange_windows(root_container.children->items[p], -1, -1); |
225 | -1, -1); | ||
226 | } | 254 | } |
227 | } | 255 | } |
228 | 256 | ||
@@ -231,18 +259,18 @@ struct sway_container *container_output_destroy(struct sway_container *output) { | |||
231 | wl_list_remove(&output->sway_output->mode.link); | 259 | wl_list_remove(&output->sway_output->mode.link); |
232 | 260 | ||
233 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | 261 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); |
234 | container_destroy(output); | 262 | free_swayc(output); |
235 | 263 | ||
236 | return &root_container; | 264 | return &root_container; |
237 | } | 265 | } |
238 | 266 | ||
239 | struct sway_container *container_view_destroy(struct sway_container *view) { | 267 | swayc_t *destroy_view(swayc_t *view) { |
240 | if (!view) { | 268 | if (!view) { |
241 | return NULL; | 269 | return NULL; |
242 | } | 270 | } |
243 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | 271 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); |
244 | struct sway_container *parent = view->parent; | 272 | swayc_t *parent = view->parent; |
245 | container_destroy(view); | 273 | free_swayc(view); |
246 | 274 | ||
247 | // TODO WLR: Destroy empty containers | 275 | // TODO WLR: Destroy empty containers |
248 | /* | 276 | /* |
@@ -253,55 +281,7 @@ struct sway_container *container_view_destroy(struct sway_container *view) { | |||
253 | return parent; | 281 | return parent; |
254 | } | 282 | } |
255 | 283 | ||
256 | struct sway_container *container_set_layout(struct sway_container *container, | 284 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { |
257 | enum sway_container_layout layout) { | ||
258 | if (container->type == C_WORKSPACE) { | ||
259 | container->workspace_layout = layout; | ||
260 | if (layout == L_HORIZ || layout == L_VERT) { | ||
261 | container->layout = layout; | ||
262 | } | ||
263 | } else { | ||
264 | container->layout = layout; | ||
265 | } | ||
266 | return container; | ||
267 | } | ||
268 | |||
269 | void container_descendents(struct sway_container *root, | ||
270 | enum sway_container_type type, | ||
271 | void (*func)(struct sway_container *item, void *data), void *data) { | ||
272 | for (int i = 0; i < root->children->length; ++i) { | ||
273 | struct sway_container *item = root->children->items[i]; | ||
274 | if (item->type == type) { | ||
275 | func(item, data); | ||
276 | } | ||
277 | if (item->children && item->children->length) { | ||
278 | container_descendents(item, type, func, data); | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | struct sway_container *container_find(struct sway_container *container, | ||
284 | bool (*test)(struct sway_container *view, void *data), void *data) { | ||
285 | if (!container->children) { | ||
286 | return NULL; | ||
287 | } | ||
288 | // TODO: floating windows | ||
289 | for (int i = 0; i < container->children->length; ++i) { | ||
290 | struct sway_container *child = container->children->items[i]; | ||
291 | if (test(child, data)) { | ||
292 | return child; | ||
293 | } else { | ||
294 | struct sway_container *res = container_find(child, test, data); | ||
295 | if (res) { | ||
296 | return res; | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | return NULL; | ||
301 | } | ||
302 | |||
303 | struct sway_container *container_parent(struct sway_container *container, | ||
304 | enum sway_container_type type) { | ||
305 | if (!sway_assert(container, "container is NULL")) { | 285 | if (!sway_assert(container, "container is NULL")) { |
306 | return NULL; | 286 | return NULL; |
307 | } | 287 | } |
@@ -314,8 +294,7 @@ struct sway_container *container_parent(struct sway_container *container, | |||
314 | return container; | 294 | return container; |
315 | } | 295 | } |
316 | 296 | ||
317 | struct sway_container *container_at(struct sway_container *parent, | 297 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, |
318 | double lx, double ly, | ||
319 | struct wlr_surface **surface, double *sx, double *sy) { | 298 | struct wlr_surface **surface, double *sx, double *sy) { |
320 | list_t *queue = get_bfs_queue(); | 299 | list_t *queue = get_bfs_queue(); |
321 | if (!queue) { | 300 | if (!queue) { |
@@ -324,13 +303,13 @@ struct sway_container *container_at(struct sway_container *parent, | |||
324 | 303 | ||
325 | list_add(queue, parent); | 304 | list_add(queue, parent); |
326 | 305 | ||
327 | struct sway_container *swayc = NULL; | 306 | swayc_t *swayc = NULL; |
328 | while (queue->length) { | 307 | while (queue->length) { |
329 | swayc = queue->items[0]; | 308 | swayc = queue->items[0]; |
330 | list_del(queue, 0); | 309 | list_del(queue, 0); |
331 | if (swayc->type == C_VIEW) { | 310 | if (swayc->type == C_VIEW) { |
332 | struct sway_view *sview = swayc->sway_view; | 311 | struct sway_view *sview = swayc->sway_view; |
333 | struct sway_container *soutput = container_parent(swayc, C_OUTPUT); | 312 | swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); |
334 | struct wlr_box *output_box = | 313 | struct wlr_box *output_box = |
335 | wlr_output_layout_get_box( | 314 | wlr_output_layout_get_box( |
336 | root_container.sway_root->output_layout, | 315 | root_container.sway_root->output_layout, |
@@ -400,8 +379,30 @@ struct sway_container *container_at(struct sway_container *parent, | |||
400 | return NULL; | 379 | return NULL; |
401 | } | 380 | } |
402 | 381 | ||
403 | void container_for_each_descendent(struct sway_container *con, | 382 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { |
404 | void (*f)(struct sway_container *con, void *data), void *data) { | 383 | if (container) { |
384 | int i; | ||
385 | if (container->children) { | ||
386 | for (i = 0; i < container->children->length; ++i) { | ||
387 | swayc_t *child = container->children->items[i]; | ||
388 | container_map(child, f, data); | ||
389 | } | ||
390 | } | ||
391 | // TODO | ||
392 | /* | ||
393 | if (container->floating) { | ||
394 | for (i = 0; i < container->floating->length; ++i) { | ||
395 | swayc_t *child = container->floating->items[i]; | ||
396 | container_map(child, f, data); | ||
397 | } | ||
398 | } | ||
399 | */ | ||
400 | f(container, data); | ||
401 | } | ||
402 | } | ||
403 | |||
404 | void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), | ||
405 | void *data) { | ||
405 | list_t *queue = get_bfs_queue(); | 406 | list_t *queue = get_bfs_queue(); |
406 | if (!queue) { | 407 | if (!queue) { |
407 | return; | 408 | return; |
@@ -414,7 +415,7 @@ void container_for_each_descendent(struct sway_container *con, | |||
414 | 415 | ||
415 | list_add(queue, con); | 416 | list_add(queue, con); |
416 | 417 | ||
417 | struct sway_container *current = NULL; | 418 | swayc_t *current = NULL; |
418 | while (queue->length) { | 419 | while (queue->length) { |
419 | current = queue->items[0]; | 420 | current = queue->items[0]; |
420 | list_del(queue, 0); | 421 | list_del(queue, 0); |
@@ -423,3 +424,15 @@ void container_for_each_descendent(struct sway_container *con, | |||
423 | list_cat(queue, current->children); | 424 | list_cat(queue, current->children); |
424 | } | 425 | } |
425 | } | 426 | } |
427 | |||
428 | swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { | ||
429 | if (container->type == C_WORKSPACE) { | ||
430 | container->workspace_layout = layout; | ||
431 | if (layout == L_HORIZ || layout == L_VERT) { | ||
432 | container->layout = layout; | ||
433 | } | ||
434 | } else { | ||
435 | container->layout = layout; | ||
436 | } | ||
437 | return container; | ||
438 | } | ||