diff options
author | Florian Müllner <fmuellner@gnome.org> | 2023-04-20 12:26:23 +0200 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-04-25 09:01:16 +0000 |
commit | 3f9ee9cd5e3c79cb53b7c3f759ad78fb40a4fe62 (patch) | |
tree | 865522469966cfe3df3d72030403fc206d11a2da | |
parent | a9ba9b7a471ec09d6d76ec6abcce04aa9847a112 (diff) | |
download | gnome-shell-3f9ee9cd5e3c79cb53b7c3f759ad78fb40a4fe62.tar.gz |
dnd: Add addClickAction() method
The events that the draggable uses to initiate a drag operation
are the same as the ones a click action consumes for clicks.
It is still possible to combine the two, but it's finicky and far
from being straight-forward. To make this easier, add a dedicated
addClickAction() method to draggables that takes care of the
setup before adding the action to the draggable actor.
In the longer term, we'll want to turn DND into an action, and
have something like GTK's gesture group to allow combining actions
that would otherwise step on each other's toes.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2742>
-rw-r--r-- | js/ui/dnd.js | 44 | ||||
-rw-r--r-- | js/ui/windowPreview.js | 47 |
2 files changed, 54 insertions, 37 deletions
diff --git a/js/ui/dnd.js b/js/ui/dnd.js index 4ba724d1f..c9bce01f5 100644 --- a/js/ui/dnd.js +++ b/js/ui/dnd.js @@ -119,6 +119,50 @@ var _Draggable = class _Draggable extends Signals.EventEmitter { this._dragCancellable = true; } + /** + * addClickAction: + * + * @param {Clutter.ClickAction} action - click action to add to draggable actor + * + * Add @action to the draggable's actor, and set it up so that it does not + * impede drag operations. + */ + addClickAction(action) { + action.connect('clicked', () => (this._actionClicked = true)); + action.connect('long-press', (a, actor, state) => { + if (state !== Clutter.LongPressState.CANCEL) + return true; + + const event = Clutter.get_current_event(); + this._dragTouchSequence = event.get_event_sequence(); + + if (this._longPressLater) + return true; + + // A click cancels a long-press before any click handler is + // run - make sure to not start a drag in that case + const laters = global.compositor.get_laters(); + this._longPressLater = laters.add(Meta.LaterType.BEFORE_REDRAW, () => { + delete this._longPressLater; + if (this._actionClicked) { + delete this._actionClicked; + return GLib.SOURCE_REMOVE; + } + action.release(); + this.startDrag( + ...action.get_coords(), + event.get_time(), + this._dragTouchSequence, + event.get_device()); + + return GLib.SOURCE_REMOVE; + }); + return true; + }); + + this.actor.add_action(action); + } + _onButtonPress(actor, event) { if (event.get_button() != 1) return Clutter.EVENT_PROPAGATE; diff --git a/js/ui/windowPreview.js b/js/ui/windowPreview.js index ab851c6a7..599759a1b 100644 --- a/js/ui/windowPreview.js +++ b/js/ui/windowPreview.js @@ -98,15 +98,10 @@ var WindowPreview = GObject.registerClass({ this._updateAttachedDialogs(); - let clickAction = new Clutter.ClickAction(); - clickAction.connect('clicked', () => this._activate()); - clickAction.connect('long-press', this._onLongPress.bind(this)); - this.add_action(clickAction); this.connect('destroy', this._onDestroy.bind(this)); this._draggable = DND.makeDraggable(this, { restoreOnSuccess: true, - manualMode: true, dragActorMaxSize: WINDOW_DND_SIZE, dragActorOpacity: DRAGGING_WINDOW_OPACITY, }); @@ -115,7 +110,16 @@ var WindowPreview = GObject.registerClass({ this._draggable.connect('drag-end', this._onDragEnd.bind(this)); this.inDrag = false; - this._selected = false; + let clickAction = new Clutter.ClickAction(); + clickAction.connect('clicked', () => this._activate()); + clickAction.connect('long-press', (action, actor, state) => { + if (state === Clutter.LongPressState.ACTIVATE) + this.showOverlay(true); + return true; + }); + + this._draggable.addClickAction(clickAction); + this._overlayEnabled = true; this._overlayShown = false; this._closeRequested = false; @@ -545,7 +549,6 @@ var WindowPreview = GObject.registerClass({ } _activate() { - this._selected = true; this.emit('selected', global.get_current_time()); } @@ -607,36 +610,6 @@ var WindowPreview = GObject.registerClass({ return super.vfunc_key_press_event(keyEvent); } - _onLongPress(action, actor, state) { - // Take advantage of the Clutter policy to consider - // a long-press canceled when the pointer movement - // exceeds dnd-drag-threshold to manually start the drag - if (state == Clutter.LongPressState.CANCEL) { - let event = Clutter.get_current_event(); - this._dragTouchSequence = event.get_event_sequence(); - - if (this._longPressLater) - return true; - - // A click cancels a long-press before any click handler is - // run - make sure to not start a drag in that case - const laters = global.compositor.get_laters(); - this._longPressLater = laters.add(Meta.LaterType.BEFORE_REDRAW, () => { - delete this._longPressLater; - if (this._selected) { - this._selected = false; - return; - } - let [x, y] = action.get_coords(); - action.release(); - this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence, event.get_device()); - }); - } else { - this.showOverlay(true); - } - return true; - } - _restack() { // We may not have a parent if DnD completed successfully, in // which case our clone will shortly be destroyed and replaced |