-
-
Notifications
You must be signed in to change notification settings - Fork 178
Expand file tree
/
Copy pathAXHelpers.swift
More file actions
74 lines (62 loc) · 2.15 KB
/
Copy pathAXHelpers.swift
File metadata and controls
74 lines (62 loc) · 2.15 KB
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//
// AXHelpers.swift
// Project: Thaw
//
// Copyright (Ice) © 2023–2025 Jordan Baird
// Copyright (Thaw) © 2026 Toni Förster
// Licensed under the GNU GPLv3
@preconcurrency import AXSwift
import Cocoa
enum AXHelpers {
private static let queue = DispatchQueue.targetingGlobal(
label: "AXHelpers.queue",
qos: .userInteractive,
attributes: .concurrent
)
@discardableResult
static func isProcessTrusted(prompt: Bool = false) -> Bool {
queue.sync { checkIsProcessTrusted(prompt: prompt) }
}
static func element(at point: CGPoint) -> UIElement? {
queue.sync { try? systemWideElement.elementAtPosition(Float(point.x), Float(point.y)) }
}
static func application(for runningApp: NSRunningApplication) -> Application? {
queue.sync { Application(runningApp) }
}
static func extrasMenuBar(for app: Application) -> UIElement? {
queue.sync { try? app.attribute(.extrasMenuBar) }
}
static func children(for element: UIElement) -> [UIElement] {
queue.sync { try? element.arrayAttribute(.children) } ?? []
}
static func isEnabled(_ element: UIElement) -> Bool {
queue.sync { try? element.attribute(.enabled) } ?? false
}
static func frame(for element: UIElement) -> CGRect? {
queue.sync { try? element.attribute(.frame) }
}
static func role(for element: UIElement) -> Role? {
queue.sync { try? element.role() }
}
static func pid(for element: UIElement) -> pid_t? {
queue.sync {
var pid: pid_t = 0
let result = AXUIElementGetPid(element.element, &pid)
return result == .success ? pid : nil
}
}
/// Performs the press action on the given element, returning whether it
/// succeeded. Used to open the menus of Electron/Chromium tray items, which
/// ignore synthetic mouse clicks.
@discardableResult
static func press(_ element: UIElement) -> Bool {
queue.sync {
do {
try element.performAction(.press)
return true
} catch {
return false
}
}
}
}