diff --git a/js/ui/dnd.js b/js/ui/dnd.js index 61776da91..a755057f1 100644 --- a/js/ui/dnd.js +++ b/js/ui/dnd.js @@ -87,6 +87,10 @@ _Draggable.prototype = { this.actor.connect('destroy', Lang.bind(this, function() { this._actorDestroyed = true; + // If the drag actor is destroyed and we were going to fix + // up its hover state, fix up the parent hover state instead + if (this.actor == this._firstLeaveActor) + this._firstLeaveActor = this._dragOrigParent; if (this._dragInProgress) this._cancelDrag(global.get_current_time()); this.disconnectAll(); @@ -101,6 +105,12 @@ _Draggable.prototype = { this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet. this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting). + // During the drag, we eat enter/leave events so that actors don't prelight or show + // tooltips. But we remember the actors that we first left/last entered so we can + // fix up the hover state after the drag ends. + this._firstLeaveActor = null; + this._lastEnterActor = null; + this._eventsGrabbed = false; }, @@ -200,6 +210,11 @@ _Draggable.prototype = { this._cancelDrag(event.get_time()); return true; } + } else if (event.type() == Clutter.EventType.LEAVE) { + if (this._firstLeaveActor == null) + this._firstLeaveActor = event.get_source(); + } else if (event.type() == Clutter.EventType.ENTER) { + this._lastEnterActor = event.get_source(); } return false; @@ -487,7 +502,7 @@ _Draggable.prototype = { if (this._actorDestroyed) { global.unset_cursor(); if (!this._buttonDown) - this._ungrabEvents(); + this._dragComplete(); this.emit('drag-end', eventTime, false); return; } @@ -544,12 +559,36 @@ _Draggable.prototype = { this._dragComplete(); }, + // Actor is an actor we have entered or left during the drag; call + // st_widget_sync_hover on all StWidget ancestors + _syncHover: function(actor) { + while (actor) { + let parent = actor.get_parent(); + if (actor instanceof St.Widget) + actor.sync_hover(); + + actor = parent; + } + }, + _dragComplete: function() { - Shell.util_set_hidden_from_pick(this._dragActor, false); + if (!this._actorDestroyed) + Shell.util_set_hidden_from_pick(this._dragActor, false); + + this._ungrabEvents(); + + if (this._firstLeaveActor) { + this._syncHover(this._firstLeaveActor); + this._firstLeaveActor = null; + } + + if (this._lastEnterActor) { + this._syncHover(this._lastEnterActor); + this._lastEnterActor = null; + } this._dragActor = undefined; currentDraggable = null; - this._ungrabEvents(); } };