Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/desktop
Steps to reproduce
- GNOME 46 on Wayland, SnapShots enabled with Include app text on,
org.gnome.desktop.interface toolkit-accessibilityset totrue. - Start a Flatpak browser after enabling that setting (Zen Browser,
app.zen_browser.zen) and take a SnapShot of it. - Start a GTK4/libadwaita app (GNOME System Monitor, not a Flatpak) and take a SnapShot of it.
Expected behavior
Both attachments carry accessibility data. Both apps expose a full tree on the AT-SPI bus; Zen's has about 1500 elements.
Actual behavior
Both captures arrive with appName and windowTitle only. The screenshot, flash and animation are fine, and nothing is logged. There are two separate causes. I checked both by calling the bundled @crowecawcaw/xa11y native module directly from Node, with the same calls SnapShotAccessibility.ts makes.
1. Flatpak apps: the window's PID is not the PID AT-SPI reports.
readCapturedWindowAccessibility does App.byPid(active.owner.processId). For a Flatpak app the compositor reports the app's own process, but the app reaches the accessibility bus through Flatpak's xdg-dbus-proxy, so the AT-SPI registry lists the tree under the proxy's PID:
207651 /app/zen/zen --name app.zen_browser.zen <- owns the window
207646 xdg-dbus-proxy --args=44 <- owns the AT-SPI connection
App.byPid(207651) -> XA11Y_SELECTOR_NOT_MATCHED: No element matched selector: application[pid=207651]
App.byPid(207646) -> 1 window: {"name":"… — Zen Browser","bounds":{"x":0,"y":0,"width":1920,"height":1048}}
There is no fallback, so every Flatpak app ends up without accessibility data.
2. GTK4 apps: the window comes back without a name.
For GNOME System Monitor the PID matches and so does the size, but the element has no name and an unexpected role:
App.byPid(210600).children()[0]
-> {"role":"group","name":null,"bounds":{"x":0,"y":0,"width":1920,"height":1048},"children":1}
same call for Zen (via the proxy PID)
-> {"role":"window","name":"… — Zen Browser", ... "children":40}
findAccessibleWindow requires the title to match, so an unnamed window never matches. libatspi sees this window correctly: Atspi.get_desktop(0) → application gnome-system-monitor (pid 210600) → child with role frame, name System Monitor, 1920x1048. So the name is lost either inside xa11y or because children() returns a different node for GTK4's AT-SPI implementation than for other toolkits.
Impact
On a stock GNOME desktop most apps are either Flatpaks or GTK4, so Include app text rarely produces anything on Linux. It fails silently, which makes it look like the app simply has no accessible text.
Version or commit
0.0.42 (AppImage)
Environment
Zorin OS 18 (Ubuntu 24.04 base), GNOME Shell 46.0, Wayland, at-spi2-core from the distro, Flatpak Zen Browser, GNOME System Monitor with libgtk-4 and libadwaita-1.
Workaround
None found.
Possible directions: for (1), when byPid finds nothing, fall back to App.list() and match on title plus size, which is what the window matcher already relies on. For (2), when exactly one window of the right PID has matching bounds, accept it even without a name, or look at why xa11y reports GTK4 frames as unnamed groups.
Activity
juliusmarminge commentedon Sep 19, 2026
Thanks for the unusually complete report — compositor vs AT-SPI PIDs, xa11y vs libatspi dumps, and two independent failure modes with the same calls
SnapShotAccessibility.tsmakes.Confirmed on current
main. This is a real Linux SnapShot accessibility lookup/matcher bug. The screenshot path is fine; Include app text is dropped silently when the reader cannot bind a window.On GNOME the capture PID comes from the compositor (
window.get_pid()inapps/desktop/gnome-extension/extension.js) and is passed throughDesktopSnapShot.tsintoreadCapturedWindowAccessibility. On Linux that function only doesApp.byPid(active.owner.processId). There is no fallback. Misses are swallowed in the worker (run().catch(() => undefined)), so the attachment still hasappName/windowTitleand no accessibility payload.That matches both of your cases:
1. Flatpak — compositor PID ≠ AT-SPI PID
The window owner is the app. The AT-SPI registry lists the tree under Flatpak’s
xdg-dbus-proxy.App.byPid(appPid)raisesXA11Y_SELECTOR_NOT_MATCHED;App.byPid(proxyPid)finds the named window. Because we never fall back toApp.list(), every Flatpak capture loses app text.WindowsForegroundFocusWorkeralready doesbyPid→App.list(), but it still filterscandidate.pid === target.processId, so that pattern would not fix this. xa11y’s own pytest helper already documents the same class of bug (“the process that registers with the accessibility API is not the one you launched”) and matches PID or name.2. GTK4 — unnamed node fails the title gate
findAccessibleWindowinapps/desktop/src/snapShot/snapShot.tsrequires a nonempty title match and bounds (±2). Tests currently reject untitled windows by size alone. For System Monitor the PID and size match, but xa11y returns{ role: "group", name: null }while libatspi still sees a namedframe. The title gate never matches.This is the same matcher family as #10896 (macOS Chrome title suffix) and a cousin of #12103 / #12524 (macOS invalid PID), but those fixes do not cover Linux AT-SPI.
Next step
We can fix both in t3code without waiting on xa11y:
byPidfinds nothing, fall back toApp.list()and reuse the existing title+size matcher. Do not require the compositor PID to equal the AT-SPI PID.nameis empty (or walk one anonymousgroupwrapper). Keep rejecting ambiguous size-only matches.The GTK4
frame→ unnamedgroupmapping is still worth an xa11y follow-up, but it should not block the matcher workaround.No workaround on our side today. Docs already say GNOME browsers need toolkit accessibility and a restart; that is necessary but not sufficient here.
cestercian commentedon Sep 19, 2026
Taking this — working on a fix.