From 38c34223319eda14cd89301b4ee7079226c41af8 Mon Sep 17 00:00:00 2001 From: Maxim Ermilov Date: Fri, 10 Sep 2010 06:00:28 +0400 Subject: [PATCH] [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 f87bf58e9..bb571ba5d 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 4a01c730e..217a83982 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 95adb2f3b..e1b1b7cb9 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 db6700557..d7deab0c1 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 });