[gnome-shell] Add API to programmatically initiate a drag



commit 1a834f7d8b5344c8d7f609419b934500e4cd134c
Author: Colin Walters <walters verbum org>
Date:   Tue Sep 1 14:07:31 2009 -0400

    Add API to programmatically initiate a drag
    
    For some use cases we have other behavior on mouse press and want
    to manually control when a drag starts.  Split out the drag initiation
    code into startDrag.

 js/ui/dnd.js |  150 ++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 93 insertions(+), 57 deletions(-)
---
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index 87cb5d8..4989d5e 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -8,15 +8,17 @@ const Tweener = imports.ui.tweener;
 
 const SNAP_BACK_ANIMATION_TIME = 0.25;
 
-function _Draggable(actor) {
-    this._init(actor);
+function _Draggable(actor, manualMode) {
+    this._init(actor, manualMode);
 }
 
 _Draggable.prototype = {
-    _init : function(actor) {
+    _init : function(actor, manualMode) {
         this.actor = actor;
-        this.actor.connect('button-press-event',
-                           Lang.bind(this, this._onButtonPress));
+        if (!manualMode)
+            this.actor.connect('button-press-event',
+                               Lang.bind(this, this._onButtonPress));
+        this._haveSourceGrab = false;
     },
 
     _onButtonPress : function (actor, event) {
@@ -25,6 +27,7 @@ _Draggable.prototype = {
         if (Tweener.getTweenCount(actor))
             return false;
 
+        this._haveSourceGrab = true;
         this._grabActor(actor);
 
         let [stageX, stageY] = event.get_coords();
@@ -66,6 +69,80 @@ _Draggable.prototype = {
             return false;
     },
 
+    /**
+     * startDrag:
+     * @actor: Origin actor for drag and drop
+     * @stageX: X coordinate of event
+     * @stageY: Y coordinate of event
+     * @time: Event timestamp
+     *
+     * Directly initiate a drag and drop operation from the given actor.
+     * This function is useful to call if you've specified manualMode
+     * for the draggable.
+     */
+    startDrag: function (actor, stageX, stageY, time) {
+        this.emit('drag-begin', time);
+
+        this._dragStartX = stageX;
+        this._dragStartY = stageY;
+
+        if (this.actor._delegate && this.actor._delegate.getDragActor) {
+            this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
+            // Drag actor does not always have to be the same as actor. For example drag actor
+            // can be an image that's part of the actor. So to perform "snap back" correctly we need
+            // to know what was the drag actor source.
+            if (this.actor._delegate.getDragActorSource) {
+                this._dragActorSource = this.actor._delegate.getDragActorSource();
+                // If the user dragged from the source, then position
+                // the dragActor over it. Otherwise, center it
+                // around the pointer
+                let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
+                let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
+                let x, y;
+                if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
+                    stageY > sourceY && stageY <= sourceY + sourceHeight) {
+                    x = sourceX;
+                    y = sourceY;
+                } else {
+                    x = stageX - this._dragActor.width / 2;
+                    y = stageY - this._dragActor.height / 2;
+                }
+                this._dragActor.set_position(x, y);
+            } else {
+                this._dragActorSource = this.actor;
+            }
+            this._dragOrigParent = undefined;
+            if (this._haveSourceGrab) {
+                this._haveSourceGrab = false;
+                this._ungrabActor(actor);
+            }
+            this._grabActor(this._dragActor);
+
+            this._dragOffsetX = this._dragActor.x - this._dragStartX;
+            this._dragOffsetY = this._dragActor.y - this._dragStartY;
+        } else {
+            this._dragActor = actor;
+            this._dragActorSource = undefined;
+            this._dragOrigParent = actor.get_parent();
+            this._dragOrigX = this._dragActor.x;
+            this._dragOrigY = this._dragActor.y;
+            this._dragOrigScale = this._dragActor.scale_x;
+
+            let [actorStageX, actorStageY] = actor.get_transformed_position();
+            this._dragOffsetX = actorStageX - this._dragStartX;
+            this._dragOffsetY = actorStageY - this._dragStartY;
+
+            // Set the actor's scale such that it will keep the same
+            // transformed size when it's reparented to the stage
+            let [scaledWidth, scaledHeight] = actor.get_transformed_size();
+            actor.set_scale(scaledWidth / actor.width,
+                           scaledHeight / actor.height);
+        }
+
+        this._dragActor.reparent(actor.get_stage());
+        this._dragActor.raise_top();
+    },
+
     _onMotion : function (actor, event) {
         let [stageX, stageY] = event.get_coords();
 
@@ -75,55 +152,7 @@ _Draggable.prototype = {
         if (!this._dragActor &&
             (Math.abs(stageX - this._dragStartX) > threshold ||
              Math.abs(stageY - this._dragStartY) > threshold)) {
-            this.emit('drag-begin', event.get_time());
-
-            if (this.actor._delegate && this.actor._delegate.getDragActor) {
-                this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
-                // Drag actor does not always have to be the same as actor. For example drag actor
-                // can be an image that's part of the actor. So to perform "snap back" correctly we need
-                // to know what was the drag actor source.
-                if (this.actor._delegate.getDragActorSource) {
-                    this._dragActorSource = this.actor._delegate.getDragActorSource();
-                    // If the user dragged from the source, then position
-                    // the dragActor over it. Otherwise, center it
-                    // around the pointer
-                    let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
-                    let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
-                    if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
-                        stageY > sourceY && stageY <= sourceY + sourceHeight)
-                        this._dragActor.set_position(sourceX, sourceY);
-                    else
-                        this._dragActor.set_position(stageX - this._dragActor.width / 2, stageY - this._dragActor.height / 2);
-                } else {
-                    this._dragActorSource = this.actor;
-                }
-                this._dragOrigParent = undefined;
-                this._ungrabActor(actor);
-                this._grabActor(this._dragActor);
-
-                this._dragOffsetX = this._dragActor.x - this._dragStartX;
-                this._dragOffsetY = this._dragActor.y - this._dragStartY;
-            } else {
-                this._dragActor = actor;
-                this._dragActorSource = undefined;
-                this._dragOrigParent = actor.get_parent();
-                this._dragOrigX = this._dragActor.x;
-                this._dragOrigY = this._dragActor.y;
-                this._dragOrigScale = this._dragActor.scale_x;
-
-                let [actorStageX, actorStageY] = actor.get_transformed_position();
-                this._dragOffsetX = actorStageX - this._dragStartX;
-                this._dragOffsetY = actorStageY - this._dragStartY;
-
-                // Set the actor's scale such that it will keep the same
-                // transformed size when it's reparented to the stage
-                let [scaledWidth, scaledHeight] = actor.get_transformed_size();
-                actor.set_scale(scaledWidth / actor.width,
-                                scaledHeight / actor.height);
-            }
-
-            this._dragActor.reparent(actor.get_stage());
-            this._dragActor.raise_top();
+                this.startDrag(actor, stageX, stageY, event.get_time());
         }
 
         // If we are dragging, update the position
@@ -149,7 +178,7 @@ _Draggable.prototype = {
                                                     event.get_time());
                 }
                 target = target.get_parent();
-            }  
+            }
         }
 
         return true;
@@ -225,6 +254,13 @@ _Draggable.prototype = {
 
 Signals.addSignalMethods(_Draggable.prototype);
 
-function makeDraggable(actor) {
-    return new _Draggable(actor);
+/**
+ * makeDraggable:
+ * @actor: Source actor
+ * @manualMode: If given, do not automatically start drag and drop on click
+ *
+ * Create an object which controls drag and drop for the given actor.
+ */
+function makeDraggable(actor, manualMode) {
+    return new _Draggable(actor, manualMode);
 }



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