Ariver
2026-06-12 6f0ede789115d393e1236d98776e91fb52c90c79
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
@preconcurrency import ApplicationServices
import CoreGraphics
import Foundation
 
private let axTrustedCheckOptionPromptKey =
    kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String
 
public enum PermissionKind: String, CaseIterable, Equatable, Sendable {
    case accessibility
    case screenRecording
}
 
public enum PermissionStatus: Equatable, Sendable {
    case granted
    case notGranted
}
 
public protocol SystemPermissionChecking {
    func status(for kind: PermissionKind) -> PermissionStatus
}
 
public protocol SystemPermissionRequesting {
    @discardableResult
    func request(_ kind: PermissionKind) -> PermissionStatus
}
 
public protocol SystemPermissionManaging: SystemPermissionChecking, SystemPermissionRequesting {}
 
public struct SystemPermissionChecker: SystemPermissionManaging {
    public init() {}
 
    public func status(for kind: PermissionKind) -> PermissionStatus {
        switch kind {
        case .accessibility:
            return AXIsProcessTrusted() ? .granted : .notGranted
        case .screenRecording:
            return CGPreflightScreenCaptureAccess() ? .granted : .notGranted
        }
    }
 
    @discardableResult
    public func request(_ kind: PermissionKind) -> PermissionStatus {
        switch kind {
        case .accessibility:
            let options = [axTrustedCheckOptionPromptKey: true] as CFDictionary
            return AXIsProcessTrustedWithOptions(options) ? .granted : .notGranted
        case .screenRecording:
            return CGRequestScreenCaptureAccess() ? .granted : .notGranted
        }
    }
}