gnome-shell r180 - trunk/js/ui



Author: danw
Date: Wed Feb  4 14:50:50 2009
New Revision: 180
URL: http://svn.gnome.org/viewvc/gnome-shell?rev=180&view=rev

Log:
Track window adds/removes in the overlay. #568983


Modified:
   trunk/js/ui/workspaces.js

Modified: trunk/js/ui/workspaces.js
==============================================================================
--- trunk/js/ui/workspaces.js	(original)
+++ trunk/js/ui/workspaces.js	Wed Feb  4 14:50:50 2009
@@ -5,6 +5,7 @@
 const GdkPixbuf = imports.gi.GdkPixbuf;
 const Gtk = imports.gi.Gtk;
 const Lang = imports.lang;
+const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
 const Pango = imports.gi.Pango;
 const Shell = imports.gi.Shell;
@@ -58,6 +59,7 @@
                                                 x: realWindow.x,
                                                 y: realWindow.y });
         this.realWindow = realWindow;
+        this.metaWindow = realWindow.meta_window;
         this.origX = realWindow.x;
         this.origY = realWindow.y;
 
@@ -250,7 +252,7 @@
                                 spacing: 4,
                                 orientation: Big.BoxOrientation.HORIZONTAL });
         
-        let icon = window.meta_window.mini_icon;
+        let icon = this.metaWindow.mini_icon;
         let iconTexture = new Clutter.Texture({ x: this.actor.x,
                                                 y: this.actor.y + this.actor.height - 16,
                                                 width: 16,
@@ -261,7 +263,7 @@
         
         let title = new Clutter.Label({ color: WINDOWCLONE_TITLE_COLOR,
                                         font_name: "Sans 12",
-                                        text: window.meta_window.title,
+                                        text: this.metaWindow.title,
                                         ellipsize: Pango.EllipsizeMode.END
                                       });
         box.append(title, Big.BoxPackFlags.EXPAND);
@@ -362,6 +364,8 @@
         let global = Shell.Global.get();
 
         this.workspaceNum = workspaceNum;
+        this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
+
         this.actor = new Clutter.Group();
         this.scale = 1.0;
 
@@ -378,12 +382,12 @@
         if (!this._desktop)
             this._desktop = new DesktopClone();
 
-        let metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
         this._desktop.connect('selected',
-                              function(clone, time) {
-                                  metaWorkspace.activate(time);
-                                  Main.hide_overlay();
-                              });
+                              Lang.bind(this,
+                                        function(clone, time) {
+                                            this._metaWorkspace.activate(time);
+                                            Main.hide_overlay();
+                                        }));
         this.actor.add_actor(this._desktop.actor);
 
         // Create clones for remaining windows that should be
@@ -395,6 +399,12 @@
             }
         }
 
+        // Track window changes
+        this._windowAddedId = this._metaWorkspace.connect('window-added',
+                                                          Lang.bind(this, this._windowAdded));
+        this._windowRemovedId = this._metaWorkspace.connect('window-removed',
+                                                            Lang.bind(this, this._windowRemoved));
+
         this._removeButton = null;
         this._visible = false;
 
@@ -403,21 +413,18 @@
         this.leavingOverlay = false;
     },
 
-    // Checks if the workspace is empty (ie, contains only a desktop window)
-    isEmpty : function() {
-        return this._windows.length == 1;
-    },
 
