diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js index 1a12a801bc..bd249cde37 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/appGroup.js @@ -61,6 +61,17 @@ const getFocusState = function(metaWindow) { return false; }; +const getLastFocusedWindow = function(metaWindows) { + let lastFocusedWindow = null; + for (let i = 0; i < metaWindows.length; i++) { + const metaWindow = metaWindows[i]; + if (!lastFocusedWindow || (metaWindow.get_user_time() > lastFocusedWindow.get_user_time())) { + lastFocusedWindow = metaWindow; + } + } + return lastFocusedWindow; +}; + var AppGroup = class AppGroup { constructor(params) { this.state = params.state; @@ -86,7 +97,7 @@ var AppGroup = class AppGroup { pressed: true }); - this.groupState.connect({ + this.groupStateConnectionId = this.groupState.connect({ isFavoriteApp: () => this.handleFavorite(true), getActor: () => this.actor, launchNewInstance: (...args) => this.launchNewInstance(...args), @@ -642,7 +653,7 @@ var AppGroup = class AppGroup { const {appId, metaWindows, lastFocused} = this.groupState; if (hasFocus === undefined) { - hasFocus = this.workspaceState.lastFocusedApp === appId; + hasFocus = this.workspaceState.lastFocusedApp === appId && getFocusState(lastFocused); } // If any of the windows associated with our app have focus, @@ -985,32 +996,31 @@ var AppGroup = class AppGroup { } windowRemoved(metaWorkspace, metaWindow, refWindow, cb) { - if (refWindow === -1) return; + if (!metaWindow) return; this.signals.disconnect('notify::title', metaWindow); this.signals.disconnect('notify::appears-focused', metaWindow); + this.signals.disconnect('notify::icon', metaWindow); + this.signals.disconnect('notify::progress', metaWindow); - this.groupState.metaWindows.splice(refWindow, 1); + const metaWindows = this.groupState.metaWindows.filter((w) => w != metaWindow); if (this.progressOverlay.visible) this.onProgressChange(); - if (this.groupState.metaWindows.length > 0 && !this.groupState.willUnmount) { - this.onWindowTitleChanged(this.groupState.lastFocused); - this.groupState.set({ - metaWindows: this.groupState.metaWindows, - lastFocused: this.groupState.metaWindows[this.groupState.metaWindows.length - 1] - }, true); - if (this.hoverMenu) this.groupState.trigger('removeThumbnailFromMenu', metaWindow); - this.calcWindowNumber(); - } else { - // This is the last window, so this group needs to be destroyed. We'll call back windowRemoved - // in workspace to put the final nail in the coffin. - if (typeof cb === 'function') { - if (this.hoverMenu && this.groupState.isFavoriteApp) { - this.groupState.trigger('removeThumbnailFromMenu', metaWindow); - } - cb(this.groupState.appId, this.groupState.isFavoriteApp); - } + const lastFocused = this.groupState.lastFocused === metaWindow + ? getLastFocusedWindow(metaWindows) + : this.groupState.lastFocused; + + this.groupState.set({metaWindows: metaWindows, lastFocused: lastFocused}, true); + + if (lastFocused) this.onWindowTitleChanged(lastFocused); + + if (this.hoverMenu) this.groupState.trigger('removeThumbnailFromMenu', metaWindow); + + this.calcWindowNumber(); + + if ((metaWindows.length === 0 || this.groupState.willUnmount) && typeof cb === 'function') { + cb(this.groupState.appId, this.groupState.isFavoriteApp); } } @@ -1123,10 +1133,12 @@ var AppGroup = class AppGroup { calcWindowNumber() { if (this.groupState.willUnmount) return; - this.groupState.set({windowCount: this.groupState.metaWindows ? this.groupState.metaWindows.length : 0}); - - if (this.groupState.windowCount > 1 && this.state.settings.enableWindowCountBadges) { - this.windowsBadgeLabel.text = this.groupState.windowCount.toString(); + const windowCount = this.groupState.metaWindows ? this.groupState.metaWindows.length : 0; + + this.groupState.set({windowCount: windowCount}); + + if (windowCount > 1 && this.state.settings.enableWindowCountBadges) { + this.windowsBadgeLabel.text = windowCount.toString(); this.windowsBadge.show(); } else { this.windowsBadge.hide(); @@ -1196,6 +1208,9 @@ var AppGroup = class AppGroup { } destroy(skipRefCleanup) { + if (this.groupStateConnectionId) { + this.groupState.disconnect(this.groupStateConnectionId); + } this.signals.disconnectAllSignals(); this.groupState.set({willUnmount: true}); diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js index ba61cc1af5..ae2708e244 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/applet.js @@ -208,7 +208,7 @@ class GroupedWindowListApplet extends Applet.Applet { // applet to avoid passing down the parent class down the constructor chain and creating circular references. // In addition to manual event emitting, store.js can emit updates on property changes when set through // store.set. Any keys emitted through store.trigger that are not declared here first will throw an error. - this.state.connect({ + this.stateConnectionId = this.state.connect({ setSettingsValue: (k, v) => this.settings.setValue(k, v), getPanel: () => (this.panel ? this.panel : null), getPanelHeight: () => this._panelHeight, @@ -428,6 +428,9 @@ class GroupedWindowListApplet extends Applet.Applet { workspace.destroy(); } }); + if (this.stateConnectionId) { + this.state.disconnect(this.stateConnectionId); + } this.settings.finalize(); unref(this, RESERVE_KEYS); MessageTray.extensionsHandlingNotifications--; @@ -445,13 +448,13 @@ class GroupedWindowListApplet extends Applet.Applet { return false; } - onWindowMonitorChanged(display, metaWindow, metaWorkspace) { - if (this.state.monitorWatchList.length !== this.numberOfMonitors) { - const currentWorkspace = this.getCurrentWorkspace(); - if (currentWorkspace !== null) { - currentWorkspace.windowRemoved(metaWorkspace, metaWindow); - currentWorkspace.windowAdded(metaWorkspace, metaWindow); - } + onWindowMonitorChanged(display, metaWindow, monitor) { + if ((this.state.monitorWatchList.length !== this.numberOfMonitors)) { + this.workspaces.forEach( workspace => { + if (!workspace) return; + workspace.windowRemoved(workspace.metaWorkspace, metaWindow); + workspace.windowAdded(workspace.metaWorkspace, metaWindow); + }); } } @@ -620,21 +623,8 @@ class GroupedWindowListApplet extends Applet.Applet { } updateTitleDisplay(titleDisplay) { - if (titleDisplay === TitleDisplay.None - || this.state.lastTitleDisplay === TitleDisplay.None) { - this.refreshCurrentWorkspace(); - } - - this.workspaces.forEach( workspace => { - workspace.appGroups.forEach( appGroup => { - if (titleDisplay === TitleDisplay.Focused) { - appGroup.hideLabel(); - } - appGroup.handleTitleDisplayChange(); - }); - }); - this.state.set({lastTitleDisplay: titleDisplay}); + this.refreshAllWorkspaces(); } getAppFromWindow(metaWindow) { @@ -779,7 +769,7 @@ class GroupedWindowListApplet extends Applet.Applet { currentWorkspace.appGroups[z].groupState.lastFocused : source.groupState.metaWindows[z]; Main.activateWindow(_window, global.get_current_time()); - setTimeout(() => this.state.set({scrollActive: false}, 4000)); + setTimeout(() => this.state.set({scrollActive: false}), 4000); } } @@ -1027,7 +1017,6 @@ class GroupedWindowListApplet extends Applet.Applet { _onWindowAppChanged(tracker, metaWindow) { if (!metaWindow) return; - this.workspaces.forEach(workspace => { if (!workspace) return; workspace.windowRemoved(workspace.metaWorkspace, metaWindow); @@ -1042,7 +1031,7 @@ class GroupedWindowListApplet extends Applet.Applet { _onNotificationReceived(mtray, notification) { let appId = notification.source.app?.get_id(); - + if (!appId) { return; } diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/workspace.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/workspace.js index ff25863aa3..e98d70fd5e 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/workspace.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/workspace.js @@ -11,7 +11,7 @@ const {RESERVE_KEYS} = Me.imports.constants; var Workspace = class Workspace { constructor(params) { this.state = params.state; - this.state.connect({ + this.stateConnectionId = this.state.connect({ orientation: () => this.on_orientation_changed(false) }); this.workspaceState = createStore({ @@ -234,14 +234,19 @@ var Workspace = class Workspace { shouldWindowBeAdded(metaWindow) { return (this.state.settings.showAllWorkspaces - || metaWindow.is_on_all_workspaces() - || metaWindow.get_workspace() === this.metaWorkspace) + || metaWindow.is_on_all_workspaces() + || (metaWindow.get_workspace().index() === this.metaWorkspace.index())) && Main.isInteresting(metaWindow) && this.state.monitorWatchList.indexOf(metaWindow.get_monitor()) > -1; } - windowWorkspaceChanged(display, metaWorkspace, metaWindow) { - this.windowAdded(metaWindow, metaWorkspace); + windowWorkspaceChanged(display, metaWindow, metaWorkspace) { + // If the window is removed the metaWorkspace will be null. + if (metaWorkspace) { + this.windowAdded(metaWorkspace, metaWindow); + } else { + this.windowRemoved(metaWorkspace, metaWindow); + } } windowAdded(metaWorkspace, metaWindow, app, isFavoriteApp) { @@ -352,15 +357,16 @@ var Workspace = class Workspace { windowRemoved(metaWorkspace, metaWindow) { if (!this.state) return; - if ((metaWindow.is_on_all_workspaces() || this.state.settings.showAllWorkspaces - || !this.state.settings.showAllWorkspaces) + // Abort the remove if the window is just changing workspaces, window + // should always remain indexed on all workspaces while its mapped. + if (this.state.settings.showAllWorkspaces && !this.state.removingWindowFromWorkspaces && + metaWindow.has_focus() && (global.workspace_manager.get_active_workspace_index() !== metaWorkspace.index())) + return; + + // If the window is on all workspaces or we're showing windows in all workspaces, + // make sure to remove the window from all workspaces. + if ((metaWindow.is_on_all_workspaces() || this.state.settings.showAllWorkspaces) && !this.state.removingWindowFromWorkspaces) { - // Abort the remove if the window is just changing workspaces, window - // should always remain indexed on all workspaces while its mapped. - // if (!metaWindow.showing_on_its_workspace()) return; - if ((this.state.settings.showAllWorkspaces) && (metaWindow.has_focus() - && global.workspace_manager.get_active_workspace_index() - !== metaWorkspace.index())) return; this.state.removingWindowFromWorkspaces = true; this.state.trigger('removeWindowFromAllWorkspaces', metaWindow); return; @@ -392,7 +398,7 @@ var Workspace = class Workspace { const refAppId = this.appGroups[refApp].groupState.appId; - this.appGroups[refApp].destroy(true); + this.appGroups[refApp].destroy(); this.appGroups[refApp] = undefined; this.appGroups.splice(refApp, 1); @@ -412,7 +418,7 @@ var Workspace = class Workspace { } } } else { - this.appGroups[refApp].destroy(true); + this.appGroups[refApp].destroy(); this.appGroups[refApp] = undefined; this.appGroups.splice(refApp, 1); } @@ -421,6 +427,9 @@ var Workspace = class Workspace { } destroy() { + if (this.stateConnectionId) { + this.state.disconnect(this.stateConnectionId); + } this.signals.disconnectAllSignals(); this.appGroups.forEach( appGroup => appGroup.destroy() ); this.workspaceState.destroy();