aerospace fork
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960import AppKitimport Common
/// The subscription is active as long as you keep this class in memoryfinal class AxSubscription { let obs: AXObserver let ax: AXUIElement let axThreadToken: AxAppThreadToken = axTaskLocalAppThreadToken ?? dieT("axTaskLocalAppThreadToken is not initialized") var notifKeys: Set<String> = []
private init(obs: AXObserver, ax: AXUIElement) { axThreadToken.checkEquals(axTaskLocalAppThreadToken) self.obs = obs self.ax = ax }
private func subscribe(_ key: String) throws -> Bool { axThreadToken.checkEquals(axTaskLocalAppThreadToken) if AXObserverAddNotification(obs, ax, key as CFString, nil) == .success { notifKeys.insert(key) return true } else { return false } }
static func bulkSubscribe( _ nsApp: NSRunningApplication, _ ax: AXUIElement, _ job: RunLoopJob, _ handlerToNotifKeyMapping: HandlerToNotifKeyMapping, ) throws -> [AxSubscription] { var result: [AxSubscription] = [] var visitedNotifKeys: Set<String> = [] for unsafe (handler, notifKeys) in unsafe handlerToNotifKeyMapping { try job.checkCancellation() guard let obs = unsafe AXObserver.new(nsApp.processIdentifier, handler) else { return [] } let subscription = AxSubscription(obs: obs, ax: ax) for key: String in notifKeys { try job.checkCancellation() assert(visitedNotifKeys.insert(key).inserted) if try !subscription.subscribe(key) { return [] } } CFRunLoopAddSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(obs), .defaultMode) result.append(subscription) } return result }
deinit { axThreadToken.checkEquals(axTaskLocalAppThreadToken) CFRunLoopRemoveSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(obs), .defaultMode) for notifKey in notifKeys { AXObserverRemoveNotification(obs, ax, notifKey as CFString) } }}
typealias HandlerToNotifKeyMapping = [(AXObserverCallback, [String])]