dnd: Get dragging device from the triggering events
Instead of fetching the CLUTTER_POINTER_DEVICE device. It will be wrong if drags get initiated from tablet pointers. This allows for DnD operations to be started, moved, and more importantly finished through tablet devices. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/540
This commit is contained in:
parent
6845c6f958
commit
c2961f2152
64
js/ui/dnd.js
64
js/ui/dnd.js
@ -119,7 +119,7 @@ var _Draggable = class _Draggable {
|
|||||||
return Clutter.EVENT_PROPAGATE;
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
|
||||||
this._buttonDown = true;
|
this._buttonDown = true;
|
||||||
this._grabActor();
|
this._grabActor(event.get_device());
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
this._dragStartX = stageX;
|
this._dragStartX = stageX;
|
||||||
@ -136,10 +136,8 @@ var _Draggable = class _Draggable {
|
|||||||
if (Tweener.getTweenCount(actor))
|
if (Tweener.getTweenCount(actor))
|
||||||
return Clutter.EVENT_PROPAGATE;
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
|
||||||
this._touchSequence = event.get_event_sequence();
|
|
||||||
|
|
||||||
this._buttonDown = true;
|
this._buttonDown = true;
|
||||||
this._grabActor();
|
this._grabActor(event.get_device(), event.get_event_sequence());
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
this._dragStartX = stageX;
|
this._dragStartX = stageX;
|
||||||
@ -148,16 +146,14 @@ var _Draggable = class _Draggable {
|
|||||||
return Clutter.EVENT_PROPAGATE;
|
return Clutter.EVENT_PROPAGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_grabDevice(actor) {
|
_grabDevice(actor, pointer, touchSequence) {
|
||||||
let manager = Clutter.DeviceManager.get_default();
|
if (touchSequence)
|
||||||
let pointer = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
|
pointer.sequence_grab(touchSequence, actor);
|
||||||
|
|
||||||
if (pointer && this._touchSequence)
|
|
||||||
pointer.sequence_grab(this._touchSequence, actor);
|
|
||||||
else if (pointer)
|
else if (pointer)
|
||||||
pointer.grab (actor);
|
pointer.grab (actor);
|
||||||
|
|
||||||
this._grabbedDevice = pointer;
|
this._grabbedDevice = pointer;
|
||||||
|
this._touchSequence = touchSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ungrabDevice() {
|
_ungrabDevice() {
|
||||||
@ -170,8 +166,8 @@ var _Draggable = class _Draggable {
|
|||||||
this._grabbedDevice = null;
|
this._grabbedDevice = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_grabActor() {
|
_grabActor(device, touchSequence) {
|
||||||
this._grabDevice(this.actor);
|
this._grabDevice(this.actor, device, touchSequence);
|
||||||
this._onEventId = this.actor.connect('event',
|
this._onEventId = this.actor.connect('event',
|
||||||
this._onEvent.bind(this));
|
this._onEvent.bind(this));
|
||||||
}
|
}
|
||||||
@ -185,11 +181,11 @@ var _Draggable = class _Draggable {
|
|||||||
this._onEventId = null;
|
this._onEventId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_grabEvents() {
|
_grabEvents(device, touchSequence) {
|
||||||
if (!this._eventsGrabbed) {
|
if (!this._eventsGrabbed) {
|
||||||
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
|
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
|
||||||
if (this._eventsGrabbed)
|
if (this._eventsGrabbed)
|
||||||
this._grabDevice(_getEventHandlerActor());
|
this._grabDevice(_getEventHandlerActor(), device, touchSequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,14 +197,29 @@ var _Draggable = class _Draggable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_eventIsRelease(event) {
|
||||||
|
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
|
||||||
|
let buttonMask = (Clutter.ModifierType.BUTTON1_MASK |
|
||||||
|
Clutter.ModifierType.BUTTON2_MASK |
|
||||||
|
Clutter.ModifierType.BUTTON3_MASK);
|
||||||
|
/* We only obey the last button release from the device,
|
||||||
|
* other buttons may get pressed/released during the DnD op.
|
||||||
|
*/
|
||||||
|
return (event.get_state() & buttonMask) == 0;
|
||||||
|
} else if (event.type() == Clutter.EventType.TOUCH_END) {
|
||||||
|
/* For touch, we only obey the pointer emulating sequence */
|
||||||
|
return global.display.is_pointer_emulating_sequence(event.get_event_sequence());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
_onEvent(actor, event) {
|
_onEvent(actor, event) {
|
||||||
// We intercept BUTTON_RELEASE event to know that the button was released in case we
|
// We intercept BUTTON_RELEASE event to know that the button was released in case we
|
||||||
// didn't start the drag, to drop the draggable in case the drag was in progress, and
|
// didn't start the drag, to drop the draggable in case the drag was in progress, and
|
||||||
// to complete the drag and ensure that whatever happens to be under the pointer does
|
// to complete the drag and ensure that whatever happens to be under the pointer does
|
||||||
// not get triggered if the drag was cancelled with Esc.
|
// not get triggered if the drag was cancelled with Esc.
|
||||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE ||
|
if (this._eventIsRelease(event)) {
|
||||||
(event.type() == Clutter.EventType.TOUCH_END &&
|
|
||||||
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
|
|
||||||
this._buttonDown = false;
|
this._buttonDown = false;
|
||||||
if (this._dragState == DragState.DRAGGING) {
|
if (this._dragState == DragState.DRAGGING) {
|
||||||
return this._dragActorDropped(event);
|
return this._dragActorDropped(event);
|
||||||
@ -268,7 +279,19 @@ var _Draggable = class _Draggable {
|
|||||||
* This function is useful to call if you've specified manualMode
|
* This function is useful to call if you've specified manualMode
|
||||||
* for the draggable.
|
* for the draggable.
|
||||||
*/
|
*/
|
||||||
startDrag(stageX, stageY, time, sequence) {
|
startDrag(stageX, stageY, time, sequence, device) {
|
||||||
|
if (device == undefined) {
|
||||||
|
let event = Clutter.get_current_event();
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
device = event.get_device();
|
||||||
|
|
||||||
|
if (device == undefined) {
|
||||||
|
let manager = Clutter.DeviceManager.get_default();
|
||||||
|
device = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
currentDraggable = this;
|
currentDraggable = this;
|
||||||
this._dragState = DragState.DRAGGING;
|
this._dragState = DragState.DRAGGING;
|
||||||
|
|
||||||
@ -283,8 +306,7 @@ var _Draggable = class _Draggable {
|
|||||||
if (this._onEventId)
|
if (this._onEventId)
|
||||||
this._ungrabActor();
|
this._ungrabActor();
|
||||||
|
|
||||||
this._touchSequence = sequence;
|
this._grabEvents(device, sequence);
|
||||||
this._grabEvents();
|
|
||||||
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||||
|
|
||||||
this._dragX = this._dragStartX = stageX;
|
this._dragX = this._dragStartX = stageX;
|
||||||
@ -401,7 +423,7 @@ var _Draggable = class _Draggable {
|
|||||||
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
||||||
if ((Math.abs(stageX - this._dragStartX) > threshold ||
|
if ((Math.abs(stageX - this._dragStartX) > threshold ||
|
||||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||||
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence);
|
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence, event.get_device());
|
||||||
this._updateDragPosition(event);
|
this._updateDragPosition(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user