Skip to content

feat(macos): add list_windows and a window_id for get_app_state - #124

Open
hyprcat wants to merge 1 commit into
iFurySt:mainfrom
hyprcat:feat/list-windows
Open

hyprcat wants to merge 1 commit into
iFurySt:mainfrom
hyprcat:feat/list-windows

Conversation

@hyprcat

@hyprcat hyprcat commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

What

  • New macOS tool list_windows {app}: lists a running app's windows as accessibility reports them on the current Space: window_id (the CGWindowID query already takes), title, subrole, focused, minimized, bounds (screen points). It never launches, activates or raises the app.
  • get_app_state takes window_id: the tree, screenshot, focus and selection come from that window, which is not activated or raised. Later actions and their read-back stay on it until get_app_state is called without window_id; if the window closes, the read-back returns the key window. An unknown id is an error.
  • When the bound window isn't the key window, focus held in another window isn't reported, so type_text refuses instead of typing into the other window; key_method: "sky_key" types into the bound window.
  • JS: app.listWindows(), app.getAXState({ windowId }).
  • Linux/Windows: list_windows is not exposed (unsupportedTool, like query / select_text), and get_app_state rejects window_id.

Why

Relates to #83, finding 1. get_app_state always reads the app's focused window, and nothing lets a caller see or pick another one; query already accepted a window_id, but nothing returned one. The binding has to cover action read-back, otherwise a click's result switches back to the focused window, replaces the cached snapshot, and the next index lands in the other window again. Window-scoped indexes (the larger API question in #83) are not part of this.

Verification

  • swift test: 383 tests, 7 skipped, 0 failures. New tests: tool list and schema, invalid window_id values, missing app, an absent app returning appNotFound without being launched, list_windows failing on a revoked lease before resolving the app.
  • Node REPL: 45 passed. Go: the new Linux/Windows tests pass; go vet passes for both.
  • Live, on a non-activating two-window test app: the default read gives A; window_id=B gives B; clicking B's button reads back B with the change; type_text refuses while A's field holds focus; sky_key types into B; an unknown id errors; the front app is unchanged.

Notes

  • press_key with the default method still goes to the app's key window when another window is bound (documented; only type_text refuses).
  • fix(macos): root the snapshot at the app's focused sheet #118 also touches windowElement(for:) (to find sheets); the two compose, and whichever merges second needs a small rebase.

get_app_state always reads the app's focused window, and nothing lets a
caller see or pick another one (iFurySt#83, finding 1). list_windows lists a
running app's windows as accessibility reports them on the current Space,
with the CGWindowID that query already takes as window_id, plus title,
subrole, focused, minimized and bounds. It never launches, activates or
raises the app.

get_app_state takes the same window_id and roots the snapshot at that
window through the existing _AXUIElementGetWindow binding: no activation,
no raise, no title fallback to another window. Follow-up reads (action
read-back, sky_key read-back) stay on that window until get_app_state is
called without window_id, or fall back to the key window once it closes.
Focus held in another window is not reported for a bound window, so
type_text refuses instead of writing into the other window.

Linux and Windows do not expose list_windows (unsupportedTool, like query
and select_text) and reject window_id on get_app_state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant