Skip to content

feat(windows): handle SELECTION_CHANGED → UIA TextSelectionChanged - #553

Merged
deblasis merged 1 commit into
windowsfrom
feat/windows-selection-changed-uia
Jun 26, 2026
Merged

deblasis merged 1 commit into
windowsfrom
feat/windows-selection-changed-uia

Conversation

@deblasis

Copy link
Copy Markdown
Owner

Closes #550. Stacked on #552 (base = fix/windows-action-tag-realign); review/merge that first.

What

Upstream ghostty-org#12902 added a payload-less GHOSTTY_ACTION_SELECTION_CHANGED, fired on a selection state transition. macOS posts NSAccessibility .selectedTextChanged; this wires the Windows equivalent so the UIA text provider (added in #542–#545) notifies assistive tech.

Flow: GhosttyHost.OnAction → resolve TerminalControl → RaiseSelectionChanged() → TerminalAutomationPeer.RaiseSelectionChangedEvent() → RaiseAutomationEvent(TextPatternOnTextSelectionChanged).

Changes

  • GhosttyActions.cs: add SelectionChanged = 51 to the dispatched subset (+ pin in GhosttyActionsLayoutTests).
  • GhosttyHost.cs: dispatch case (payload-less, resolve-guarded, same shape as SetTitle/MouseShape).
  • TerminalControl.xaml.cs: RaiseSelectionChanged() — no-ops when no peer exists (no AT client).
  • TerminalAutomationPeer.cs: RaiseSelectionChangedEvent() — raises the UIA event, guarded by ListenerExists.

Design notes

  • No debounce — matches macOS (posts directly) and core already coalesces selection transitions (Surface.zig); the raise is inert without an AT listener, so per-change cost under drag-select is negligible. (Issue listed debounce as optional; can add if profiling shows churn.)

⚠️ Verification (cannot build on macOS — CsWin32; no C# CI)

  • Windows build of Ghostty.sln
  • Ghostty.Tests → GhosttyActionsLayoutTests green
  • Confirm AutomationEvents.TextPatternOnTextSelectionChanged is the correct WinUI 3 event id (highest-risk line — API name verified against UWP/WinUI UIA, not compiled here)
  • Smoke test under Narrator / an automation client: selecting + clearing fires TextSelectionChanged

🤖 Generated with Claude Code

@deblasis
deblasis changed the base branch from fix/windows-action-tag-realign to windows June 26, 2026 08:36
Upstream ghostty-org#12902 added a payload-less GHOSTTY_ACTION_SELECTION_CHANGED,
fired on a selection state transition; the apprt is expected to read the
current selection and notify accessibility. macOS posts NSAccessibility
.selectedTextChanged -- this wires the Windows equivalent.

Add SelectionChanged (51) to the dispatched GhosttyActionTag subset and
route it through GhosttyHost.OnAction to the surface's TerminalControl,
which forwards to its UIA TerminalAutomationPeer. The peer raises
TextPatternOnTextSelectionChanged, guarded by ListenerExists so it is
inert without an attached AT client; the control no-ops when no peer has
been created (no AT client). Pins the new ordinal in
GhosttyActionsLayoutTests.

Closes #550.

Not built locally: the C# app only compiles on Windows (CsWin32). Needs
a Windows build plus a screen-reader/automation-client smoke test, and
confirmation that AutomationEvents.TextPatternOnTextSelectionChanged is
the correct WinUI 3 event id.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@deblasis
deblasis force-pushed the feat/windows-selection-changed-uia branch from 9dd50cc to a7e2f49 Compare June 26, 2026 08:38
@deblasis
deblasis marked this pull request as ready for review June 26, 2026 08:38
@deblasis
deblasis merged commit e088054 into windows Jun 26, 2026
98 checks passed
@deblasis
deblasis deleted the feat/windows-selection-changed-uia branch June 26, 2026 08:38
deblasis added a commit that referenced this pull request Jul 18, 2026
…553)

Wire upstream's payload-less GHOSTTY_ACTION_SELECTION_CHANGED to the Windows UIA text provider so assistive tech re-queries the selection, mirroring macOS posting NSAccessibility .selectedTextChanged.

Add SelectionChanged (51) to the dispatched GhosttyActionTag subset and route it through GhosttyHost.OnAction to the surface's TerminalControl, which forwards to its UIA TerminalAutomationPeer. The peer raises TextPatternOnTextSelectionChanged, guarded by ListenerExists so it is inert without an attached AT client; the control no-ops when no peer has been created. Pins the new ordinal in GhosttyActionsLayoutTests.

Closes #550.
deblasis added a commit that referenced this pull request Jul 29, 2026
…553)

Wire upstream's payload-less GHOSTTY_ACTION_SELECTION_CHANGED to the Windows UIA text provider so assistive tech re-queries the selection, mirroring macOS posting NSAccessibility .selectedTextChanged.

Add SelectionChanged (51) to the dispatched GhosttyActionTag subset and route it through GhosttyHost.OnAction to the surface's TerminalControl, which forwards to its UIA TerminalAutomationPeer. The peer raises TextPatternOnTextSelectionChanged, guarded by ListenerExists so it is inert without an attached AT client; the control no-ops when no peer has been created. Pins the new ordinal in GhosttyActionsLayoutTests.

Closes #550.
deblasis added a commit that referenced this pull request Aug 10, 2026
…553)

Wire upstream's payload-less GHOSTTY_ACTION_SELECTION_CHANGED to the Windows UIA text provider so assistive tech re-queries the selection, mirroring macOS posting NSAccessibility .selectedTextChanged.

Add SelectionChanged (51) to the dispatched GhosttyActionTag subset and route it through GhosttyHost.OnAction to the surface's TerminalControl, which forwards to its UIA TerminalAutomationPeer. The peer raises TextPatternOnTextSelectionChanged, guarded by ListenerExists so it is inert without an attached AT client; the control no-ops when no peer has been created. Pins the new ordinal in GhosttyActionsLayoutTests.

Closes #550.
deblasis added a commit that referenced this pull request Aug 21, 2026
…553)

Wire upstream's payload-less GHOSTTY_ACTION_SELECTION_CHANGED to the Windows UIA text provider so assistive tech re-queries the selection, mirroring macOS posting NSAccessibility .selectedTextChanged.

Add SelectionChanged (51) to the dispatched GhosttyActionTag subset and route it through GhosttyHost.OnAction to the surface's TerminalControl, which forwards to its UIA TerminalAutomationPeer. The peer raises TextPatternOnTextSelectionChanged, guarded by ListenerExists so it is inert without an attached AT client; the control no-ops when no peer has been created. Pins the new ordinal in GhosttyActionsLayoutTests.

Closes #550.
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.

windows: handle GHOSTTY_ACTION_SELECTION_CHANGED → fire UIA TextSelectionChanged

1 participant