aerospace fork
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211import AppKitimport Common
@MainActorprivate var activeRefreshTask: Task<(), any Error>? = nil
@MainActorfunc scheduleCancellableCompleteRefreshSession( _ event: RefreshSessionEvent, optimisticallyPreLayoutWorkspaces: Bool = false,) { activeRefreshTask?.cancel() activeRefreshTask = Task.startUnstructured { @MainActor in try checkCancellation() await runHeavyCompleteRefreshSession( event, assumeCancellable: true, optimisticallyPreLayoutWorkspaces: optimisticallyPreLayoutWorkspaces, ) }}
@MainActorfunc runHeavyCompleteRefreshSession( _ event: RefreshSessionEvent, assumeCancellable: Bool, layoutWorkspaces shouldLayoutWorkspaces: Bool = true, optimisticallyPreLayoutWorkspaces: Bool = false,) async { let state = signposter.beginInterval(#function, "event: \(event) axTaskLocalAppThreadToken: \(axTaskLocalAppThreadToken?.idForDebug)") defer { signposter.endInterval(#function, state) } if !TrayMenuModel.shared.isEnabled { return } let res = await Result { try await $refreshSessionEvent.withValue(event) { let nativeFocused = try await getNativeFocusedWindow(.cancellable) if let nativeFocused { try await debugWindowsIfRecording(nativeFocused, .cancellable) } updateFocusCache(nativeFocused)
if shouldLayoutWorkspaces && optimisticallyPreLayoutWorkspaces { try await layoutWorkspaces() }
await refreshModel_nonCancellable() try await refresh() gcMonitors()
updateTrayText() SecureInputPanel.shared.refresh() try await normalizeLayoutReason() if shouldLayoutWorkspaces { try await layoutWorkspaces() } } } switch res { case .success(()): break case .failure(let err as CancellationError): check(assumeCancellable, "Non cancellable refresh session was canceled: \(err) (\(type(of: err)))") case .failure(let err): die("Illegal error: \(err)") }}
@MainActorfunc runLightSession<T>( _ event: RefreshSessionEvent, _: RunSessionGuard, body: @MainActor () async throws -> T,) async throws -> T { let state = signposter.beginInterval(#function, "event: \(event) axTaskLocalAppThreadToken: \(axTaskLocalAppThreadToken?.idForDebug)") defer { signposter.endInterval(#function, state) } activeRefreshTask?.cancel() // Give priority to runSession activeRefreshTask = nil return try await $refreshSessionEvent.withValue(event) { let nativeFocused = try await getNativeFocusedWindow(.cancellable) if let nativeFocused { try await debugWindowsIfRecording(nativeFocused, .cancellable) } updateFocusCache(nativeFocused) let focusBefore = focus.windowOrNil
await refreshModel_nonCancellable() let result = try await body() await refreshModel_nonCancellable()
let focusAfter = focus.windowOrNil
updateTrayText() SecureInputPanel.shared.refresh() if !event.isFocusFollowsMouse { try await layoutWorkspaces() } if focusBefore != focusAfter { focusAfter?.nativeFocus() // syncFocusToMacOs } if !event.isFocusFollowsMouse { scheduleCancellableCompleteRefreshSession(event) } return result }}
struct RunSessionGuard: Sendable { @MainActor static var isServerEnabled: RunSessionGuard? { TrayMenuModel.shared.isEnabled ? forceRun : nil } @MainActor static func isServerEnabled(orIsEnableCommand command: (any Command)?) -> RunSessionGuard? { command is EnableCommand ? .forceRun : .isServerEnabled } @MainActor static func checkServerIsEnabledOrDie( file: StaticString = #fileID, line: Int = #line, column: Int = #column, function: String = #function, ) -> RunSessionGuard { .isServerEnabled ?? dieT("server is disabled", file: file, line: line, column: column, function: function) } static let forceRun = RunSessionGuard() private init() {}}
@MainActorfunc refreshModel_nonCancellable() async { if refreshSessionEvent?.isFocusFollowsMouse == true { await checkOnFocusChangedCallbacks_nonCancellable() } else { Workspace.garbageCollectUnusedWorkspaces() await checkOnFocusChangedCallbacks_nonCancellable() normalizeContainers() }}
@MainActorprivate func refresh() async throws { // Garbage collect terminated apps and windows before working with all windows let mapping = try await MacApp.refreshAllAndGetAliveWindowIds(frontmostAppBundleId: NSWorkspace.shared.frontmostApplication?.bundleIdentifier) let aliveWindowIds = mapping.values.flatMap(id).toSet()
for window in MacWindow.allWindows { if !aliveWindowIds.contains(window.windowId) { window.garbageCollect(skipClosedWindowsCache: false) } } for (app, windowIds) in mapping { for windowId in windowIds { try await MacWindow.getOrRegister(windowId: windowId, macApp: app) } }
// Garbage collect workspaces after apps, because workspaces contain apps. Workspace.garbageCollectUnusedWorkspaces()}
func refreshObs(_: AXObserver, _: AXUIElement, notif: CFString, _: UnsafeMutableRawPointer?) { let notif = notif as String Task.startUnstructured { @MainActor in if !TrayMenuModel.shared.isEnabled { return } scheduleCancellableCompleteRefreshSession(.ax(notif)) }}
enum OptimalHideCorner { case bottomLeftCorner, bottomRightCorner}
@MainActorprivate func layoutWorkspaces() async throws { if !TrayMenuModel.shared.isEnabled { for workspace in Workspace.all { workspace.allLeafWindowsRecursive.forEach { ($0 as! MacWindow).unhideFromCorner() } // todo as! try await workspace.layoutWorkspace() // Unhide tiling windows from corner } return } let monitors = monitorInfos var monitorToOptimalHideCorner: [CGPoint: OptimalHideCorner] = [:] for monitor in monitors { let xOff = monitor.width * 0.1 let yOff = monitor.height * 0.1 // brc = bottomRightCorner let brc1 = monitor.rect.bottomRightCorner + CGPoint(x: 2, y: -yOff) let brc2 = monitor.rect.bottomRightCorner + CGPoint(x: -xOff, y: 2) let brc3 = monitor.rect.bottomRightCorner + CGPoint(x: 2, y: 2)
// blc = bottomLeftCorner let blc1 = monitor.rect.bottomLeftCorner + CGPoint(x: -2, y: -yOff) let blc2 = monitor.rect.bottomLeftCorner + CGPoint(x: xOff, y: 2) let blc3 = monitor.rect.bottomLeftCorner + CGPoint(x: -2, y: 2)
func contains(_ monitor: MonitorInfo, _ point: CGPoint) -> Int { monitor.rect.contains(point) ? 1 : 0 } let important = 10
let corner: OptimalHideCorner = monitors.sumOfInt { contains($0, blc1) + contains($0, blc2) + important * contains($0, blc3) } < monitors.sumOfInt { contains($0, brc1) + contains($0, brc2) + important * contains($0, brc3) } ? .bottomLeftCorner : .bottomRightCorner monitorToOptimalHideCorner[monitor.rect.topLeftCorner] = corner }
// to reduce flicker, first unhide visible workspaces, then hide invisible ones for monitor in monitors { let workspace = monitor.activeWorkspace workspace.allLeafWindowsRecursive.forEach { ($0 as! MacWindow).unhideFromCorner() } // todo as! try await workspace.layoutWorkspace() } for workspace in Workspace.all where !workspace.isVisible { let corner = monitorToOptimalHideCorner[workspace.workspaceMonitor.rect.topLeftCorner] ?? .bottomRightCorner for window in workspace.allLeafWindowsRecursive { try await (window as! MacWindow).hideInCorner(corner) // todo as! } }}
@MainActorprivate func normalizeContainers() { // Can't do it only for visible workspace because most of the commands support --window-id and --workspace flags for workspace in Workspace.all { workspace.normalizeContainers() }}