From d226d8ce05ba913738bf0b3d52af96e0da2dbdbd Mon Sep 17 00:00:00 2001 From: Maycon Date: Wed, 29 Apr 2026 13:40:27 -0300 Subject: [PATCH] fix: disconnect FeatureIndicator settings handler + clear theme ref Two small lifecycle fixes that surface during repeated enable/disable cycles (e.g. while iterating on the extension during development): 1. FeatureIndicator.constructor connects to `extension.settings` without storing the handler id. `Gio.Settings` returned by `getSettings()` is cached for the lifetime of the gnome-shell process, so the handler outlives the indicator: each cycle accumulates another callback, all firing on previous (destroyed) indicators when the user toggles tiling-mode-enabled or quick-settings-enabled. Track the id and disconnect in destroy(). 2. extension.js disable() set `this.themeWm = null`, but the field assigned in enable() is `this.theme` (an ExtensionThemeManager). The original statement was a typo / no-op leaving the real reference dangling on the extension object after disable. Replace with `this.theme = null`. Both are zero-behaviour changes for the happy path; they only affect state cleanup at disable time. --- extension.js | 4 +++- lib/extension/indicator.js | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/extension.js b/extension.js index 13414016..5a89b735 100644 --- a/extension.js +++ b/extension.js @@ -65,7 +65,9 @@ export default class ForgeExtension extends Extension { this.keybindings?.disable(); this.keybindings = null; this.extWm = null; - this.themeWm = null; + // The field assigned in enable() is `this.theme`, not `this.themeWm`, + // so the previous statement was a no-op leaving `this.theme` dangling. + this.theme = null; this.configMgr = null; this.settings = null; this.kbdSettings = null; diff --git a/lib/extension/indicator.js b/lib/extension/indicator.js index 309dcf20..0d06f5ef 100644 --- a/lib/extension/indicator.js +++ b/lib/extension/indicator.js @@ -118,7 +118,10 @@ export class FeatureIndicator extends SystemIndicator { this._indicator.visible = tilingModeEnabled && quickSettingsEnabled; - this.extension.settings.connect("changed", (_, name) => { + // settings is a long-lived Gio.Settings (cached by getSettings()) so we + // must disconnect on destroy — otherwise every enable/disable cycle + // accumulates another handler firing on the previous indicator. + this._settingsChangedId = this.extension.settings.connect("changed", (_, name) => { switch (name) { case "tiling-mode-enabled": case "quick-settings-enabled": @@ -126,4 +129,12 @@ export class FeatureIndicator extends SystemIndicator { } }); } + + destroy() { + if (this._settingsChangedId) { + this.extension.settings.disconnect(this._settingsChangedId); + this._settingsChangedId = 0; + } + super.destroy(); + } }