[gnome-shell] [DND] change cursor when dragging



commit 38c34223319eda14cd89301b4ee7079226c41af8
Author: Maxim Ermilov <zaspire rambler ru>
Date:   Fri Sep 10 06:00:28 2010 +0400

    [DND] change cursor when dragging
    
    Return a DND.DragMotionResult constant from delegate _handleDragMotion
    methods as well as the existing return value from the drag monitor method dragMotion.
    https://bugzilla.gnome.org/show_bug.cgi?id=607821

 js/ui/appDisplay.js     |   23 +++++++++++++++++++++++
 js/ui/dnd.js            |   42 +++++++++++++++++++++++++++---------------
 js/ui/workspace.js      |    9 +++++++++
 js/ui/workspacesView.js |   41 ++++++++++++++++++++++++++++++++---------
 4 files changed, 91 insertions(+), 24 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index f87bf58..bb571ba 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -1035,6 +1035,29 @@ AppWell.prototype = {
         }
     },
 
+    handleDragOver : function(source, actor, x, y, time) {
+        let app = null;
+        if (source instanceof AppWellIcon)
+            app = this._appSystem.get_app(source.getId());
+        else if (source instanceof Workspace.WindowClone)
+            app = this._tracker.get_window_app(source.metaWindow);
+
+        // Don't allow favoriting of transient apps
+        if (app == null || app.is_transient())
+            return DND.DragMotionResult.NO_DROP;
+
+        let id = app.get_id();
+
+        let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
+
+        let srcIsFavorite = (id in favorites);
+
+        if (srcIsFavorite)
+            return DND.DragMotionResult.NO_DROP;
+
+        return DND.DragMotionResult.COPY_DROP;
+    },
+
     // Draggable target interface
     acceptDrop : function(source, actor, x, y, time) {
         let app = null;
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index 4a01c73..217a839 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
 const Gtk = imports.gi.Gtk;
 const St = imports.gi.St;
 const Lang = imports.lang;
+const Shell = imports.gi.Shell;
 const Signals = imports.signals;
 const Tweener = imports.ui.tweener;
 const Main = imports.ui.main;
@@ -24,6 +25,12 @@ const DragMotionResult = {
     CONTINUE:  3
 };
 
+const DRAG_CURSOR_MAP = {
+    0: Shell.Cursor.UNSUPPORTED_TARGET,
+    1: Shell.Cursor.COPY,
+    2: Shell.Cursor.MOVE
+};
+
 const DragDropResult = {
     FAILURE:  0,
     SUCCESS:  1,
@@ -203,6 +210,7 @@ _Draggable.prototype = {
         if (this._onEventId)
             this._ungrabActor();
         this._grabEvents();
+        global.set_cursor(Shell.Cursor.IN_DRAG);
 
         this._dragX = this._dragStartX = stageX;
         this._dragY = this._dragStartY = stageY;
@@ -335,36 +343,38 @@ _Draggable.prototype = {
                 x: stageX,
                 y: stageY,
                 dragActor: this._dragActor,
+                source: this.actor._delegate,
                 targetActor: target
             };
             for (let i = 0; i < dragMonitors.length; i++) {
                 let motionFunc = dragMonitors[i].dragMotion;
-                if (motionFunc)
-                    switch (motionFunc(dragEvent)) {
-                        case DragMotionResult.NO_DROP:
-                        case DragMotionResult.COPY_DROP:
-                        case DragMotionResult.MOVE_DROP:
-                            // TODO: set a special cursor or something ;)
-                            return true;
-                        case DragMotionResult.CONTINUE:
-                            continue;
+                if (motionFunc) {
+                    let result = motionFunc(dragEvent);
+                    if (result != DragMotionResult.CONTINUE) {
+                        global.set_cursor(DRAG_CURSOR_MAP[result]);
+                        return true;
                     }
+                }
             }
-
             while (target) {
                 if (target._delegate && target._delegate.handleDragOver) {
                     let [r, targX, targY] = target.transform_stage_point(stageX, stageY);
                     // We currently loop through all parents on drag-over even if one of the children has handled it.
                     // We can check the return value of the function and break the loop if it's true if we don't want
                     // to continue checking the parents.
-                    target._delegate.handleDragOver(this.actor._delegate,
-                                                    this._dragActor,
-                                                    targX,
-                                                    targY,
-                                                    event.get_time());
+                    let result = target._delegate.handleDragOver(this.actor._delegate,
+                                                                 this._dragActor,
+                                                                 targX,
+                                                                 targY,
+                                                                 event.get_time());
+                    if (result != DragMotionResult.CONTINUE) {
+                        global.set_cursor(DRAG_CURSOR_MAP[result]);
+                        return true;
+                    }
                 }
                 target = target.get_parent();
             }
+            global.set_cursor(Shell.Cursor.IN_DRAG);
         }
 
         return true;
@@ -418,6 +428,7 @@ _Draggable.prototype = {
                     }
 
                     this._dragInProgress = false;
+                    global.unset_cursor();
                     this.emit('drag-end', event.get_time(), true);
                     this._dragComplete();
                     return true;
@@ -491,6 +502,7 @@ _Draggable.prototype = {
         } else {
             dragActor.destroy();
         }
+        global.unset_cursor();
         this.emit('drag-end', eventTime, false);
 
         this._animationInProgress = false;
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index 95adb2f..e1b1b7c 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -1586,6 +1586,15 @@ Workspace.prototype = {
     },
 
     // Draggable target interface
+    handleDragOver : function(source, actor, x, y, time) {
+        if (source instanceof WindowClone)
+            return DND.DragMotionResult.MOVE_DROP;
+        if (source.shellWorkspaceLaunch)
+            return DND.DragMotionResult.COPY_DROP;
+
+        return DND.DragMotionResult.CONTINUE;
+    },
+
     acceptDrop : function(source, actor, x, y, time) {
         if (source instanceof WindowClone) {
             let win = source.realWindow;
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index db67005..d7deab0 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -269,6 +269,14 @@ GenericWorkspacesView.prototype = {
         throw new Error('Not implemented');
     },
 
+    _handleDragOverNewWorkspace: function(source, dropActor, x, y, time) {
+        if (source instanceof Workspace.WindowClone)
+            return DND.DragMotionResult.MOVE_DROP;
+        if (source.shellWorkspaceLaunch)
+            return DND.DragMotionResult.COPY_DROP;
+        return DND.DragMotionResult.CONTINUE;
+    },
+
     _acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
         let ws = this.addWorkspace();
         if (ws == null)
@@ -487,14 +495,15 @@ NewWorkspaceArea.prototype = {
     }
 };
 
-function WorkspaceIndicator(activateWorkspace, workspaceAcceptDrop, scrollEventCb) {
-    this._init(activateWorkspace, workspaceAcceptDrop, scrollEventCb);
+function WorkspaceIndicator(activateWorkspace, workspaceAcceptDrop, workspaceHandleDragOver, scrollEventCb) {
+    this._init(activateWorkspace, workspaceAcceptDrop, workspaceHandleDragOver, scrollEventCb);
 }
 
 WorkspaceIndicator.prototype = {
-    _init: function(activateWorkspace, workspaceAcceptDrop, scrollEventCb) {
+    _init: function(activateWorkspace, workspaceAcceptDrop, workspaceHandleDragOver, scrollEventCb) {
         this._activateWorkspace = activateWorkspace;
         this._workspaceAcceptDrop = workspaceAcceptDrop;
+        this._workspaceHandleDragOver = workspaceHandleDragOver;
         this._scrollEventCb = scrollEventCb;
         let actor = new St.Bin({ style_class: 'panel-button' });
 
@@ -592,6 +601,9 @@ WorkspaceIndicator.prototype = {
             else
                 return false;
         });
+        actor._delegate.handleDragOver = Lang.bind(this, function(source, actor, x, y, time) {
+            return this._workspaceHandleDragOver(i, source, actor, x, y, time);
+        });
 
         actor.connect('scroll-event', this._scrollEventCb);
 
@@ -1187,7 +1199,7 @@ SingleView.prototype = {
             leftWorkspace.setReservedSlot(dragEvent.dragActor._delegate);
             this._dragOverLastX = leftEdge;
 
-            return DND.DragMotionResult.MOVE_DROP;
+            return DND.DragMotionResult.CONTINUE;
         }
         let rightEdge = primary.x + primary.width - 1;
         let switchRight = (dragEvent.x >= rightEdge && rightWorkspace);
@@ -1196,15 +1208,17 @@ SingleView.prototype = {
             rightWorkspace.setReservedSlot(dragEvent.dragActor._delegate);
             this._dragOverLastX = rightEdge;
 
-            return DND.DragMotionResult.MOVE_DROP;
+            return DND.DragMotionResult.CONTINUE;
         }
         this._dragOverLastX = dragEvent.x;
+        let result = DND.DragMotionResult.CONTINUE;
 
         // check hover state of new workspace area / inactive workspaces
         if (leftWorkspace) {
             if (dragEvent.targetActor == this._leftShadow) {
                 hoverWorkspace = leftWorkspace;
                 leftWorkspace.opacity = leftWorkspace.actor.opacity = 255;
+                result = leftWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
             } else {
                 leftWorkspace.opacity = leftWorkspace.actor.opacity = 200;
             }
@@ -1214,18 +1228,19 @@ SingleView.prototype = {
             if (dragEvent.targetActor == this._rightShadow) {
                 hoverWorkspace = rightWorkspace;
                 rightWorkspace.opacity = rightWorkspace.actor.opacity = 255;
+                result = rightWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
             } else {
                 rightWorkspace.opacity = rightWorkspace.actor.opacity = 200;
             }
         } else {
             let targetParent = dragEvent.targetActor.get_parent();
-            if (targetParent == this._newWorkspaceArea.actor)
+            if (targetParent == this._newWorkspaceArea.actor) {
                 this._newWorkspaceArea.setStyle(true);
-            else
+                result = this._handleDragOverNewWorkspace(dragEvent.source, dragEvent.dragActor);
+            } else
                 this._newWorkspaceArea.setStyle(false);
         }
 
-
         // handle delayed workspace switches
         if (hoverWorkspace) {
             if (!this._timeoutId)
@@ -1242,7 +1257,7 @@ SingleView.prototype = {
             }
         }
 
-        return DND.DragMotionResult.CONTINUE;
+        return result;
     },
 
     _dragEnd: function() {
@@ -1377,6 +1392,10 @@ SingleView.prototype = {
             if (this._workspaces[i] != undefined)
                 return this._workspaces[i].acceptDrop(source, actor, x, y, time);
             return false;
+        }), Lang.bind(this, function(i, source, actor, x, y, time) {
+            if (this._workspaces[i] != undefined)
+                return this._workspaces[i].handleDragOver(source, actor, x, y, time);
+            return DND.DragMotionResult.CONTINUE;
         }), Lang.bind(this, this._onScrollEvent));
 
         actor.add(indicator.actor, { expand: true, x_fill: true, y_fill: true });
@@ -1464,6 +1483,10 @@ WorkspacesControls.prototype = {
             function(source, actor, x, y, time) {
                 return this._currentView._acceptNewWorkspaceDrop(source, actor, x, y, time);
             });
+        this._addButton._delegate.handleDragOver = Lang.bind(this,
+            function(source, actor, x, y, time) {
+                return this._currentView._handleDragOverNewWorkspace(source, actor, x, y, time);
+            });
         this.actor.add(this._addButton, { y_fill: false,
                                           y_align: St.Align.START });
 



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