Mission Control Turbo: macOS multitasking turbocharged
1import AppKit
2import ApplicationServices
3
4/// Bridge to macOS Accessibility APIs for window activation and title retrieval.
5enum AccessibilityBridge {
6 /// Check if we have Accessibility permission.
7 static var hasPermission: Bool {
8 AXIsProcessTrusted()
9 }
10
11 /// Prompt the user to grant Accessibility permission if not already granted.
12 static func requestPermissionIfNeeded() {
13 let options = [kAXTrustedCheckOptionPrompt.takeUnretainedValue(): true] as CFDictionary
14 AXIsProcessTrustedWithOptions(options)
15 }
16
17 /// Activate the window with the given window ID and PID.
18 static func activateWindow(pid: pid_t, windowID: CGWindowID) -> Bool {
19 guard let app = NSRunningApplication(processIdentifier: pid) else { return false }
20
21 // Activate the application
22 app.activate()
23
24 // Use Accessibility to raise the specific window
25 let appElement = AXUIElementCreateApplication(pid)
26 var windowsRef: CFTypeRef?
27 let result = AXUIElementCopyAttributeValue(appElement, kAXWindowsAttribute as CFString, &windowsRef)
28 guard result == .success, let axWindows = windowsRef as? [AXUIElement] else {
29 return true // App activated but couldn't raise specific window
30 }
31
32 for axWindow in axWindows {
33 if let cgWindowID = axWindowID(for: axWindow), cgWindowID == windowID {
34 AXUIElementPerformAction(axWindow, kAXRaiseAction as CFString)
35 return true
36 }
37 }
38
39 return true
40 }
41
42 /// Get the title of a window via Accessibility (fallback when CGWindowList doesn't have it).
43 static func windowTitle(pid: pid_t, windowID: CGWindowID) -> String? {
44 let appElement = AXUIElementCreateApplication(pid)
45 var windowsRef: CFTypeRef?
46 let result = AXUIElementCopyAttributeValue(appElement, kAXWindowsAttribute as CFString, &windowsRef)
47 guard result == .success, let axWindows = windowsRef as? [AXUIElement] else {
48 return nil
49 }
50
51 for axWindow in axWindows {
52 if let cgWinID = axWindowID(for: axWindow), cgWinID == windowID {
53 var titleRef: CFTypeRef?
54 let titleResult = AXUIElementCopyAttributeValue(axWindow, kAXTitleAttribute as CFString, &titleRef)
55 if titleResult == .success, let title = titleRef as? String {
56 return title
57 }
58 }
59 }
60 return nil
61 }
62
63 /// Move a window to a new position using AXUIElement.
64 /// The point should be in Quartz coordinates (top-left origin).
65 static func moveWindow(pid: pid_t, windowID: CGWindowID, to point: CGPoint) -> Bool {
66 let appElement = AXUIElementCreateApplication(pid)
67 var windowsRef: CFTypeRef?
68 let result = AXUIElementCopyAttributeValue(appElement, kAXWindowsAttribute as CFString, &windowsRef)
69 guard result == .success, let axWindows = windowsRef as? [AXUIElement] else {
70 return false
71 }
72
73 for axWindow in axWindows {
74 if let cgWinID = axWindowID(for: axWindow), cgWinID == windowID {
75 var position = point
76 guard let axValue = AXValueCreate(.cgPoint, &position) else { return false }
77 let setResult = AXUIElementSetAttributeValue(axWindow, kAXPositionAttribute as CFString, axValue)
78 return setResult == .success
79 }
80 }
81 return false
82 }
83
84 // MARK: - Private
85
86 /// Map an AXUIElement to a CGWindowID using the private _AXUIElementGetWindow API.
87 private static func axWindowID(for element: AXUIElement) -> CGWindowID? {
88 var windowID: CGWindowID = 0
89 let result = _AXUIElementGetWindow(element, &windowID)
90 return result == .success ? windowID : nil
91 }
92}
93
94// Private API declaration — widely used by AltTab, Rectangle, yabai, etc.
95@_silgen_name("_AXUIElementGetWindow")
96func _AXUIElementGetWindow(_ element: AXUIElement, _ windowID: UnsafeMutablePointer<CGWindowID>) -> AXError