[gnome-shell/wip/rstrode/rhel-8.0.0: 34/50] dnd: Repick target actor if destroyed mid iteration
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/rstrode/rhel-8.0.0: 34/50] dnd: Repick target actor if destroyed mid iteration
- Date: Sun, 17 Feb 2019 17:31:42 +0000 (UTC)
commit a77b7447d73398a4d2b05489b09f51c37b0f41ac
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Thu Jan 3 11:53:13 2019 +0100
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
js/ui/dnd.js | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
---
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index 431c60d6c..9e961a186 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -411,10 +411,15 @@ var _Draggable = new Lang.Class({
return true;
},
+ _pickTargetActor() {
+ return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
+ this._dragX, this._dragY);
+ },
+
_updateDragHover() {
this._updateHoverId = 0;
- let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
- this._dragX, this._dragY);
+ let target = this._pickTargetActor();
+
let dragEvent = {
x: this._dragX,
y: this._dragY,
@@ -422,6 +427,18 @@ var _Draggable = new Lang.Class({
source: this.actor._delegate,
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++) {
let motionFunc = dragMonitors[i].dragMotion;
if (motionFunc) {
@@ -432,6 +449,7 @@ var _Draggable = new Lang.Class({
}
}
}
+ dragEvent.targetActor.disconnect(targetActorDestroyHandlerId);
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]