|
|
42f94a |
From e0414e7cc7cc9e997659f297637f35d9202b6dab Mon Sep 17 00:00:00 2001
|
|
|
42f94a |
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
|
|
42f94a |
Date: Tue, 5 Dec 2017 22:41:17 +0100
|
|
|
42f94a |
Subject: [PATCH] dnd: Nullify _dragActor after we've destroyed it, and avoid
|
|
|
42f94a |
invalid access
|
|
|
42f94a |
|
|
|
42f94a |
We need to avoid that we use the _dragActor instance after that it has
|
|
|
42f94a |
been destroyed or we'll get errors. We now set it to null when this
|
|
|
42f94a |
happens, protecting any access to that.
|
|
|
42f94a |
|
|
|
42f94a |
Add a DragState enum-like object to keep track of the state
|
|
|
42f94a |
instead of using booleans.
|
|
|
42f94a |
|
|
|
42f94a |
Remove duplicated handler on 'destroy' and just use a generic one.
|
|
|
42f94a |
|
|
|
42f94a |
https://bugzilla.gnome.org/show_bug.cgi?id=791233
|
|
|
42f94a |
---
|
|
|
42f94a |
js/ui/dnd.js | 65 +++++++++++++++++++++++++++++++---------------------
|
|
|
42f94a |
1 file changed, 39 insertions(+), 26 deletions(-)
|
|
|
42f94a |
|
|
|
42f94a |
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
|
|
|
42f94a |
index a38607c24..431c60d6c 100644
|
|
|
42f94a |
--- a/js/ui/dnd.js
|
|
|
42f94a |
+++ b/js/ui/dnd.js
|
|
|
42f94a |
@@ -27,6 +27,12 @@ var DragMotionResult = {
|
|
|
42f94a |
CONTINUE: 3
|
|
|
42f94a |
};
|
|
|
42f94a |
|
|
|
42f94a |
+var DragState = {
|
|
|
42f94a |
+ INIT: 0,
|
|
|
42f94a |
+ DRAGGING: 1,
|
|
|
42f94a |
+ CANCELLED: 2,
|
|
|
42f94a |
+};
|
|
|
42f94a |
+
|
|
|
42f94a |
var DRAG_CURSOR_MAP = {
|
|
|
42f94a |
0: Meta.Cursor.DND_UNSUPPORTED_TARGET,
|
|
|
42f94a |
1: Meta.Cursor.DND_COPY,
|
|
|
42f94a |
@@ -78,6 +84,8 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
dragActorOpacity: undefined });
|
|
|
42f94a |
|
|
|
42f94a |
this.actor = actor;
|
|
|
42f94a |
+ this._dragState = DragState.INIT;
|
|
|
42f94a |
+
|
|
|
42f94a |
if (!params.manualMode) {
|
|
|
42f94a |
this.actor.connect('button-press-event',
|
|
|
42f94a |
this._onButtonPress.bind(this));
|
|
|
42f94a |
@@ -88,7 +96,7 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
this.actor.connect('destroy', () => {
|
|
|
42f94a |
this._actorDestroyed = true;
|
|
|
42f94a |
|
|
|
42f94a |
- if (this._dragInProgress && this._dragCancellable)
|
|
|
42f94a |
+ if (this._dragState == DragState.DRAGGING && this._dragCancellable)
|
|
|
42f94a |
this._cancelDrag(global.get_current_time());
|
|
|
42f94a |
this.disconnectAll();
|
|
|
42f94a |
});
|
|
|
42f94a |
@@ -100,7 +108,6 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
this._dragActorOpacity = params.dragActorOpacity;
|
|
|
42f94a |
|
|
|
42f94a |
this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
|
|
|
42f94a |
- this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
|
|
42f94a |
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
|
|
|
42f94a |
this._dragCancellable = true;
|
|
|
42f94a |
|
|
|
42f94a |
@@ -206,9 +213,10 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
(event.type() == Clutter.EventType.TOUCH_END &&
|
|
|
42f94a |
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
|
|
|
42f94a |
this._buttonDown = false;
|
|
|
42f94a |
- if (this._dragInProgress) {
|
|
|
42f94a |
+ if (this._dragState == DragState.DRAGGING) {
|
|
|
42f94a |
return this._dragActorDropped(event);
|
|
|
42f94a |
- } else if (this._dragActor != null && !this._animationInProgress) {
|
|
|
42f94a |
+ } else if ((this._dragActor != null || this._dragState == DragState.CANCELLED) &&
|
|
|
42f94a |
+ !this._animationInProgress) {
|
|
|
42f94a |
// Drag must have been cancelled with Esc.
|
|
|
42f94a |
this._dragComplete();
|
|
|
42f94a |
return Clutter.EVENT_STOP;
|
|
|
42f94a |
@@ -222,14 +230,14 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
} else if (event.type() == Clutter.EventType.MOTION ||
|
|
|
42f94a |
(event.type() == Clutter.EventType.TOUCH_UPDATE &&
|
|
|
42f94a |
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
|
|
|
42f94a |
- if (this._dragInProgress) {
|
|
|
42f94a |
+ if (this._dragActor && this._dragState == DragState.DRAGGING) {
|
|
|
42f94a |
return this._updateDragPosition(event);
|
|
|
42f94a |
- } else if (this._dragActor == null) {
|
|
|
42f94a |
+ } else if (this._dragActor == null && this._dragState != DragState.CANCELLED) {
|
|
|
42f94a |
return this._maybeStartDrag(event);
|
|
|
42f94a |
}
|
|
|
42f94a |
// We intercept KEY_PRESS event so that we can process Esc key press to cancel
|
|
|
42f94a |
// dragging and ignore all other key presses.
|
|
|
42f94a |
- } else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragInProgress) {
|
|
|
42f94a |
+ } else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragState == DragState.DRAGGING) {
|
|
|
42f94a |
let symbol = event.get_key_symbol();
|
|
|
42f94a |
if (symbol == Clutter.Escape) {
|
|
|
42f94a |
this._cancelDrag(event.get_time());
|
|
|
42f94a |
@@ -265,7 +273,7 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
*/
|
|
|
42f94a |
startDrag(stageX, stageY, time, sequence) {
|
|
|
42f94a |
currentDraggable = this;
|
|
|
42f94a |
- this._dragInProgress = true;
|
|
|
42f94a |
+ this._dragState = DragState.DRAGGING;
|
|
|
42f94a |
|
|
|
42f94a |
// Special-case St.Button: the pointer grab messes with the internal
|
|
|
42f94a |
// state, so force a reset to a reasonable state here
|
|
|
42f94a |
@@ -342,6 +350,13 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
|
|
42f94a |
}
|
|
|
42f94a |
|
|
|
42f94a |
+ this._dragActorDestroyId = this._dragActor.connect('destroy', () => {
|
|
|
42f94a |
+ // Cancel ongoing animation (if any)
|
|
|
42f94a |
+ this._finishAnimation();
|
|
|
42f94a |
+
|
|
|
42f94a |
+ this._dragActor = null;
|
|
|
42f94a |
+ this._dragState = DragState.CANCELLED;
|
|
|
42f94a |
+ });
|
|
|
42f94a |
this._dragOrigOpacity = this._dragActor.opacity;
|
|
|
42f94a |
if (this._dragActorOpacity != undefined)
|
|
|
42f94a |
this._dragActor.opacity = this._dragActorOpacity;
|
|
|
42f94a |
@@ -500,7 +515,7 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
event.get_time())) {
|
|
|
42f94a |
// If it accepted the drop without taking the actor,
|
|
|
42f94a |
// handle it ourselves.
|
|
|
42f94a |
- if (this._dragActor.get_parent() == Main.uiGroup) {
|
|
|
42f94a |
+ if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {
|
|
|
42f94a |
if (this._restoreOnSuccess) {
|
|
|
42f94a |
this._restoreDragActor(event.get_time());
|
|
|
42f94a |
return true;
|
|
|
42f94a |
@@ -508,7 +523,7 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
this._dragActor.destroy();
|
|
|
42f94a |
}
|
|
|
42f94a |
|
|
|
42f94a |
- this._dragInProgress = false;
|
|
|
42f94a |
+ this._dragState = DragState.INIT;
|
|
|
42f94a |
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
|
|
42f94a |
this.emit('drag-end', event.get_time(), true);
|
|
|
42f94a |
this._dragComplete();
|
|
|
42f94a |
@@ -557,20 +572,22 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
|
|
|
42f94a |
_cancelDrag(eventTime) {
|
|
|
42f94a |
this.emit('drag-cancelled', eventTime);
|
|
|
42f94a |
- this._dragInProgress = false;
|
|
|
42f94a |
- let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
|
|
|
42f94a |
+ let wasCancelled = (this._dragState == DragState.CANCELLED);
|
|
|
42f94a |
+ this._dragState = DragState.CANCELLED;
|
|
|
42f94a |
|
|
|
42f94a |
- if (this._actorDestroyed) {
|
|
|
42f94a |
+ if (this._actorDestroyed || wasCancelled) {
|
|
|
42f94a |
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
|
|
42f94a |
if (!this._buttonDown)
|
|
|
42f94a |
this._dragComplete();
|
|
|
42f94a |
this.emit('drag-end', eventTime, false);
|
|
|
42f94a |
- if (!this._dragOrigParent)
|
|
|
42f94a |
+ if (!this._dragOrigParent && this._dragActor)
|
|
|
42f94a |
this._dragActor.destroy();
|
|
|
42f94a |
|
|
|
42f94a |
return;
|
|
|
42f94a |
}
|
|
|
42f94a |
|
|
|
42f94a |
+ let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
|
|
|
42f94a |
+
|
|
|
42f94a |
this._animateDragEnd(eventTime,
|
|
|
42f94a |
{ x: snapBackX,
|
|
|
42f94a |
y: snapBackY,
|
|
|
42f94a |
@@ -581,7 +598,7 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
},
|
|
|
42f94a |
|
|
|
42f94a |
_restoreDragActor(eventTime) {
|
|
|
42f94a |
- this._dragInProgress = false;
|
|
|
42f94a |
+ this._dragState = DragState.INIT;
|
|
|
42f94a |
let [restoreX, restoreY, restoreScale] = this._getRestoreLocation();
|
|
|
42f94a |
|
|
|
42f94a |
// fade the actor back in at its original location
|
|
|
42f94a |
@@ -596,12 +613,6 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
_animateDragEnd(eventTime, params) {
|
|
|
42f94a |
this._animationInProgress = true;
|
|
|
42f94a |
|
|
|
42f94a |
- // finish animation if the actor gets destroyed
|
|
|
42f94a |
- // during it
|
|
|
42f94a |
- this._dragActorDestroyId =
|
|
|
42f94a |
- this._dragActor.connect('destroy',
|
|
|
42f94a |
- this._finishAnimation.bind(this));
|
|
|
42f94a |
-
|
|
|
42f94a |
params['opacity'] = this._dragOrigOpacity;
|
|
|
42f94a |
params['transition'] = 'easeOutQuad';
|
|
|
42f94a |
params['onComplete'] = this._onAnimationComplete;
|
|
|
42f94a |
@@ -624,9 +635,6 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
},
|
|
|
42f94a |
|
|
|
42f94a |
_onAnimationComplete(dragActor, eventTime) {
|
|
|
42f94a |
- dragActor.disconnect(this._dragActorDestroyId);
|
|
|
42f94a |
- this._dragActorDestroyId = 0;
|
|
|
42f94a |
-
|
|
|
42f94a |
if (this._dragOrigParent) {
|
|
|
42f94a |
Main.uiGroup.remove_child(this._dragActor);
|
|
|
42f94a |
this._dragOrigParent.add_actor(this._dragActor);
|
|
|
42f94a |
@@ -641,7 +649,7 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
},
|
|
|
42f94a |
|
|
|
42f94a |
_dragComplete() {
|
|
|
42f94a |
- if (!this._actorDestroyed)
|
|
|
42f94a |
+ if (!this._actorDestroyed && this._dragActor)
|
|
|
42f94a |
Shell.util_set_hidden_from_pick(this._dragActor, false);
|
|
|
42f94a |
|
|
|
42f94a |
this._ungrabEvents();
|
|
|
42f94a |
@@ -652,7 +660,12 @@ var _Draggable = new Lang.Class({
|
|
|
42f94a |
this._updateHoverId = 0;
|
|
|
42f94a |
}
|
|
|
42f94a |
|
|
|
42f94a |
- this._dragActor = undefined;
|
|
|
42f94a |
+ if (this._dragActor) {
|
|
|
42f94a |
+ this._dragActor.disconnect(this._dragActorDestroyId);
|
|
|
42f94a |
+ this._dragActor = null;
|
|
|
42f94a |
+ }
|
|
|
42f94a |
+
|
|
|
42f94a |
+ this._dragState = DragState.INIT;
|
|
|
42f94a |
currentDraggable = null;
|
|
|
42f94a |
}
|
|
|
42f94a |
});
|
|
|
42f94a |
--
|
|
|
42f94a |
2.19.1
|
|
|
42f94a |
|