-    // Change Workspace's removability.
-    setRemovable : function(removable, buttonSize) {
+    updateRemovable : function() {
         let global = Shell.Global.get();
+        let removable = (this._windows.length == 1 /* just desktop */ &&
+                         this.workspaceNum == global.screen.n_workspaces - 1);
 
         if (removable) {
             if (this._removeButton)
                 return;
 
-            this._removeButton = new Clutter.Texture({ width: buttonSize,
-                                                       height: buttonSize,
+            this._removeButton = new Clutter.Texture({ width: Workspaces.buttonSize,
+                                                       height: Workspaces.buttonSize,
                                                        reactive: true
                                                      });
             this._removeButton.set_from_file(global.imagedir + "remove-workspace.svg");
@@ -539,39 +546,74 @@
         }
     },
 
-    // Remove a window from the workspace - this is called to fix up the visual
-    // display for changes to the window state that have already been made
-    removeWindow : function(win) {
+    _windowRemoved : function(metaWorkspace, metaWin) {
+        let global = Shell.Global.get();
+        let win = metaWin.get_compositor_private();
+
         // find the position of the window in our list
-        let index = - 1;
+        let index = - 1, clone;
         for (let i = 0; i < this._windows.length; i++) {
-            if (this._windows[i].realWindow == win) {
+            if (this._windows[i].metaWindow == metaWin) {
                 index = i;
+                clone = this._windows[index];
                 break;
             }
         }
 
         if (index == -1)
             return;
-
-        let clone = this._windows[index];
         this._windows.splice(index, 1);
+
+        // If metaWin.get_compositor_private() returned non-NULL, that
+        // means the window still exists (and is just being moved to
+        // another workspace or something), so set its overlayHint
+        // accordingly. (If it returned NULL, then the window is being
+        // destroyed; we'd like to animate this, but it's too late at
+        // this point.)
+        if (win) {
+            let [stageX, stageY] = clone.actor.get_transformed_position();
+            let [stageWidth, stageHeight] = clone.actor.get_transformed_size();
+            win._overlayHint = {
+                x: stageX,
+                y: stageY,
+                scale: stageWidth / clone.actor.width
+            };
+        }
         clone.destroy();
 
         this._positionWindows();
+        this.updateRemovable();
     },
 
-    // Add a window from the workspace - this is called to fix up the visual
-    // display for changes to the window state that have already been made.
-    // x/y/scale are used to give an initial position for the window (if the
-    // window was dropped on the workspace, say) - the window will then be
-    // animated to the final location.
-    addWindow : function(win, x, y, scale) {
+    _windowAdded : function(metaWorkspace, metaWin) {
+        let win = metaWin.get_compositor_private();
+
+        if (!win) {
+            // Newly-created windows are added to a workspace before
+            // the compositor finds out about them...
+            Mainloop.idle_add(Lang.bind(this,
+                                        function () {
+                                            if (metaWin.get_compositor_private())
+                                                this._windowAdded(metaWorkspace, metaWin);
+                                            return false;
+                                        }));
+            return;
+        }
+
         let clone = this._addWindowClone(win);
-        clone.actor.set_position (x, y);
-        clone.actor.set_scale (scale, scale);
-        
+
+        if (win._overlayHint) {
+            let x = (win._overlayHint.x - this.actor.x) / this.scale;
+            let y = (win._overlayHint.y - this.actor.y) / this.scale;
+            let scale = win._overlayHint.scale / this.scale;
+            delete win._overlayHint;
+
+            clone.actor.set_position (x, y);
+            clone.actor.set_scale (scale, scale);
+        }
+
         this._positionWindows();
+        this.updateRemovable();
     },
 
     // Animate the full-screen to overlay transition.
@@ -693,8 +735,13 @@
     },
     
     destroy : function() {
+        let global = Shell.Global.get();
+
         this.actor.destroy();
         this.actor = null;
+
+        this._metaWorkspace.disconnect(this._windowAddedId);
+        this._metaWorkspace.disconnect(this._windowRemovedId);
     },
 
     // Tests if @win belongs to this workspaces
@@ -756,14 +803,13 @@
     _onCloneSelected : function (clone, time) {
         let global = Shell.Global.get();
         let activeWorkspace = global.screen.get_active_workspace_index();
-        let w = clone.realWindow;
-        let windowWorkspace = w.get_workspace();
+        let windowWorkspace = clone.realWindow.get_workspace();
 
         if (windowWorkspace != activeWorkspace) {
             let workspace = global.screen.get_workspace_by_index(windowWorkspace);
-            workspace.activate_with_focus(w.get_meta_window(), time);
+            workspace.activate_with_focus(clone.metaWindow, time);
         } else
-            w.get_meta_window().activate(time);
+            clone.metaWindow.activate(time);
         Main.hide_overlay();
     },
 
@@ -838,14 +884,16 @@
                          });
 
         // Create (+) and (-) buttons
-        this._buttonSize = Math.floor(this._bottomHeight * 3/5);
-        this._plusX = this._x + this._width - this._buttonSize;
+        // FIXME: figure out a better way to communicate buttonSize
+        // to the Workspace
+        Workspaces.buttonSize = Math.floor(this._bottomHeight * 3/5);
+        this._plusX = this._x + this._width - Workspaces.buttonSize;
         this._plusY = screenHeight - Math.floor(this._bottomHeight * 4/5);
 
         let plus = new Clutter.Texture({ x: this._plusX,
                                          y: this._plusY,
-                                         width: this._buttonSize,
-                                         height: this._buttonSize,
+                                         width: Workspaces.buttonSize,
+                                         height: Workspaces.buttonSize,
                                          reactive: true
                                        });
         plus.set_from_file(global.imagedir + "add-workspace.svg");
@@ -854,8 +902,7 @@
         plus.lower_bottom();
 
         let lastWorkspace = this._workspaces[this._workspaces.length - 1];
-        if (lastWorkspace.isEmpty())
-            lastWorkspace.setRemovable(true, this._buttonSize);
+        lastWorkspace.updateRemovable(true);
 
         // Position/scale the desktop windows and their children
         for (let w = 0; w < this._workspaces.length; w++)
@@ -1039,7 +1086,7 @@
         let lostWorkspaces = [];
 
         // The old last workspace is no longer removable.
-        this._workspaces[oldNumWorkspaces - 1].setRemovable(false);
+        this._workspaces[oldNumWorkspaces - 1].updateRemovable();
 
         if (newNumWorkspaces > oldNumWorkspaces) {
             // Create new workspace groups
@@ -1056,8 +1103,7 @@
 
         // The new last workspace may be removable
         let newLastWorkspace = this._workspaces[this._workspaces.length - 1];
-        if (newLastWorkspace.isEmpty())
-            newLastWorkspace.setRemovable(true, this._buttonSize);
+        newLastWorkspace.updateRemovable();
 
         // Figure out the new layout
         this._positionWorkspaces(global);
@@ -1080,6 +1126,7 @@
             // Slide old workspaces out
             for (let w = 0; w < lostWorkspaces.length; w++) {
                 let workspace = lostWorkspaces[w];
+                workspace.actor.raise(this._backdrop);
                 workspace.slideOut(function () { workspace.destroy(); });
             }
 
@@ -1135,17 +1182,17 @@
         if (targetWorkspace == null || targetWorkspace == sourceWorkspace)
             return;
 
-        // Window position and scale relative to the new workspace
-        targetX = (windowX - myX - targetWorkspace.gridX) / targetWorkspace.scale;
-        targetY = (windowY - myY - targetWorkspace.gridY) / targetWorkspace.scale;
-        targetScale = clone.actor.scale_x / targetWorkspace.scale;
-
-        let metaWindow = clone.realWindow.get_meta_window();
-        metaWindow.change_workspace_by_index(targetWorkspace.workspaceNum,
-                                             false, // don't create workspace
-                                             time);
-        sourceWorkspace.removeWindow(clone.realWindow);
-        targetWorkspace.addWindow(clone.realWindow, targetX, targetY, targetScale);
+        // Set a hint on the Mutter.Window so its initial position in the
+        // overlay will be correct
+        clone.realWindow._overlayHint = {
+            x: clone.actor.x,
+            y: clone.actor.y,
+            scale: clone.actor.scale_x
+        };
+
+        clone.metaWindow.change_workspace_by_index(targetWorkspace.workspaceNum,
+                                                   false, // don't create workspace
+                                                   time);
     }
 };
 



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