import Gio from "gi://Gio"; import Meta from "gi://Meta"; import Clutter from "gi://Clutter"; import { Extension } from "resource:///org/gnome/shell/extensions/extension.js"; import { EventEmitter } from "resource:///org/gnome/shell/misc/signals.js"; import * as Main from "resource:///org/gnome/shell/ui/main.js"; import { Button as PanelMenuButton } from "resource:///org/gnome/shell/ui/panelMenu.js"; export default class MyExtension extends Extension { button?: PanelMenuButton; settings?: Gio.Settings; float: boolean = false; updateFloat: EventEmitter = new EventEmitter(); _actorSignalIds?: Map; _windowSignalIds?: Map; _workspace?: Meta.Workspace; enable() { this._workspace = global.workspaceManager.get_active_workspace(); this._windowSignalIds = new Map(); this._actorSignalIds = new Map(); // this.button = new ToggleButton(this); // Main.panel.addToStatusArea(this.uuid, this.button); this._actorSignalIds.set(Main.overview, [ Main.overview.connect("showing", () => this._updateFloating.bind(this)), Main.overview.connect("hiding", () => this._updateFloating.bind(this)), ]); this._actorSignalIds.set(Main.sessionMode, [Main.sessionMode.connect("updated", () => this._updateFloating.bind(this))]); for (const window_actor of global.get_window_actors()) { this._onWindowActorAdded(window_actor.get_parent(), window_actor); } this._workspace.connect("window-added", (workspace, window) => { setTimeout(() => { console.log("window-added ", window.title); this._onWindowActorAdded.bind(this)(workspace, window.get_compositor_private()); }, 10); }); this._workspace.connect("window-removed", (workspace, window) => { setTimeout(() => { console.log("window-removed ", window.title); this._onWindowActorRemoved.bind(this)(workspace, window.get_compositor_private()); }, 10); }); this._actorSignalIds.set(global.window_manager, [global.window_manager.connect("switch-workspace", this._updateFloating.bind(this))]); } disable() { // for (const actorSignalIds of [this._actorSignalIds, this._windowSignalIds]) { // for (const [actor, signalIds] of actorSignalIds!) { // for (const signalId of signalIds) { // console.log("SignalID ", signalId); // console.log("Actor ", actor instanceof Clutter.Actor); // } // } // } this._actorSignalIds?.clear(); this._windowSignalIds?.clear(); this._setFloat(false); } _onWindowActorAdded(container: any, metaWindowActor: Meta.WindowActor) { if (metaWindowActor.metaWindow.skipTaskbar) return; if (this._windowSignalIds === undefined) return; this._windowSignalIds.set(metaWindowActor.metaWindow.title, [ metaWindowActor.connect("notify::allocation", this._updateFloating.bind(this)), metaWindowActor.connect("notify::visible", this._updateFloating.bind(this)), ]); } _onWindowActorRemoved(container: any, metaWindowActor: Meta.WindowActor) { if (this._windowSignalIds === undefined) return; this._updateFloating(); for (const signalId of this._windowSignalIds.get(metaWindowActor.metaWindow.title)) { metaWindowActor.disconnect(signalId); } this._windowSignalIds.delete("test"); } _updateFloating() { const workspace_manager = global.workspaceManager; const active_workspace = workspace_manager.get_active_workspace(); const windows = active_workspace.list_windows().filter((metaWindow) => { return !metaWindow.skip_taskbar && metaWindow.showing_on_its_workspace() && !metaWindow.is_hidden(); }); const maximized = windows.some((metaWindow) => { return metaWindow.maximizedHorizontally; }); this._setFloat(!maximized); } _setFloat(float: boolean) { Main.panel.add_style_class_name(float ? "floating" : "solid"); Main.panel.remove_style_class_name(float ? "solid" : "floating"); } }