Ariver
2026-06-19 b1368b6a51379714958af82cb1e3dc24183b0583
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import ApplicationServices
import CoreGraphics
import Foundation
 
struct PrivateWindowActivationOutcome {
    let getProcessStatus: OSStatus
    let setFrontError: CGError?
    let makeKeyFirstError: CGError?
    let makeKeySecondError: CGError?
 
    var succeeded: Bool {
        getProcessStatus == 0
            && (setFrontError == nil || setFrontError == .success)
            && (makeKeyFirstError == nil || makeKeyFirstError == .success)
            && (makeKeySecondError == nil || makeKeySecondError == .success)
    }
}
 
final class PrivateWindowActivationBridge: @unchecked Sendable {
    enum BridgeError: Error {
        case frameworkUnavailable
        case symbolUnavailable(String)
    }
 
    private typealias SLPSSetFrontProcessWithOptionsFunction = @convention(c) (
        UnsafeMutablePointer<ProcessSerialNumber>,
        CGWindowID,
        UInt32
    ) -> CGError
    private typealias SLPSPostEventRecordToFunction = @convention(c) (
        UnsafeMutablePointer<ProcessSerialNumber>,
        UnsafeMutablePointer<UInt8>
    ) -> CGError
 
    static let shared = try? PrivateWindowActivationBridge()
 
    private let handle: UnsafeMutableRawPointer?
    private let setFrontProcessWithOptions: SLPSSetFrontProcessWithOptionsFunction
    private let postEventRecordTo: SLPSPostEventRecordToFunction
 
    private init() throws {
        guard let handle = dlopen("/System/Library/PrivateFrameworks/SkyLight.framework/SkyLight", RTLD_LAZY) else {
            throw BridgeError.frameworkUnavailable
        }
 
        self.handle = handle
        self.setFrontProcessWithOptions = try Self.symbol("_SLPSSetFrontProcessWithOptions", in: handle)
        self.postEventRecordTo = try Self.symbol("SLPSPostEventRecordTo", in: handle)
    }
 
    deinit {
        if let handle {
            dlclose(handle)
        }
    }
 
    func activate(processIdentifier: Int32, windowID: UInt32) -> PrivateWindowActivationOutcome {
        var psn = ProcessSerialNumber()
        let getProcessStatus = GetProcessForPID(pid_t(processIdentifier), &psn)
        guard getProcessStatus == 0 else {
            return PrivateWindowActivationOutcome(
                getProcessStatus: getProcessStatus,
                setFrontError: nil,
                makeKeyFirstError: nil,
                makeKeySecondError: nil
            )
        }
 
        let cgWindowID = CGWindowID(windowID)
        let setFrontError = setFrontProcessWithOptions(&psn, cgWindowID, 0x200)
        let makeKeyErrors = makeKeyWindow(processSerialNumber: &psn, windowID: cgWindowID)
        return PrivateWindowActivationOutcome(
            getProcessStatus: getProcessStatus,
            setFrontError: setFrontError,
            makeKeyFirstError: makeKeyErrors.0,
            makeKeySecondError: makeKeyErrors.1
        )
    }
 
    private func makeKeyWindow(
        processSerialNumber: inout ProcessSerialNumber,
        windowID: CGWindowID
    ) -> (CGError, CGError) {
        var mutableWindowID = windowID
        var bytes = [UInt8](repeating: 0, count: 0xf8)
        bytes[0x04] = 0xf8
        bytes[0x3a] = 0x10
        memcpy(&bytes[0x3c], &mutableWindowID, MemoryLayout<UInt32>.size)
        memset(&bytes[0x20], 0xff, 0x10)
 
        bytes[0x08] = 0x01
        let first = bytes.withUnsafeMutableBufferPointer { buffer in
            postEventRecordTo(&processSerialNumber, buffer.baseAddress!)
        }
 
        bytes[0x08] = 0x02
        let second = bytes.withUnsafeMutableBufferPointer { buffer in
            postEventRecordTo(&processSerialNumber, buffer.baseAddress!)
        }
 
        return (first, second)
    }
 
    private static func symbol<T>(_ name: String, in handle: UnsafeMutableRawPointer) throws -> T {
        guard let rawSymbol = dlsym(handle, name) else {
            throw BridgeError.symbolUnavailable(name)
        }
 
        return unsafeBitCast(rawSymbol, to: T.self)
    }
}
 
@_silgen_name("GetProcessForPID") @discardableResult
private func GetProcessForPID(_ pid: pid_t, _ psn: UnsafeMutablePointer<ProcessSerialNumber>) -> OSStatus
 
enum PrivateAXWindowIDReader {
    static func windowID(for window: AXUIElement) -> UInt32? {
        var windowID = CGWindowID(0)
        guard _AXUIElementGetWindow(window, &windowID) == .success, windowID != 0 else {
            return nil
        }
 
        return UInt32(windowID)
    }
}
 
@_silgen_name("_AXUIElementGetWindow") @discardableResult
private func _AXUIElementGetWindow(_ axUIElement: AXUIElement, _ windowID: UnsafeMutablePointer<CGWindowID>) -> AXError