altTab: Update the switcher when apps and/or windows get stopped/closed

Make sure that the items from the applications switcher and the windows
switcher are removed when the related applications get stopped, or some
of the associated windows closed.

https://bugzilla.gnome.org/show_bug.cgi?id=620106
This commit is contained in:
Florian Müllner 2018-02-08 10:38:04 +00:00 committed by Florian Müllner
parent f2d12e22b5
commit 5122b06839
2 changed files with 71 additions and 6 deletions

View File

@ -252,7 +252,7 @@ var AppSwitcherPopup = new Lang.Class({
let appIcon = this._items[this._selectedIndex]; let appIcon = this._items[this._selectedIndex];
if (this._currentWindow < 0) if (this._currentWindow < 0)
appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp); appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp);
else else if (appIcon.cachedWindows[this._currentWindow])
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp); Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
this.parent(); this.parent();
@ -343,13 +343,18 @@ var AppSwitcherPopup = new Lang.Class({
}) })
}); });
this._thumbnails = null; this._thumbnails = null;
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED); if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
}, },
_createThumbnails : function() { _createThumbnails : function() {
this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows); this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
this._thumbnails.connect('item-activated', Lang.bind(this, this._windowActivated)); this._thumbnails.connect('item-activated', Lang.bind(this, this._windowActivated));
this._thumbnails.connect('item-entered', Lang.bind(this, this._windowEntered)); this._thumbnails.connect('item-entered', Lang.bind(this, this._windowEntered));
this._thumbnails.actor.connect('destroy', () => {
this._thumbnails = null;
this._thumbnailsFocused = false;
});
this.actor.add_actor(this._thumbnails.actor); this.actor.add_actor(this._thumbnails.actor);
@ -645,6 +650,10 @@ var AppSwitcher = new Lang.Class({
_onDestroy: function() { _onDestroy: function() {
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId); Mainloop.source_remove(this._mouseTimeOutId);
this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId);
});
}, },
_setIconSize: function() { _setIconSize: function() {
@ -745,7 +754,7 @@ var AppSwitcher = new Lang.Class({
// show a dim arrow, but show a bright arrow when they are // show a dim arrow, but show a bright arrow when they are
// highlighted. // highlighted.
highlight : function(n, justOutline) { highlight : function(n, justOutline) {
if (this._curApp != -1) { if (this.icons[this._curApp]) {
if (this.icons[this._curApp].cachedWindows.length == 1) if (this.icons[this._curApp].cachedWindows.length == 1)
this._arrows[this._curApp].hide(); this._arrows[this._curApp].hide();
else else
@ -767,6 +776,11 @@ var AppSwitcher = new Lang.Class({
this.icons.push(appIcon); this.icons.push(appIcon);
let item = this.addItem(appIcon.actor, appIcon.label); let item = this.addItem(appIcon.actor, appIcon.label);
appIcon._stateChangedId = appIcon.app.connect('notify::state', app => {
if (app.state != Shell.AppState.RUNNING)
this._removeIcon(app);
});
let n = this._arrows.length; let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' }); let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', function() { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); }); arrow.connect('repaint', function() { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
@ -777,7 +791,25 @@ var AppSwitcher = new Lang.Class({
arrow.hide(); arrow.hide();
else else
item.add_accessible_state (Atk.StateType.EXPANDABLE); item.add_accessible_state (Atk.StateType.EXPANDABLE);
} },
_removeIcon: function(app) {
let index = this.icons.findIndex(icon => {
return icon.app == app;
});
if (index === -1)
return;
this.icons.splice(index, 1);
this.removeItem(index);
if (this._curApp == index)
this._curApp = SwitcherPopup.mod(index, this.icons.length);
if (this.icons.length > 0)
this.highlight(this._curApp);
else
this.actor.destroy();
},
}); });
var ThumbnailList = new Lang.Class({ var ThumbnailList = new Lang.Class({
@ -816,6 +848,8 @@ var ThumbnailList = new Lang.Class({
} }
} }
this.actor.connect('destroy', this._onDestroy.bind(this));
}, },
addClones : function (availHeight) { addClones : function (availHeight) {
@ -840,12 +874,38 @@ var ThumbnailList = new Lang.Class({
let clone = _createWindowClone(mutterWindow, thumbnailSize); let clone = _createWindowClone(mutterWindow, thumbnailSize);
this._thumbnailBins[i].set_height(binHeight); this._thumbnailBins[i].set_height(binHeight);
this._thumbnailBins[i].add_actor(clone); this._thumbnailBins[i].add_actor(clone);
clone._destroyId = mutterWindow.connect('destroy', Lang.bind(this, this._removeThumbnail, clone));
this._clones.push(clone); this._clones.push(clone);
} }
// Make sure we only do this once // Make sure we only do this once
this._thumbnailBins = new Array(); this._thumbnailBins = new Array();
} },
_removeThumbnail: function(source, clone) {
let index = this._clones.indexOf(clone);
if (index === -1)
return;
this._clones.splice(index, 1);
this._windows.splice(index, 1);
this._labels.splice(index, 1);
this.removeItem(index);
if (this._clones.length > 0)
this.highlight(SwitcherPopup.mod(index, this._clones.length));
else
this.actor.destroy();
},
_onDestroy: function() {
this._clones.forEach(clone => {
if (clone.source)
clone.source.disconnect(clone._destroyId);
});
},
}); });
var WindowIcon = new Lang.Class({ var WindowIcon = new Lang.Class({

View File

@ -418,6 +418,11 @@ var SwitcherList = new Lang.Class({
return bbox; return bbox;
}, },
removeItem: function(index) {
let item = this._items.splice(index, 1);
item[0].destroy();
},
_onItemClicked: function (index) { _onItemClicked: function (index) {
this._itemActivated(index); this._itemActivated(index);
}, },
@ -432,7 +437,7 @@ var SwitcherList = new Lang.Class({
}, },
highlight: function(index, justOutline) { highlight: function(index, justOutline) {
if (this._highlighted != -1) { if (this._items[this._highlighted]) {
this._items[this._highlighted].remove_style_pseudo_class('outlined'); this._items[this._highlighted].remove_style_pseudo_class('outlined');
this._items[this._highlighted].remove_style_pseudo_class('selected'); this._items[this._highlighted].remove_style_pseudo_class('selected');
} }