[gnome-shell] [dnd] Add monitoring hooks for motion/drop events
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] [dnd] Add monitoring hooks for motion/drop events
- Date: Wed, 16 Jun 2010 18:59:30 +0000 (UTC)
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]