diff --git a/gnome-shell-extension/ai-control-popup@local/extension.js b/gnome-shell-extension/ai-control-popup@local/extension.js index 295e18a..1762663 100644 --- a/gnome-shell-extension/ai-control-popup@local/extension.js +++ b/gnome-shell-extension/ai-control-popup@local/extension.js @@ -79,6 +79,7 @@ export default class AiControlPopupExtension extends Extension { const win = this._findWindow(); if (win && win.showing_on_its_workspace()) { this._call('Hide'); + this._disconnectOutsideClick(); return; } // Fenster unsichtbar halten, bis es am Platz sitzt (kein Sprung Mitte->Tray). @@ -86,6 +87,37 @@ export default class AiControlPopupExtension extends Extension { if (actor) actor.opacity = 0; this._call('Show'); this._positionWhenReady(); + this._connectOutsideClick(); + } + + // Klick auf leere Desktop-Fläche oder Shell-Chrome wechselt den Fensterfokus + // nicht — der Blur-Pfad der App greift dort nicht. Solche Klicks landen im + // Shell-Stage: solange das Popup offen ist, hier abgreifen und Hide relayen. + _connectOutsideClick() { + if (this._clickId) return; + this._clickId = global.stage.connect('captured-event', (_stage, event) => { + if (event.type() !== Clutter.EventType.BUTTON_PRESS) return Clutter.EVENT_PROPAGATE; + const win = this._findWindow(); + if (!win || !win.showing_on_its_workspace()) { + this._disconnectOutsideClick(); + return Clutter.EVENT_PROPAGATE; + } + const [x, y] = event.get_coords(); + // Panel-Button toggelt selbst; Klicks ins Popup erreichen den Stage nicht. + const [bx, by] = this._button.get_transformed_position(); + if (x >= bx && x < bx + this._button.width && y >= by && y < by + this._button.height) { + return Clutter.EVENT_PROPAGATE; + } + this._call('Hide'); + this._disconnectOutsideClick(); + return Clutter.EVENT_PROPAGATE; + }); + } + + _disconnectOutsideClick() { + if (!this._clickId) return; + global.stage.disconnect(this._clickId); + this._clickId = 0; } _call(method) { @@ -186,6 +218,7 @@ export default class AiControlPopupExtension extends Extension { global.window_manager.disconnect(this._mapId); this._mapId = 0; } + this._disconnectOutsideClick(); this._removeButton(); this._proxy = null; }