diff options
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/arrange.c | 25 | ||||
-rw-r--r-- | sway/tree/container.c | 184 | ||||
-rw-r--r-- | sway/tree/layout.c | 2 | ||||
-rw-r--r-- | sway/tree/output.c | 2 | ||||
-rw-r--r-- | sway/tree/view.c | 76 | ||||
-rw-r--r-- | sway/tree/workspace.c | 3 |
6 files changed, 160 insertions, 132 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index ac99c5df..cb3f8ba2 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c | |||
@@ -144,6 +144,19 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) { | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | /** | ||
148 | * If a container has been deleted from the pending tree state, we must add it | ||
149 | * to the transaction so it can be freed afterwards. To do this, we iterate the | ||
150 | * server's destroying_containers list and add all of them. We may add more than | ||
151 | * what we need to, but this is easy and has no negative consequences. | ||
152 | */ | ||
153 | static void add_deleted_containers(struct sway_transaction *transaction) { | ||
154 | for (int i = 0; i < server.destroying_containers->length; ++i) { | ||
155 | struct sway_container *child = server.destroying_containers->items[i]; | ||
156 | transaction_add_container(transaction, child); | ||
157 | } | ||
158 | } | ||
159 | |||
147 | static void arrange_children_of(struct sway_container *parent, | 160 | static void arrange_children_of(struct sway_container *parent, |
148 | struct sway_transaction *transaction); | 161 | struct sway_transaction *transaction); |
149 | 162 | ||
@@ -158,6 +171,7 @@ static void arrange_floating(struct sway_container *floating, | |||
158 | } | 171 | } |
159 | transaction_add_container(transaction, floater); | 172 | transaction_add_container(transaction, floater); |
160 | } | 173 | } |
174 | transaction_add_container(transaction, floating); | ||
161 | } | 175 | } |
162 | 176 | ||
163 | static void arrange_children_of(struct sway_container *parent, | 177 | static void arrange_children_of(struct sway_container *parent, |
@@ -290,7 +304,16 @@ void arrange_windows(struct sway_container *container, | |||
290 | case C_TYPES: | 304 | case C_TYPES: |
291 | break; | 305 | break; |
292 | } | 306 | } |
293 | transaction_add_damage(transaction, container_get_box(container)); | 307 | // Add damage for whatever container arrange_windows() was called with, |
308 | // unless it was called with the special floating container, in which case | ||
309 | // we'll damage the entire output. | ||
310 | if (container->type == C_CONTAINER && container->layout == L_FLOATING) { | ||
311 | struct sway_container *output = container_parent(container, C_OUTPUT); | ||
312 | transaction_add_damage(transaction, container_get_box(output)); | ||
313 | } else { | ||
314 | transaction_add_damage(transaction, container_get_box(container)); | ||
315 | } | ||
316 | add_deleted_containers(transaction); | ||
294 | } | 317 | } |
295 | 318 | ||
296 | void arrange_and_commit(struct sway_container *container) { | 319 | void arrange_and_commit(struct sway_container *container) { |
diff --git a/sway/tree/container.c b/sway/tree/container.c index b071f394..484d26a5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include "sway/ipc-server.h" | 16 | #include "sway/ipc-server.h" |
17 | #include "sway/output.h" | 17 | #include "sway/output.h" |
18 | #include "sway/server.h" | 18 | #include "sway/server.h" |
19 | #include "sway/tree/arrange.h" | ||
20 | #include "sway/tree/layout.h" | 19 | #include "sway/tree/layout.h" |
21 | #include "sway/tree/view.h" | 20 | #include "sway/tree/view.h" |
22 | #include "sway/tree/workspace.h" | 21 | #include "sway/tree/workspace.h" |
@@ -113,10 +112,11 @@ struct sway_container *container_create(enum sway_container_type type) { | |||
113 | c->layout = L_NONE; | 112 | c->layout = L_NONE; |
114 | c->type = type; | 113 | c->type = type; |
115 | c->alpha = 1.0f; | 114 | c->alpha = 1.0f; |
115 | c->instructions = create_list(); | ||
116 | 116 | ||
117 | if (type != C_VIEW) { | 117 | if (type != C_VIEW) { |
118 | c->children = create_list(); | 118 | c->children = create_list(); |
119 | //c->pending.children = create_list(); | 119 | c->current.children = create_list(); |
120 | } | 120 | } |
121 | 121 | ||
122 | wl_signal_init(&c->events.destroy); | 122 | wl_signal_init(&c->events.destroy); |
@@ -133,43 +133,68 @@ struct sway_container *container_create(enum sway_container_type type) { | |||
133 | return c; | 133 | return c; |
134 | } | 134 | } |
135 | 135 | ||
136 | static void _container_destroy(struct sway_container *cont) { | 136 | static void container_workspace_free(struct sway_workspace *ws) { |
137 | if (cont == NULL) { | 137 | list_foreach(ws->output_priority, free); |
138 | return; | 138 | list_free(ws->output_priority); |
139 | } | 139 | ws->floating->destroying = true; |
140 | 140 | container_free(ws->floating); | |
141 | wl_signal_emit(&cont->events.destroy, cont); | 141 | free(ws); |
142 | } | ||
142 | 143 | ||
143 | struct sway_container *parent = cont->parent; | 144 | void container_free(struct sway_container *cont) { |
144 | if (cont->children != NULL && cont->children->length) { | 145 | if (!sway_assert(cont->destroying, |
145 | // remove children until there are no more, container_destroy calls | 146 | "Tried to free container which wasn't marked as destroying")) { |
146 | // container_remove_child, which removes child from this container | 147 | return; |
147 | while (cont->children != NULL && cont->children->length > 0) { | ||
148 | struct sway_container *child = cont->children->items[0]; | ||
149 | ipc_event_window(child, "close"); | ||
150 | container_remove_child(child); | ||
151 | _container_destroy(child); | ||
152 | } | ||
153 | } | ||
154 | if (cont->marks) { | ||
155 | list_foreach(cont->marks, free); | ||
156 | list_free(cont->marks); | ||
157 | } | ||
158 | if (parent) { | ||
159 | parent = container_remove_child(cont); | ||
160 | } | 148 | } |
161 | if (cont->name) { | 149 | if (!sway_assert(cont->instructions->length == 0, |
162 | free(cont->name); | 150 | "Tried to free container with pending instructions")) { |
151 | return; | ||
163 | } | 152 | } |
164 | 153 | free(cont->name); | |
165 | wlr_texture_destroy(cont->title_focused); | 154 | wlr_texture_destroy(cont->title_focused); |
166 | wlr_texture_destroy(cont->title_focused_inactive); | 155 | wlr_texture_destroy(cont->title_focused_inactive); |
167 | wlr_texture_destroy(cont->title_unfocused); | 156 | wlr_texture_destroy(cont->title_unfocused); |
168 | wlr_texture_destroy(cont->title_urgent); | 157 | wlr_texture_destroy(cont->title_urgent); |
169 | 158 | ||
159 | for (int i = 0; i < server.destroying_containers->length; ++i) { | ||
160 | if (server.destroying_containers->items[i] == cont) { | ||
161 | list_del(server.destroying_containers, i); | ||
162 | break; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | list_free(cont->instructions); | ||
170 | list_free(cont->children); | 167 | list_free(cont->children); |
171 | //list_free(cont->pending.children); | 168 | list_free(cont->current.children); |
172 | cont->children = NULL; | 169 | |
170 | switch (cont->type) { | ||
171 | case C_ROOT: | ||
172 | break; | ||
173 | case C_OUTPUT: | ||
174 | cont->sway_output->swayc = NULL; | ||
175 | break; | ||
176 | case C_WORKSPACE: | ||
177 | container_workspace_free(cont->sway_workspace); | ||
178 | break; | ||
179 | case C_CONTAINER: | ||
180 | break; | ||
181 | case C_VIEW: | ||
182 | { | ||
183 | struct sway_view *view = cont->sway_view; | ||
184 | view->swayc = NULL; | ||
185 | free(view->title_format); | ||
186 | view->title_format = NULL; | ||
187 | |||
188 | if (view->destroying) { | ||
189 | view_free(view); | ||
190 | } | ||
191 | } | ||
192 | break; | ||
193 | case C_TYPES: | ||
194 | sway_assert(false, "Didn't expect to see C_TYPES here"); | ||
195 | break; | ||
196 | } | ||
197 | |||
173 | free(cont); | 198 | free(cont); |
174 | } | 199 | } |
175 | 200 | ||
@@ -186,7 +211,6 @@ static struct sway_container *container_workspace_destroy( | |||
186 | } | 211 | } |
187 | 212 | ||
188 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | 213 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); |
189 | ipc_event_window(workspace, "close"); | ||
190 | 214 | ||
191 | struct sway_container *parent = workspace->parent; | 215 | struct sway_container *parent = workspace->parent; |
192 | if (!workspace_is_empty(workspace) && output) { | 216 | if (!workspace_is_empty(workspace) && output) { |
@@ -209,25 +233,6 @@ static struct sway_container *container_workspace_destroy( | |||
209 | container_move_to(floating->children->items[i], | 233 | container_move_to(floating->children->items[i], |
210 | new_workspace->sway_workspace->floating); | 234 | new_workspace->sway_workspace->floating); |
211 | } | 235 | } |
212 | arrange_and_commit(new_workspace); | ||
213 | } | ||
214 | |||
215 | struct sway_workspace *sway_workspace = workspace->sway_workspace; | ||
216 | |||
217 | // This emits the destroy event and also destroys the swayc. | ||
218 | _container_destroy(workspace); | ||
219 | |||
220 | // Clean up the floating container | ||
221 | sway_workspace->floating->parent = NULL; | ||
222 | _container_destroy(sway_workspace->floating); | ||
223 | |||
224 | list_foreach(sway_workspace->output_priority, free); | ||
225 | list_free(sway_workspace->output_priority); | ||
226 | |||
227 | free(sway_workspace); | ||
228 | |||
229 | if (output) { | ||
230 | output_damage_whole(output->sway_output); | ||
231 | } | 236 | } |
232 | 237 | ||
233 | return parent; | 238 | return parent; |
@@ -266,14 +271,13 @@ static struct sway_container *container_output_destroy( | |||
266 | container_add_child(new_output, workspace); | 271 | container_add_child(new_output, workspace); |
267 | ipc_event_workspace(workspace, NULL, "move"); | 272 | ipc_event_workspace(workspace, NULL, "move"); |
268 | } else { | 273 | } else { |
269 | container_workspace_destroy(workspace); | 274 | container_destroy(workspace); |
270 | } | 275 | } |
271 | 276 | ||
272 | container_sort_workspaces(new_output); | 277 | container_sort_workspaces(new_output); |
273 | } | 278 | } |
274 | } | 279 | } |
275 | } | 280 | } |
276 | arrange_and_commit(&root_container); | ||
277 | 281 | ||
278 | wl_list_remove(&output->sway_output->mode.link); | 282 | wl_list_remove(&output->sway_output->mode.link); |
279 | wl_list_remove(&output->sway_output->transform.link); | 283 | wl_list_remove(&output->sway_output->transform.link); |
@@ -285,12 +289,8 @@ static struct sway_container *container_output_destroy( | |||
285 | output->sway_output->swayc = NULL; | 289 | output->sway_output->swayc = NULL; |
286 | 290 | ||
287 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | 291 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); |
288 | _container_destroy(output); | ||
289 | return &root_container; | ||
290 | } | ||
291 | 292 | ||
292 | static void container_root_finish(struct sway_container *con) { | 293 | return &root_container; |
293 | wlr_log(L_ERROR, "TODO: destroy the root container"); | ||
294 | } | 294 | } |
295 | 295 | ||
296 | bool container_reap_empty(struct sway_container *con) { | 296 | bool container_reap_empty(struct sway_container *con) { |
@@ -306,13 +306,13 @@ bool container_reap_empty(struct sway_container *con) { | |||
306 | case C_WORKSPACE: | 306 | case C_WORKSPACE: |
307 | if (!workspace_is_visible(con) && workspace_is_empty(con)) { | 307 | if (!workspace_is_visible(con) && workspace_is_empty(con)) { |
308 | wlr_log(L_DEBUG, "Destroying workspace via reaper"); | 308 | wlr_log(L_DEBUG, "Destroying workspace via reaper"); |
309 | container_workspace_destroy(con); | 309 | container_destroy(con); |
310 | return true; | 310 | return true; |
311 | } | 311 | } |
312 | break; | 312 | break; |
313 | case C_CONTAINER: | 313 | case C_CONTAINER: |
314 | if (con->children->length == 0) { | 314 | if (con->children->length == 0) { |
315 | _container_destroy(con); | 315 | container_destroy(con); |
316 | return true; | 316 | return true; |
317 | } | 317 | } |
318 | case C_VIEW: | 318 | case C_VIEW: |
@@ -349,46 +349,48 @@ struct sway_container *container_flatten(struct sway_container *container) { | |||
349 | return container; | 349 | return container; |
350 | } | 350 | } |
351 | 351 | ||
352 | /** | ||
353 | * container_destroy() is the first step in destroying a container. We'll emit | ||
354 | * events, detach it from the tree and mark it as destroying. The container will | ||
355 | * remain in memory until it's no longer used by a transaction, then it will be | ||
356 | * freed via container_free(). | ||
357 | */ | ||
352 | struct sway_container *container_destroy(struct sway_container *con) { | 358 | struct sway_container *container_destroy(struct sway_container *con) { |
353 | if (con == NULL) { | 359 | if (con == NULL) { |
354 | return NULL; | 360 | return NULL; |
355 | } | 361 | } |
362 | if (con->destroying) { | ||
363 | return NULL; | ||
364 | } | ||
356 | 365 | ||
357 | struct sway_container *parent = con->parent; | 366 | // The below functions move their children to somewhere else. |
367 | if (con->type == C_OUTPUT) { | ||
368 | container_output_destroy(con); | ||
369 | } else if (con->type == C_WORKSPACE) { | ||
370 | // Workspaces will refuse to be destroyed if they're the last workspace | ||
371 | // on their output. | ||
372 | if (!container_workspace_destroy(con)) { | ||
373 | return NULL; | ||
374 | } | ||
375 | } | ||
358 | 376 | ||
359 | switch (con->type) { | 377 | // At this point the container being destroyed shouldn't have any children |
360 | case C_ROOT: | 378 | // unless sway is terminating. |
361 | container_root_finish(con); | 379 | if (!server.terminating) { |
362 | break; | 380 | if (!sway_assert(!con->children || con->children->length == 0, |
363 | case C_OUTPUT: | 381 | "Didn't expect to see children here")) { |
364 | // dont try to reap the root after this | 382 | return NULL; |
365 | container_output_destroy(con); | 383 | } |
366 | break; | ||
367 | case C_WORKSPACE: | ||
368 | // dont try to reap the output after this | ||
369 | container_workspace_destroy(con); | ||
370 | break; | ||
371 | case C_CONTAINER: | ||
372 | if (con->children->length) { | ||
373 | for (int i = 0; i < con->children->length; ++i) { | ||
374 | struct sway_container *child = con->children->items[0]; | ||
375 | ipc_event_window(child, "close"); | ||
376 | container_remove_child(child); | ||
377 | container_add_child(parent, child); | ||
378 | } | ||
379 | } | ||
380 | ipc_event_window(con, "close"); | ||
381 | _container_destroy(con); | ||
382 | break; | ||
383 | case C_VIEW: | ||
384 | _container_destroy(con); | ||
385 | break; | ||
386 | case C_TYPES: | ||
387 | wlr_log(L_ERROR, "container_destroy called on an invalid " | ||
388 | "container"); | ||
389 | break; | ||
390 | } | 384 | } |
391 | 385 | ||
386 | wl_signal_emit(&con->events.destroy, con); | ||
387 | ipc_event_window(con, "close"); | ||
388 | |||
389 | struct sway_container *parent = container_remove_child(con); | ||
390 | |||
391 | con->destroying = true; | ||
392 | list_add(server.destroying_containers, con); | ||
393 | |||
392 | return container_reap_empty_recursive(parent); | 394 | return container_reap_empty_recursive(parent); |
393 | } | 395 | } |
394 | 396 | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3724361d..14631ad4 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -30,7 +30,9 @@ void layout_init(void) { | |||
30 | root_container.type = C_ROOT; | 30 | root_container.type = C_ROOT; |
31 | root_container.layout = L_NONE; | 31 | root_container.layout = L_NONE; |
32 | root_container.name = strdup("root"); | 32 | root_container.name = strdup("root"); |
33 | root_container.instructions = create_list(); | ||
33 | root_container.children = create_list(); | 34 | root_container.children = create_list(); |
35 | root_container.current.children = create_list(); | ||
34 | wl_signal_init(&root_container.events.destroy); | 36 | wl_signal_init(&root_container.events.destroy); |
35 | 37 | ||
36 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | 38 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 8af319d5..e2927cdb 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -29,7 +29,6 @@ static void restore_workspaces(struct sway_container *output) { | |||
29 | } | 29 | } |
30 | 30 | ||
31 | container_sort_workspaces(output); | 31 | container_sort_workspaces(output); |
32 | arrange_and_commit(&root_container); | ||
33 | } | 32 | } |
34 | 33 | ||
35 | struct sway_container *output_create( | 34 | struct sway_container *output_create( |
@@ -66,7 +65,6 @@ struct sway_container *output_create( | |||
66 | 65 | ||
67 | struct sway_container *output = container_create(C_OUTPUT); | 66 | struct sway_container *output = container_create(C_OUTPUT); |
68 | output->sway_output = sway_output; | 67 | output->sway_output = sway_output; |
69 | sway_output->swayc = output; | ||
70 | output->name = strdup(name); | 68 | output->name = strdup(name); |
71 | if (output->name == NULL) { | 69 | if (output->name == NULL) { |
72 | container_destroy(output); | 70 | container_destroy(output); |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 658a94e8..cb36f123 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -25,47 +25,60 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
25 | view->impl = impl; | 25 | view->impl = impl; |
26 | view->executed_criteria = create_list(); | 26 | view->executed_criteria = create_list(); |
27 | view->marks = create_list(); | 27 | view->marks = create_list(); |
28 | view->instructions = create_list(); | ||
29 | wl_signal_init(&view->events.unmap); | 28 | wl_signal_init(&view->events.unmap); |
30 | } | 29 | } |
31 | 30 | ||
32 | void view_destroy(struct sway_view *view) { | 31 | void view_free(struct sway_view *view) { |
33 | if (view == NULL) { | 32 | if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) { |
34 | return; | 33 | return; |
35 | } | 34 | } |
36 | 35 | if (!sway_assert(view->destroying, | |
37 | if (view->surface != NULL) { | 36 | "Tried to free view which wasn't marked as destroying")) { |
38 | view_unmap(view); | 37 | return; |
39 | } | 38 | } |
40 | 39 | if (!sway_assert(view->swayc == NULL, | |
41 | if (!sway_assert(view->instructions->length == 0, | 40 | "Tried to free view which still has a swayc " |
42 | "Tried to destroy view with pending instructions")) { | 41 | "(might have a pending transaction?)")) { |
43 | return; | 42 | return; |
44 | } | 43 | } |
45 | |||
46 | list_free(view->executed_criteria); | 44 | list_free(view->executed_criteria); |
47 | 45 | ||
48 | for (int i = 0; i < view->marks->length; ++i) { | 46 | list_foreach(view->marks, free); |
49 | free(view->marks->items[i]); | ||
50 | } | ||
51 | list_free(view->marks); | 47 | list_free(view->marks); |
52 | 48 | ||
53 | list_free(view->instructions); | ||
54 | |||
55 | wlr_texture_destroy(view->marks_focused); | 49 | wlr_texture_destroy(view->marks_focused); |
56 | wlr_texture_destroy(view->marks_focused_inactive); | 50 | wlr_texture_destroy(view->marks_focused_inactive); |
57 | wlr_texture_destroy(view->marks_unfocused); | 51 | wlr_texture_destroy(view->marks_unfocused); |
58 | wlr_texture_destroy(view->marks_urgent); | 52 | wlr_texture_destroy(view->marks_urgent); |
59 | 53 | ||
60 | container_destroy(view->swayc); | 54 | if (view->impl->free) { |
61 | 55 | view->impl->free(view); | |
62 | if (view->impl->destroy) { | ||
63 | view->impl->destroy(view); | ||
64 | } else { | 56 | } else { |
65 | free(view); | 57 | free(view); |
66 | } | 58 | } |
67 | } | 59 | } |
68 | 60 | ||
61 | /** | ||
62 | * The view may or may not be involved in a transaction. For example, a view may | ||
63 | * unmap then attempt to destroy itself before we've applied the new layout. If | ||
64 | * an unmapping view is still involved in a transaction then it'll still have a | ||
65 | * swayc. | ||
66 | * | ||
67 | * If there's no transaction we can simply free the view. Otherwise the | ||
68 | * destroying flag will make the view get freed when the transaction is | ||
69 | * finished. | ||
70 | */ | ||
71 | void view_destroy(struct sway_view *view) { | ||
72 | if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { | ||
73 | return; | ||
74 | } | ||
75 | view->destroying = true; | ||
76 | |||
77 | if (!view->swayc) { | ||
78 | view_free(view); | ||
79 | } | ||
80 | } | ||
81 | |||
69 | const char *view_get_title(struct sway_view *view) { | 82 | const char *view_get_title(struct sway_view *view) { |
70 | if (view->impl->get_string_prop) { | 83 | if (view->impl->get_string_prop) { |
71 | return view->impl->get_string_prop(view, VIEW_PROP_TITLE); | 84 | return view->impl->get_string_prop(view, VIEW_PROP_TITLE); |
@@ -356,6 +369,9 @@ static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { | |||
356 | 369 | ||
357 | void view_for_each_surface(struct sway_view *view, | 370 | void view_for_each_surface(struct sway_view *view, |
358 | wlr_surface_iterator_func_t iterator, void *user_data) { | 371 | wlr_surface_iterator_func_t iterator, void *user_data) { |
372 | if (!view->surface) { | ||
373 | return; | ||
374 | } | ||
359 | if (view->impl->for_each_surface) { | 375 | if (view->impl->for_each_surface) { |
360 | view->impl->for_each_surface(view, iterator, user_data); | 376 | view->impl->for_each_surface(view, iterator, user_data); |
361 | } else { | 377 | } else { |
@@ -523,11 +539,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
523 | view_handle_container_reparent(&view->container_reparent, NULL); | 539 | view_handle_container_reparent(&view->container_reparent, NULL); |
524 | } | 540 | } |
525 | 541 | ||
526 | void view_unmap(struct sway_view *view) { | 542 | struct sway_container *view_unmap(struct sway_view *view) { |
527 | if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { | ||
528 | return; | ||
529 | } | ||
530 | |||
531 | wl_signal_emit(&view->events.unmap, view); | 543 | wl_signal_emit(&view->events.unmap, view); |
532 | 544 | ||
533 | if (view->is_fullscreen) { | 545 | if (view->is_fullscreen) { |
@@ -535,22 +547,10 @@ void view_unmap(struct sway_view *view) { | |||
535 | ws->sway_workspace->fullscreen = NULL; | 547 | ws->sway_workspace->fullscreen = NULL; |
536 | } | 548 | } |
537 | 549 | ||
538 | container_damage_whole(view->swayc); | ||
539 | |||
540 | wl_list_remove(&view->surface_new_subsurface.link); | 550 | wl_list_remove(&view->surface_new_subsurface.link); |
541 | wl_list_remove(&view->container_reparent.link); | 551 | wl_list_remove(&view->container_reparent.link); |
542 | 552 | ||
543 | struct sway_container *parent = container_destroy(view->swayc); | 553 | return container_destroy(view->swayc); |
544 | |||
545 | view->swayc = NULL; | ||
546 | view->surface = NULL; | ||
547 | |||
548 | if (view->title_format) { | ||
549 | free(view->title_format); | ||
550 | view->title_format = NULL; | ||
551 | } | ||
552 | |||
553 | arrange_and_commit(parent); | ||
554 | } | 554 | } |
555 | 555 | ||
556 | void view_update_position(struct sway_view *view, double lx, double ly) { | 556 | void view_update_position(struct sway_view *view, double lx, double ly) { |
@@ -924,7 +924,7 @@ void view_update_marks_textures(struct sway_view *view) { | |||
924 | } | 924 | } |
925 | 925 | ||
926 | bool view_is_visible(struct sway_view *view) { | 926 | bool view_is_visible(struct sway_view *view) { |
927 | if (!view->swayc) { | 927 | if (!view->swayc || view->swayc->destroying) { |
928 | return false; | 928 | return false; |
929 | } | 929 | } |
930 | struct sway_container *workspace = | 930 | struct sway_container *workspace = |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index ead752ad..5eb4be0f 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -430,6 +430,9 @@ bool workspace_switch(struct sway_container *workspace) { | |||
430 | } | 430 | } |
431 | 431 | ||
432 | bool workspace_is_visible(struct sway_container *ws) { | 432 | bool workspace_is_visible(struct sway_container *ws) { |
433 | if (ws->destroying) { | ||
434 | return false; | ||
435 | } | ||
433 | struct sway_container *output = container_parent(ws, C_OUTPUT); | 436 | struct sway_container *output = container_parent(ws, C_OUTPUT); |
434 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 437 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
435 | struct sway_container *focus = seat_get_focus_inactive(seat, output); | 438 | struct sway_container *focus = seat_get_focus_inactive(seat, output); |