From 9305dc6fe747fa4f97498420b224e377bee7356d Mon Sep 17 00:00:00 2001 From: anaximeno Date: Wed, 21 Jan 2026 08:02:47 -0100 Subject: [PATCH 01/10] Properly disconnect from local state signals to avoid errors during applet reload --- .../applets/grouped-window-list@cinnamon.org/appGroup.js | 5 ++++- .../applets/grouped-window-list@cinnamon.org/applet.js | 5 ++++- .../applets/grouped-window-list@cinnamon.org/workspace.js | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) 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..806f64d8d9 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 @@ -86,7 +86,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), @@ -1196,6 +1196,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..be3d99ed95 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--; 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..e3b6f4ee33 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({ @@ -421,6 +421,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(); From 8733de3b77826885e1d7b699020651938409cf30 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Mon, 23 Feb 2026 14:54:13 -0100 Subject: [PATCH 02/10] gwl: Improve window state management --- .../appGroup.js | 2 ++ .../workspace.js | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) 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 806f64d8d9..36cf9fee98 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 @@ -989,6 +989,8 @@ var AppGroup = class AppGroup { 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); 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 e3b6f4ee33..9c8f5c6a77 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 @@ -352,15 +352,17 @@ 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 (!metaWindow.showing_on_its_workspace()) return; + if ((this.state.settings.showAllWorkspaces) && (metaWindow.has_focus() + && global.workspace_manager.get_active_workspace_index() + !== metaWorkspace.index())) return; + + // If the window is on all workspaces or we're showing 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; From ebc3a309f93eaa31bf108df4aa92efa9fe766d7d Mon Sep 17 00:00:00 2001 From: anaximeno Date: Wed, 21 Jan 2026 04:01:38 -0100 Subject: [PATCH 03/10] Refresh all workspaces when the title display setting is changed This works well enough and guarantees all workspaces are in the same state both when enabling and disabling the title display options. --- .../grouped-window-list@cinnamon.org/applet.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) 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 be3d99ed95..b6677e6490 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 @@ -623,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) { From 4fd113123a97fa746bb286ddedab78682226ab39 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Tue, 17 Feb 2026 13:47:49 -0100 Subject: [PATCH 04/10] gwl: Avoid adding the window again after removal This was triggering when using the show window in all workspaces option and was leading the app group representation to an irregular state where removed windows would still be counted and show irresponsible thumbnails. --- .../applets/grouped-window-list@cinnamon.org/workspace.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 9c8f5c6a77..094581e614 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 @@ -240,8 +240,10 @@ var Workspace = class Workspace { && 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, in that + // case we wouldn't want to add the window again. + if (metaWorkspace) this.windowAdded(metaWorkspace, metaWindow); } windowAdded(metaWorkspace, metaWindow, app, isFavoriteApp) { From 38ce963f5f9079a26ff8c3dfdeefdf5dc9c1a572 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Mon, 23 Feb 2026 15:04:06 -0100 Subject: [PATCH 05/10] gwl: Only set appGroup focus if app actually has focus --- .../applets/grouped-window-list@cinnamon.org/appGroup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 36cf9fee98..2394e17793 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 @@ -642,7 +642,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, From f90012a339b99deb5554d23ef01998b78a11e305 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Mon, 23 Feb 2026 15:29:10 -0100 Subject: [PATCH 06/10] gwl: Clarify comment --- .../applets/grouped-window-list@cinnamon.org/workspace.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 094581e614..7f9d0d815b 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 @@ -361,7 +361,7 @@ var Workspace = class Workspace { && global.workspace_manager.get_active_workspace_index() !== metaWorkspace.index())) return; - // If the window is on all workspaces or we're showing all workspaces, + // 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) { From bc85e28ebb140a35f45b1b04176173f5c28da609 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Wed, 25 Feb 2026 05:42:19 -0100 Subject: [PATCH 07/10] gwl: Improve state handling during window removal This fixes some annyoing issues during the removal of windows that would some time leave a ghost window instance in app groups. I've also improved the handled of some signals to ensure the window is only added again if it is inside a valid workspace and the workspace is similar to the current workspace receiving the signal. --- .../appGroup.js | 38 +++++++++++++------ .../applet.js | 26 ++++++++----- .../workspace.js | 17 +++++---- 3 files changed, 53 insertions(+), 28 deletions(-) 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 2394e17793..388078df48 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,16 @@ const getFocusState = function(metaWindow) { return false; }; +const getLastFocusedWindow = function(metaWindows) { + let lastFocusedWindow = null; + for (let i = 0; i < metaWindows.length; i++) { + if (!lastFocusedWindow || (metaWindows[i].get_user_time() > lastFocusedWindow.get_user_time())) { + lastFocusedWindow = metaWindows[i]; + } + } + return lastFocusedWindow; +}; + var AppGroup = class AppGroup { constructor(params) { this.state = params.state; @@ -992,19 +1002,21 @@ var AppGroup = class AppGroup { 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.groupState.willUnmount) { + const lastFocused = this.groupState.lastFocused === metaWindow + ? getLastFocusedWindow(metaWindows) + : this.groupState.lastFocused; + this.groupState.set({metaWindows: metaWindows, lastFocused: lastFocused}, true); + this.onWindowTitleChanged(lastFocused); if (this.hoverMenu) this.groupState.trigger('removeThumbnailFromMenu', metaWindow); this.calcWindowNumber(); - } else { + } + + if (metaWindows.length === 0) { // 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') { @@ -1125,10 +1137,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(); 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 b6677e6490..f7c1e0681f 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 @@ -448,12 +448,16 @@ 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) { + const metaWorkspace = metaWindow.get_workspace(); + if ((this.state.monitorWatchList.length !== this.numberOfMonitors) && metaWorkspace) { + const windowWorkspace = this.workspaces.find( + workspace => workspace.metaWorkspace && workspace.metaWorkspace.index() === metaWorkspace.index() + ); + + if (windowWorkspace !== null) { + windowWorkspace.windowRemoved(metaWorkspace, metaWindow); + windowWorkspace.windowAdded(metaWorkspace, metaWindow); } } } @@ -769,7 +773,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); } } @@ -1018,10 +1022,14 @@ class GroupedWindowListApplet extends Applet.Applet { _onWindowAppChanged(tracker, metaWindow) { if (!metaWindow) return; + const windowWorkspace = metaWindow.get_workspace(); + this.workspaces.forEach(workspace => { if (!workspace) return; - workspace.windowRemoved(workspace.metaWorkspace, metaWindow); - workspace.windowAdded(workspace.metaWorkspace, metaWindow); + if (windowWorkspace && (workspace.metaWorkspace.index() === windowWorkspace.index())) { + workspace.windowRemoved(workspace.metaWorkspace, metaWindow); + workspace.windowAdded(workspace.metaWorkspace, metaWindow); + } }); } 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 7f9d0d815b..5ab29e2725 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 @@ -243,7 +243,11 @@ var Workspace = class Workspace { windowWorkspaceChanged(display, metaWindow, metaWorkspace) { // If the window is removed the metaWorkspace will be null, in that // case we wouldn't want to add the window again. - if (metaWorkspace) this.windowAdded(metaWorkspace, metaWindow); + if (metaWorkspace && this.metaWorkspace.index() === metaWorkspace.index()) { + this.windowAdded(metaWorkspace, metaWindow); + } else { + this.windowRemoved(metaWorkspace, metaWindow); + } } windowAdded(metaWorkspace, metaWindow, app, isFavoriteApp) { @@ -356,10 +360,9 @@ var Workspace = class Workspace { // 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; + 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. @@ -396,7 +399,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); @@ -416,7 +419,7 @@ var Workspace = class Workspace { } } } else { - this.appGroups[refApp].destroy(true); + this.appGroups[refApp].destroy(); this.appGroups[refApp] = undefined; this.appGroups.splice(refApp, 1); } From b1db3472dfb344313335f052733e55b8fb495af0 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Wed, 25 Feb 2026 12:02:44 -0100 Subject: [PATCH 08/10] gwl: Simplify appGroup windowRemoved method It makes sense to call the callback to clean the appGroup if willUnmount is set true as well, however no need to only perform updates to the groupstate otherwise considering things like removing thumbnails have to be performed anyways, and considering the appGroup, in case of no open windows in the appGroup, or willUnmount is set, will be removed anyways, it likely shouldn't cause issues. --- .../appGroup.js | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) 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 388078df48..e0d17544b9 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 @@ -995,36 +995,36 @@ 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); - const metaWindows = this.groupState.metaWindows.filter((w) => w != metaWindow); + const metaWindows = this.groupState.metaWindows.filter((w) => w != metaWindow); if (this.progressOverlay.visible) this.onProgressChange(); - if (!this.groupState.willUnmount) { - const lastFocused = this.groupState.lastFocused === metaWindow - ? getLastFocusedWindow(metaWindows) - : this.groupState.lastFocused; - this.groupState.set({metaWindows: metaWindows, lastFocused: lastFocused}, true); - this.onWindowTitleChanged(lastFocused); - if (this.hoverMenu) this.groupState.trigger('removeThumbnailFromMenu', metaWindow); - this.calcWindowNumber(); - } + 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 (metaWindows.length === 0) { + if (this.hoverMenu) this.groupState.trigger('removeThumbnailFromMenu', metaWindow); + + this.calcWindowNumber(); + + if ((metaWindows.length === 0 || this.groupState.willUnmount) && typeof cb === 'function') { // 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); + if (this.hoverMenu && this.groupState.isFavoriteApp) { + this.groupState.trigger('removeThumbnailFromMenu', metaWindow); } + cb(this.groupState.appId, this.groupState.isFavoriteApp); } } From 9990948ec02ca204150d7f7cb0ae84b9009bf488 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Thu, 26 Feb 2026 19:59:46 -0100 Subject: [PATCH 09/10] gwl: Let workspace.windowAdded arbitrate over if metaWindow should be added to the workspace This already checks if window is in correct workspace and/or windows should be shown in all workspaces, plus checking the monitor using the shouldWindowBeAdded method. --- .../appGroup.js | 10 +++---- .../applet.js | 27 +++++++------------ .../workspace.js | 9 +++---- 3 files changed, 16 insertions(+), 30 deletions(-) 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 e0d17544b9..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 @@ -64,8 +64,9 @@ const getFocusState = function(metaWindow) { const getLastFocusedWindow = function(metaWindows) { let lastFocusedWindow = null; for (let i = 0; i < metaWindows.length; i++) { - if (!lastFocusedWindow || (metaWindows[i].get_user_time() > lastFocusedWindow.get_user_time())) { - lastFocusedWindow = metaWindows[i]; + const metaWindow = metaWindows[i]; + if (!lastFocusedWindow || (metaWindow.get_user_time() > lastFocusedWindow.get_user_time())) { + lastFocusedWindow = metaWindow; } } return lastFocusedWindow; @@ -1019,11 +1020,6 @@ var AppGroup = class AppGroup { this.calcWindowNumber(); if ((metaWindows.length === 0 || this.groupState.willUnmount) && typeof cb === 'function') { - // 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 (this.hoverMenu && this.groupState.isFavoriteApp) { - this.groupState.trigger('removeThumbnailFromMenu', metaWindow); - } cb(this.groupState.appId, this.groupState.isFavoriteApp); } } 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 f7c1e0681f..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 @@ -449,16 +449,12 @@ class GroupedWindowListApplet extends Applet.Applet { } onWindowMonitorChanged(display, metaWindow, monitor) { - const metaWorkspace = metaWindow.get_workspace(); - if ((this.state.monitorWatchList.length !== this.numberOfMonitors) && metaWorkspace) { - const windowWorkspace = this.workspaces.find( - workspace => workspace.metaWorkspace && workspace.metaWorkspace.index() === metaWorkspace.index() - ); - - if (windowWorkspace !== null) { - windowWorkspace.windowRemoved(metaWorkspace, metaWindow); - windowWorkspace.windowAdded(metaWorkspace, metaWindow); - } + if ((this.state.monitorWatchList.length !== this.numberOfMonitors)) { + this.workspaces.forEach( workspace => { + if (!workspace) return; + workspace.windowRemoved(workspace.metaWorkspace, metaWindow); + workspace.windowAdded(workspace.metaWorkspace, metaWindow); + }); } } @@ -1021,15 +1017,10 @@ class GroupedWindowListApplet extends Applet.Applet { _onWindowAppChanged(tracker, metaWindow) { if (!metaWindow) return; - - const windowWorkspace = metaWindow.get_workspace(); - this.workspaces.forEach(workspace => { if (!workspace) return; - if (windowWorkspace && (workspace.metaWorkspace.index() === windowWorkspace.index())) { - workspace.windowRemoved(workspace.metaWorkspace, metaWindow); - workspace.windowAdded(workspace.metaWorkspace, metaWindow); - } + workspace.windowRemoved(workspace.metaWorkspace, metaWindow); + workspace.windowAdded(workspace.metaWorkspace, metaWindow); }); } @@ -1040,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 5ab29e2725..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 @@ -234,16 +234,15 @@ 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, metaWindow, metaWorkspace) { - // If the window is removed the metaWorkspace will be null, in that - // case we wouldn't want to add the window again. - if (metaWorkspace && this.metaWorkspace.index() === metaWorkspace.index()) { + // If the window is removed the metaWorkspace will be null. + if (metaWorkspace) { this.windowAdded(metaWorkspace, metaWindow); } else { this.windowRemoved(metaWorkspace, metaWindow); From 08a731dfa4d15eec18de2499555bfbf505b4c843 Mon Sep 17 00:00:00 2001 From: anaximeno Date: Tue, 17 Mar 2026 22:16:09 -0100 Subject: [PATCH 10/10] gwl: Adjust state check handling --- .../applets/grouped-window-list@cinnamon.org/appGroup.js | 2 +- .../applets/grouped-window-list@cinnamon.org/state.js | 4 ++-- .../applets/grouped-window-list@cinnamon.org/workspace.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) 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 bd249cde37..d1f1a3c232 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 @@ -1208,7 +1208,7 @@ var AppGroup = class AppGroup { } destroy(skipRefCleanup) { - if (this.groupStateConnectionId) { + if (this.groupStateConnectionId > 0) { this.groupState.disconnect(this.groupStateConnectionId); } this.signals.disconnectAllSignals(); diff --git a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/state.js b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/state.js index 758e1d9a9e..126448a61a 100644 --- a/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/state.js +++ b/files/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/state.js @@ -252,14 +252,14 @@ var createStore = function(state = {}, listeners = [], connections = 0) { } if (listener) { let newKeys = intersect(keys, listener.keys, true); - listener.keys.concat(newKeys); + listener.keys = listener.keys.concat(newKeys); } else { listeners.push({keys, callback, id}); } } function connect(actions, callback) { - const id = connections++; + const id = ++connections; if (Array.isArray(actions)) { _connect(actions, callback, id); } else if (typeof actions === 'string') { 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 e98d70fd5e..893c59c28a 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 @@ -235,7 +235,7 @@ var Workspace = class Workspace { shouldWindowBeAdded(metaWindow) { return (this.state.settings.showAllWorkspaces || metaWindow.is_on_all_workspaces() - || (metaWindow.get_workspace().index() === this.metaWorkspace.index())) + || (metaWindow.get_workspace() === this.metaWorkspace)) && Main.isInteresting(metaWindow) && this.state.monitorWatchList.indexOf(metaWindow.get_monitor()) > -1; }