From 3c6737f738074b5759c4af12baa0fc9f177d35e2 Mon Sep 17 00:00:00 2001 From: Stefano Facchini Date: Fri, 17 Feb 2012 15:57:27 +0100 Subject: [PATCH] autoWorkspaces: fix creation of new workspaces with application launchers In the workspace-collecting code we add a check to avoid collecting a workspace if any startup sequence is running there. Since the sequence can take some time to load, an helper function is also added which keeps the (empty) workspace around for a very short time, while waiting for the sequence to start. https://bugzilla.gnome.org/show_bug.cgi?id=664202 --- js/ui/main.js | 31 ++++++++++++++++++++++++++----- js/ui/workspaceThumbnail.js | 11 ++++++++++- src/shell-window-tracker.c | 6 ++++++ src/shell-window-tracker.h | 1 + 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/js/ui/main.js b/js/ui/main.js index a71acba8c..ac9330c10 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -171,9 +171,11 @@ function start() { // and recalculate application associations, so to avoid // races for now we initialize it here. It's better to // be predictable anyways. - Shell.WindowTracker.get_default(); + let tracker = Shell.WindowTracker.get_default(); Shell.AppUsage.get_default(); + tracker.connect('startup-sequence-changed', _queueCheckWorkspaces); + // The stage is always covered so Clutter doesn't need to clear it; however // the color is used as the default contents for the Mutter root background // actor so set it anyways. @@ -286,15 +288,23 @@ function _checkWorkspaces() { for (i = 0; i < _workspaces.length; i++) { let lastRemoved = _workspaces[i]._lastRemovedWindow; - if (lastRemoved && - (lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN || - lastRemoved.get_window_type() == Meta.WindowType.DIALOG || - lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG)) + if ((lastRemoved && + (lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN || + lastRemoved.get_window_type() == Meta.WindowType.DIALOG || + lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG)) || + _workspaces[i]._keepAliveId) emptyWorkspaces[i] = false; else emptyWorkspaces[i] = true; } + let sequences = Shell.WindowTracker.get_default().get_startup_sequences(); + for (i = 0; i < sequences.length; i++) { + let index = sequences[i].get_workspace(); + if (index >= 0 && index <= global.screen.n_workspaces) + emptyWorkspaces[index] = false; + } + let windows = global.get_window_actors(); for (i = 0; i < windows.length; i++) { let win = windows[i]; @@ -342,6 +352,17 @@ function _checkWorkspaces() { return false; } +function keepWorkspaceAlive(workspace, duration) { + if (workspace._keepAliveId) + Mainloop.source_remove(workspace._keepAliveId); + + workspace._keepAliveId = Mainloop.timeout_add(duration, function() { + workspace._keepAliveId = 0; + _queueCheckWorkspaces(); + return false; + }); +} + function _windowRemoved(workspace, window) { workspace._lastRemovedWindow = window; _queueCheckWorkspaces(); diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js index 7553a4c82..a5fd53472 100644 --- a/js/ui/workspaceThumbnail.js +++ b/js/ui/workspaceThumbnail.js @@ -25,6 +25,8 @@ const SLIDE_ANIMATION_TIME = 0.2; // placeholder exactly. const WORKSPACE_CUT_SIZE = 10; +const WORKSPACE_KEEP_ALIVE_TIME = 100; + const WindowClone = new Lang.Class({ Name: 'WindowClone', @@ -684,9 +686,16 @@ const ThumbnailsBox = new Lang.Class({ // ... and bam, a workspace, good as new. source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true, time); - else if (source.shellWorkspaceLaunch) + else if (source.shellWorkspaceLaunch) { source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex, timestamp: time }); + // This new workspace will be automatically removed if the application fails + // to open its first window within some time, as tracked by Shell.WindowTracker. + // Here, we only add a very brief timeout to avoid the _immediate_ removal of the + // workspace while we wait for the startup sequence to load. + Main.keepWorkspaceAlive(global.screen.get_workspace_by_index(newWorkspaceIndex), + WORKSPACE_KEEP_ALIVE_TIME); + } return true; }, diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c index a914fc63a..97d7aed4f 100644 --- a/src/shell-window-tracker.c +++ b/src/shell-window-tracker.c @@ -816,6 +816,12 @@ shell_startup_sequence_get_completed (ShellStartupSequence *sequence) return sn_startup_sequence_get_completed ((SnStartupSequence*)sequence); } +int +shell_startup_sequence_get_workspace (ShellStartupSequence *sequence) +{ + return sn_startup_sequence_get_workspace ((SnStartupSequence*)sequence); +} + /** * shell_startup_sequence_create_icon: * @sequence: diff --git a/src/shell-window-tracker.h b/src/shell-window-tracker.h index 99c4cf618..14626bf60 100644 --- a/src/shell-window-tracker.h +++ b/src/shell-window-tracker.h @@ -50,6 +50,7 @@ const char *shell_startup_sequence_get_id (ShellStartupSequence *sequence); ShellApp *shell_startup_sequence_get_app (ShellStartupSequence *sequence); const char *shell_startup_sequence_get_name (ShellStartupSequence *sequence); gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence); +int shell_startup_sequence_get_workspace (ShellStartupSequence *sequence); ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size); G_END_DECLS