[gnome-shell] [dnd] Add monitoring hooks for motion/drop events



commit c50e32436685f24b3b3875076cd0ea81269535f1
Author: Florian Müllner <fmuellner gnome org>
Date:   Sun Jun 6 16:22:27 2010 +0200

    [dnd] Add monitoring hooks for motion/drop events
    
    Sometimes it is desirable to be able to react to DND events that
    happen outside a target actor's bounds, e.g. to implement reactive
    screen edges. Add a simple interface which allows to hook into
    drag motion and drop handling without jumping through ugly hoops.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=620504

 js/ui/dnd.js |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)
---
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index dad1cd0..4a01c73 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -17,8 +17,22 @@ const SNAP_BACK_ANIMATION_TIME = 0.25;
 // Time to animate to original position on success
 const REVERT_ANIMATION_TIME = 0.75;
 
+const DragMotionResult = {
+    NO_DROP:   0,
+    COPY_DROP: 1,
+    MOVE_DROP: 2,
+    CONTINUE:  3
+};
+
+const DragDropResult = {
+    FAILURE:  0,
+    SUCCESS:  1,
+    CONTINUE: 2
+};
+
 let eventHandlerActor = null;
 let currentDraggable = null;
+let dragMonitors = [];
 
 function _getEventHandlerActor() {
     if (!eventHandlerActor) {
@@ -36,6 +50,18 @@ function _getEventHandlerActor() {
     return eventHandlerActor;
 }
 
+function addDragMonitor(monitor) {
+    dragMonitors.push(monitor);
+}
+
+function removeMonitor(monitor) {
+    for (let i = 0; i < dragMonitors.length; i++)
+        if (dragMonitors[i] == monitor) {
+            dragMonitors.splice(i, 1);
+            return;
+        }
+}
+
 function _Draggable(actor, params) {
     this._init(actor, params);
 }
@@ -294,12 +320,37 @@ _Draggable.prototype = {
         if (this._dragActor) {
             this._dragActor.set_position(stageX + this._dragOffsetX,
                                          stageY + this._dragOffsetY);
+
             // Because we want to find out what other actor is located at the current position of this._dragActor,
             // we have to temporarily hide this._dragActor.
             this._dragActor.hide();
             let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
                                                                       stageX, stageY);
             this._dragActor.show();
+
+            // We call observers only once per motion with the innermost
+            // target actor. If necessary, the observer can walk the
+            // parent itself.
+            let dragEvent = {
+                x: stageX,
+                y: stageY,
+                dragActor: this._dragActor,
+                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;
+                    }
+            }
+
             while (target) {
                 if (target._delegate && target._delegate.handleDragOver) {
                     let [r, targX, targY] = target.transform_stage_point(stageX, stageY);
@@ -327,6 +378,27 @@ _Draggable.prototype = {
         let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
                                                                   dropX, dropY);
         this._dragActor.show();
+
+        // We call observers only once per motion with the innermost
+        // target actor. If necessary, the observer can walk the
+        // parent itself.
+        let dropEvent = {
+            dropActor: this._dragActor,
+            targetActor: target,
+            clutterEvent: event
+        };
+        for (let i = 0; i < dragMonitors.length; i++) {
+            let dropFunc = dragMonitors[i].dragDrop;
+            if (dropFunc)
+                switch (dropFunc(dropEvent)) {
+                    case DragDropResult.FAILURE:
+                    case DragDropResult.SUCCESS:
+                        return true;
+                    case DragDropResult.CONTINUE:
+                        continue;
+                }
+        }
+
         while (target) {
             if (target._delegate && target._delegate.acceptDrop) {
                 let [r, targX, targY] = target.transform_stage_point(dropX, dropY);



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