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>
This commit is contained in:
parent
a9ba9b7a47
commit
3f9ee9cd5e
44
js/ui/dnd.js
44
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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user