Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

AXWrapper

AXWrapper is a lightweight Swift package that wraps the native macOS Accessibility APIs.

It is intended to be used as a small dependency in other macOS projects that need:

  • AXUIElement access
  • typed AX attribute reads and writes
  • AX actions
  • AXObserver wrappers
  • accessibility permission helpers

Requirements

  • macOS 14+
  • Swift 6.2+

Add As A Package

Local package

dependencies: [
    .package(path: "/absolute/path/to/ax-monitor")
]

Git package

dependencies: [
    .package(url: "https://your-git-url.git", branch: "main")
]

Then add the product to your target:

.target(
    name: "YourApp",
    dependencies: [
        .product(name: "AXWrapper", package: "AXWrapper")
    ]
)

Import it with:

import AXWrapper

Quickstart

Check permissions

import AXWrapper

@MainActor
func ensurePermissions() -> Bool {
    AXPermissionHelpers.hasAccessibilityPermissions()
}

To prompt for accessibility access:

import AXWrapper

@MainActor
func requestPermissions() -> Bool {
    AXPermissionHelpers.askForAccessibilityIfNeeded()
}

Read the focused app and focused element

import AXWrapper

@MainActor
func printFocusedElement() throws {
    let appElement = try AXUIElement.focusedApplication()
    let app = Element(appElement)

    print("App role:", app.role() ?? "unknown")
    print("Focused element:", app.focusedUIElement()?.briefDescription() ?? "none")
}

Read attributes

import AXWrapper

@MainActor
func inspect(_ element: Element) {
    print("Role:", element.role() ?? "nil")
    print("Title:", element.title() ?? "nil")
    print("Identifier:", element.identifier() ?? "nil")
    print("Frame:", String(describing: element.frame()))
}

Traverse children

import AXWrapper

@MainActor
func dumpChildren(_ element: Element) {
    let children = element.children() ?? []
    for child in children {
        print(child.briefDescription())
    }
}

Perform actions

import AXWrapper

@MainActor
func press(_ element: Element) throws {
    try element.performAction(.press)
}

Set values

import AXWrapper

@MainActor
func setText(_ element: Element, value: String) {
    _ = element.setValue(value, forAttribute: AXAttributeNames.kAXValueAttribute)
}

AXObserver Usage

Watch a specific element

import AXWrapper

@MainActor
func watch(_ element: Element) throws -> NotificationWatcher {
    let watcher = NotificationWatcher(forElement: element, notification: .valueChanged) {
        pid,
        notification,
        rawElement,
        userInfo in

        let wrapped = Element(rawElement)
        print("PID:", pid)
        print("Notification:", notification.rawValue)
        print("Element:", wrapped.briefDescription())
        print("User info:", userInfo ?? [:])
    }

    try watcher.start()
    return watcher
}

Subscribe directly through AXObserverCenter

import AXWrapper

@MainActor
func subscribeToApp(pid: pid_t) {
    let result = AXObserverCenter.shared.subscribe(
        pid: pid,
        notification: .focusedUIElementChanged
    ) { pid, notification, rawElement, userInfo in
        print(pid, notification.rawValue, Element(rawElement).briefDescription(), userInfo ?? [:])
    }

    print(result)
}

Main Types

  • Element: Swift wrapper around AXUIElement
  • Attribute<T>: typed AX attribute key
  • AXPermissionHelpers: accessibility trust helpers
  • AXObserverCenter: subscription-based AXObserver wrapper
  • AXObserverManager: lower-level observer manager
  • NotificationWatcher: lifecycle wrapper for a single observation

Build

swift build

About

Minimal wrapper for the macos accessibility api

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages