[gnome-shell] workspaceThumbnail: move event handling to ThumbnailsBox



commit 369c1b0a413233ad2adb64475f4e62d768e7674e
Author: Stefano Facchini <stefano facchini gmail com>
Date:   Fri Feb 10 18:59:05 2012 +0100

    workspaceThumbnail: move event handling to ThumbnailsBox
    
    Currently, click and drop events are handled by each WorkspaceThumbnail
    instance. With the introduction of the workspace cut and the request
    to extend the reactive area of the workspace selector to the edge
    of the monitor, it becomes more convenient to do all the event handling
    inside ThumbnailsBox, even if this requires some manual layout computation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=643319

 js/ui/workspaceThumbnail.js |  173 ++++++++++++++++++++++++-------------------
 1 files changed, 97 insertions(+), 76 deletions(-)
---
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index a5fd534..05e239c 100644
--- a/js/ui/workspaceThumbnail.js
+++ b/js/ui/workspaceThumbnail.js
@@ -158,8 +158,7 @@ const WorkspaceThumbnail = new Lang.Class({
 
         this._removed = false;
 
-        this.actor = new St.Widget({ reactive: true,
-                                     clip_to_allocation: true,
+        this.actor = new St.Widget({ clip_to_allocation: true,
                                      style_class: 'workspace-thumbnail' });
         this.actor._delegate = this;
 
@@ -167,15 +166,6 @@ const WorkspaceThumbnail = new Lang.Class({
         this.actor.add_actor(this._contents);
 
         this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
-        this.actor.connect('button-press-event', Lang.bind(this,
-            function(actor, event) {
-                return true;
-            }));
-        this.actor.connect('button-release-event', Lang.bind(this,
-            function(actor, event) {
-                this._activate();
-                return true;
-            }));
 
         this._background = Meta.BackgroundActor.new_for_screen(global.screen);
         this._contents.add_actor(this._background);
@@ -407,7 +397,9 @@ const WorkspaceThumbnail = new Lang.Class({
         let clone = new WindowClone(win);
 
         clone.connect('selected',
-                      Lang.bind(this, this._activate));
+                      Lang.bind(this, function(clone, time) {
+                          this.activate(time);
+                      }));
         clone.connect('drag-begin',
                       Lang.bind(this, function(clone) {
                           Main.overview.beginWindowDrag();
@@ -432,7 +424,7 @@ const WorkspaceThumbnail = new Lang.Class({
         return clone;
     },
 
-    _activate : function (clone, time) {
+    activate : function (time) {
         if (this.state > ThumbnailState.NORMAL)
             return;
 
@@ -443,8 +435,8 @@ const WorkspaceThumbnail = new Lang.Class({
             this.metaWorkspace.activate(time);
     },
 
-    // Draggable target interface
-    handleDragOver : function(source, actor, x, y, time) {
+    // Draggable target interface used only by ThumbnailsBox
+    handleDragOverInternal : function(source, time) {
         if (source == Main.xdndHandler) {
             this.metaWorkspace.activate(time);
             return DND.DragMotionResult.CONTINUE;
@@ -453,11 +445,6 @@ const WorkspaceThumbnail = new Lang.Class({
         if (this.state > ThumbnailState.NORMAL)
             return DND.DragMotionResult.CONTINUE;
 
-        let [w, h] = this.actor.get_transformed_size();
-        // Bubble up if we're in the "workspace cut".
-        if (y < WORKSPACE_CUT_SIZE || y > h - WORKSPACE_CUT_SIZE)
-            return DND.DragMotionResult.CONTINUE;
-
         if (source.realWindow && !this._isMyWindow(source.realWindow))
             return DND.DragMotionResult.MOVE_DROP;
         if (source.shellWorkspaceLaunch)
@@ -466,7 +453,7 @@ const WorkspaceThumbnail = new Lang.Class({
         return DND.DragMotionResult.CONTINUE;
     },
 
-    acceptDrop : function(source, actor, x, y, time) {
+    acceptDropInternal : function(source, time) {
         if (this.state > ThumbnailState.NORMAL)
             return false;
 
@@ -504,7 +491,8 @@ const ThumbnailsBox = new Lang.Class({
     Name: 'ThumbnailsBox',
 
     _init: function() {
-        this.actor = new Shell.GenericContainer({ style_class: 'workspace-thumbnails',
+        this.actor = new Shell.GenericContainer({ reactive: true,
+                                                  style_class: 'workspace-thumbnails',
                                                   request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
         this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
         this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
@@ -533,6 +521,7 @@ const ThumbnailsBox = new Lang.Class({
         this._indicator = indicator;
         this.actor.add_actor(indicator);
 
+        this._dropWorkspace = -1;
         this._dropPlaceholderPos = -1;
         this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
         this.actor.add_actor(this._dropPlaceholder);
@@ -550,6 +539,9 @@ const ThumbnailsBox = new Lang.Class({
 
         this._thumbnails = [];
 
+        this.actor.connect('button-press-event', function() { return true; });
+        this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
+
         Main.overview.connect('item-drag-begin',
                               Lang.bind(this, this._onDragBegin));
         Main.overview.connect('item-drag-end',
@@ -564,6 +556,22 @@ const ThumbnailsBox = new Lang.Class({
                               Lang.bind(this, this._onDragCancelled));
     },
 
+    _onButtonRelease: function(actor, event) {
+        let [stageX, stageY] = event.get_coords();
+        let [r, x, y] = this.actor.transform_stage_point(stageX, stageY);
+
+        for (let i = 0; i < this._thumbnails.length; i++) {
+            let thumbnail = this._thumbnails[i]
+            let [w, h] = thumbnail.actor.get_transformed_size();
+            if (y >= thumbnail.actor.y && y <= thumbnail.actor.y + h) {
+                thumbnail.activate(event.time);
+                break;
+            }
+        }
+
+        return true;
+    },
+
     _onDragBegin: function() {
         this._dragCancelled = false;
         this._dragMonitor = {
@@ -609,95 +617,108 @@ const ThumbnailsBox = new Lang.Class({
 
     // Draggable target interface
     handleDragOver : function(source, actor, x, y, time) {
-        if (!source.realWindow && !source.shellWorkspaceLaunch)
+        if (!source.realWindow && !source.shellWorkspaceLaunch && source != Main.xdndHandler)
             return DND.DragMotionResult.CONTINUE;
 
         if (!Meta.prefs_get_dynamic_workspaces())
             return DND.DragMotionResult.CONTINUE;
 
         let spacing = this.actor.get_theme_node().get_length('spacing');
-        let thumbHeight = this._porthole.height * this._scale;
 
-        let workspace = -1;
-        let firstThumbY;
+        this._dropWorkspace = -1;
+        let placeholderPos = -1;
+        let targetBase;
         if (this._dropPlaceholderPos == 0)
-            firstThumbY = this._dropPlaceholder.y;
+            targetBase = this._dropPlaceholder.y;
         else
-            firstThumbY = this._thumbnails[0].actor.y;
-        for (let i = 0; i < this._thumbnails.length; i ++) {
-            let targetBase = firstThumbY + (thumbHeight + spacing) * i;
-
+            targetBase = this._thumbnails[0].actor.y;
+        let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE;
+        let length = this._thumbnails.length;
+        for (let i = 0; i < length; i ++) {
             // Allow the reorder target to have a 10px "cut" into
             // each side of the thumbnail, to make dragging onto the
             // placeholder easier
-            let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE;
+            let [w, h] = this._thumbnails[i].actor.get_transformed_size();
             let targetBottom = targetBase + WORKSPACE_CUT_SIZE;
+            let nextTargetBase = targetBase + h + spacing;
+            let nextTargetTop =  nextTargetBase - spacing - ((i == length - 1) ? 0: WORKSPACE_CUT_SIZE);
 
             // Expand the target to include the placeholder, if it exists.
             if (i == this._dropPlaceholderPos)
                 targetBottom += this._dropPlaceholder.get_height();
 
-            if (y > targetTop && y <= targetBottom) {
-                workspace = i;
+            if (y > targetTop && y <= targetBottom && source != Main.xdndHandler) {
+                placeholderPos = i;
                 break;
+            } else if (y > targetBottom && y <= nextTargetTop) {
+                this._dropWorkspace = i;
+                break
             }
+
+            targetBase = nextTargetBase;
+            targetTop = nextTargetTop;
         }
 
-        if (this._dropPlaceholderPos != workspace) {
-            this._dropPlaceholderPos = workspace;
+        if (this._dropPlaceholderPos != placeholderPos) {
+            this._dropPlaceholderPos = placeholderPos;
             this.actor.queue_relayout();
         }
 
-        if (workspace == -1)
+        if (this._dropWorkspace != -1)
+            return this._thumbnails[this._dropWorkspace].handleDragOverInternal(source, time);
+        else if (this._dropPlaceholderPos != -1)
+            return DND.DragMotionResult.MOVE_DROP;
+        else
             return DND.DragMotionResult.CONTINUE;
-
-        return DND.DragMotionResult.MOVE_DROP;
     },
 
     acceptDrop: function(source, actor, x, y, time) {
-        if (this._dropPlaceholderPos == -1)
-            return false;
+        if (this._dropWorkspace != -1) {
+            return this._thumbnails[this._dropWorkspace].acceptDropInternal(source, time);
+        } else if (this._dropPlaceholderPos != -1) {
+            if (!source.realWindow && !source.shellWorkspaceLaunch)
+                return false;
 
-        if (!source.realWindow && !source.shellWorkspaceLaunch)
-            return false;
+            let isWindow = !!source.realWindow;
 
-        let isWindow = !!source.realWindow;
+            // To create a new workspace, we first slide all the windows on workspaces
+            // below us to the next workspace, leaving a blank workspace for us to recycle.
+            let newWorkspaceIndex;
+            [newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1];
 
-        // To create a new workspace, we first slide all the windows on workspaces
-        // below us to the next workspace, leaving a blank workspace for us to recycle.
-        let newWorkspaceIndex;
-        [newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1];
+            // Nab all the windows below us.
+            let windows = global.get_window_actors().filter(function(win) {
+                if (isWindow)
+                    return win.get_workspace() >= newWorkspaceIndex && win != source;
+                else
+                    return win.get_workspace() >= newWorkspaceIndex;
+            });
+
+            // ... move them down one.
+            windows.forEach(function(win) {
+                win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
+                                                          true, time);
+            });
 
-        // Nab all the windows below us.
-        let windows = global.get_window_actors().filter(function(win) {
             if (isWindow)
-                return win.get_workspace() >= newWorkspaceIndex && win != source;
-            else
-                return win.get_workspace() >= newWorkspaceIndex;
-        });
-
-        // ... move them down one.
-        windows.forEach(function(win) {
-            win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
-                                                      true, time);
-        });
-
-        if (isWindow)
-            // ... and bam, a workspace, good as new.
-            source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
-                                                        true, time);
-        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);
-        }
+                // ... and bam, a workspace, good as new.
+                source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
+                                                            true, time);
+            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;
+            return true;
+        } else {
+            return false;
+        }
     },
 
     show: function() {



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