fix: some apps have messy launch behavior

See discussion: https://github.com/lwouis/alt-tab-macos/issues/117#issuecomment-583868046
This commit is contained in:
louis.pontoise authored and lwouis committed 2020-03-10 14:00:37 +09:00
1 parent 6c440a7926
commit 7eb216d43c
2 files changed
+17 -13

No files matched your search

+7 -5
View File
@@ -49,13 +49,15 @@ extension AXUIElement {
return attribute(kAXSubroleAttribute, String.self)
}
func subscribeWithRetry(_ axObserver: AXObserver, _ notification: String, _ pointer: UnsafeMutableRawPointer?) {
func subscribeWithRetry(_ axObserver: AXObserver, _ notification: String, _ pointer: UnsafeMutableRawPointer?, _ callback: (() -> Void)? = nil, _ previousResult: AXError? = nil) {
let result = AXObserverAddNotification(axObserver, self, notification as CFString, pointer)
if result != .success && result != .notificationUnsupported && result != .notificationAlreadyRegistered {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(10), execute: {
self.subscribeWithRetry(axObserver, notification, pointer)
})
if result == .success || result == .notificationUnsupported || result == .notificationAlreadyRegistered {
callback?()
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(10), execute: {
self.subscribeWithRetry(axObserver, notification, pointer, callback, result)
})
}
private func attribute<T>(_ key: String, _ type: T.Type) -> T? {
+10 -8
View File
@@ -4,6 +4,7 @@ class Application: NSObject {
var runningApplication: NSRunningApplication
var axUiElement: AXUIElement?
var axObserver: AXObserver?
var isReallyFinishedLaunching = false
init(_ runningApplication: NSRunningApplication) {
self.runningApplication = runningApplication
@@ -22,13 +23,7 @@ class Application: NSObject {
private func addAndObserveWindows() {
axUiElement = AXUIElementCreateApplication(runningApplication.processIdentifier)
AXObserverCreate(runningApplication.processIdentifier, axObserverCallback, &axObserver)
observeAllWindows()
}
private func observeAllWindows() {
let windows = getActualWindows()
debugPrint("Adding app: " + (runningApplication.bundleIdentifier ?? "nil"), windows.map { $0.title() })
addWindows(windows)
debugPrint("Adding app: " + (runningApplication.bundleIdentifier ?? "nil"))
observeEvents()
}
@@ -65,7 +60,14 @@ class Application: NSObject {
kAXApplicationHiddenNotification,
kAXApplicationShownNotification,
] {
axUiElement!.subscribeWithRetry(axObserver, notification, selfPointer)
axUiElement!.subscribeWithRetry(axObserver, notification, selfPointer, {
// some apps have `isFinishedLaunching == true` but are actually not finished, and will return .cannotComplete
// we consider them ready when the first subscription succeeds, and list their windows again at that point
if !self.isReallyFinishedLaunching {
self.isReallyFinishedLaunching = true
self.observeNewWindows()
}
})
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(axObserver), .defaultMode)
}