From 82ec7bee5fd01fec85c998b34bd6df2e4052825b Mon Sep 17 00:00:00 2001 From: Nikita Bobko Date: Wed, 27 Nov 2024 01:23:06 +0100 Subject: [PATCH] 5/n Reorganize FrozenTreeNode and closedWindowsCache --- .../tree/frozen/FrozenTreeNode.swift | 46 +++++++++++++ .../AppBundle/tree/frozen/FrozenWindow.swift | 0 ...zenTree.swift => closedWindowsCache.swift} | 66 +++---------------- 3 files changed, 56 insertions(+), 56 deletions(-) create mode 100644 Sources/AppBundle/tree/frozen/FrozenTreeNode.swift delete mode 100644 Sources/AppBundle/tree/frozen/FrozenWindow.swift rename Sources/AppBundle/tree/frozen/{FrozenTree.swift => closedWindowsCache.swift} (76%) diff --git a/Sources/AppBundle/tree/frozen/FrozenTreeNode.swift b/Sources/AppBundle/tree/frozen/FrozenTreeNode.swift new file mode 100644 index 00000000..4ed1744a --- /dev/null +++ b/Sources/AppBundle/tree/frozen/FrozenTreeNode.swift @@ -0,0 +1,46 @@ +import AppKit +import Common + +enum FrozenTreeNode { + case container(FrozenContainer) + case window(FrozenWindow) +} + +struct FrozenContainer { + let children: [FrozenTreeNode] + let layout: Layout + let orientation: Orientation + let weight: CGFloat + + init(_ container: TilingContainer) { + children = container.children.map { + switch $0.nodeCases { + case .window(let w): .window(FrozenWindow(w)) + case .tilingContainer(let c): .container(FrozenContainer(c)) + case .workspace, + .macosMinimizedWindowsContainer, + .macosHiddenAppsWindowsContainer, + .macosFullscreenWindowsContainer, + .macosPopupWindowsContainer: + illegalChildParentRelation(child: $0, parent: container) + } + } + layout = container.layout + orientation = container.orientation + weight = getWeightOrNil(container) ?? 1 + } +} + +struct FrozenWindow { + let id: UInt32 + let weight: CGFloat + + init(_ window: Window) { + id = window.windowId + weight = getWeightOrNil(window) ?? 1 + } +} + +private func getWeightOrNil(_ node: TreeNode) -> CGFloat? { + ((node.parent as? TilingContainer)?.orientation).map { node.getWeight($0) } +} diff --git a/Sources/AppBundle/tree/frozen/FrozenWindow.swift b/Sources/AppBundle/tree/frozen/FrozenWindow.swift deleted file mode 100644 index e69de29b..00000000 diff --git a/Sources/AppBundle/tree/frozen/FrozenTree.swift b/Sources/AppBundle/tree/frozen/closedWindowsCache.swift similarity index 76% rename from Sources/AppBundle/tree/frozen/FrozenTree.swift rename to Sources/AppBundle/tree/frozen/closedWindowsCache.swift index 66dcf4e9..1e9539f6 100644 --- a/Sources/AppBundle/tree/frozen/FrozenTree.swift +++ b/Sources/AppBundle/tree/frozen/closedWindowsCache.swift @@ -1,5 +1,12 @@ import AppKit -import Common + +/// First line of defence against lock screen +/// +/// When you lock the screen, all accessibility API becomes unobservable (all attributes become empty, window id +/// becomes nil, etc.) which tricks AeroSpace into thinking that all windows were closed. +/// That's why every time a window dies AeroSpace caches the "entire world" (unless window is already presented in the cache) +/// so that once the screen is unlocked, AeroSpace could restore windows to where they were +private var closedWindowsCache = FrozenWorld(workspaces: [], monitors: []) struct FrozenMonitor { let topLeftCorner: CGPoint @@ -25,62 +32,10 @@ struct FrozenWorkspace { floatingWindows = workspace.floatingWindows.map(FrozenWindow.init) macosUnconventionalWindows = workspace.macOsNativeHiddenAppsWindowsContainer.children.map { FrozenWindow($0 as! Window) } + - workspace.macOsNativeFullscreenWindowsContainer.children.map { FrozenWindow($0 as! Window) } - } -} - -enum FrozenTreeNode { - case container(FrozenContainer) - case window(FrozenWindow) -} - -struct FrozenContainer { - let children: [FrozenTreeNode] - let layout: Layout - let orientation: Orientation - let weight: CGFloat - - init(_ container: TilingContainer) { - children = container.children.map { - switch $0.nodeCases { - case .window(let w): .window(FrozenWindow(w)) - case .tilingContainer(let c): .container(FrozenContainer(c)) - case .workspace, - .macosMinimizedWindowsContainer, - .macosHiddenAppsWindowsContainer, - .macosFullscreenWindowsContainer, - .macosPopupWindowsContainer: - illegalChildParentRelation(child: $0, parent: container) - } - } - layout = container.layout - orientation = container.orientation - weight = getWeightOrNil(container) ?? 1 + workspace.macOsNativeFullscreenWindowsContainer.children.map { FrozenWindow($0 as! Window) } } } -struct FrozenWindow { - let id: UInt32 - let weight: CGFloat - - init(_ window: Window) { - id = window.windowId - weight = getWeightOrNil(window) ?? 1 - } -} - -func getWeightOrNil(_ node: TreeNode) -> CGFloat? { - ((node.parent as? TilingContainer)?.orientation).map { node.getWeight($0) } -} - -/// First line of defence against lock screen -/// -/// When you lock the screen, all accessibility API becomes unobservable (all attributes become empty, window id -/// becomes nil, etc.) which tricks AeroSpace into thinking that all windows were closed. -/// That's why every time a window dies AeroSpace caches the "entire world" (unless window is already presented in the cache) -/// so that once the screen is unlocked, AeroSpace could restore windows to where they were -private var closedWindowsCache = FrozenWorld(workspaces: [], monitors: []) - func cacheClosedWindowIfNeeded(window: Window) { if closedWindowsCache.windowIds.contains(window.windowId) { return // already cached @@ -134,8 +89,7 @@ private func restoreTreeRecursive(frozenContainer: FrozenContainer, parent: NonL index: index ) - loop: - for (index, child) in frozenContainer.children.enumerated() { + loop: for (index, child) in frozenContainer.children.enumerated() { switch child { case .window(let w): // Stop the loop if can't find the window, because otherwise all the subsequent windows will have incorrect index