summaryrefslogtreecommitdiffstats
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c284
-rw-r--r--sway/tree/layout.c4
-rw-r--r--sway/tree/output.c108
-rw-r--r--sway/tree/root.c2
-rw-r--r--sway/tree/view.c10
-rw-r--r--sway/tree/workspace.c63
6 files changed, 215 insertions, 256 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index a8c6e667..6da6212c 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -104,209 +104,52 @@ struct sway_container *container_create(enum sway_container_type type) {
104 return c; 104 return c;
105} 105}
106 106
107static void container_workspace_free(struct sway_workspace *ws) { 107void container_destroy(struct sway_container *con) {
108 list_foreach(ws->output_priority, free); 108 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
109 list_free(ws->output_priority); 109 "Expected a container or view")) {
110 list_free(ws->floating); 110 return;
111 free(ws); 111 }
112} 112 if (!sway_assert(con->destroying,
113
114void container_free(struct sway_container *cont) {
115 if (!sway_assert(cont->destroying,
116 "Tried to free container which wasn't marked as destroying")) { 113 "Tried to free container which wasn't marked as destroying")) {
117 return; 114 return;
118 } 115 }
119 if (!sway_assert(cont->ntxnrefs == 0, "Tried to free container " 116 if (!sway_assert(con->ntxnrefs == 0, "Tried to free container "
120 "which is still referenced by transactions")) { 117 "which is still referenced by transactions")) {
121 return; 118 return;
122 } 119 }
123 free(cont->name); 120 free(con->name);
124 free(cont->formatted_title); 121 free(con->formatted_title);
125 wlr_texture_destroy(cont->title_focused); 122 wlr_texture_destroy(con->title_focused);
126 wlr_texture_destroy(cont->title_focused_inactive); 123 wlr_texture_destroy(con->title_focused_inactive);
127 wlr_texture_destroy(cont->title_unfocused); 124 wlr_texture_destroy(con->title_unfocused);
128 wlr_texture_destroy(cont->title_urgent); 125 wlr_texture_destroy(con->title_urgent);
129 list_free(cont->children); 126 list_free(con->children);
130 list_free(cont->current.children); 127 list_free(con->current.children);
131 list_free(cont->outputs); 128 list_free(con->outputs);
132
133 switch (cont->type) {
134 case C_ROOT:
135 break;
136 case C_OUTPUT:
137 break;
138 case C_WORKSPACE:
139 container_workspace_free(cont->sway_workspace);
140 break;
141 case C_CONTAINER:
142 break;
143 case C_VIEW:
144 {
145 struct sway_view *view = cont->sway_view;
146 view->swayc = NULL;
147 free(view->title_format);
148 view->title_format = NULL;
149
150 if (view->destroying) {
151 view_free(view);
152 }
153 }
154 break;
155 case C_TYPES:
156 sway_assert(false, "Didn't expect to see C_TYPES here");
157 break;
158 }
159
160 free(cont);
161}
162
163static struct sway_container *container_destroy_noreaping(
164 struct sway_container *con);
165
166static struct sway_container *container_workspace_destroy(
167 struct sway_container *workspace) {
168 if (!sway_assert(workspace, "cannot destroy null workspace")) {
169 return NULL;
170 }
171
172 struct sway_container *output = container_parent(workspace, C_OUTPUT);
173
174 // If we're destroying the output, it will be NULL here. Return the root so
175 // that it doesn't appear that the workspace has refused to be destoyed,
176 // which would leave it in a broken state with no parent.
177 if (output == NULL) {
178 return &root_container;
179 }
180
181 // Do not destroy this if it's the last workspace on this output
182 if (output->children->length == 1) {
183 return NULL;
184 }
185
186 wlr_log(WLR_DEBUG, "destroying workspace '%s'", workspace->name);
187
188 if (!workspace_is_empty(workspace)) {
189 // Move children to a different workspace on this output
190 struct sway_container *new_workspace = NULL;
191 for (int i = 0; i < output->children->length; i++) {
192 if (output->children->items[i] != workspace) {
193 new_workspace = output->children->items[i];
194 break;
195 }
196 }
197
198 wlr_log(WLR_DEBUG, "moving children to different workspace '%s' -> '%s'",
199 workspace->name, new_workspace->name);
200 for (int i = 0; i < workspace->children->length; i++) {
201 container_move_to(workspace->children->items[i], new_workspace);
202 }
203 list_t *floating = workspace->sway_workspace->floating;
204 for (int i = 0; i < floating->length; i++) {
205 struct sway_container *floater = floating->items[i];
206 container_remove_child(floater);
207 workspace_add_floating(new_workspace, floater);
208 }
209 }
210
211 return output;
212}
213
214static void untrack_output(struct sway_container *con, void *data) {
215 struct sway_output *output = data;
216 int index = list_find(con->outputs, output);
217 if (index != -1) {
218 list_del(con->outputs, index);
219 }
220}
221
222static struct sway_container *container_output_destroy(
223 struct sway_container *output) {
224 if (!sway_assert(output, "cannot destroy null output")) {
225 return NULL;
226 }
227
228 if (output->children->length > 0) {
229 // TODO save workspaces when there are no outputs.
230 // TODO also check if there will ever be no outputs except for exiting
231 // program
232 if (root_container.children->length > 1) {
233 // Move workspace from this output to another output
234 struct sway_container *fallback_output =
235 root_container.children->items[0];
236 if (fallback_output == output) {
237 fallback_output = root_container.children->items[1];
238 }
239
240 while (output->children->length) {
241 struct sway_container *workspace = output->children->items[0];
242
243 struct sway_container *new_output =
244 workspace_output_get_highest_available(workspace, output);
245 if (!new_output) {
246 new_output = fallback_output;
247 workspace_output_add_priority(workspace, new_output);
248 }
249 129
250 container_remove_child(workspace); 130 if (con->type == C_VIEW) {
251 if (!workspace_is_empty(workspace)) { 131 struct sway_view *view = con->sway_view;
252 container_add_child(new_output, workspace); 132 view->swayc = NULL;
253 ipc_event_workspace(NULL, workspace, "move"); 133 free(view->title_format);
254 } else { 134 view->title_format = NULL;
255 container_destroy(workspace);
256 }
257 135
258 output_sort_workspaces(new_output); 136 if (view->destroying) {
259 } 137 view_destroy(view);
260 } 138 }
261 } 139 }
262 140
263 root_for_each_container(untrack_output, output->sway_output); 141 free(con);
264
265 wl_list_remove(&output->sway_output->mode.link);
266 wl_list_remove(&output->sway_output->transform.link);
267 wl_list_remove(&output->sway_output->scale.link);
268
269 wl_list_remove(&output->sway_output->damage_destroy.link);
270 wl_list_remove(&output->sway_output->damage_frame.link);
271
272 output->sway_output->swayc = NULL;
273 output->sway_output = NULL;
274
275 wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
276
277 return &root_container;
278} 142}
279 143
280/** 144void container_begin_destroy(struct sway_container *con) {
281 * Implement the actual destroy logic, without reaping. 145 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
282 */ 146 "Expected a container or view")) {
283static struct sway_container *container_destroy_noreaping( 147 return;
284 struct sway_container *con) {
285 if (con == NULL) {
286 return NULL;
287 }
288 if (con->destroying) {
289 return NULL;
290 } 148 }
291 149
292 wl_signal_emit(&con->events.destroy, con); 150 wl_signal_emit(&con->events.destroy, con);
293
294 // emit IPC event
295 if (con->type == C_VIEW) { 151 if (con->type == C_VIEW) {
296 ipc_event_window(con, "close"); 152 ipc_event_window(con, "close");
297 } else if (con->type == C_WORKSPACE) {
298 ipc_event_workspace(NULL, con, "empty");
299 }
300
301 // The below functions move their children to somewhere else.
302 if (con->type == C_OUTPUT) {
303 container_output_destroy(con);
304 } else if (con->type == C_WORKSPACE) {
305 // Workspaces will refuse to be destroyed if they're the last workspace
306 // on their output.
307 if (!container_workspace_destroy(con)) {
308 return NULL;
309 }
310 } 153 }
311 154
312 container_end_mouse_operation(con); 155 container_end_mouse_operation(con);
@@ -318,51 +161,22 @@ static struct sway_container *container_destroy_noreaping(
318 root_scratchpad_remove_container(con); 161 root_scratchpad_remove_container(con);
319 } 162 }
320 163
321 if (!con->parent) { 164 if (con->parent) {
322 return NULL; 165 container_remove_child(con);
323 }
324
325 return container_remove_child(con);
326}
327
328bool container_reap_empty(struct sway_container *con) {
329 switch (con->type) {
330 case C_ROOT:
331 case C_OUTPUT:
332 // dont reap these
333 break;
334 case C_WORKSPACE:
335 if (!workspace_is_visible(con) && workspace_is_empty(con)) {
336 wlr_log(WLR_DEBUG, "Destroying workspace via reaper");
337 container_destroy_noreaping(con);
338 return true;
339 }
340 break;
341 case C_CONTAINER:
342 if (con->children->length == 0) {
343 container_destroy_noreaping(con);
344 return true;
345 }
346 case C_VIEW:
347 break;
348 case C_TYPES:
349 sway_assert(false, "container_reap_empty called on an invalid "
350 "container");
351 break;
352 } 166 }
353
354 return false;
355} 167}
356 168
357struct sway_container *container_reap_empty_recursive( 169struct sway_container *container_reap_empty(struct sway_container *con) {
358 struct sway_container *con) { 170 while (con && con->type == C_CONTAINER) {
359 while (con) {
360 struct sway_container *next = con->parent; 171 struct sway_container *next = con->parent;
361 if (!container_reap_empty(con)) { 172 if (con->children->length == 0) {
362 break; 173 container_begin_destroy(con);
363 } 174 }
364 con = next; 175 con = next;
365 } 176 }
177 if (con && con->type == C_WORKSPACE) {
178 workspace_consider_destroy(con);
179 }
366 return con; 180 return con;
367} 181}
368 182
@@ -371,34 +185,12 @@ struct sway_container *container_flatten(struct sway_container *container) {
371 struct sway_container *child = container->children->items[0]; 185 struct sway_container *child = container->children->items[0];
372 struct sway_container *parent = container->parent; 186 struct sway_container *parent = container->parent;
373 container_replace_child(container, child); 187 container_replace_child(container, child);
374 container_destroy_noreaping(container); 188 container_begin_destroy(container);
375 container = parent; 189 container = parent;
376 } 190 }
377 return container; 191 return container;
378} 192}
379 193
380/**
381 * container_destroy() is the first step in destroying a container. We'll emit
382 * events, detach it from the tree and mark it as destroying. The container will
383 * remain in memory until it's no longer used by a transaction, then it will be
384 * freed via container_free().
385 *
386 * This function just wraps container_destroy_noreaping(), then does reaping.
387 */
388struct sway_container *container_destroy(struct sway_container *con) {
389 if (con->is_fullscreen) {
390 struct sway_container *ws = container_parent(con, C_WORKSPACE);
391 ws->sway_workspace->fullscreen = NULL;
392 }
393 struct sway_container *parent = container_destroy_noreaping(con);
394
395 if (!parent) {
396 return NULL;
397 }
398
399 return container_reap_empty_recursive(parent);
400}
401
402static void container_close_func(struct sway_container *container, void *data) { 194static void container_close_func(struct sway_container *container, void *data) {
403 if (container->type == C_VIEW) { 195 if (container->type == C_VIEW) {
404 view_close(container->sway_view); 196 view_close(container->sway_view);
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index a3de44ce..12e7342b 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -302,7 +302,7 @@ static void workspace_rejigger(struct sway_container *ws,
302 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT; 302 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
303 303
304 container_flatten(ws); 304 container_flatten(ws);
305 container_reap_empty_recursive(original_parent); 305 container_reap_empty(original_parent);
306 container_create_notify(new_parent); 306 container_create_notify(new_parent);
307} 307}
308 308
@@ -325,7 +325,7 @@ static void move_out_of_tabs_stacks(struct sway_container *container,
325 container_insert_child(new_parent->parent, container, offs < 0 ? 0 : 1); 325 container_insert_child(new_parent->parent, container, offs < 0 ? 0 : 1);
326 } else { 326 } else {
327 container_insert_child(new_parent, container, offs < 0 ? 0 : 1); 327 container_insert_child(new_parent, container, offs < 0 ? 0 : 1);
328 container_reap_empty_recursive(new_parent->parent); 328 container_reap_empty(new_parent->parent);
329 container_flatten(new_parent->parent); 329 container_flatten(new_parent->parent);
330 } 330 }
331 container_create_notify(new_parent); 331 container_create_notify(new_parent);
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 6da63064..80636c11 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -10,6 +10,7 @@
10#include "log.h" 10#include "log.h"
11 11
12static void restore_workspaces(struct sway_container *output) { 12static void restore_workspaces(struct sway_container *output) {
13 // Workspace output priority
13 for (int i = 0; i < root_container.children->length; i++) { 14 for (int i = 0; i < root_container.children->length; i++) {
14 struct sway_container *other = root_container.children->items[i]; 15 struct sway_container *other = root_container.children->items[i];
15 if (other == output) { 16 if (other == output) {
@@ -29,6 +30,15 @@ static void restore_workspaces(struct sway_container *output) {
29 } 30 }
30 } 31 }
31 32
33 // Saved workspaces
34 list_t *saved = root_container.sway_root->saved_workspaces;
35 for (int i = 0; i < saved->length; ++i) {
36 struct sway_container *ws = saved->items[i];
37 container_add_child(output, ws);
38 ipc_event_workspace(NULL, ws, "move");
39 }
40 saved->length = 0;
41
32 output_sort_workspaces(output); 42 output_sort_workspaces(output);
33} 43}
34 44
@@ -68,7 +78,7 @@ struct sway_container *output_create(
68 output->sway_output = sway_output; 78 output->sway_output = sway_output;
69 output->name = strdup(name); 79 output->name = strdup(name);
70 if (output->name == NULL) { 80 if (output->name == NULL) {
71 container_destroy(output); 81 output_begin_destroy(output);
72 return NULL; 82 return NULL;
73 } 83 }
74 84
@@ -103,6 +113,102 @@ struct sway_container *output_create(
103 return output; 113 return output;
104} 114}
105 115
116static void output_evacuate(struct sway_container *output) {
117 if (!output->children->length) {
118 return;
119 }
120 struct sway_container *fallback_output = NULL;
121 if (root_container.children->length > 1) {
122 fallback_output = root_container.children->items[0];
123 if (fallback_output == output) {
124 fallback_output = root_container.children->items[1];
125 }
126 }
127
128 while (output->children->length) {
129 struct sway_container *workspace = output->children->items[0];
130
131 struct sway_container *new_output =
132 workspace_output_get_highest_available(workspace, output);
133 if (!new_output) {
134 new_output = fallback_output;
135 }
136
137 container_remove_child(workspace);
138
139 if (new_output) {
140 workspace_output_add_priority(workspace, new_output);
141 container_add_child(new_output, workspace);
142 output_sort_workspaces(new_output);
143 ipc_event_workspace(NULL, workspace, "move");
144 } else {
145 list_add(root_container.sway_root->saved_workspaces, workspace);
146 }
147 }
148}
149
150void output_destroy(struct sway_container *output) {
151 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
152 return;
153 }
154 if (!sway_assert(output->destroying,
155 "Tried to free output which wasn't marked as destroying")) {
156 return;
157 }
158 if (!sway_assert(output->ntxnrefs == 0, "Tried to free output "
159 "which is still referenced by transactions")) {
160 return;
161 }
162 free(output->name);
163 free(output->formatted_title);
164 wlr_texture_destroy(output->title_focused);
165 wlr_texture_destroy(output->title_focused_inactive);
166 wlr_texture_destroy(output->title_unfocused);
167 wlr_texture_destroy(output->title_urgent);
168 list_free(output->children);
169 list_free(output->current.children);
170 list_free(output->outputs);
171 free(output);
172
173 // NOTE: We don't actually destroy the sway_output here
174}
175
176static void untrack_output(struct sway_container *con, void *data) {
177 struct sway_output *output = data;
178 int index = list_find(con->outputs, output);
179 if (index != -1) {
180 list_del(con->outputs, index);
181 }
182}
183
184void output_begin_destroy(struct sway_container *output) {
185 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
186 return;
187 }
188 wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
189 wl_signal_emit(&output->events.destroy, output);
190
191 output_evacuate(output);
192
193 output->destroying = true;
194 container_set_dirty(output);
195
196 root_for_each_container(untrack_output, output->sway_output);
197
198 wl_list_remove(&output->sway_output->mode.link);
199 wl_list_remove(&output->sway_output->transform.link);
200 wl_list_remove(&output->sway_output->scale.link);
201 wl_list_remove(&output->sway_output->damage_destroy.link);
202 wl_list_remove(&output->sway_output->damage_frame.link);
203
204 output->sway_output->swayc = NULL;
205 output->sway_output = NULL;
206
207 if (output->parent) {
208 container_remove_child(output);
209 }
210}
211
106void output_for_each_workspace(struct sway_container *output, 212void output_for_each_workspace(struct sway_container *output,
107 void (*f)(struct sway_container *con, void *data), void *data) { 213 void (*f)(struct sway_container *con, void *data), void *data) {
108 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { 214 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
diff --git a/sway/tree/root.c b/sway/tree/root.c
index c27ff2c3..5602f0a0 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -39,6 +39,7 @@ void root_create(void) {
39 wl_list_init(&root_container.sway_root->drag_icons); 39 wl_list_init(&root_container.sway_root->drag_icons);
40 wl_signal_init(&root_container.sway_root->events.new_container); 40 wl_signal_init(&root_container.sway_root->events.new_container);
41 root_container.sway_root->scratchpad = create_list(); 41 root_container.sway_root->scratchpad = create_list();
42 root_container.sway_root->saved_workspaces = create_list();
42 43
43 root_container.sway_root->output_layout_change.notify = 44 root_container.sway_root->output_layout_change.notify =
44 output_layout_handle_change; 45 output_layout_handle_change;
@@ -50,6 +51,7 @@ void root_destroy(void) {
50 // sway_root 51 // sway_root
51 wl_list_remove(&root_container.sway_root->output_layout_change.link); 52 wl_list_remove(&root_container.sway_root->output_layout_change.link);
52 list_free(root_container.sway_root->scratchpad); 53 list_free(root_container.sway_root->scratchpad);
54 list_free(root_container.sway_root->saved_workspaces);
53 wlr_output_layout_destroy(root_container.sway_root->output_layout); 55 wlr_output_layout_destroy(root_container.sway_root->output_layout);
54 free(root_container.sway_root); 56 free(root_container.sway_root);
55 57
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 7bf7325a..ba4a880f 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -35,7 +35,7 @@ void view_init(struct sway_view *view, enum sway_view_type type,
35 wl_signal_init(&view->events.unmap); 35 wl_signal_init(&view->events.unmap);
36} 36}
37 37
38void view_free(struct sway_view *view) { 38void view_destroy(struct sway_view *view) {
39 if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) { 39 if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) {
40 return; 40 return;
41 } 41 }
@@ -75,14 +75,14 @@ void view_free(struct sway_view *view) {
75 * destroying flag will make the view get freed when the transaction is 75 * destroying flag will make the view get freed when the transaction is
76 * finished. 76 * finished.
77 */ 77 */
78void view_destroy(struct sway_view *view) { 78void view_begin_destroy(struct sway_view *view) {
79 if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { 79 if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) {
80 return; 80 return;
81 } 81 }
82 view->destroying = true; 82 view->destroying = true;
83 83
84 if (!view->swayc) { 84 if (!view->swayc) {
85 view_free(view); 85 view_destroy(view);
86 } 86 }
87} 87}
88 88
@@ -560,7 +560,9 @@ void view_unmap(struct sway_view *view) {
560 } 560 }
561 561
562 bool was_fullscreen = view->swayc->is_fullscreen; 562 bool was_fullscreen = view->swayc->is_fullscreen;
563 struct sway_container *surviving_ancestor = container_destroy(view->swayc); 563 struct sway_container *parent = view->swayc->parent;
564 container_begin_destroy(view->swayc);
565 struct sway_container *surviving_ancestor = container_reap_empty(parent);
564 566
565 // If the workspace wasn't reaped 567 // If the workspace wasn't reaped
566 if (surviving_ancestor && surviving_ancestor->type >= C_WORKSPACE) { 568 if (surviving_ancestor && surviving_ancestor->type >= C_WORKSPACE) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index cf50ee09..93c4b3d3 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -79,6 +79,65 @@ struct sway_container *workspace_create(struct sway_container *output,
79 return workspace; 79 return workspace;
80} 80}
81 81
82void workspace_destroy(struct sway_container *workspace) {
83 if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
84 return;
85 }
86 if (!sway_assert(workspace->destroying,
87 "Tried to free workspace which wasn't marked as destroying")) {
88 return;
89 }
90 if (!sway_assert(workspace->ntxnrefs == 0, "Tried to free workspace "
91 "which is still referenced by transactions")) {
92 return;
93 }
94 // sway_workspace
95 struct sway_workspace *ws = workspace->sway_workspace;
96 list_foreach(ws->output_priority, free);
97 list_free(ws->output_priority);
98 list_free(ws->floating);
99 free(ws);
100
101 // swayc
102 free(workspace->name);
103 free(workspace->formatted_title);
104 wlr_texture_destroy(workspace->title_focused);
105 wlr_texture_destroy(workspace->title_focused_inactive);
106 wlr_texture_destroy(workspace->title_unfocused);
107 wlr_texture_destroy(workspace->title_urgent);
108 list_free(workspace->children);
109 list_free(workspace->current.children);
110 list_free(workspace->outputs);
111 free(workspace);
112}
113
114void workspace_begin_destroy(struct sway_container *workspace) {
115 if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
116 return;
117 }
118 wlr_log(WLR_DEBUG, "Destroying workspace '%s'", workspace->name);
119 wl_signal_emit(&workspace->events.destroy, workspace);
120 ipc_event_workspace(NULL, workspace, "empty"); // intentional
121
122 workspace->destroying = true;
123 container_set_dirty(workspace);
124
125 if (workspace->parent) {
126 container_remove_child(workspace);
127 }
128}
129
130void workspace_consider_destroy(struct sway_container *ws) {
131 if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
132 return;
133 }
134 struct sway_seat *seat = input_manager_current_seat(input_manager);
135 if (ws->children->length == 0 && ws->sway_workspace->floating->length == 0
136 && seat_get_active_child(seat, ws->parent) != ws) {
137 workspace_begin_destroy(ws);
138 }
139}
140
82char *prev_workspace_name = NULL; 141char *prev_workspace_name = NULL;
83 142
84void next_name_map(struct sway_container *ws, void *data) { 143void next_name_map(struct sway_container *ws, void *data) {
@@ -421,9 +480,7 @@ bool workspace_switch(struct sway_container *workspace,
421 // no op. We therefore need to send the IPC event and clean up the old 480 // no op. We therefore need to send the IPC event and clean up the old
422 // workspace here. 481 // workspace here.
423 ipc_event_workspace(active_ws, workspace, "focus"); 482 ipc_event_workspace(active_ws, workspace, "focus");
424 if (!workspace_is_visible(active_ws) && workspace_is_empty(active_ws)) { 483 workspace_consider_destroy(active_ws);
425 container_destroy(active_ws);
426 }
427 } 484 }
428 seat_set_focus(seat, next); 485 seat_set_focus(seat, next);
429 struct sway_container *output = container_parent(workspace, C_OUTPUT); 486 struct sway_container *output = container_parent(workspace, C_OUTPUT);