diff --git a/src/container.ts b/src/container.ts index 8809878..3ba35cf 100644 --- a/src/container.ts +++ b/src/container.ts @@ -12,24 +12,18 @@ enum Orientation { export default class WindowContainer { - _id: number; _tiledItems: (WindowWrapper | WindowContainer)[]; _tiledWindowLookup: Map; - _workspace: number; _orientation: Orientation = Orientation.HORIZONTAL; _workArea: Rect; - constructor(monitorId: number, workspaceArea: Rect, workspace: number) { - this._id = monitorId; - this._workspace = workspace; + constructor(workspaceArea: Rect,) { + // this._id = monitorId; this._tiledItems = []; this._tiledWindowLookup = new Map(); this._workArea = workspaceArea; } - getWorkspace(): number { - return this._workspace; - } move(rect: Rect): void { this._workArea = rect; @@ -108,75 +102,103 @@ export default class WindowContainer { } tileWindows() { - Logger.log("TILING WINDOWS ON MONITOR", this._id) + Logger.log("TILING WINDOWS IN CONTAINER") - Logger.log("Workspace", this._workspace); Logger.log("WorkArea", this._workArea); - // Get all windows for current workspace - let tilable = this._getTilableItems(); + // Get all windows for current workspaceArea + this._tileItems() - if (tilable.length !== 0) { - this._tileItems(tilable) - } return true } - _getTilableItems(): (WindowWrapper | WindowContainer)[] { - return Array.from(this._tiledItems.values()) - } - - _tileItems(windows: (WindowWrapper | WindowContainer)[]) { - if (windows.length === 0) { + _tileItems() { + if (this._tiledItems.length === 0) { return; } - if (this._orientation === Orientation.HORIZONTAL) { - this._tileHorizontally(windows); - } else { - this._tileVertically(windows); - } + const bounds = this.getBounds(); + this._tiledItems.forEach((item, index) => { + const rect = bounds[index]; + if (item instanceof WindowContainer) { + item.move(rect); + } else { + item.safelyResizeWindow(rect); + } + }) } - _tileVertically(items: (WindowWrapper | WindowContainer)[]) { - const containerHeight = Math.floor(this._workArea.height / items.length); - items.forEach((item, index) => { + getBounds(): Rect[] { + if (this._orientation === Orientation.HORIZONTAL) { + return this.getHorizontalBounds(); + } + return this.getVerticalBounds(); + } + + getVerticalBounds(): Rect[] { + const items = this._tiledItems + const containerHeight = Math.floor(this._workArea.height / items.length); + return items.map((_, index) => { const y = this._workArea.y + (index * containerHeight); - const rect = { + return { 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); - } - } + } as Rect; }); } - _tileHorizontally(windows: (WindowWrapper | WindowContainer)[]) { - const windowWidth = Math.floor(this._workArea.width / windows.length); + getHorizontalBounds(): Rect[] { + const windowWidth = Math.floor(this._workArea.width / this._tiledItems.length); - windows.forEach((item, index) => { + return this._tiledItems.map((_, index) => { const x = this._workArea.x + (index * windowWidth); - const rect = { + return { x: x, y: this._workArea.y, width: windowWidth, height: this._workArea.height - }; - if (item != null) { - if (item instanceof WindowContainer) { - item.move(rect) - } else { - item.safelyResizeWindow(rect); - } - } + } as Rect; }); } + getIndexOfItemNested(item: WindowWrapper): number { + for (let i = 0; i < this._tiledItems.length; i++) { + const container = this._tiledItems[i]; + if (container instanceof WindowContainer) { + const index = container.getIndexOfItemNested(item); + if (index !== -1) { + return i; + } + } else if (container.getWindowId() === item.getWindowId()) { + return i; + } + } + return -1; + } + + // TODO: update this to work with nested containers - all other logic should already be working + itemDragged(item: WindowWrapper, x: number, y: number): void { + let original_index = this.getIndexOfItemNested(item); + + if (original_index === -1) { + Logger.error("Item not found in container during drag op", item.getWindowId()); + return; + } + let new_index = this.getIndexOfItemNested(item); + this.getBounds().forEach((rect, index) => { + if (rect.x < x && rect.x + rect.width > x && rect.y < y && rect.y + rect.height > y) { + new_index = index; + } + }) + if (original_index !== new_index) { + this._tiledItems.splice(original_index, 1); + this._tiledItems.splice(new_index, 0, item); + this.tileWindows() + } + + } + + } \ No newline at end of file diff --git a/src/monitor.ts b/src/monitor.ts index 4f8c6dd..a676efd 100644 --- a/src/monitor.ts +++ b/src/monitor.ts @@ -23,7 +23,7 @@ export default class Monitor { const workspaceCount = global.workspace_manager.get_n_workspaces() Logger.log("Workspace Count", workspaceCount); for (let i = 0; i < workspaceCount; i++) { - this._workspaces.push(new WindowContainer(monitorId, this._workArea, i)); + this._workspaces.push(new WindowContainer(this._workArea)); } } @@ -61,7 +61,6 @@ export default class Monitor { addWindow(winWrap: WindowWrapper) { const window_workspace = winWrap.getWindow().get_workspace().index(); - Logger.log("Adding window to workspace", window_workspace); this._workspaces[window_workspace].addWindow(winWrap); } @@ -72,4 +71,16 @@ export default class Monitor { this._workspaces[activeWorkspace.index()].tileWindows() } + removeWorkspace(workspaceId: number): void { + this._workspaces.splice(workspaceId, 1); + } + + addWorkspace(): void { + this._workspaces.push(new WindowContainer(this._workArea)); + } + + itemDragged(item: WindowWrapper, x: number, y: number): void { + this._workspaces[item.getWorkspace()].itemDragged(item, x, y); + } + } \ No newline at end of file diff --git a/src/window.ts b/src/window.ts index 75e75a8..6834141 100644 --- a/src/window.ts +++ b/src/window.ts @@ -32,6 +32,18 @@ export class WindowWrapper { return this._window.get_id(); } + getWorkspace(): number { + return this._window.get_workspace().index(); + } + + getMonitor(): number { + return this._window.get_monitor(); + } + + getRect(): Rect { + return this._window.get_frame_rect(); + } + connectWindowSignals( windowManager: IWindowManager, ): void { @@ -67,6 +79,10 @@ export class WindowWrapper { }), this._window.connect("workspace-changed", (_metaWindow) => { Logger.log("WORKSPACE CHANGED FOR WINDOW", this._window.get_id()); + windowManager.handleWindowChangedWorkspace(this); + }), + this._window.connect("position-changed", (_metaWindow) => { + windowManager.handleWindowPositionChanged(this); }), ); } diff --git a/src/windowManager.ts b/src/windowManager.ts index f5c017d..d2d3a72 100644 --- a/src/windowManager.ts +++ b/src/windowManager.ts @@ -23,41 +23,33 @@ export interface IWindowManager { handleWindowUnminimized(winWrap: WindowWrapper): void; + handleWindowChangedWorkspace(winWrap: WindowWrapper): void; + + handleWindowPositionChanged(winWrap: WindowWrapper): void; - // removeFromTree(window: Meta.Window): void; syncActiveWindow(): number | null; } const _UNUSED_MONITOR_ID = -1 +const _UNUSED_WINDOW_ID = -1 + export default class WindowManager implements IWindowManager { - _displaySignals: number[]; - _windowManagerSignals: number[]; - _workspaceManagerSignals: number[]; - _overviewSignals: number[]; + _displaySignals: number[] = []; + _windowManagerSignals: number[] = []; + _workspaceManagerSignals: number[] = []; + _overviewSignals: number[] = []; - _activeWindowId: number | null; - _grabbedWindowMonitor: number; - _monitors: Map; - _sessionProxy: Gio.DBusProxy | null; - _lockedSignalId: number | null; - _isScreenLocked: boolean; + _activeWindowId: number | null = null; + _monitors: Map = new Map(); - _minimizedItems: Map; + _minimizedItems: Map = new Map(); + + _grabbedWindowMonitor: number = _UNUSED_MONITOR_ID; + _grabbedWindowId: number = _UNUSED_WINDOW_ID; constructor() { - this._displaySignals = []; - this._windowManagerSignals = []; - this._workspaceManagerSignals = []; - this._overviewSignals = []; - this._activeWindowId = null; - this._grabbedWindowMonitor = _UNUSED_MONITOR_ID; - this._monitors = new Map(); - this._sessionProxy = null; - this._lockedSignalId = null; - this._isScreenLocked = false; // Initialize to unlocked state - this._minimizedItems = new Map(); } @@ -93,7 +85,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",); console.log(display.get_workspace_manager().get_active_workspace_index()) }), global.display.connect("in-fullscreen-changed", () => { @@ -113,9 +105,15 @@ export default class WindowManager implements IWindowManager { }), global.workspace_manager.connect("workspace-added", (_, wsIndex) => { Logger.log("WORKSPACE ADDED", wsIndex); + this._monitors.forEach((monitor: Monitor) => { + monitor.addWorkspace(); + }) }), global.workspace_manager.connect("workspace-removed", (_, wsIndex) => { Logger.log("WORKSPACE REMOVED", wsIndex); + this._monitors.forEach((monitor: Monitor) => { + monitor.removeWorkspace(wsIndex); + }) }), global.workspace_manager.connect("active-workspace-changed", (source) => { Logger.log("Active workspace-changed", source.get_active_workspace().index()); @@ -197,12 +195,15 @@ export default class WindowManager implements IWindowManager { Logger.log("Grab Op Start"); Logger.log(display, window, op) Logger.log(window.get_monitor()) + this._grabbedWindowMonitor = window.get_monitor(); + this._grabbedWindowId = window.get_id(); } handleGrabOpEnd(display: Meta.Display, window: Meta.Window, op: Meta.GrabOp): void { Logger.log("Grab Op End ", op); Logger.log("primary display", display.get_primary_monitor()) + this._grabbedWindowId = _UNUSED_WINDOW_ID; var rect = window.get_frame_rect() Logger.info("Release Location", window.get_monitor(), rect.x, rect.y, rect.width, rect.height) const old_mon_id = this._grabbedWindowMonitor; @@ -229,6 +230,20 @@ export default class WindowManager implements IWindowManager { Logger.info("monitor_start and monitor_end", this._grabbedWindowMonitor, window.get_monitor()); } + public handleWindowPositionChanged(winWrap: WindowWrapper): void { + if (winWrap.getWindowId() === this._grabbedWindowId) { + const rect = winWrap.getRect(); + Logger.log("GRABBED WINDOW POSITION CHANGED", rect.x); + const [mouseX, mouseY, _] = global.get_pointer(); + this._monitors.get(winWrap.getMonitor())?.itemDragged(winWrap, mouseX, mouseY); + + // Log or use the coordinates + console.log(`Mouse position: X=${mouseX}, Y=${mouseY}`); + + } + } + + public handleWindowMinimized(winWrap: WindowWrapper): void { Logger.warn("WARNING MINIMIZING WINDOW"); Logger.log("WARNING MINIMIZED", JSON.stringify(winWrap)); @@ -253,6 +268,13 @@ export default class WindowManager implements IWindowManager { this._tileMonitors() } + + public handleWindowChangedWorkspace(winWrap: WindowWrapper): void { + const monitor = winWrap.getWindow().get_monitor(); + this._monitors.get(monitor)?.removeWindow(winWrap); + this._monitors.get(monitor)?.addWindow(winWrap); + } + public captureExistingWindows() { Logger.log("CAPTURING WINDOWS") const workspace = global.workspace_manager.get_active_workspace(); @@ -303,6 +325,7 @@ export default class WindowManager implements IWindowManager { this._addWindowWrapperToMonitor(wrapper); } + _addWindowWrapperToMonitor(winWrap: WindowWrapper) { if (winWrap.getWindow().minimized) { this._minimizedItems.set(winWrap.getWindow().get_id(), winWrap);