diff --git a/src/container.ts b/src/container.ts index 8ccfddf..e25f5d5 100644 --- a/src/container.ts +++ b/src/container.ts @@ -1,116 +1,161 @@ import {WindowWrapper} from "./window.js"; import {Logger} from "./utils/logger.js"; -import Mtk from "@girs/mtk-16"; import Meta from "gi://Meta"; -import GLib from "gi://GLib"; import queueEvent from "./utils/events.js"; import {Rect} from "./utils/rect.js"; +enum Orientation { + HORIZONTAL = 0, + VERTICAL = 1, +} + export default class WindowContainer { _id: number; - _windows: Map; - _minimizedWindows: Map; + _items: Map; + _minimizedItems: Map; + _workspace: number; + _orientation: Orientation = Orientation.HORIZONTAL; _workArea: Rect; - constructor(monitorId: number, workspaceArea: Rect) { - this._windows = new Map(); - this._minimizedWindows = new Map(); - const workspace = global.workspace_manager.get_active_workspace(); + constructor(monitorId: number, workspaceArea: Rect, workspace: number) { this._id = monitorId; - const _workArea = workspace.get_work_area_for_monitor( - this._id - ); + this._workspace = workspace; + this._items = new Map(); + this._minimizedItems = new Map(); + this._workArea = workspaceArea; + } + + getWorkspace(): number { + return this._workspace; + } + + move(rect: Rect): void { + this._workArea = rect; + this._tileWindows(); } addWindow(winWrap: WindowWrapper): void { // Add window to managed windows - this._windows.set(winWrap.getWindowId(), winWrap); - queueEvent({ - name: "tiling-windows", - callback: () => { - this._tileWindows(); - } - }, 100) + if (!winWrap.getWindow().minimized) { + this._items.set(winWrap.getWindowId(), winWrap); + queueEvent({ + name: "tiling-windows", + callback: () => { + this._tileWindows(); + } + }, 100) + } else { + this._minimizedItems.set(winWrap.getWindowId(), winWrap); + } } - getWindow(win_id: number): WindowWrapper | undefined { - return this._windows.get(win_id) + getWindow(win_id: number): WindowWrapper | WindowContainer | undefined { + return this._items.get(win_id) } removeWindow(win_id: number): void { - this._windows.delete(win_id) - // TODO: Should there be re-tiling in this function? + this._items.delete(win_id) this._tileWindows() } minimizeWindow(winWrap: WindowWrapper): void { - this._windows.delete(winWrap.getWindowId()) - this._minimizedWindows.set(winWrap.getWindowId(), winWrap) + this._items.delete(winWrap.getWindowId()) + this._minimizedItems.set(winWrap.getWindowId(), winWrap) } unminimizeWindow(winWrap: WindowWrapper): void { - if (this._minimizedWindows.has(winWrap.getWindowId())) { - this._windows.set(winWrap.getWindowId(), winWrap); - this._minimizedWindows.delete(winWrap.getWindowId()); + if (this._minimizedItems.has(winWrap.getWindowId())) { + this._items.set(winWrap.getWindowId(), winWrap); + this._minimizedItems.delete(winWrap.getWindowId()); } } disconnectSignals(): void { - this._windows.forEach((window) => { - window.disconnectWindowSignals(); + this._items.forEach((item) => { + if (item instanceof WindowContainer) { + item.disconnectSignals() + } else { + item.disconnectWindowSignals(); + } } ) } removeAllWindows(): void { - this._windows.clear() + this._items.clear() } _tileWindows() { Logger.log("TILING WINDOWS ON MONITOR", this._id) - const workspace = global.workspace_manager.get_active_workspace(); - const workArea = workspace.get_work_area_for_monitor( - this._id - ); - Logger.log("Workspace", workspace); - Logger.log("WorkArea", workArea); + Logger.log("Workspace", this._workspace); + Logger.log("WorkArea", this._workArea); // Get all windows for current workspace + let tilable = this._getTilableItems(); - let windows = this._getTilableWindows(workspace) - - if (windows.length !== 0) { - this._tileHorizontally(windows, workArea) + if (tilable.length !== 0) { + this._tileHorizontally(tilable, ) } return true } - _getTilableWindows(workspace: Meta.Workspace): WindowWrapper[] { - - return Array.from(this._windows.values()) - .filter(({_window}) => { - Logger.log("TILING WINDOW:", _window.get_id()) - return _window.get_workspace() === workspace; - }) - .map(x => x); + _getTilableItems(): (WindowWrapper|WindowContainer)[] { + return Array.from(this._items.values()) } - _tileHorizontally(windows: (WindowWrapper)[], workArea: Mtk.Rectangle) { - const windowWidth = Math.floor(workArea.width / windows.length); - windows.forEach((window, index) => { - const x = workArea.x + (index * windowWidth); + _tileItems(windows: (WindowWrapper|WindowContainer)[]) { + if (windows.length === 0){ + return; + } + if (this._orientation === Orientation.HORIZONTAL) { + this._tileHorizontally(windows); + } else { + this._tileVertically(windows); + } + } + + _tileVertically(items: (WindowWrapper|WindowContainer)[]) { + const containerHeight = Math.floor(this._workArea.height / items.length); + + items.forEach((item, index) => { + const y = this._workArea.y + (index * containerHeight); + const rect = { + x: this._workArea.x, + y: y, + width: this._workArea.width, + height: containerHeight + }; + if (item != null) { + if (item instanceof WindowContainer) { + item.move(rect) + } else { + item.safelyResizeWindow(rect); + } + } + }); + } + + _tileHorizontally(windows: (WindowWrapper|WindowContainer)[]) { + const windowWidth = Math.floor(this._workArea.width / windows.length); + + windows.forEach((item, index) => { + const x = this._workArea.x + (index * windowWidth); const rect = { x: x, - y: workArea.y, + y: this._workArea.y, width: windowWidth, - height: workArea.height + height: this._workArea.height }; - if (window != null) { - window.safelyResizeWindow(rect); + if (item != null) { + if (item instanceof WindowContainer) { + item.move(rect) + } else { + item.safelyResizeWindow(rect); + } } }); } diff --git a/src/monitor.ts b/src/monitor.ts new file mode 100644 index 0000000..f46d7bf --- /dev/null +++ b/src/monitor.ts @@ -0,0 +1,32 @@ +import {WindowWrapper} from "./window.js"; +import {Rect} from "./utils/rect.js"; +import queueEvent from "./utils/events.js"; +import {Logger} from "./utils/logger.js"; +import Meta from "gi://Meta"; +import Mtk from "@girs/mtk-16"; + +import WindowContainer from "./container.js"; +import Window = Meta.Window; + +export default class Monitor { + + _id: number; + _workArea: Rect; + // _activeWorkspace: number; + // _workspaces: Map; + + constructor(monitorId: number) { + this._id = monitorId; + const workspace = global.workspace_manager.get_active_workspace(); + this._workArea = workspace.get_work_area_for_monitor(this._id); + // this._activeWorkspace = workspace + Logger.log("CREATING MONITOR", monitorId); + const workspaces = global.workspace_manager.get_n_workspaces(); + Logger.log("WORKSPACE COUNT", workspaces); + // this._rootContainer = new WindowContainer(monitorId, this._workArea, ); + } + + // removeAllWindows(): void { + // for (WindowContainer container of this._workspaces.values()) {} + // } +} \ No newline at end of file diff --git a/src/window.ts b/src/window.ts index ae08531..c24af9e 100644 --- a/src/window.ts +++ b/src/window.ts @@ -36,7 +36,7 @@ export class WindowWrapper { Logger.log("REMOVING WINDOW", windowId); windowManager.handleWindowClosed(this) }), - this._window.connect('notify::minimized', () => { + this._window.connect('notify::minimized', (we) => { if (this._window.minimized) { Logger.log(`Window minimized: ${windowId}`); windowManager.handleWindowMinimized(this); @@ -47,6 +47,16 @@ export class WindowWrapper { } }), + this._window.connect( + 'workspace-changed', + (window) => { + const workspace = window.get_workspace(); + const workspaceIndex = workspace ? workspace.index() : -1; + console.log(`Window moved to workspace ${workspaceIndex}`); + }, + this + ); + , this._window.connect('notify::has-focus', () => { if (this._window.has_focus()) { windowManager._activeWindowId = windowId; diff --git a/src/windowManager.ts b/src/windowManager.ts index aba8da1..6b32708 100644 --- a/src/windowManager.ts +++ b/src/windowManager.ts @@ -9,6 +9,7 @@ import {Logger} from "./utils/logger.js"; import WindowContainer from "./container.js"; import {MessageTray} from "@girs/gnome-shell/ui/messageTray"; import queueEvent, {QueuedEvent} from "./utils/events.js"; +import Monitor from "./monitor.js"; export interface IWindowManager { @@ -17,7 +18,9 @@ export interface IWindowManager { // addWindow(window: Meta.Window): void; handleWindowClosed(winWrap: WindowWrapper): void; + handleWindowMinimized(winWrap: WindowWrapper): void; + handleWindowUnminimized(winWrap: WindowWrapper): void; @@ -35,7 +38,7 @@ export default class WindowManager implements IWindowManager { _activeWindowId: number | null; _grabbedWindowMonitor: number; - _monitors: Map; + _monitors: Map; _sessionProxy: Gio.DBusProxy | null; _lockedSignalId: number | null; _isScreenLocked: boolean; @@ -61,7 +64,7 @@ export default class WindowManager implements IWindowManager { const mon_count = global.display.get_n_monitors(); for (let i = 0; i < mon_count; i++) { - this._monitors.set(i, new WindowContainer(i)); + this._monitors.set(i, new Monitor(i)); } this.captureExistingWindows(); @@ -85,7 +88,7 @@ export default class WindowManager implements IWindowManager { Logger.log("SHOWING DESKTOP CHANGED"); }), global.display.connect("workareas-changed", (display) => { - Logger.log("WORK AREAS CHANGED"); + Logger.log("WORK AREAS CHANGED", display.); }), global.display.connect("in-fullscreen-changed", () => { Logger.log("IN FULL SCREEN CHANGED"); @@ -103,13 +106,13 @@ export default class WindowManager implements IWindowManager { Logger.log("SHOWING DESKTOP CHANGED AT WORKSPACE LEVEL"); }), global.workspace_manager.connect("workspace-added", (_, wsIndex) => { - Logger.log("WORKSPACE ADDED"); + Logger.log("WORKSPACE ADDED", wsIndex); }), global.workspace_manager.connect("workspace-removed", (_, wsIndex) => { - Logger.log("WORKSPACE REMOVED"); + Logger.log("WORKSPACE REMOVED", wsIndex); }), - global.workspace_manager.connect("active-workspace-changed", () => { - Logger.log("Active workspace-changed"); + global.workspace_manager.connect("active-workspace-changed", (source) => { + Logger.log("Active workspace-changed", source.get_active_workspace().index()); }), ]; @@ -117,6 +120,7 @@ export default class WindowManager implements IWindowManager { Main.overview.connect("hiding", () => { // this.fromOverview = true; Logger.log("HIDING OVERVIEW") + this._tileMonitors(); // const eventObj = { // name: "focus-after-overview", // callback: () => { @@ -142,9 +146,10 @@ export default class WindowManager implements IWindowManager { } removeAllWindows(): void { - this._monitors.forEach((monitor: WindowContainer) => { - monitor.removeAllWindows(); - }) + //TODO: RECONNECT + // this._monitors.forEach((monitor: Monitor) => { + // monitor.removeAllWindows(); + // }) } @@ -154,9 +159,10 @@ export default class WindowManager implements IWindowManager { } disconnectMonitorSignals(): void { - this._monitors.forEach((monitor: WindowContainer) => { - monitor.disconnectSignals(); - }) + //TODO: RECONNECT + // this._monitors.forEach((monitor: Monitor) => { + // monitor.disconnectSignals(); + // }) } disconnectDisplaySignals(): void { @@ -198,13 +204,15 @@ export default class WindowManager implements IWindowManager { if (old_mon === undefined || new_mon === undefined) { return; } - let wrapped = old_mon.getWindow(window.get_id()) - if (wrapped === undefined) { - wrapped = new WindowWrapper(window, this.handleWindowMinimized); - } else { - old_mon.removeWindow(window.get_id()) - } - new_mon.addWindow(wrapped) + //TODO: RECONNECT + + // let wrapped = old_mon.getWindow(window.get_id()) + // if (wrapped === undefined) { + // wrapped = new WindowWrapper(window, this.handleWindowMinimized); + // } else { + // old_mon.removeWindow(window.get_id()) + // } + // new_mon.addWindow(wrapped) } this._tileMonitors(); Logger.info("monitor_start and monitor_end", this._grabbedWindowMonitor, window.get_monitor()); @@ -216,14 +224,16 @@ export default class WindowManager implements IWindowManager { const monitor_id = winWrap.getWindow().get_monitor() Logger.log("WARNING MINIMIZED", monitor_id); Logger.warn("WARNING MINIMIZED", this._monitors); - this._monitors.get(monitor_id)?.minimizeWindow(winWrap); + //TODO: RECONNECT + // this._monitors.get(monitor_id)?.minimizeWindow(winWrap); this._tileMonitors() } public handleWindowUnminimized(winWrap: WindowWrapper): void { Logger.log("WINDOW UNMINIMIZED"); const monitor_id = winWrap.getWindow().get_monitor() - this._monitors.get(monitor_id)?.unminimizeWindow(winWrap); + //TODO: RECONNECT + // this._monitors.get(monitor_id)?.unminimizeWindow(winWrap); this._tileMonitors() } @@ -259,7 +269,8 @@ export default class WindowManager implements IWindowManager { // window.disconnectWindowSignals() const mon_id = window._window.get_monitor(); - this._monitors.get(mon_id)?.removeWindow(window.getWindowId()); + //TODO: RECONNECT + // this._monitors.get(mon_id)?.removeWindow(window.getWindowId()); // Remove from managed windows this.syncActiveWindow(); @@ -269,17 +280,21 @@ export default class WindowManager implements IWindowManager { public addWindowToMonitor(window: Meta.Window) { + Logger.log("ADDING WINDOW TO MONITOR", window, window); var wrapper = new WindowWrapper(window, this.handleWindowMinimized) wrapper.connectWindowSignals(this); - // wrapper.connectWindowSignals(this) - this._monitors.get(window.get_monitor())?.addWindow(wrapper) + //TODO: RECONNECT + + // this._monitors.get(window.get_monitor())?.addWindow(wrapper) } _tileMonitors(): void { for (const monitor of this._monitors.values()) { - monitor._tileWindows() + //TODO: RECONNECT + + // monitor._tileWindows() } }