mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 18:37:24 +00:00
macOS only enumerated on-screen windows and dropped minimized AX windows, so an app whose window was minimized, hidden or on another Space (any full-screen app) could not be observed, and agents fell back to --restore-window, which activated every window of the app and switched the user's Space. Enumerate every window, keep the off-screen ones accessibility can still read (other-Space windows by remote token, closed windows dropped by their Space membership), and report their real minimized and off-screen state. Background pointer and key input on such a window refuses before sending anything. --restore-window now raises only the target window, once per request, and delivery is measured from whether the target became frontmost.
41 lines
1.8 KiB
Swift
41 lines
1.8 KiB
Swift
import CoreGraphics
|
|
import Darwin
|
|
import Foundation
|
|
|
|
/// Which windows belong to a Space. Minimized, hidden and other-Space windows do; a closed window an app keeps around does not.
|
|
public enum WindowSpaces {
|
|
/// Nil when SkyLight's lookup is missing, so closed windows can't be told apart from other-Space ones.
|
|
public static func windowsInAnySpace(_ windowIDs: [CGWindowID]) -> Set<CGWindowID>? {
|
|
guard let symbols else { return nil }
|
|
let connection = symbols.mainConnection()
|
|
return Set(windowIDs.filter { windowID in
|
|
let spaces = symbols.copySpacesForWindows(connection, allSpacesMask, [NSNumber(value: windowID)] as CFArray)?
|
|
.takeRetainedValue() as? [NSNumber]
|
|
return spaces?.isEmpty == false
|
|
})
|
|
}
|
|
|
|
private static let allSpacesMask: Int32 = 0x7
|
|
|
|
private typealias MainConnectionID = @convention(c) () -> Int32
|
|
private typealias CopySpacesForWindows = @convention(c) (Int32, Int32, CFArray) -> Unmanaged<CFArray>?
|
|
|
|
private struct Symbols {
|
|
let mainConnection: MainConnectionID
|
|
let copySpacesForWindows: CopySpacesForWindows
|
|
}
|
|
|
|
private static let symbols: Symbols? = {
|
|
let skyLight = dlopen("/System/Library/PrivateFrameworks/SkyLight.framework/SkyLight", RTLD_LAZY)
|
|
guard let main = dlsym(skyLight, "SLSMainConnectionID"),
|
|
let copy = dlsym(skyLight, "SLSCopySpacesForWindows")
|
|
else { return nil }
|
|
// SAFETY: SkyLight exports CGSConnectionID SLSMainConnectionID(void) and
|
|
// CFArrayRef SLSCopySpacesForWindows(CGSConnectionID, CGSSpaceMask, CFArrayRef), returning a +1 array (as yabai uses them).
|
|
return Symbols(
|
|
mainConnection: unsafeBitCast(main, to: MainConnectionID.self),
|
|
copySpacesForWindows: unsafeBitCast(copy, to: CopySpacesForWindows.self)
|
|
)
|
|
}()
|
|
}
|