From 75d1230dd16cf576bdfd00093b7ee3e9f95765cd Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Thu, 6 Jan 2011 20:21:27 +0100 Subject: [PATCH] AppSwitcher: Delay activating appIcons when the thumbnail list is open When aiming for the thumbnails with the mouse one might cross an icon by accident which causes the thumbnail list to be closed, which is frustrating. Fix this by delaying the icon activation when the thumbnail list is open. https://bugzilla.gnome.org/show_bug.cgi?id=636650 --- js/ui/altTab.js | 62 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/js/ui/altTab.js b/js/ui/altTab.js index aa0e7e246..a8d3e79ea 100644 --- a/js/ui/altTab.js +++ b/js/ui/altTab.js @@ -15,6 +15,8 @@ const POPUP_APPICON_SIZE = 96; const POPUP_SCROLL_TIME = 0.10; // seconds const POPUP_FADE_TIME = 0.1; // seconds +const APP_ICON_HOVER_TIMEOUT = 750; // milliseconds + const DISABLE_HOVER_TIMEOUT = 500; // milliseconds const THUMBNAIL_DEFAULT_SIZE = 256; @@ -50,6 +52,8 @@ AltTabPopup.prototype = { this._thumbnailTimeoutId = 0; this._motionTimeoutId = 0; + this.thumbnailsVisible = false; + // Initially disable hover so we ignore the enter-event if // the switcher appears underneath the current pointer location this._disableHover(); @@ -133,7 +137,7 @@ AltTabPopup.prototype = { this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside)); this.actor.connect('scroll-event', Lang.bind(this, this._onScroll)); - this._appSwitcher = new AppSwitcher(apps); + this._appSwitcher = new AppSwitcher(apps, this); this.actor.add_actor(this._appSwitcher.actor); this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated)); this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered)); @@ -457,11 +461,15 @@ AltTabPopup.prototype = { }, _destroyThumbnails : function() { - Tweener.addTween(this._thumbnails.actor, + let thumbnailsActor = this._thumbnails.actor; + Tweener.addTween(thumbnailsActor, { opacity: 0, time: THUMBNAIL_FADE_TIME, transition: 'easeOutQuad', - onComplete: function() { this.destroy(); } + onComplete: Lang.bind(this, function() { + thumbnailsActor.destroy(); + this.thumbnailsVisible = false; + }) }); this._thumbnails = null; }, @@ -477,7 +485,8 @@ AltTabPopup.prototype = { Tweener.addTween(this._thumbnails.actor, { opacity: 255, time: THUMBNAIL_FADE_TIME, - transition: 'easeOutQuad' + transition: 'easeOutQuad', + onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; }) }); } }; @@ -591,16 +600,20 @@ SwitcherList.prototype = { this._list.add_actor(bbox); let n = this._items.length; - bbox.connect('clicked', Lang.bind(this, function () { - this._itemActivated(n); - })); - bbox.connect('enter-event', Lang.bind(this, function () { - this._itemEntered(n); - })); + bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); })); + bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); })); this._items.push(bbox); }, + _onItemClicked: function (index) { + this._itemActivated(index); + }, + + _onItemEnter: function (index) { + this._itemEntered(index); + }, + addSeparator: function () { let box = new St.Bin({ style_class: 'separator' }); this._separator = box; @@ -819,14 +832,14 @@ AppIcon.prototype = { } }; -function AppSwitcher(apps) { - this._init(apps); +function AppSwitcher(apps, altTabPopup) { + this._init(apps, altTabPopup); } AppSwitcher.prototype = { __proto__ : SwitcherList.prototype, - _init : function(apps) { + _init : function(apps, altTabPopup) { SwitcherList.prototype._init.call(this, true); // Construct the AppIcons, sort by time, add to the popup @@ -858,6 +871,8 @@ AppSwitcher.prototype = { this._curApp = -1; this._iconSize = 0; + this._altTabPopup = altTabPopup; + this._mouseTimeOutId = 0; }, _getPreferredHeight: function (actor, forWidth, alloc) { @@ -922,6 +937,27 @@ AppSwitcher.prototype = { } }, + // We override SwitcherList's _onItemEnter method to delay + // activation when the thumbnail list is open + _onItemEnter: function (index) { + if (this._mouseTimeOutId != 0) + Mainloop.source_remove(this._mouseTimeOutId); + if (this._altTabPopup.thumbnailsVisible) { + this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT, + Lang.bind(this, function () { + this._enterItem(index); + })); + } else + this._itemEntered(index); + }, + + _enterItem: function(index) { + let [x, y, mask] = global.get_pointer(); + let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); + if (this._items[index].contains(pickedActor)) + this._itemEntered(index); + }, + // We override SwitcherList's highlight() method to also deal with // the AppSwitcher->ThumbnailList arrows. Apps with only 1 window // will hide their arrows by default, but show them when their