Skip to content
/ ZMAX Public
forked from zumuya/ZMAX

Bridging AX (Accessibility) APIs to Swift.

License

Notifications You must be signed in to change notification settings

soundflix/ZMAX

 
 

Repository files navigation

ZMAX

ZMAX is a framework that bridges AX (Accessibility) APIs to Swift.

  • Requirements: OS X 10.15 or later
  • Swift version: 5.2

Installation

Carthage

To install this framework using Carthage, add the following line to your Cartfile.

github "soundflix/ZMAX"

General usage

Getting an application element

let runningApps = NSWorkspace.shared.runningApplications
if let safariApp = runningApps.first(where: { $0.bundleIdentifier == "com.apple.Safari" }) {
	let safari = safariApp.accessibilityElement
}

Getting an attribute

let windows = try safari.getAttribute(for: .windows) as [AXUIElement]

Performing an action

try minimizeButton.performAction(.press)

Example: Pressing minimize buttons in Safari

let runningApps = NSWorkspace.shared.runningApplications
if let safariApp = runningApps.first(where: { $0.bundleIdentifier == "com.apple.Safari" }) {
	let safari = safariApp.accessibilityElement
	
	let windows = try safari.getAttribute(for: .windows) as [AXUIElement]
	for window in windows {
		let minimizeButton = try window.getAttribute(for: .minimizeButton) as AXUIElement
		try minimizeButton.performAction(.press)
	}
}

Observing

Example: Observing focused UI element changes in Safari

let runningApps = NSWorkspace.shared.runningApplications
if let safariApp = runningApps.first(where: { $0.bundleIdentifier == "com.apple.Safari" }) {
	let safari = safariApp.accessibilityElement
	
	let observer = try safariApp.newAccessibilityObserver()
	try observer.observe(element: safari, notification: .focusedUiElementChanged) { element, changes in
		if let role = try? element.getAttribute(for: .role) as String {
			print("focused element changed to \(role).")
		}
	}
	self.safariObserver = observer //keep it!
}

Using original APIs

Since this framework just extends original AXUIElement type, you can use original APIs without casting.

let axError = AXUIElementPerformAction(minimizeButton, (kAXPressAction as CFString))

Error

This framework extends AXError with LocalizedError protocol.

Throwing

You can throw an AXError as a Swift error.

let axError = AXUIElementPerformAction(minimizeButton, (kAXPressAction as CFString))
if (axError != .success) {
	throw axError
}

Throwing with method

By using AXError.throwIfNotSuccess() method, you can call existing functions with try keyword.

try AXUIElementPerformAction(finder.accessibilityElement, kAXPressAction as CFString).throwIfNotSuccess()

Localizing messages

This framework doesn't contain any localization for error messages. But you can provide and customize messages.

AXError.localizedDescriptionHandlers.append { error in
	NSLocalizedString(String(format: "AXError_description_%i", error.rawValue), comment: "")
}
AXError.recoverySuggestionHandlers.append { error in
	NSLocalizedString(String(format: "AXError_recoverySuggestion_%i", error.rawValue), comment: "")
}

Troubleshooting

When it doesn't work, check following:

  • Your app is not limited to use accessibility APIs by sandbox.
  • Your app is allowed to use accessibility APIs in System Preferences.

License

This framework is distributed under the terms of the MIT License.

About

Bridging AX (Accessibility) APIs to Swift.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 100.0%