Fix lock up when dropping icon on dash

Resolves: #1630134
This commit is contained in:
Ray Strode 2018-09-19 12:55:03 -04:00
parent 083ac56809
commit b87281edcb
2 changed files with 234 additions and 1 deletions

View File

@ -0,0 +1,227 @@
From 82c72f377a91cfa75fed1102f92ff4685c7e74da Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 19 Sep 2018 11:47:35 -0400
Subject: [PATCH] dnd: don't try to access destroyed dragActor
The dragComplete handler incorrectly checks
this._actorDestroyed to see if the drag actor
is destroyed. The drag actor may not be the same
as the main actor.
The end result is an exception in drop handling,
leading to a shell lockup.
This commit changes the code to always set
this._dragActor to undefined when it's destroyed,
and check for that condition instead of
this._actorDestroyed in the dragComplete handler.
Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/577
---
js/ui/dnd.js | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index 634a7d6d7..6c563a3ba 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -479,121 +479,124 @@ var _Draggable = new Lang.Class({
switch (dropFunc(dropEvent)) {
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
return true;
case DragDropResult.CONTINUE:
continue;
}
}
// At this point it is too late to cancel a drag by destroying
// the actor, the fate of which is decided by acceptDrop and its
// side-effects
this._dragCancellable = false;
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [r, targX, targY] = target.transform_stage_point(dropX, dropY);
if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor,
targX,
targY,
event.get_time())) {
// If it accepted the drop without taking the actor,
// handle it ourselves.
if (this._dragActor.get_parent() == Main.uiGroup) {
if (this._restoreOnSuccess) {
this._restoreDragActor(event.get_time());
return true;
} else
this._dragActor.destroy();
+ this._dragActor = undefined;
}
this._dragInProgress = false;
global.display.set_cursor(Meta.Cursor.DEFAULT);
this.emit('drag-end', event.get_time(), true);
this._dragComplete();
return true;
}
}
target = target.get_parent();
}
this._cancelDrag(event.get_time());
return true;
},
_getRestoreLocation() {
let x, y, scale;
if (this._dragActorSource && this._dragActorSource.visible) {
// Snap the clone back to its source
[x, y] = this._dragActorSource.get_transformed_position();
let [sourceScaledWidth, sourceScaledHeight] = this._dragActorSource.get_transformed_size();
scale = sourceScaledWidth ? this._dragActor.width / sourceScaledWidth : 0;
} else if (this._dragOrigParent) {
// Snap the actor back to its original position within
// its parent, adjusting for the fact that the parent
// may have been moved or scaled
let [parentX, parentY] = this._dragOrigParent.get_transformed_position();
let [parentWidth, parentHeight] = this._dragOrigParent.get_size();
let [parentScaledWidth, parentScaledHeight] = this._dragOrigParent.get_transformed_size();
let parentScale = 1.0;
if (parentWidth != 0)
parentScale = parentScaledWidth / parentWidth;
x = parentX + parentScale * this._dragOrigX;
y = parentY + parentScale * this._dragOrigY;
scale = this._dragOrigScale * parentScale;
} else {
// Snap back actor to its original stage position
x = this._snapBackX;
y = this._snapBackY;
scale = this._snapBackScale;
}
return [x, y, scale];
},
_cancelDrag(eventTime) {
this.emit('drag-cancelled', eventTime);
this._dragInProgress = false;
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
if (this._actorDestroyed) {
global.display.set_cursor(Meta.Cursor.DEFAULT);
if (!this._buttonDown)
this._dragComplete();
this.emit('drag-end', eventTime, false);
- if (!this._dragOrigParent)
+ if (!this._dragOrigParent) {
this._dragActor.destroy();
+ this._dragActor = undefined;
+ }
return;
}
this._animateDragEnd(eventTime,
{ x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
time: SNAP_BACK_ANIMATION_TIME,
});
},
_restoreDragActor(eventTime) {
this._dragInProgress = false;
let [restoreX, restoreY, restoreScale] = this._getRestoreLocation();
// fade the actor back in at its original location
this._dragActor.set_position(restoreX, restoreY);
this._dragActor.set_scale(restoreScale, restoreScale);
this._dragActor.opacity = 0;
this._animateDragEnd(eventTime,
{ time: REVERT_ANIMATION_TIME });
},
_animateDragEnd(eventTime, params) {
this._animationInProgress = true;
// finish animation if the actor gets destroyed
@@ -607,68 +610,69 @@ var _Draggable = new Lang.Class({
params['onComplete'] = this._onAnimationComplete;
params['onCompleteScope'] = this;
params['onCompleteParams'] = [this._dragActor, eventTime];
// start the animation
Tweener.addTween(this._dragActor, params)
},
_finishAnimation() {
if (!this._animationInProgress)
return
this._animationInProgress = false;
if (!this._buttonDown)
this._dragComplete();
global.display.set_cursor(Meta.Cursor.DEFAULT);
},
_onAnimationComplete(dragActor, eventTime) {
dragActor.disconnect(this._dragActorDestroyId);
this._dragActorDestroyId = 0;
if (this._dragOrigParent) {
Main.uiGroup.remove_child(this._dragActor);
this._dragOrigParent.add_actor(this._dragActor);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
dragActor.set_position(this._dragOrigX, this._dragOrigY);
} else {
dragActor.destroy();
+ this._dragActor = undefined;
}
this.emit('drag-end', eventTime, false);
this._finishAnimation();
},
_dragComplete() {
- if (!this._actorDestroyed)
+ if (this._dragActor)
Shell.util_set_hidden_from_pick(this._dragActor, false);
this._ungrabEvents();
global.sync_pointer();
if (this._updateHoverId) {
GLib.source_remove(this._updateHoverId);
this._updateHoverId = 0;
}
this._dragActor = undefined;
currentDraggable = null;
}
});
Signals.addSignalMethods(_Draggable.prototype);
/**
* makeDraggable:
* @actor: Source actor
* @params: (optional) Additional parameters
*
* Create an object which controls drag and drop for the given actor.
*
* If %manualMode is %true in @params, do not automatically start
* drag and drop on click
*
* If %dragActorMaxSize is present in @params, the drag actor will
* be scaled down to be no larger than that size in pixels.
*
--
2.17.1

View File

@ -1,6 +1,6 @@
Name: gnome-shell
Version: 3.30.0
Release: 4%{?dist}
Release: 5%{?dist}
Summary: Window management and application launching for GNOME
Group: User Interface/Desktops
@ -20,6 +20,8 @@ Patch2: 0001-network-Don-t-assume-the-active-connection-has-been-.patch
# https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/240
Patch3: 0001-Fix-connection-to-wifi-APs-from-user-menu-RH-1628263.patch
Patch4: 0001-dnd-don-t-try-to-access-destroyed-dragActor.patch
%define libcroco_version 0.6.8
%define eds_version 3.17.2
%define gnome_desktop_version 3.7.90
@ -215,6 +217,10 @@ glib-compile-schemas --allow-any-name %{_datadir}/glib-2.0/schemas &> /dev/null
%{_mandir}/man1/%{name}.1.gz
%changelog
* Wed Sep 19 2018 Ray Strode <rstrode@redhat.com> - 3.30.0-5
- Fix lock up when dropping icon on dash
Resolves: #1630134
* Tue Sep 18 2018 Adam Williamson <awilliam@redhat.com> - 3.30.0-4
- Fix connecting to wifi from user menu (RHBZ #1628263)