Replies: 2 comments
|
Hi @egarim, happy to see you here!
Thank you very much for working on this! |
|
Quick update — I've opened the PR for this: #24381 (tracking issue #24380). It ended up going a bit further than just the read path, so it lands the X11 head at behavioral parity with the macOS/WASM heads in one branch:
Verified headless (Xvfb + dbus + at-spi2-core): an external AT-SPI client reads the tree and drives controls over the bus — The commits are already split along the read-path → live-events/write-path line, so if you'd rather review (or merge) it as smaller PRs, I'm happy to break it up — just say the word. @MartinZikmund @ramezgerges Two Tmds.DBus.Protocol 0.92 gotchas worth flagging for whoever reviews: |
Uh oh!
There was an error while loading. Please reload this page.
Target:
Uno.UI.Runtime.Skia.X11Summary
6.6 brought Skia accessibility to Windows, macOS and WebAssembly, "with further
target platform support to come." I'd like to help bring the Linux / X11
one, and I've built a working proof-of-concept to de-risk it — not just the
read path: an AT-SPI client can read and drive a Uno app entirely over the
accessibility bus.
On Linux the Skia head renders to X11 but publishes no AT-SPI tree, so a Uno
app is invisible to Orca and to AT-SPI-based automation.
Skia.X11already has aDBus/layer but noAccessibility/provider — that's the gap.What the PoC proves
A standalone AT-SPI server, written on
Tmds.DBus.Protocol(the same D-Bus stackthe head already uses), verified headless in a Docker container (Xvfb + dbus +
at-spi2-core). It walks a Uno app's automation peers and serves them over the
accessibility bus:
Read path
org.a11y.atspi.Socket.Embedorg.a11y.atspi.Accessible+Componentper controlthe visual tree)
Write path — the part that makes it useful to more than screen readers
Action— press / toggle / expand or collapse / select, dispatched to the UIthread and executed through the control's automation provider
(
IInvokeProvider/IToggleProvider/IExpandCollapseProvider/ISelectionItemProvider)Value— slider read + clamped write throughIRangeValueProviderEditableText+ a minimalTextread side — type into an entry throughIValueProvider, read it back over the busSelection— enumerate and select combo itemsLive events
StateChanged(focused,checked,expanded),PropertyChange(accessible-valuefor slider/text),SelectionChangedEvery claim above is a headless proof in the repo, e.g.:
Two pieces of hardening worth mentioning:
app built on a toolkit that already ships a native AT-SPI backend on Linux;
4/4 behavioral proofs pass on both, and the per-control dump (role /
interfaces / actions / states) is identical for all six control types. The
bridge behaves like a native backend from a client's point of view, not like
an approximation.
libatspiderives the role name fromthe numeric role id, not from
GetRoleName, so the ids must be the realAtspiRoleenum values or everything comes back mislabeled. A small xUnitsuite (no display needed) locks the mapping.
The code is already factored along the line a real backend needs: a
platform-neutral
PeerTree(peer-tree walk, live state, write-path throughthe automation providers, change notifications) and a separate AT-SPI/D-Bus
transport that consumes it. Binding into Uno means swapping the tree's source,
not rewriting the protocol half.
Repo (MIT, full container repro): https://github.com/egarim/uno-atspi-bridge
Write-up: https://jocheojeda.com/2026/08/23/uno-linux-accessibility-backend/
What this is NOT (yet)
Deliberately open, and the reason this is a discussion rather than a PR:
children-changedevents for runtime mutations yet. (Live state is tracked; live structure
is not.)
FrameworkElementAutomationPeerAPI from app code —a real backend should hook Uno's internal automation abstraction, the
same seam the macOS/WASM providers use.
Textis minimal (GetText+CharacterCount) — no caret, selectionranges, or attribute runs.
The ask
already on it?
providers attach to the automation abstraction and to the X11 window host
lifecycle?
Uno.UI.Runtime.Skia.X11(
Accessibility/), reuse the existingDBus/layer, and bring the tests.Happy to split it into reviewable PRs — suggested split: read path +
registration first, then live events, then the write path
(Action/Value/EditableText/Selection), then dynamic tree updates.
Glad to connect on LinkedIn or X if that's faster.
All reactions