@@ -120,7 +120,7 @@ public class Gala.WorkspaceManager : Object {
120120 // or else things might get broke
121121 DragDropAction . cancel_all_by_id (" multitaskingview-window" );
122122
123- remove_workspace (prev_workspace);
123+ queue_remove_workspace (prev_workspace);
124124 }
125125 }
126126
@@ -178,7 +178,7 @@ public class Gala.WorkspaceManager : Object {
178178 && Utils . get_n_windows (workspace, true , window) == 0
179179 && workspace != last_workspace
180180 ) {
181- remove_workspace (workspace);
181+ queue_remove_workspace (workspace);
182182 }
183183
184184 // if window is the second last and empty, make it the last workspace
@@ -187,7 +187,7 @@ public class Gala.WorkspaceManager : Object {
187187 && Utils . get_n_windows (workspace, true , window) == 0
188188 && workspace. index () == last_workspace_index - 1
189189 ) {
190- remove_workspace (last_workspace);
190+ queue_remove_workspace (last_workspace);
191191 }
192192 }
193193
@@ -221,12 +221,27 @@ public class Gala.WorkspaceManager : Object {
221221 manager. append_new_workspace (false , display. get_current_time ());
222222 }
223223
224+ private void queue_remove_workspace (Meta .Workspace workspace ) {
225+ // workspace has already been removed
226+ if (workspace in workspaces_marked_removed) {
227+ return ;
228+ }
229+
230+ workspaces_marked_removed. add (workspace);
231+
232+ // We might be here because of a signal emition from the ws machinery (e.g. workspace.window_removed).
233+ // Often the function emitting the signal doesn't take a ref on the ws so if we remove it right
234+ // away it will be freed. But because the function often accesses it after the singal emition this leads
235+ // to warnings and in some cases a crash.
236+ Idle . add (() = > remove_workspace (workspace));
237+ }
238+
224239 /**
225240 * Make sure we switch to a different workspace and remove the given one
226241 *
227242 * @param workspace The workspace to remove
228243 */
229- private void remove_workspace (Meta .Workspace workspace ) {
244+ private bool remove_workspace (Meta .Workspace workspace ) {
230245 unowned Meta . Display display = workspace. get_display ();
231246 unowned Meta . WorkspaceManager manager = display. get_workspace_manager ();
232247 var time = display. get_current_time ();
@@ -246,17 +261,12 @@ public class Gala.WorkspaceManager : Object {
246261 }
247262 }
248263
249- // workspace has already been removed
250- if (workspace in workspaces_marked_removed) {
251- return ;
252- }
253-
254264 workspace. window_added. disconnect (queue_window_added);
255265 workspace. window_removed. disconnect (window_removed);
256266
257- workspaces_marked_removed. add (workspace);
258-
259267 manager. remove_workspace (workspace, time);
268+
269+ return Source . REMOVE ;
260270 }
261271
262272 /**
@@ -292,7 +302,7 @@ public class Gala.WorkspaceManager : Object {
292302 foreach (var workspace in manager. get_workspaces ()) {
293303 var last_index = manager. get_n_workspaces () - 1 ;
294304 if (Utils . get_n_windows (workspace) == 0 && workspace. index () != last_index) {
295- remove_workspace (workspace);
305+ queue_remove_workspace (workspace);
296306 }
297307 }
298308 }
0 commit comments