[gnome-shell] autoWorkspaces: fix creation of new workspaces with application launchers



commit 3c6737f738074b5759c4af12baa0fc9f177d35e2
Author: Stefano Facchini <stefano facchini gmail com>
Date:   Fri Feb 17 15:57:27 2012 +0100

    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 a71acba..ac9330c 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 7553a4c..a5fd534 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 a914fc6..97d7aed 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 99c4cf6..14626bf 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]