dnd: Repick target actor if destroyed mid iteration
The picked target actor may be destroyed (e.g. hover style change resulting in the ClutterTexture to be destroyed). If we don't handle this, GJS will abort when it sees the exception caused by Javascript code trying to access the destroyed target actor. To handle it, listen on the 'destroy' signal on the target actor, and repick, so a valid actor is passed to the next motion callback. Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/632
This commit is contained in:
parent
2159d6886f
commit
4259676f6e
22
js/ui/dnd.js
22
js/ui/dnd.js
@ -411,10 +411,15 @@ var _Draggable = new Lang.Class({
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_pickTargetActor() {
|
||||||
|
return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
||||||
|
this._dragX, this._dragY);
|
||||||
|
},
|
||||||
|
|
||||||
_updateDragHover() {
|
_updateDragHover() {
|
||||||
this._updateHoverId = 0;
|
this._updateHoverId = 0;
|
||||||
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
let target = this._pickTargetActor();
|
||||||
this._dragX, this._dragY);
|
|
||||||
let dragEvent = {
|
let dragEvent = {
|
||||||
x: this._dragX,
|
x: this._dragX,
|
||||||
y: this._dragY,
|
y: this._dragY,
|
||||||
@ -422,6 +427,18 @@ var _Draggable = new Lang.Class({
|
|||||||
source: this.actor._delegate,
|
source: this.actor._delegate,
|
||||||
targetActor: target
|
targetActor: target
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let targetActorDestroyHandlerId;
|
||||||
|
let handleTargetActorDestroyClosure;
|
||||||
|
handleTargetActorDestroyClosure = () => {
|
||||||
|
target = this._pickTargetActor();
|
||||||
|
dragEvent.targetActor = target;
|
||||||
|
targetActorDestroyHandlerId =
|
||||||
|
target.connect('destroy', handleTargetActorDestroyClosure);
|
||||||
|
};
|
||||||
|
targetActorDestroyHandlerId =
|
||||||
|
target.connect('destroy', handleTargetActorDestroyClosure);
|
||||||
|
|
||||||
for (let i = 0; i < dragMonitors.length; i++) {
|
for (let i = 0; i < dragMonitors.length; i++) {
|
||||||
let motionFunc = dragMonitors[i].dragMotion;
|
let motionFunc = dragMonitors[i].dragMotion;
|
||||||
if (motionFunc) {
|
if (motionFunc) {
|
||||||
@ -432,6 +449,7 @@ var _Draggable = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dragEvent.targetActor.disconnect(targetActorDestroyHandlerId);
|
||||||
|
|
||||||
while (target) {
|
while (target) {
|
||||||
if (target._delegate && target._delegate.handleDragOver) {
|
if (target._delegate && target._delegate.handleDragOver) {
|
||||||
|
Loading…
Reference in New Issue
Block a user