Skip to content

Commit

Permalink
fix: some apps have messy launch behavior
Browse files Browse the repository at this point in the history
See discussion: #117 (comment)
  • Loading branch information
louis.pontoise committed Feb 9, 2020
1 parent 5d36e04 commit e4a1523
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 13 deletions.
12 changes: 7 additions & 5 deletions alt-tab-macos/api-wrappers/AXUIElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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? {
Expand Down
18 changes: 10 additions & 8 deletions alt-tab-macos/logic/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
}

Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit e4a1523

Please sign in to comment.