Skip to content

Accessibility: announce new terminal output to screen readers#544

Merged
deblasis merged 2 commits into
windowsfrom
a11y-uia-announce
Jun 19, 2026
Merged

Accessibility: announce new terminal output to screen readers#544
deblasis merged 2 commits into
windowsfrom
a11y-uia-announce

Conversation

@deblasis

Copy link
Copy Markdown
Owner

Completes the screen reader support for the terminal: new output is now spoken
as it arrives when a screen reader is attached.

On Windows, a screen reader does not automatically read new text in a plain UIA
text control, so command output was readable on navigation but not heard. This
adds a conservative announcement path. A short timer on the UI thread feeds the
cached screen text to a pure diff policy that announces only complete new lines,
holds a partial line until its newline arrives, batches new lines into one
notification, and summarizes large bursts as a count. The result is raised as a
UIA notification.

It is gated to be completely inert unless an assistive technology is present: the
timer body returns early unless the OS reports a screen reader is running and the
surface is focused and foreground. Users without a screen reader see no behavior
change and pay nothing beyond a cached read.

macOS has no equivalent here. Its accessibility is pull only, with no
announcements and no timer, because VoiceOver reads the value on its own. This
announcement path is a Windows specific addition.

The diff, batch, and summary policy is a pure type in Ghostty.Core with unit
tests. The only native addition is a single Win32 call to read the screen reader
flag. No Zig changes.

Verified locally:

  • dotnet build and dotnet test pass on x64 (the announcer adds 9 tests).
  • With the OS screen reader flag set and a command printing known output, the app
    runs the announcement path live with no crash and the output present for the
    policy to consume. The flag is restored afterward.

Left for manual testing: a real pass with NVDA and JAWS to hear the spoken output.

When a screen reader is attached and the terminal is focused, new output is
spoken via a UIA notification. A poll on the UI thread feeds the cached
screen text to a pure announcer that diffs out new complete lines, holds
partial lines, batches, and summarizes large bursts. Gated on the OS
screen-reader flag and focus, so it is completely inert otherwise. The
diff policy is pure logic in Ghostty.Core with unit tests. No native
changes beyond one Win32 call for the screen-reader flag.
@deblasis deblasis marked this pull request as ready for review June 19, 2026 08:37
Cache the automation peer on the control and drive the announce timer off the
owner's Loaded/Unloaded so re-querying a loaded control reuses one peer and
one timer instead of accumulating them. Also: singular 'new line' summary,
simpler change check, and a note that announcements degrade to silence when
output exceeds the scrollback buffer.
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