diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 871 |
1 files changed, 314 insertions, 557 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index 520b4566..0cb8d0a5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -24,97 +24,39 @@ | |||
24 | #include "log.h" | 24 | #include "log.h" |
25 | #include "stringop.h" | 25 | #include "stringop.h" |
26 | 26 | ||
27 | const char *container_type_to_str(enum sway_container_type type) { | 27 | struct sway_container *container_create(struct sway_view *view) { |
28 | switch (type) { | ||
29 | case C_ROOT: | ||
30 | return "C_ROOT"; | ||
31 | case C_OUTPUT: | ||
32 | return "C_OUTPUT"; | ||
33 | case C_WORKSPACE: | ||
34 | return "C_WORKSPACE"; | ||
35 | case C_CONTAINER: | ||
36 | return "C_CONTAINER"; | ||
37 | case C_VIEW: | ||
38 | return "C_VIEW"; | ||
39 | default: | ||
40 | return "C_UNKNOWN"; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | void container_create_notify(struct sway_container *container) { | ||
45 | if (container->type == C_VIEW) { | ||
46 | ipc_event_window(container, "new"); | ||
47 | } else if (container->type == C_WORKSPACE) { | ||
48 | ipc_event_workspace(NULL, container, "init"); | ||
49 | } | ||
50 | wl_signal_emit(&root_container.sway_root->events.new_container, container); | ||
51 | } | ||
52 | |||
53 | void container_update_textures_recursive(struct sway_container *con) { | ||
54 | if (con->type == C_CONTAINER || con->type == C_VIEW) { | ||
55 | container_update_title_textures(con); | ||
56 | } | ||
57 | |||
58 | if (con->type == C_VIEW) { | ||
59 | view_update_marks_textures(con->sway_view); | ||
60 | } else { | ||
61 | for (int i = 0; i < con->children->length; ++i) { | ||
62 | struct sway_container *child = con->children->items[i]; | ||
63 | container_update_textures_recursive(child); | ||
64 | } | ||
65 | |||
66 | if (con->type == C_WORKSPACE) { | ||
67 | for (int i = 0; i < con->sway_workspace->floating->length; ++i) { | ||
68 | struct sway_container *floater = | ||
69 | con->sway_workspace->floating->items[i]; | ||
70 | container_update_textures_recursive(floater); | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | struct sway_container *container_create(enum sway_container_type type) { | ||
77 | // next id starts at 1 because 0 is assigned to root_container in layout.c | ||
78 | static size_t next_id = 1; | ||
79 | struct sway_container *c = calloc(1, sizeof(struct sway_container)); | 28 | struct sway_container *c = calloc(1, sizeof(struct sway_container)); |
80 | if (!c) { | 29 | if (!c) { |
30 | wlr_log(WLR_ERROR, "Unable to allocate sway_container"); | ||
81 | return NULL; | 31 | return NULL; |
82 | } | 32 | } |
83 | c->id = next_id++; | 33 | node_init(&c->node, N_CONTAINER, c); |
84 | c->layout = L_NONE; | 34 | c->layout = L_NONE; |
85 | c->type = type; | 35 | c->view = view; |
86 | c->alpha = 1.0f; | 36 | c->alpha = 1.0f; |
87 | 37 | ||
88 | if (type != C_VIEW) { | 38 | if (!view) { |
89 | c->children = create_list(); | 39 | c->children = create_list(); |
90 | c->current.children = create_list(); | 40 | c->current.children = create_list(); |
91 | } | 41 | } |
92 | c->outputs = create_list(); | 42 | c->outputs = create_list(); |
93 | 43 | ||
94 | wl_signal_init(&c->events.destroy); | 44 | wl_signal_init(&c->events.destroy); |
95 | 45 | wl_signal_emit(&root->events.new_node, &c->node); | |
96 | c->has_gaps = false; | ||
97 | c->gaps_inner = 0; | ||
98 | c->gaps_outer = 0; | ||
99 | c->current_gaps = 0; | ||
100 | 46 | ||
101 | return c; | 47 | return c; |
102 | } | 48 | } |
103 | 49 | ||
104 | void container_destroy(struct sway_container *con) { | 50 | void container_destroy(struct sway_container *con) { |
105 | if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, | 51 | if (!sway_assert(con->node.destroying, |
106 | "Expected a container or view")) { | ||
107 | return; | ||
108 | } | ||
109 | if (!sway_assert(con->destroying, | ||
110 | "Tried to free container which wasn't marked as destroying")) { | 52 | "Tried to free container which wasn't marked as destroying")) { |
111 | return; | 53 | return; |
112 | } | 54 | } |
113 | if (!sway_assert(con->ntxnrefs == 0, "Tried to free container " | 55 | if (!sway_assert(con->node.ntxnrefs == 0, "Tried to free container " |
114 | "which is still referenced by transactions")) { | 56 | "which is still referenced by transactions")) { |
115 | return; | 57 | return; |
116 | } | 58 | } |
117 | free(con->name); | 59 | free(con->title); |
118 | free(con->formatted_title); | 60 | free(con->formatted_title); |
119 | wlr_texture_destroy(con->title_focused); | 61 | wlr_texture_destroy(con->title_focused); |
120 | wlr_texture_destroy(con->title_focused_inactive); | 62 | wlr_texture_destroy(con->title_focused_inactive); |
@@ -124,14 +66,14 @@ void container_destroy(struct sway_container *con) { | |||
124 | list_free(con->current.children); | 66 | list_free(con->current.children); |
125 | list_free(con->outputs); | 67 | list_free(con->outputs); |
126 | 68 | ||
127 | if (con->type == C_VIEW) { | 69 | if (con->view) { |
128 | struct sway_view *view = con->sway_view; | 70 | struct sway_view *view = con->view; |
129 | view->swayc = NULL; | 71 | view->container = NULL; |
130 | free(view->title_format); | 72 | free(view->title_format); |
131 | view->title_format = NULL; | 73 | view->title_format = NULL; |
132 | 74 | ||
133 | if (view->destroying) { | 75 | if (view->destroying) { |
134 | view_destroy(view); | 76 | view_destroy(con->view); |
135 | } | 77 | } |
136 | } | 78 | } |
137 | 79 | ||
@@ -139,115 +81,57 @@ void container_destroy(struct sway_container *con) { | |||
139 | } | 81 | } |
140 | 82 | ||
141 | void container_begin_destroy(struct sway_container *con) { | 83 | void container_begin_destroy(struct sway_container *con) { |
142 | if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, | 84 | if (con->view) { |
143 | "Expected a container or view")) { | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | if (con->type == C_VIEW) { | ||
148 | ipc_event_window(con, "close"); | 85 | ipc_event_window(con, "close"); |
149 | } | 86 | } |
150 | wl_signal_emit(&con->events.destroy, con); | 87 | wl_signal_emit(&con->node.events.destroy, &con->node); |
151 | 88 | ||
152 | container_end_mouse_operation(con); | 89 | container_end_mouse_operation(con); |
153 | 90 | ||
154 | con->destroying = true; | 91 | con->node.destroying = true; |
155 | container_set_dirty(con); | 92 | node_set_dirty(&con->node); |
156 | 93 | ||
157 | if (con->scratchpad) { | 94 | if (con->scratchpad) { |
158 | root_scratchpad_remove_container(con); | 95 | root_scratchpad_remove_container(con); |
159 | } | 96 | } |
160 | 97 | ||
161 | if (con->parent) { | 98 | if (con->parent || con->workspace) { |
162 | container_remove_child(con); | 99 | container_detach(con); |
163 | } | 100 | } |
164 | } | 101 | } |
165 | 102 | ||
166 | struct sway_container *container_reap_empty(struct sway_container *con) { | 103 | void container_reap_empty(struct sway_container *con) { |
167 | while (con && con->type == C_CONTAINER) { | 104 | if (con->view) { |
168 | struct sway_container *next = con->parent; | 105 | return; |
169 | if (con->children->length == 0) { | ||
170 | container_begin_destroy(con); | ||
171 | } | ||
172 | con = next; | ||
173 | } | 106 | } |
174 | if (con && con->type == C_WORKSPACE) { | 107 | struct sway_workspace *ws = con->workspace; |
175 | workspace_consider_destroy(con); | 108 | while (con) { |
176 | if (con->destroying) { | 109 | if (con->children->length) { |
177 | con = con->parent; | 110 | return; |
178 | } | 111 | } |
112 | struct sway_container *parent = con->parent; | ||
113 | container_begin_destroy(con); | ||
114 | con = parent; | ||
179 | } | 115 | } |
180 | return con; | 116 | workspace_consider_destroy(ws); |
181 | } | 117 | } |
182 | 118 | ||
183 | struct sway_container *container_flatten(struct sway_container *container) { | 119 | struct sway_container *container_flatten(struct sway_container *container) { |
184 | while (container->type == C_CONTAINER && container->children->length == 1) { | 120 | if (container->view) { |
121 | return NULL; | ||
122 | } | ||
123 | while (container && container->children->length == 1) { | ||
185 | struct sway_container *child = container->children->items[0]; | 124 | struct sway_container *child = container->children->items[0]; |
186 | struct sway_container *parent = container->parent; | 125 | struct sway_container *parent = container->parent; |
187 | container_replace_child(container, child); | 126 | container_replace(container, child); |
188 | container_begin_destroy(container); | 127 | container_begin_destroy(container); |
189 | container = parent; | 128 | container = parent; |
190 | } | 129 | } |
191 | return container; | 130 | return container; |
192 | } | 131 | } |
193 | 132 | ||
194 | static void container_close_func(struct sway_container *container, void *data) { | ||
195 | if (container->type == C_VIEW) { | ||
196 | view_close(container->sway_view); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | struct sway_container *container_close(struct sway_container *con) { | ||
201 | if (!sway_assert(con != NULL, | ||
202 | "container_close called with a NULL container")) { | ||
203 | return NULL; | ||
204 | } | ||
205 | |||
206 | struct sway_container *parent = con->parent; | ||
207 | |||
208 | if (con->type == C_VIEW) { | ||
209 | view_close(con->sway_view); | ||
210 | } else if (con->type == C_CONTAINER) { | ||
211 | container_for_each_child(con, container_close_func, NULL); | ||
212 | } else if (con->type == C_WORKSPACE) { | ||
213 | workspace_for_each_container(con, container_close_func, NULL); | ||
214 | } | ||
215 | |||
216 | return parent; | ||
217 | } | ||
218 | |||
219 | struct sway_container *container_view_create(struct sway_container *sibling, | ||
220 | struct sway_view *sway_view) { | ||
221 | if (!sway_assert(sibling, | ||
222 | "container_view_create called with NULL sibling/parent")) { | ||
223 | return NULL; | ||
224 | } | ||
225 | const char *title = view_get_title(sway_view); | ||
226 | struct sway_container *swayc = container_create(C_VIEW); | ||
227 | wlr_log(WLR_DEBUG, "Adding new view %p:%s to container %p %d %s", | ||
228 | swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); | ||
229 | // Setup values | ||
230 | swayc->sway_view = sway_view; | ||
231 | swayc->width = 0; | ||
232 | swayc->height = 0; | ||
233 | |||
234 | if (sibling->type == C_WORKSPACE) { | ||
235 | // Case of focused workspace, just create as child of it | ||
236 | container_add_child(sibling, swayc); | ||
237 | } else { | ||
238 | // Regular case, create as sibling of current container | ||
239 | container_add_sibling(sibling, swayc); | ||
240 | } | ||
241 | container_create_notify(swayc); | ||
242 | return swayc; | ||
243 | } | ||
244 | |||
245 | struct sway_container *container_find_child(struct sway_container *container, | 133 | struct sway_container *container_find_child(struct sway_container *container, |
246 | bool (*test)(struct sway_container *view, void *data), void *data) { | 134 | bool (*test)(struct sway_container *con, void *data), void *data) { |
247 | if (!sway_assert(container->type == C_CONTAINER || | ||
248 | container->type == C_VIEW, "Expected a container or view")) { | ||
249 | return NULL; | ||
250 | } | ||
251 | if (!container->children) { | 135 | if (!container->children) { |
252 | return NULL; | 136 | return NULL; |
253 | } | 137 | } |
@@ -264,46 +148,32 @@ struct sway_container *container_find_child(struct sway_container *container, | |||
264 | return NULL; | 148 | return NULL; |
265 | } | 149 | } |
266 | 150 | ||
267 | struct sway_container *container_parent(struct sway_container *container, | 151 | static void surface_at_view(struct sway_container *con, double lx, double ly, |
268 | enum sway_container_type type) { | ||
269 | if (!sway_assert(container, "container is NULL")) { | ||
270 | return NULL; | ||
271 | } | ||
272 | if (!sway_assert(type < C_TYPES && type >= C_ROOT, "invalid type")) { | ||
273 | return NULL; | ||
274 | } | ||
275 | do { | ||
276 | container = container->parent; | ||
277 | } while (container && container->type != type); | ||
278 | return container; | ||
279 | } | ||
280 | |||
281 | static void surface_at_view(struct sway_container *swayc, double lx, double ly, | ||
282 | struct wlr_surface **surface, double *sx, double *sy) { | 152 | struct wlr_surface **surface, double *sx, double *sy) { |
283 | if (!sway_assert(swayc->type == C_VIEW, "Expected a view")) { | 153 | if (!sway_assert(con->view, "Expected a view")) { |
284 | return; | 154 | return; |
285 | } | 155 | } |
286 | struct sway_view *sview = swayc->sway_view; | 156 | struct sway_view *view = con->view; |
287 | double view_sx = lx - sview->x + sview->geometry.x; | 157 | double view_sx = lx - view->x + view->geometry.x; |
288 | double view_sy = ly - sview->y + sview->geometry.y; | 158 | double view_sy = ly - view->y + view->geometry.y; |
289 | 159 | ||
290 | double _sx, _sy; | 160 | double _sx, _sy; |
291 | struct wlr_surface *_surface = NULL; | 161 | struct wlr_surface *_surface = NULL; |
292 | switch (sview->type) { | 162 | switch (view->type) { |
293 | #ifdef HAVE_XWAYLAND | 163 | #ifdef HAVE_XWAYLAND |
294 | case SWAY_VIEW_XWAYLAND: | 164 | case SWAY_VIEW_XWAYLAND: |
295 | _surface = wlr_surface_surface_at(sview->surface, | 165 | _surface = wlr_surface_surface_at(view->surface, |
296 | view_sx, view_sy, &_sx, &_sy); | 166 | view_sx, view_sy, &_sx, &_sy); |
297 | break; | 167 | break; |
298 | #endif | 168 | #endif |
299 | case SWAY_VIEW_XDG_SHELL_V6: | 169 | case SWAY_VIEW_XDG_SHELL_V6: |
300 | _surface = wlr_xdg_surface_v6_surface_at( | 170 | _surface = wlr_xdg_surface_v6_surface_at( |
301 | sview->wlr_xdg_surface_v6, | 171 | view->wlr_xdg_surface_v6, |
302 | view_sx, view_sy, &_sx, &_sy); | 172 | view_sx, view_sy, &_sx, &_sy); |
303 | break; | 173 | break; |
304 | case SWAY_VIEW_XDG_SHELL: | 174 | case SWAY_VIEW_XDG_SHELL: |
305 | _surface = wlr_xdg_surface_surface_at( | 175 | _surface = wlr_xdg_surface_surface_at( |
306 | sview->wlr_xdg_surface, | 176 | view->wlr_xdg_surface, |
307 | view_sx, view_sy, &_sx, &_sy); | 177 | view_sx, view_sy, &_sx, &_sy); |
308 | break; | 178 | break; |
309 | } | 179 | } |
@@ -317,65 +187,72 @@ static void surface_at_view(struct sway_container *swayc, double lx, double ly, | |||
317 | /** | 187 | /** |
318 | * container_at for a container with layout L_TABBED. | 188 | * container_at for a container with layout L_TABBED. |
319 | */ | 189 | */ |
320 | static struct sway_container *container_at_tabbed(struct sway_container *parent, | 190 | static struct sway_container *container_at_tabbed(struct sway_node *parent, |
321 | double lx, double ly, | 191 | double lx, double ly, |
322 | struct wlr_surface **surface, double *sx, double *sy) { | 192 | struct wlr_surface **surface, double *sx, double *sy) { |
323 | if (ly < parent->y || ly > parent->y + parent->height) { | 193 | struct wlr_box box; |
194 | node_get_box(parent, &box); | ||
195 | if (ly < box.y || ly > box.y + box.height) { | ||
324 | return NULL; | 196 | return NULL; |
325 | } | 197 | } |
326 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 198 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
199 | list_t *children = node_get_children(parent); | ||
327 | 200 | ||
328 | // Tab titles | 201 | // Tab titles |
329 | int title_height = container_titlebar_height(); | 202 | int title_height = container_titlebar_height(); |
330 | if (ly < parent->y + title_height) { | 203 | if (ly < box.y + title_height) { |
331 | int tab_width = parent->width / parent->children->length; | 204 | int tab_width = box.width / children->length; |
332 | int child_index = (lx - parent->x) / tab_width; | 205 | int child_index = (lx - box.x) / tab_width; |
333 | if (child_index >= parent->children->length) { | 206 | if (child_index >= children->length) { |
334 | child_index = parent->children->length - 1; | 207 | child_index = children->length - 1; |
335 | } | 208 | } |
336 | struct sway_container *child = parent->children->items[child_index]; | 209 | struct sway_container *child = children->items[child_index]; |
337 | return seat_get_focus_inactive(seat, child); | 210 | struct sway_node *node = seat_get_focus_inactive(seat, &child->node); |
211 | return node->sway_container; | ||
338 | } | 212 | } |
339 | 213 | ||
340 | // Surfaces | 214 | // Surfaces |
341 | struct sway_container *current = seat_get_active_child(seat, parent); | 215 | struct sway_node *current = seat_get_active_child(seat, parent); |
342 | |||
343 | return tiling_container_at(current, lx, ly, surface, sx, sy); | 216 | return tiling_container_at(current, lx, ly, surface, sx, sy); |
344 | } | 217 | } |
345 | 218 | ||
346 | /** | 219 | /** |
347 | * container_at for a container with layout L_STACKED. | 220 | * container_at for a container with layout L_STACKED. |
348 | */ | 221 | */ |
349 | static struct sway_container *container_at_stacked( | 222 | static struct sway_container *container_at_stacked(struct sway_node *parent, |
350 | struct sway_container *parent, double lx, double ly, | 223 | double lx, double ly, |
351 | struct wlr_surface **surface, double *sx, double *sy) { | 224 | struct wlr_surface **surface, double *sx, double *sy) { |
352 | if (ly < parent->y || ly > parent->y + parent->height) { | 225 | struct wlr_box box; |
226 | node_get_box(parent, &box); | ||
227 | if (ly < box.y || ly > box.y + box.height) { | ||
353 | return NULL; | 228 | return NULL; |
354 | } | 229 | } |
355 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 230 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
231 | list_t *children = node_get_children(parent); | ||
356 | 232 | ||
357 | // Title bars | 233 | // Title bars |
358 | int title_height = container_titlebar_height(); | 234 | int title_height = container_titlebar_height(); |
359 | int child_index = (ly - parent->y) / title_height; | 235 | int child_index = (ly - box.y) / title_height; |
360 | if (child_index < parent->children->length) { | 236 | if (child_index < children->length) { |
361 | struct sway_container *child = parent->children->items[child_index]; | 237 | struct sway_container *child = children->items[child_index]; |
362 | return seat_get_focus_inactive(seat, child); | 238 | struct sway_node *node = seat_get_focus_inactive(seat, &child->node); |
239 | return node->sway_container; | ||
363 | } | 240 | } |
364 | 241 | ||
365 | // Surfaces | 242 | // Surfaces |
366 | struct sway_container *current = seat_get_active_child(seat, parent); | 243 | struct sway_node *current = seat_get_active_child(seat, parent); |
367 | |||
368 | return tiling_container_at(current, lx, ly, surface, sx, sy); | 244 | return tiling_container_at(current, lx, ly, surface, sx, sy); |
369 | } | 245 | } |
370 | 246 | ||
371 | /** | 247 | /** |
372 | * container_at for a container with layout L_HORIZ or L_VERT. | 248 | * container_at for a container with layout L_HORIZ or L_VERT. |
373 | */ | 249 | */ |
374 | static struct sway_container *container_at_linear(struct sway_container *parent, | 250 | static struct sway_container *container_at_linear(struct sway_node *parent, |
375 | double lx, double ly, | 251 | double lx, double ly, |
376 | struct wlr_surface **surface, double *sx, double *sy) { | 252 | struct wlr_surface **surface, double *sx, double *sy) { |
377 | for (int i = 0; i < parent->children->length; ++i) { | 253 | list_t *children = node_get_children(parent); |
378 | struct sway_container *child = parent->children->items[i]; | 254 | for (int i = 0; i < children->length; ++i) { |
255 | struct sway_container *child = children->items[i]; | ||
379 | struct wlr_box box = { | 256 | struct wlr_box box = { |
380 | .x = child->x, | 257 | .x = child->x, |
381 | .y = child->y, | 258 | .y = child->y, |
@@ -383,7 +260,7 @@ static struct sway_container *container_at_linear(struct sway_container *parent, | |||
383 | .height = child->height, | 260 | .height = child->height, |
384 | }; | 261 | }; |
385 | if (wlr_box_contains_point(&box, lx, ly)) { | 262 | if (wlr_box_contains_point(&box, lx, ly)) { |
386 | return tiling_container_at(child, lx, ly, surface, sx, sy); | 263 | return tiling_container_at(&child->node, lx, ly, surface, sx, sy); |
387 | } | 264 | } |
388 | } | 265 | } |
389 | return NULL; | 266 | return NULL; |
@@ -391,12 +268,11 @@ static struct sway_container *container_at_linear(struct sway_container *parent, | |||
391 | 268 | ||
392 | static struct sway_container *floating_container_at(double lx, double ly, | 269 | static struct sway_container *floating_container_at(double lx, double ly, |
393 | struct wlr_surface **surface, double *sx, double *sy) { | 270 | struct wlr_surface **surface, double *sx, double *sy) { |
394 | for (int i = 0; i < root_container.children->length; ++i) { | 271 | for (int i = 0; i < root->outputs->length; ++i) { |
395 | struct sway_container *output = root_container.children->items[i]; | 272 | struct sway_output *output = root->outputs->items[i]; |
396 | for (int j = 0; j < output->children->length; ++j) { | 273 | for (int j = 0; j < output->workspaces->length; ++j) { |
397 | struct sway_container *workspace = output->children->items[j]; | 274 | struct sway_workspace *ws = output->workspaces->items[j]; |
398 | struct sway_workspace *ws = workspace->sway_workspace; | 275 | if (!workspace_is_visible(ws)) { |
399 | if (!workspace_is_visible(workspace)) { | ||
400 | continue; | 276 | continue; |
401 | } | 277 | } |
402 | // Items at the end of the list are on top, so iterate the list in | 278 | // Items at the end of the list are on top, so iterate the list in |
@@ -410,7 +286,7 @@ static struct sway_container *floating_container_at(double lx, double ly, | |||
410 | .height = floater->height, | 286 | .height = floater->height, |
411 | }; | 287 | }; |
412 | if (wlr_box_contains_point(&box, lx, ly)) { | 288 | if (wlr_box_contains_point(&box, lx, ly)) { |
413 | return tiling_container_at(floater, lx, ly, | 289 | return tiling_container_at(&floater->node, lx, ly, |
414 | surface, sx, sy); | 290 | surface, sx, sy); |
415 | } | 291 | } |
416 | } | 292 | } |
@@ -419,25 +295,24 @@ static struct sway_container *floating_container_at(double lx, double ly, | |||
419 | return NULL; | 295 | return NULL; |
420 | } | 296 | } |
421 | 297 | ||
422 | struct sway_container *tiling_container_at( | 298 | struct sway_container *tiling_container_at(struct sway_node *parent, |
423 | struct sway_container *con, double lx, double ly, | 299 | double lx, double ly, |
424 | struct wlr_surface **surface, double *sx, double *sy) { | 300 | struct wlr_surface **surface, double *sx, double *sy) { |
425 | if (con->type == C_VIEW) { | 301 | if (node_is_view(parent)) { |
426 | surface_at_view(con, lx, ly, surface, sx, sy); | 302 | surface_at_view(parent->sway_container, lx, ly, surface, sx, sy); |
427 | return con; | 303 | return parent->sway_container; |
428 | } | 304 | } |
429 | if (!con->children->length) { | 305 | if (!node_get_children(parent)) { |
430 | return NULL; | 306 | return NULL; |
431 | } | 307 | } |
432 | 308 | switch (node_get_layout(parent)) { | |
433 | switch (con->layout) { | ||
434 | case L_HORIZ: | 309 | case L_HORIZ: |
435 | case L_VERT: | 310 | case L_VERT: |
436 | return container_at_linear(con, lx, ly, surface, sx, sy); | 311 | return container_at_linear(parent, lx, ly, surface, sx, sy); |
437 | case L_TABBED: | 312 | case L_TABBED: |
438 | return container_at_tabbed(con, lx, ly, surface, sx, sy); | 313 | return container_at_tabbed(parent, lx, ly, surface, sx, sy); |
439 | case L_STACKED: | 314 | case L_STACKED: |
440 | return container_at_stacked(con, lx, ly, surface, sx, sy); | 315 | return container_at_stacked(parent, lx, ly, surface, sx, sy); |
441 | case L_NONE: | 316 | case L_NONE: |
442 | return NULL; | 317 | return NULL; |
443 | } | 318 | } |
@@ -472,19 +347,16 @@ static bool surface_is_popup(struct wlr_surface *surface) { | |||
472 | return false; | 347 | return false; |
473 | } | 348 | } |
474 | 349 | ||
475 | struct sway_container *container_at(struct sway_container *workspace, | 350 | struct sway_container *container_at(struct sway_workspace *workspace, |
476 | double lx, double ly, | 351 | double lx, double ly, |
477 | struct wlr_surface **surface, double *sx, double *sy) { | 352 | struct wlr_surface **surface, double *sx, double *sy) { |
478 | if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { | ||
479 | return NULL; | ||
480 | } | ||
481 | struct sway_container *c; | 353 | struct sway_container *c; |
354 | // Focused view's popups | ||
482 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 355 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
483 | struct sway_container *focus = | 356 | struct sway_container *focus = seat_get_focused_container(seat); |
484 | seat_get_focus_inactive(seat, &root_container); | ||
485 | bool is_floating = focus && container_is_floating_or_child(focus); | 357 | bool is_floating = focus && container_is_floating_or_child(focus); |
486 | // Focused view's popups | 358 | // Focused view's popups |
487 | if (focus && focus->type == C_VIEW) { | 359 | if (focus && focus->view) { |
488 | surface_at_view(focus, lx, ly, surface, sx, sy); | 360 | surface_at_view(focus, lx, ly, surface, sx, sy); |
489 | if (*surface && surface_is_popup(*surface)) { | 361 | if (*surface && surface_is_popup(*surface)) { |
490 | return focus; | 362 | return focus; |
@@ -492,7 +364,7 @@ struct sway_container *container_at(struct sway_container *workspace, | |||
492 | *surface = NULL; | 364 | *surface = NULL; |
493 | } | 365 | } |
494 | // If focused is floating, focused view's non-popups | 366 | // If focused is floating, focused view's non-popups |
495 | if (focus && focus->type == C_VIEW && is_floating) { | 367 | if (focus && focus->view && is_floating) { |
496 | surface_at_view(focus, lx, ly, surface, sx, sy); | 368 | surface_at_view(focus, lx, ly, surface, sx, sy); |
497 | if (*surface) { | 369 | if (*surface) { |
498 | return focus; | 370 | return focus; |
@@ -504,7 +376,7 @@ struct sway_container *container_at(struct sway_container *workspace, | |||
504 | return c; | 376 | return c; |
505 | } | 377 | } |
506 | // If focused is tiling, focused view's non-popups | 378 | // If focused is tiling, focused view's non-popups |
507 | if (focus && focus->type == C_VIEW && !is_floating) { | 379 | if (focus && focus->view && !is_floating) { |
508 | surface_at_view(focus, lx, ly, surface, sx, sy); | 380 | surface_at_view(focus, lx, ly, surface, sx, sy); |
509 | if (*surface) { | 381 | if (*surface) { |
510 | return focus; | 382 | return focus; |
@@ -512,7 +384,7 @@ struct sway_container *container_at(struct sway_container *workspace, | |||
512 | *surface = NULL; | 384 | *surface = NULL; |
513 | } | 385 | } |
514 | // Tiling (non-focused) | 386 | // Tiling (non-focused) |
515 | if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) { | 387 | if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { |
516 | return c; | 388 | return c; |
517 | } | 389 | } |
518 | return NULL; | 390 | return NULL; |
@@ -521,10 +393,6 @@ struct sway_container *container_at(struct sway_container *workspace, | |||
521 | void container_for_each_child(struct sway_container *container, | 393 | void container_for_each_child(struct sway_container *container, |
522 | void (*f)(struct sway_container *container, void *data), | 394 | void (*f)(struct sway_container *container, void *data), |
523 | void *data) { | 395 | void *data) { |
524 | if (!sway_assert(container->type == C_CONTAINER || | ||
525 | container->type == C_VIEW, "Expected a container or view")) { | ||
526 | return; | ||
527 | } | ||
528 | if (container->children) { | 396 | if (container->children) { |
529 | for (int i = 0; i < container->children->length; ++i) { | 397 | for (int i = 0; i < container->children->length; ++i) { |
530 | struct sway_container *child = container->children->items[i]; | 398 | struct sway_container *child = container->children->items[i]; |
@@ -536,7 +404,7 @@ void container_for_each_child(struct sway_container *container, | |||
536 | 404 | ||
537 | bool container_has_ancestor(struct sway_container *descendant, | 405 | bool container_has_ancestor(struct sway_container *descendant, |
538 | struct sway_container *ancestor) { | 406 | struct sway_container *ancestor) { |
539 | while (descendant && descendant->type != C_ROOT) { | 407 | while (descendant) { |
540 | descendant = descendant->parent; | 408 | descendant = descendant->parent; |
541 | if (descendant == ancestor) { | 409 | if (descendant == ancestor) { |
542 | return true; | 410 | return true; |
@@ -545,27 +413,10 @@ bool container_has_ancestor(struct sway_container *descendant, | |||
545 | return false; | 413 | return false; |
546 | } | 414 | } |
547 | 415 | ||
548 | int container_count_descendants_of_type(struct sway_container *con, | ||
549 | enum sway_container_type type) { | ||
550 | int children = 0; | ||
551 | if (con->type == type) { | ||
552 | children++; | ||
553 | } | ||
554 | if (con->children) { | ||
555 | for (int i = 0; i < con->children->length; i++) { | ||
556 | struct sway_container *child = con->children->items[i]; | ||
557 | children += container_count_descendants_of_type(child, type); | ||
558 | } | ||
559 | } | ||
560 | return children; | ||
561 | } | ||
562 | |||
563 | void container_damage_whole(struct sway_container *container) { | 416 | void container_damage_whole(struct sway_container *container) { |
564 | for (int i = 0; i < root_container.children->length; ++i) { | 417 | for (int i = 0; i < root->outputs->length; ++i) { |
565 | struct sway_container *cont = root_container.children->items[i]; | 418 | struct sway_output *output = root->outputs->items[i]; |
566 | if (cont->type == C_OUTPUT) { | 419 | output_damage_whole_container(output, container); |
567 | output_damage_whole_container(cont->sway_output, container); | ||
568 | } | ||
569 | } | 420 | } |
570 | } | 421 | } |
571 | 422 | ||
@@ -582,10 +433,6 @@ struct sway_output *container_get_effective_output(struct sway_container *con) { | |||
582 | 433 | ||
583 | static void update_title_texture(struct sway_container *con, | 434 | static void update_title_texture(struct sway_container *con, |
584 | struct wlr_texture **texture, struct border_colors *class) { | 435 | struct wlr_texture **texture, struct border_colors *class) { |
585 | if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, | ||
586 | "Unexpected type %s", container_type_to_str(con->type))) { | ||
587 | return; | ||
588 | } | ||
589 | struct sway_output *output = container_get_effective_output(con); | 436 | struct sway_output *output = container_get_effective_output(con); |
590 | if (!output) { | 437 | if (!output) { |
591 | return; | 438 | return; |
@@ -664,9 +511,10 @@ void container_calculate_title_height(struct sway_container *container) { | |||
664 | * An example tree representation is: V[Terminal, Firefox] | 511 | * An example tree representation is: V[Terminal, Firefox] |
665 | * If buffer is not NULL, also populate the buffer with the representation. | 512 | * If buffer is not NULL, also populate the buffer with the representation. |
666 | */ | 513 | */ |
667 | static size_t get_tree_representation(struct sway_container *parent, char *buffer) { | 514 | size_t container_build_representation(enum sway_container_layout layout, |
515 | list_t *children, char *buffer) { | ||
668 | size_t len = 2; | 516 | size_t len = 2; |
669 | switch (parent->layout) { | 517 | switch (layout) { |
670 | case L_VERT: | 518 | case L_VERT: |
671 | lenient_strcat(buffer, "V["); | 519 | lenient_strcat(buffer, "V["); |
672 | break; | 520 | break; |
@@ -683,17 +531,17 @@ static size_t get_tree_representation(struct sway_container *parent, char *buffe | |||
683 | lenient_strcat(buffer, "D["); | 531 | lenient_strcat(buffer, "D["); |
684 | break; | 532 | break; |
685 | } | 533 | } |
686 | for (int i = 0; i < parent->children->length; ++i) { | 534 | for (int i = 0; i < children->length; ++i) { |
687 | if (i != 0) { | 535 | if (i != 0) { |
688 | ++len; | 536 | ++len; |
689 | lenient_strcat(buffer, " "); | 537 | lenient_strcat(buffer, " "); |
690 | } | 538 | } |
691 | struct sway_container *child = parent->children->items[i]; | 539 | struct sway_container *child = children->items[i]; |
692 | const char *identifier = NULL; | 540 | const char *identifier = NULL; |
693 | if (child->type == C_VIEW) { | 541 | if (child->view) { |
694 | identifier = view_get_class(child->sway_view); | 542 | identifier = view_get_class(child->view); |
695 | if (!identifier) { | 543 | if (!identifier) { |
696 | identifier = view_get_app_id(child->sway_view); | 544 | identifier = view_get_app_id(child->view); |
697 | } | 545 | } |
698 | } else { | 546 | } else { |
699 | identifier = child->formatted_title; | 547 | identifier = child->formatted_title; |
@@ -711,25 +559,25 @@ static size_t get_tree_representation(struct sway_container *parent, char *buffe | |||
711 | return len; | 559 | return len; |
712 | } | 560 | } |
713 | 561 | ||
714 | void container_notify_subtree_changed(struct sway_container *container) { | 562 | void container_update_representation(struct sway_container *con) { |
715 | if (!container || container->type < C_WORKSPACE) { | 563 | if (!con->view) { |
716 | return; | 564 | size_t len = container_build_representation(con->layout, |
717 | } | 565 | con->children, NULL); |
718 | free(container->formatted_title); | 566 | free(con->formatted_title); |
719 | container->formatted_title = NULL; | 567 | con->formatted_title = calloc(len + 1, sizeof(char)); |
720 | 568 | if (!sway_assert(con->formatted_title, | |
721 | size_t len = get_tree_representation(container, NULL); | 569 | "Unable to allocate title string")) { |
722 | char *buffer = calloc(len + 1, sizeof(char)); | 570 | return; |
723 | if (!sway_assert(buffer, "Unable to allocate title string")) { | 571 | } |
724 | return; | 572 | container_build_representation(con->layout, con->children, |
573 | con->formatted_title); | ||
574 | container_calculate_title_height(con); | ||
575 | container_update_title_textures(con); | ||
725 | } | 576 | } |
726 | get_tree_representation(container, buffer); | 577 | if (con->parent) { |
727 | 578 | container_update_representation(con->parent); | |
728 | container->formatted_title = buffer; | 579 | } else if (con->workspace) { |
729 | if (container->type != C_WORKSPACE) { | 580 | workspace_update_representation(con->workspace); |
730 | container_calculate_title_height(container); | ||
731 | container_update_title_textures(container); | ||
732 | container_notify_subtree_changed(container->parent); | ||
733 | } | 581 | } |
734 | } | 582 | } |
735 | 583 | ||
@@ -738,11 +586,7 @@ size_t container_titlebar_height() { | |||
738 | } | 586 | } |
739 | 587 | ||
740 | void container_init_floating(struct sway_container *con) { | 588 | void container_init_floating(struct sway_container *con) { |
741 | if (!sway_assert(con->type == C_VIEW || con->type == C_CONTAINER, | 589 | struct sway_workspace *ws = con->workspace; |
742 | "Expected a view or container")) { | ||
743 | return; | ||
744 | } | ||
745 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||
746 | int min_width, min_height; | 590 | int min_width, min_height; |
747 | int max_width, max_height; | 591 | int max_width, max_height; |
748 | 592 | ||
@@ -778,13 +622,13 @@ void container_init_floating(struct sway_container *con) { | |||
778 | max_height = config->floating_maximum_height; | 622 | max_height = config->floating_maximum_height; |
779 | } | 623 | } |
780 | 624 | ||
781 | if (con->type == C_CONTAINER) { | 625 | if (!con->view) { |
782 | con->width = max_width; | 626 | con->width = max_width; |
783 | con->height = max_height; | 627 | con->height = max_height; |
784 | con->x = ws->x + (ws->width - con->width) / 2; | 628 | con->x = ws->x + (ws->width - con->width) / 2; |
785 | con->y = ws->y + (ws->height - con->height) / 2; | 629 | con->y = ws->y + (ws->height - con->height) / 2; |
786 | } else { | 630 | } else { |
787 | struct sway_view *view = con->sway_view; | 631 | struct sway_view *view = con->view; |
788 | view->width = fmax(min_width, fmin(view->natural_width, max_width)); | 632 | view->width = fmax(min_width, fmin(view->natural_width, max_width)); |
789 | view->height = fmax(min_height, fmin(view->natural_height, max_height)); | 633 | view->height = fmax(min_height, fmin(view->natural_height, max_height)); |
790 | view->x = ws->x + (ws->width - view->width) / 2; | 634 | view->x = ws->x + (ws->width - view->width) / 2; |
@@ -794,7 +638,7 @@ void container_init_floating(struct sway_container *con) { | |||
794 | view->border_top = view->border_bottom = true; | 638 | view->border_top = view->border_bottom = true; |
795 | view->border_left = view->border_right = true; | 639 | view->border_left = view->border_right = true; |
796 | 640 | ||
797 | container_set_geometry_from_floating_view(view->swayc); | 641 | container_set_geometry_from_floating_view(con); |
798 | } | 642 | } |
799 | } | 643 | } |
800 | 644 | ||
@@ -804,32 +648,41 @@ void container_set_floating(struct sway_container *container, bool enable) { | |||
804 | } | 648 | } |
805 | 649 | ||
806 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 650 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
807 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); | 651 | struct sway_workspace *workspace = container->workspace; |
808 | 652 | ||
809 | if (enable) { | 653 | if (enable) { |
810 | struct sway_container *old_parent = container_remove_child(container); | 654 | struct sway_container *old_parent = container->parent; |
655 | container_detach(container); | ||
811 | workspace_add_floating(workspace, container); | 656 | workspace_add_floating(workspace, container); |
812 | container_init_floating(container); | 657 | container_init_floating(container); |
813 | if (container->type == C_VIEW) { | 658 | if (container->view) { |
814 | view_set_tiled(container->sway_view, false); | 659 | view_set_tiled(container->view, false); |
660 | } | ||
661 | if (old_parent) { | ||
662 | container_reap_empty(old_parent); | ||
815 | } | 663 | } |
816 | container_reap_empty(old_parent); | ||
817 | } else { | 664 | } else { |
818 | // Returning to tiled | 665 | // Returning to tiled |
819 | if (container->scratchpad) { | 666 | if (container->scratchpad) { |
820 | root_scratchpad_remove_container(container); | 667 | root_scratchpad_remove_container(container); |
821 | } | 668 | } |
822 | container_remove_child(container); | 669 | container_detach(container); |
823 | struct sway_container *reference = | 670 | struct sway_container *reference = |
824 | seat_get_focus_inactive_tiling(seat, workspace); | 671 | seat_get_focus_inactive_tiling(seat, workspace); |
825 | if (reference->type == C_VIEW) { | 672 | if (reference && reference->view) { |
826 | reference = reference->parent; | 673 | reference = reference->parent; |
827 | } | 674 | } |
828 | container_add_child(reference, container); | 675 | if (reference) { |
829 | container->width = container->parent->width; | 676 | container_add_child(reference, container); |
830 | container->height = container->parent->height; | 677 | container->width = reference->width; |
831 | if (container->type == C_VIEW) { | 678 | container->height = reference->height; |
832 | view_set_tiled(container->sway_view, true); | 679 | } else { |
680 | workspace_add_tiling(workspace, container); | ||
681 | container->width = workspace->width; | ||
682 | container->height = workspace->height; | ||
683 | } | ||
684 | if (container->view) { | ||
685 | view_set_tiled(container->view, true); | ||
833 | } | 686 | } |
834 | container->is_sticky = false; | 687 | container->is_sticky = false; |
835 | } | 688 | } |
@@ -840,14 +693,13 @@ void container_set_floating(struct sway_container *container, bool enable) { | |||
840 | } | 693 | } |
841 | 694 | ||
842 | void container_set_geometry_from_floating_view(struct sway_container *con) { | 695 | void container_set_geometry_from_floating_view(struct sway_container *con) { |
843 | if (!sway_assert(con->type == C_VIEW, "Expected a view")) { | 696 | if (!sway_assert(con->view, "Expected a view")) { |
844 | return; | 697 | return; |
845 | } | 698 | } |
846 | if (!sway_assert(container_is_floating(con), | 699 | if (!sway_assert(container_is_floating(con), "Expected a floating view")) { |
847 | "Expected a floating view")) { | ||
848 | return; | 700 | return; |
849 | } | 701 | } |
850 | struct sway_view *view = con->sway_view; | 702 | struct sway_view *view = con->view; |
851 | size_t border_width = 0; | 703 | size_t border_width = 0; |
852 | size_t top = 0; | 704 | size_t top = 0; |
853 | 705 | ||
@@ -861,12 +713,12 @@ void container_set_geometry_from_floating_view(struct sway_container *con) { | |||
861 | con->y = view->y - top; | 713 | con->y = view->y - top; |
862 | con->width = view->width + border_width * 2; | 714 | con->width = view->width + border_width * 2; |
863 | con->height = top + view->height + border_width; | 715 | con->height = top + view->height + border_width; |
864 | container_set_dirty(con); | 716 | node_set_dirty(&con->node); |
865 | } | 717 | } |
866 | 718 | ||
867 | bool container_is_floating(struct sway_container *container) { | 719 | bool container_is_floating(struct sway_container *container) { |
868 | return container->parent && container->parent->type == C_WORKSPACE && | 720 | return !container->parent && container->workspace && |
869 | list_find(container->parent->sway_workspace->floating, container) != -1; | 721 | list_find(container->workspace->floating, container) != -1; |
870 | } | 722 | } |
871 | 723 | ||
872 | void container_get_box(struct sway_container *container, struct wlr_box *box) { | 724 | void container_get_box(struct sway_container *container, struct wlr_box *box) { |
@@ -883,16 +735,16 @@ void container_floating_translate(struct sway_container *con, | |||
883 | double x_amount, double y_amount) { | 735 | double x_amount, double y_amount) { |
884 | con->x += x_amount; | 736 | con->x += x_amount; |
885 | con->y += y_amount; | 737 | con->y += y_amount; |
886 | if (con->type == C_VIEW) { | 738 | if (con->view) { |
887 | con->sway_view->x += x_amount; | 739 | con->view->x += x_amount; |
888 | con->sway_view->y += y_amount; | 740 | con->view->y += y_amount; |
889 | } else { | 741 | } else { |
890 | for (int i = 0; i < con->children->length; ++i) { | 742 | for (int i = 0; i < con->children->length; ++i) { |
891 | struct sway_container *child = con->children->items[i]; | 743 | struct sway_container *child = con->children->items[i]; |
892 | container_floating_translate(child, x_amount, y_amount); | 744 | container_floating_translate(child, x_amount, y_amount); |
893 | } | 745 | } |
894 | } | 746 | } |
895 | container_set_dirty(con); | 747 | node_set_dirty(&con->node); |
896 | } | 748 | } |
897 | 749 | ||
898 | /** | 750 | /** |
@@ -902,17 +754,16 @@ void container_floating_translate(struct sway_container *con, | |||
902 | * one, otherwise we'll choose whichever output is closest to the container's | 754 | * one, otherwise we'll choose whichever output is closest to the container's |
903 | * center. | 755 | * center. |
904 | */ | 756 | */ |
905 | struct sway_container *container_floating_find_output( | 757 | struct sway_output *container_floating_find_output(struct sway_container *con) { |
906 | struct sway_container *con) { | ||
907 | double center_x = con->x + con->width / 2; | 758 | double center_x = con->x + con->width / 2; |
908 | double center_y = con->y + con->height / 2; | 759 | double center_y = con->y + con->height / 2; |
909 | struct sway_container *closest_output = NULL; | 760 | struct sway_output *closest_output = NULL; |
910 | double closest_distance = DBL_MAX; | 761 | double closest_distance = DBL_MAX; |
911 | for (int i = 0; i < root_container.children->length; ++i) { | 762 | for (int i = 0; i < root->outputs->length; ++i) { |
912 | struct sway_container *output = root_container.children->items[i]; | 763 | struct sway_output *output = root->outputs->items[i]; |
913 | struct wlr_box output_box; | 764 | struct wlr_box output_box; |
914 | double closest_x, closest_y; | 765 | double closest_x, closest_y; |
915 | container_get_box(output, &output_box); | 766 | output_get_box(output, &output_box); |
916 | wlr_box_closest_point(&output_box, center_x, center_y, | 767 | wlr_box_closest_point(&output_box, center_x, center_y, |
917 | &closest_x, &closest_y); | 768 | &closest_x, &closest_y); |
918 | if (center_x == closest_x && center_y == closest_y) { | 769 | if (center_x == closest_x && center_y == closest_y) { |
@@ -937,18 +788,18 @@ void container_floating_move_to(struct sway_container *con, | |||
937 | return; | 788 | return; |
938 | } | 789 | } |
939 | container_floating_translate(con, lx - con->x, ly - con->y); | 790 | container_floating_translate(con, lx - con->x, ly - con->y); |
940 | struct sway_container *old_workspace = container_parent(con, C_WORKSPACE); | 791 | struct sway_workspace *old_workspace = con->workspace; |
941 | struct sway_container *new_output = container_floating_find_output(con); | 792 | struct sway_output *new_output = container_floating_find_output(con); |
942 | if (!sway_assert(new_output, "Unable to find any output")) { | 793 | if (!sway_assert(new_output, "Unable to find any output")) { |
943 | return; | 794 | return; |
944 | } | 795 | } |
945 | struct sway_container *new_workspace = | 796 | struct sway_workspace *new_workspace = |
946 | output_get_active_workspace(new_output->sway_output); | 797 | output_get_active_workspace(new_output); |
947 | if (old_workspace != new_workspace) { | 798 | if (old_workspace != new_workspace) { |
948 | container_remove_child(con); | 799 | container_detach(con); |
949 | workspace_add_floating(new_workspace, con); | 800 | workspace_add_floating(new_workspace, con); |
950 | arrange_windows(old_workspace); | 801 | arrange_workspace(old_workspace); |
951 | arrange_windows(new_workspace); | 802 | arrange_workspace(new_workspace); |
952 | workspace_detect_urgent(old_workspace); | 803 | workspace_detect_urgent(old_workspace); |
953 | workspace_detect_urgent(new_workspace); | 804 | workspace_detect_urgent(new_workspace); |
954 | } | 805 | } |
@@ -959,22 +810,14 @@ void container_floating_move_to_center(struct sway_container *con) { | |||
959 | "Expected a floating container")) { | 810 | "Expected a floating container")) { |
960 | return; | 811 | return; |
961 | } | 812 | } |
962 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | 813 | struct sway_workspace *ws = con->workspace; |
963 | double new_lx = ws->x + (ws->width - con->width) / 2; | 814 | double new_lx = ws->x + (ws->width - con->width) / 2; |
964 | double new_ly = ws->y + (ws->height - con->height) / 2; | 815 | double new_ly = ws->y + (ws->height - con->height) / 2; |
965 | container_floating_translate(con, new_lx - con->x, new_ly - con->y); | 816 | container_floating_translate(con, new_lx - con->x, new_ly - con->y); |
966 | } | 817 | } |
967 | 818 | ||
968 | void container_set_dirty(struct sway_container *container) { | ||
969 | if (container->dirty) { | ||
970 | return; | ||
971 | } | ||
972 | container->dirty = true; | ||
973 | list_add(server.dirty_containers, container); | ||
974 | } | ||
975 | |||
976 | static bool find_urgent_iterator(struct sway_container *con, void *data) { | 819 | static bool find_urgent_iterator(struct sway_container *con, void *data) { |
977 | return con->type == C_VIEW && view_is_urgent(con->sway_view); | 820 | return con->view && view_is_urgent(con->view); |
978 | } | 821 | } |
979 | 822 | ||
980 | bool container_has_urgent_child(struct sway_container *container) { | 823 | bool container_has_urgent_child(struct sway_container *container) { |
@@ -991,12 +834,12 @@ void container_end_mouse_operation(struct sway_container *container) { | |||
991 | } | 834 | } |
992 | 835 | ||
993 | static void set_fullscreen_iterator(struct sway_container *con, void *data) { | 836 | static void set_fullscreen_iterator(struct sway_container *con, void *data) { |
994 | if (con->type != C_VIEW) { | 837 | if (!con->view) { |
995 | return; | 838 | return; |
996 | } | 839 | } |
997 | if (con->sway_view->impl->set_fullscreen) { | 840 | if (con->view->impl->set_fullscreen) { |
998 | bool *enable = data; | 841 | bool *enable = data; |
999 | con->sway_view->impl->set_fullscreen(con->sway_view, *enable); | 842 | con->view->impl->set_fullscreen(con->view, *enable); |
1000 | } | 843 | } |
1001 | } | 844 | } |
1002 | 845 | ||
@@ -1005,9 +848,9 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { | |||
1005 | return; | 848 | return; |
1006 | } | 849 | } |
1007 | 850 | ||
1008 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); | 851 | struct sway_workspace *workspace = container->workspace; |
1009 | if (enable && workspace->sway_workspace->fullscreen) { | 852 | if (enable && workspace->fullscreen) { |
1010 | container_set_fullscreen(workspace->sway_workspace->fullscreen, false); | 853 | container_set_fullscreen(workspace->fullscreen, false); |
1011 | } | 854 | } |
1012 | 855 | ||
1013 | set_fullscreen_iterator(container, &enable); | 856 | set_fullscreen_iterator(container, &enable); |
@@ -1016,36 +859,32 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { | |||
1016 | container->is_fullscreen = enable; | 859 | container->is_fullscreen = enable; |
1017 | 860 | ||
1018 | if (enable) { | 861 | if (enable) { |
1019 | workspace->sway_workspace->fullscreen = container; | 862 | workspace->fullscreen = container; |
1020 | container->saved_x = container->x; | 863 | container->saved_x = container->x; |
1021 | container->saved_y = container->y; | 864 | container->saved_y = container->y; |
1022 | container->saved_width = container->width; | 865 | container->saved_width = container->width; |
1023 | container->saved_height = container->height; | 866 | container->saved_height = container->height; |
1024 | 867 | ||
1025 | struct sway_seat *seat; | 868 | struct sway_seat *seat; |
1026 | struct sway_container *focus, *focus_ws; | 869 | struct sway_workspace *focus_ws; |
1027 | wl_list_for_each(seat, &input_manager->seats, link) { | 870 | wl_list_for_each(seat, &input_manager->seats, link) { |
1028 | focus = seat_get_focus(seat); | 871 | focus_ws = seat_get_focused_workspace(seat); |
1029 | if (focus) { | 872 | if (focus_ws) { |
1030 | focus_ws = focus; | ||
1031 | if (focus_ws->type != C_WORKSPACE) { | ||
1032 | focus_ws = container_parent(focus_ws, C_WORKSPACE); | ||
1033 | } | ||
1034 | if (focus_ws == workspace) { | 873 | if (focus_ws == workspace) { |
1035 | seat_set_focus(seat, container); | 874 | seat_set_focus(seat, &container->node); |
1036 | } | 875 | } |
1037 | } | 876 | } |
1038 | } | 877 | } |
1039 | } else { | 878 | } else { |
1040 | workspace->sway_workspace->fullscreen = NULL; | 879 | workspace->fullscreen = NULL; |
1041 | if (container_is_floating(container)) { | 880 | if (container_is_floating(container)) { |
1042 | container->x = container->saved_x; | 881 | container->x = container->saved_x; |
1043 | container->y = container->saved_y; | 882 | container->y = container->saved_y; |
1044 | container->width = container->saved_width; | 883 | container->width = container->saved_width; |
1045 | container->height = container->saved_height; | 884 | container->height = container->saved_height; |
1046 | struct sway_container *output = | 885 | struct sway_output *output = |
1047 | container_floating_find_output(container); | 886 | container_floating_find_output(container); |
1048 | if (!container_has_ancestor(container, output)) { | 887 | if (workspace->output != output) { |
1049 | container_floating_move_to_center(container); | 888 | container_floating_move_to_center(container); |
1050 | } | 889 | } |
1051 | } else { | 890 | } else { |
@@ -1060,7 +899,7 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { | |||
1060 | } | 899 | } |
1061 | 900 | ||
1062 | bool container_is_floating_or_child(struct sway_container *container) { | 901 | bool container_is_floating_or_child(struct sway_container *container) { |
1063 | while (container->parent && container->parent->type != C_WORKSPACE) { | 902 | while (container->parent) { |
1064 | container = container->parent; | 903 | container = container->parent; |
1065 | } | 904 | } |
1066 | return container_is_floating(container); | 905 | return container_is_floating(container); |
@@ -1072,7 +911,7 @@ bool container_is_fullscreen_or_child(struct sway_container *container) { | |||
1072 | return true; | 911 | return true; |
1073 | } | 912 | } |
1074 | container = container->parent; | 913 | container = container->parent; |
1075 | } while (container && container->type != C_WORKSPACE); | 914 | } while (container); |
1076 | 915 | ||
1077 | return false; | 916 | return false; |
1078 | } | 917 | } |
@@ -1090,42 +929,37 @@ static void surface_send_leave_iterator(struct wlr_surface *surface, | |||
1090 | } | 929 | } |
1091 | 930 | ||
1092 | void container_discover_outputs(struct sway_container *con) { | 931 | void container_discover_outputs(struct sway_container *con) { |
1093 | if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, | ||
1094 | "Expected a container or view")) { | ||
1095 | return; | ||
1096 | } | ||
1097 | struct wlr_box con_box = { | 932 | struct wlr_box con_box = { |
1098 | .x = con->current.swayc_x, | 933 | .x = con->current.con_x, |
1099 | .y = con->current.swayc_y, | 934 | .y = con->current.con_y, |
1100 | .width = con->current.swayc_width, | 935 | .width = con->current.con_width, |
1101 | .height = con->current.swayc_height, | 936 | .height = con->current.con_height, |
1102 | }; | 937 | }; |
1103 | struct sway_output *old_output = container_get_effective_output(con); | 938 | struct sway_output *old_output = container_get_effective_output(con); |
1104 | 939 | ||
1105 | for (int i = 0; i < root_container.children->length; ++i) { | 940 | for (int i = 0; i < root->outputs->length; ++i) { |
1106 | struct sway_container *output = root_container.children->items[i]; | 941 | struct sway_output *output = root->outputs->items[i]; |
1107 | struct sway_output *sway_output = output->sway_output; | ||
1108 | struct wlr_box output_box; | 942 | struct wlr_box output_box; |
1109 | container_get_box(output, &output_box); | 943 | output_get_box(output, &output_box); |
1110 | struct wlr_box intersection; | 944 | struct wlr_box intersection; |
1111 | bool intersects = | 945 | bool intersects = |
1112 | wlr_box_intersection(&con_box, &output_box, &intersection); | 946 | wlr_box_intersection(&con_box, &output_box, &intersection); |
1113 | int index = list_find(con->outputs, sway_output); | 947 | int index = list_find(con->outputs, output); |
1114 | 948 | ||
1115 | if (intersects && index == -1) { | 949 | if (intersects && index == -1) { |
1116 | // Send enter | 950 | // Send enter |
1117 | wlr_log(WLR_DEBUG, "Con %p entered output %p", con, sway_output); | 951 | wlr_log(WLR_DEBUG, "Container %p entered output %p", con, output); |
1118 | if (con->type == C_VIEW) { | 952 | if (con->view) { |
1119 | view_for_each_surface(con->sway_view, | 953 | view_for_each_surface(con->view, |
1120 | surface_send_enter_iterator, sway_output->wlr_output); | 954 | surface_send_enter_iterator, output->wlr_output); |
1121 | } | 955 | } |
1122 | list_add(con->outputs, sway_output); | 956 | list_add(con->outputs, output); |
1123 | } else if (!intersects && index != -1) { | 957 | } else if (!intersects && index != -1) { |
1124 | // Send leave | 958 | // Send leave |
1125 | wlr_log(WLR_DEBUG, "Con %p left output %p", con, sway_output); | 959 | wlr_log(WLR_DEBUG, "Container %p left output %p", con, output); |
1126 | if (con->type == C_VIEW) { | 960 | if (con->view) { |
1127 | view_for_each_surface(con->sway_view, | 961 | view_for_each_surface(con->view, |
1128 | surface_send_leave_iterator, sway_output->wlr_output); | 962 | surface_send_leave_iterator, output->wlr_output); |
1129 | } | 963 | } |
1130 | list_del(con->outputs, index); | 964 | list_del(con->outputs, index); |
1131 | } | 965 | } |
@@ -1135,17 +969,13 @@ void container_discover_outputs(struct sway_container *con) { | |||
1135 | double new_scale = new_output ? new_output->wlr_output->scale : -1; | 969 | double new_scale = new_output ? new_output->wlr_output->scale : -1; |
1136 | if (old_scale != new_scale) { | 970 | if (old_scale != new_scale) { |
1137 | container_update_title_textures(con); | 971 | container_update_title_textures(con); |
1138 | if (con->type == C_VIEW) { | 972 | if (con->view) { |
1139 | view_update_marks_textures(con->sway_view); | 973 | view_update_marks_textures(con->view); |
1140 | } | 974 | } |
1141 | } | 975 | } |
1142 | } | 976 | } |
1143 | 977 | ||
1144 | void container_remove_gaps(struct sway_container *c) { | 978 | void container_remove_gaps(struct sway_container *c) { |
1145 | if (!sway_assert(c->type == C_CONTAINER || c->type == C_VIEW, | ||
1146 | "Expected a container or view")) { | ||
1147 | return; | ||
1148 | } | ||
1149 | if (c->current_gaps == 0) { | 979 | if (c->current_gaps == 0) { |
1150 | return; | 980 | return; |
1151 | } | 981 | } |
@@ -1158,25 +988,20 @@ void container_remove_gaps(struct sway_container *c) { | |||
1158 | } | 988 | } |
1159 | 989 | ||
1160 | void container_add_gaps(struct sway_container *c) { | 990 | void container_add_gaps(struct sway_container *c) { |
1161 | if (!sway_assert(c->type == C_CONTAINER || c->type == C_VIEW, | ||
1162 | "Expected a container or view")) { | ||
1163 | return; | ||
1164 | } | ||
1165 | if (c->current_gaps > 0) { | 991 | if (c->current_gaps > 0) { |
1166 | return; | 992 | return; |
1167 | } | 993 | } |
1168 | // Linear containers don't have gaps because it'd create double gaps | 994 | // Linear containers don't have gaps because it'd create double gaps |
1169 | if (c->type == C_CONTAINER && | 995 | if (!c->view && c->layout != L_TABBED && c->layout != L_STACKED) { |
1170 | c->layout != L_TABBED && c->layout != L_STACKED) { | ||
1171 | return; | 996 | return; |
1172 | } | 997 | } |
1173 | // Children of tabbed/stacked containers re-use the gaps of the container | 998 | // Children of tabbed/stacked containers re-use the gaps of the container |
1174 | enum sway_container_layout layout = c->parent->layout; | 999 | enum sway_container_layout layout = container_parent_layout(c); |
1175 | if (layout == L_TABBED || layout == L_STACKED) { | 1000 | if (layout == L_TABBED || layout == L_STACKED) { |
1176 | return; | 1001 | return; |
1177 | } | 1002 | } |
1178 | 1003 | ||
1179 | struct sway_container *ws = container_parent(c, C_WORKSPACE); | 1004 | struct sway_workspace *ws = c->workspace; |
1180 | 1005 | ||
1181 | c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner; | 1006 | c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner; |
1182 | c->x += c->current_gaps; | 1007 | c->x += c->current_gaps; |
@@ -1185,222 +1010,154 @@ void container_add_gaps(struct sway_container *c) { | |||
1185 | c->height -= 2 * c->current_gaps; | 1010 | c->height -= 2 * c->current_gaps; |
1186 | } | 1011 | } |
1187 | 1012 | ||
1188 | int container_sibling_index(const struct sway_container *child) { | 1013 | enum sway_container_layout container_parent_layout(struct sway_container *con) { |
1189 | return list_find(child->parent->children, child); | 1014 | if (con->parent) { |
1015 | return con->parent->layout; | ||
1016 | } | ||
1017 | return con->workspace->layout; | ||
1190 | } | 1018 | } |
1191 | 1019 | ||
1192 | void container_handle_fullscreen_reparent(struct sway_container *con, | 1020 | enum sway_container_layout container_current_parent_layout( |
1193 | struct sway_container *old_parent) { | 1021 | struct sway_container *con) { |
1194 | if (!con->is_fullscreen) { | 1022 | if (con->current.parent) { |
1195 | return; | 1023 | return con->current.parent->current.layout; |
1196 | } | 1024 | } |
1197 | struct sway_container *old_workspace = old_parent; | 1025 | return con->current.workspace->current.layout; |
1198 | if (old_workspace && old_workspace->type != C_WORKSPACE) { | 1026 | } |
1199 | old_workspace = container_parent(old_workspace, C_WORKSPACE); | 1027 | |
1028 | list_t *container_get_siblings(const struct sway_container *container) { | ||
1029 | if (container->parent) { | ||
1030 | return container->parent->children; | ||
1200 | } | 1031 | } |
1201 | struct sway_container *new_workspace = container_parent(con, C_WORKSPACE); | 1032 | if (!container->workspace) { |
1202 | if (old_workspace == new_workspace) { | 1033 | return NULL; |
1203 | return; | ||
1204 | } | 1034 | } |
1205 | // Unmark the old workspace as fullscreen | 1035 | if (list_find(container->workspace->tiling, container) != -1) { |
1206 | if (old_workspace) { | 1036 | return container->workspace->tiling; |
1207 | old_workspace->sway_workspace->fullscreen = NULL; | ||
1208 | } | 1037 | } |
1038 | return container->workspace->floating; | ||
1039 | } | ||
1209 | 1040 | ||
1210 | // Mark the new workspace as fullscreen | 1041 | int container_sibling_index(const struct sway_container *child) { |
1211 | if (new_workspace->sway_workspace->fullscreen) { | 1042 | return list_find(container_get_siblings(child), child); |
1212 | container_set_fullscreen( | 1043 | } |
1213 | new_workspace->sway_workspace->fullscreen, false); | ||
1214 | } | ||
1215 | new_workspace->sway_workspace->fullscreen = con; | ||
1216 | 1044 | ||
1217 | // Resize container to new output dimensions | 1045 | list_t *container_get_current_siblings(struct sway_container *container) { |
1218 | struct sway_container *output = new_workspace->parent; | 1046 | if (container->current.parent) { |
1219 | con->x = output->x; | 1047 | return container->current.parent->current.children; |
1220 | con->y = output->y; | 1048 | } |
1221 | con->width = output->width; | 1049 | return container->current.workspace->current.tiling; |
1222 | con->height = output->height; | 1050 | } |
1223 | 1051 | ||
1224 | if (con->type == C_VIEW) { | 1052 | void container_handle_fullscreen_reparent(struct sway_container *con) { |
1225 | struct sway_view *view = con->sway_view; | 1053 | if (!con->is_fullscreen || con->workspace->fullscreen == con) { |
1226 | view->x = output->x; | 1054 | return; |
1227 | view->y = output->y; | ||
1228 | view->width = output->width; | ||
1229 | view->height = output->height; | ||
1230 | } else { | ||
1231 | arrange_windows(new_workspace); | ||
1232 | } | 1055 | } |
1056 | if (con->workspace->fullscreen) { | ||
1057 | container_set_fullscreen(con->workspace->fullscreen, false); | ||
1058 | } | ||
1059 | con->workspace->fullscreen = con; | ||
1060 | |||
1061 | arrange_workspace(con->workspace); | ||
1062 | } | ||
1063 | |||
1064 | static void set_workspace(struct sway_container *container, void *data) { | ||
1065 | container->workspace = container->parent->workspace; | ||
1233 | } | 1066 | } |
1234 | 1067 | ||
1235 | void container_insert_child(struct sway_container *parent, | 1068 | void container_insert_child(struct sway_container *parent, |
1236 | struct sway_container *child, int i) { | 1069 | struct sway_container *child, int i) { |
1237 | struct sway_container *old_parent = child->parent; | 1070 | if (child->workspace) { |
1238 | if (old_parent) { | 1071 | container_detach(child); |
1239 | container_remove_child(child); | ||
1240 | } | 1072 | } |
1241 | wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i); | ||
1242 | list_insert(parent->children, i, child); | 1073 | list_insert(parent->children, i, child); |
1243 | child->parent = parent; | 1074 | child->parent = parent; |
1244 | container_handle_fullscreen_reparent(child, old_parent); | 1075 | child->workspace = parent->workspace; |
1076 | container_for_each_child(child, set_workspace, NULL); | ||
1077 | container_handle_fullscreen_reparent(child); | ||
1078 | container_update_representation(parent); | ||
1245 | } | 1079 | } |
1246 | 1080 | ||
1247 | struct sway_container *container_add_sibling(struct sway_container *fixed, | 1081 | void container_add_sibling(struct sway_container *fixed, |
1248 | struct sway_container *active) { | 1082 | struct sway_container *active, int offset) { |
1249 | // TODO handle floating | 1083 | if (active->workspace) { |
1250 | struct sway_container *old_parent = NULL; | 1084 | container_detach(active); |
1251 | if (active->parent) { | 1085 | } |
1252 | old_parent = active->parent; | 1086 | list_t *siblings = container_get_siblings(fixed); |
1253 | container_remove_child(active); | 1087 | int index = list_find(siblings, fixed); |
1254 | } | 1088 | list_insert(siblings, index + offset, active); |
1255 | struct sway_container *parent = fixed->parent; | 1089 | active->parent = fixed->parent; |
1256 | int i = container_sibling_index(fixed); | 1090 | active->workspace = fixed->workspace; |
1257 | list_insert(parent->children, i + 1, active); | 1091 | container_for_each_child(active, set_workspace, NULL); |
1258 | active->parent = parent; | 1092 | container_handle_fullscreen_reparent(active); |
1259 | container_handle_fullscreen_reparent(active, old_parent); | 1093 | container_update_representation(active); |
1260 | return active->parent; | ||
1261 | } | 1094 | } |
1262 | 1095 | ||
1263 | void container_add_child(struct sway_container *parent, | 1096 | void container_add_child(struct sway_container *parent, |
1264 | struct sway_container *child) { | 1097 | struct sway_container *child) { |
1265 | wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", | 1098 | if (child->workspace) { |
1266 | child, child->type, child->width, child->height, | 1099 | container_detach(child); |
1267 | parent, parent->type, parent->width, parent->height); | 1100 | } |
1268 | struct sway_container *old_parent = child->parent; | ||
1269 | list_add(parent->children, child); | 1101 | list_add(parent->children, child); |
1270 | child->parent = parent; | 1102 | child->parent = parent; |
1271 | container_handle_fullscreen_reparent(child, old_parent); | 1103 | child->workspace = parent->workspace; |
1272 | if (old_parent) { | 1104 | container_for_each_child(child, set_workspace, NULL); |
1273 | container_set_dirty(old_parent); | 1105 | container_handle_fullscreen_reparent(child); |
1274 | } | 1106 | container_update_representation(parent); |
1275 | container_set_dirty(child); | 1107 | node_set_dirty(&child->node); |
1108 | node_set_dirty(&parent->node); | ||
1276 | } | 1109 | } |
1277 | 1110 | ||
1278 | struct sway_container *container_remove_child(struct sway_container *child) { | 1111 | void container_detach(struct sway_container *child) { |
1279 | if (child->is_fullscreen) { | 1112 | if (child->is_fullscreen) { |
1280 | struct sway_container *workspace = container_parent(child, C_WORKSPACE); | 1113 | child->workspace->fullscreen = NULL; |
1281 | workspace->sway_workspace->fullscreen = NULL; | ||
1282 | } | 1114 | } |
1283 | 1115 | ||
1284 | struct sway_container *parent = child->parent; | 1116 | struct sway_container *old_parent = child->parent; |
1285 | list_t *list = container_is_floating(child) ? | 1117 | struct sway_workspace *old_workspace = child->workspace; |
1286 | parent->sway_workspace->floating : parent->children; | 1118 | list_t *siblings = container_get_siblings(child); |
1287 | int index = list_find(list, child); | 1119 | int index = list_find(siblings, child); |
1288 | if (index != -1) { | 1120 | if (index != -1) { |
1289 | list_del(list, index); | 1121 | list_del(siblings, index); |
1290 | } | 1122 | } |
1291 | child->parent = NULL; | 1123 | child->parent = NULL; |
1292 | container_notify_subtree_changed(parent); | 1124 | child->workspace = NULL; |
1293 | 1125 | container_for_each_child(child, set_workspace, NULL); | |
1294 | container_set_dirty(parent); | ||
1295 | container_set_dirty(child); | ||
1296 | |||
1297 | return parent; | ||
1298 | } | ||
1299 | |||
1300 | enum sway_container_layout container_get_default_layout( | ||
1301 | struct sway_container *con) { | ||
1302 | if (con->type != C_OUTPUT) { | ||
1303 | con = container_parent(con, C_OUTPUT); | ||
1304 | } | ||
1305 | 1126 | ||
1306 | if (!sway_assert(con != NULL, | 1127 | if (old_parent) { |
1307 | "container_get_default_layout must be called on an attached" | 1128 | container_update_representation(old_parent); |
1308 | " container below the root container")) { | 1129 | node_set_dirty(&old_parent->node); |
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | if (config->default_layout != L_NONE) { | ||
1313 | return config->default_layout; | ||
1314 | } else if (config->default_orientation != L_NONE) { | ||
1315 | return config->default_orientation; | ||
1316 | } else if (con->width >= con->height) { | ||
1317 | return L_HORIZ; | ||
1318 | } else { | 1130 | } else { |
1319 | return L_VERT; | 1131 | workspace_update_representation(old_workspace); |
1132 | node_set_dirty(&old_workspace->node); | ||
1320 | } | 1133 | } |
1134 | node_set_dirty(&child->node); | ||
1321 | } | 1135 | } |
1322 | 1136 | ||
1323 | struct sway_container *container_replace_child(struct sway_container *child, | 1137 | void container_replace(struct sway_container *container, |
1324 | struct sway_container *new_child) { | 1138 | struct sway_container *replacement) { |
1325 | struct sway_container *parent = child->parent; | 1139 | container_add_sibling(container, replacement, 1); |
1326 | if (parent == NULL) { | 1140 | container_detach(container); |
1327 | return NULL; | ||
1328 | } | ||
1329 | |||
1330 | list_t *list = container_is_floating(child) ? | ||
1331 | parent->sway_workspace->floating : parent->children; | ||
1332 | int i = list_find(list, child); | ||
1333 | |||
1334 | if (new_child->parent) { | ||
1335 | container_remove_child(new_child); | ||
1336 | } | ||
1337 | list->items[i] = new_child; | ||
1338 | new_child->parent = parent; | ||
1339 | child->parent = NULL; | ||
1340 | |||
1341 | // Set geometry for new child | ||
1342 | new_child->x = child->x; | ||
1343 | new_child->y = child->y; | ||
1344 | new_child->width = child->width; | ||
1345 | new_child->height = child->height; | ||
1346 | |||
1347 | // reset geometry for child | ||
1348 | child->width = 0; | ||
1349 | child->height = 0; | ||
1350 | |||
1351 | return parent; | ||
1352 | } | 1141 | } |
1353 | 1142 | ||
1354 | struct sway_container *container_split(struct sway_container *child, | 1143 | struct sway_container *container_split(struct sway_container *child, |
1355 | enum sway_container_layout layout) { | 1144 | enum sway_container_layout layout) { |
1356 | // TODO floating: cannot split a floating container | 1145 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); |
1357 | if (!sway_assert(child, "child cannot be null")) { | 1146 | bool set_focus = (seat_get_focus(seat) == &child->node); |
1358 | return NULL; | ||
1359 | } | ||
1360 | if (child->type == C_WORKSPACE && child->children->length == 0) { | ||
1361 | // Special case: this just behaves like splitt | ||
1362 | child->prev_split_layout = child->layout; | ||
1363 | child->layout = layout; | ||
1364 | return child; | ||
1365 | } | ||
1366 | |||
1367 | struct sway_container *cont = container_create(C_CONTAINER); | ||
1368 | |||
1369 | wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child); | ||
1370 | 1147 | ||
1371 | cont->prev_split_layout = L_NONE; | 1148 | struct sway_container *cont = container_create(NULL); |
1372 | cont->width = child->width; | 1149 | cont->width = child->width; |
1373 | cont->height = child->height; | 1150 | cont->height = child->height; |
1374 | cont->x = child->x; | ||
1375 | cont->y = child->y; | ||
1376 | cont->current_gaps = child->current_gaps; | 1151 | cont->current_gaps = child->current_gaps; |
1152 | cont->layout = layout; | ||
1377 | 1153 | ||
1378 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); | 1154 | container_replace(child, cont); |
1379 | bool set_focus = (seat_get_focus(seat) == child); | 1155 | container_add_child(cont, child); |
1380 | |||
1381 | if (child->type == C_WORKSPACE) { | ||
1382 | struct sway_container *workspace = child; | ||
1383 | while (workspace->children->length) { | ||
1384 | struct sway_container *ws_child = workspace->children->items[0]; | ||
1385 | container_remove_child(ws_child); | ||
1386 | container_add_child(cont, ws_child); | ||
1387 | } | ||
1388 | |||
1389 | container_add_child(workspace, cont); | ||
1390 | enum sway_container_layout old_layout = workspace->layout; | ||
1391 | workspace->layout = layout; | ||
1392 | cont->layout = old_layout; | ||
1393 | } else { | ||
1394 | cont->layout = layout; | ||
1395 | container_replace_child(child, cont); | ||
1396 | container_add_child(cont, child); | ||
1397 | } | ||
1398 | 1156 | ||
1399 | if (set_focus) { | 1157 | if (set_focus) { |
1400 | seat_set_focus(seat, cont); | 1158 | seat_set_focus(seat, &cont->node); |
1401 | seat_set_focus(seat, child); | 1159 | seat_set_focus(seat, &child->node); |
1402 | } | 1160 | } |
1403 | 1161 | ||
1404 | container_notify_subtree_changed(cont); | ||
1405 | return cont; | 1162 | return cont; |
1406 | } | 1163 | } |