[PR #12358] [MERGED] Use UIA notifications for text output #29003

Open
opened 2026-01-31 09:32:11 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/12358
Author: @carlos-zamora
Created: 2/3/2022
Status: Merged
Merged: 3/11/2022
Merged by: @undefined

Base: mainHead: dev/cazamor/a11y/uia-notification-event


📝 Commits (10+)

  • 91eeb59 [Prototype] Use UIA notifications for text output
  • 2108d08 fix audit mode
  • 320b1f8 update other fake renderers for testing
  • a369772 make events synchronous; notify text line-by-line
  • e2373d1 update class name for 'versioning'
  • aa7ecb4 fix large output handling (for accevent)
  • 31762fc sapi doesn't exist
  • 551d648 std::move
  • 768dd7c suppress 'local echo' from keyboard input
  • facc78c add sapi to spellcheck

📊 Changes

23 files changed (+232 additions, -21 deletions)

View changed files

📝 .github/actions/spelling/expect/expect.txt (+1 -0)
📝 src/cascadia/TerminalControl/InteractivityAutomationPeer.cpp (+5 -0)
📝 src/cascadia/TerminalControl/InteractivityAutomationPeer.h (+2 -0)
📝 src/cascadia/TerminalControl/InteractivityAutomationPeer.idl (+1 -0)
📝 src/cascadia/TerminalControl/TermControl.cpp (+5 -0)
📝 src/cascadia/TerminalControl/TermControlAutomationPeer.cpp (+107 -0)
📝 src/cascadia/TerminalControl/TermControlAutomationPeer.h (+3 -0)
📝 src/cascadia/TerminalCore/Terminal.cpp (+5 -0)
📝 src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp (+1 -0)
📝 src/host/ScreenBufferRenderTarget.cpp (+10 -0)
📝 src/host/ScreenBufferRenderTarget.hpp (+1 -0)
📝 src/renderer/atlas/AtlasEngine.api.cpp (+5 -0)
📝 src/renderer/atlas/AtlasEngine.h (+1 -0)
📝 src/renderer/base/RenderEngineBase.cpp (+5 -0)
📝 src/renderer/base/renderer.cpp (+8 -0)
📝 src/renderer/base/renderer.hpp (+2 -0)
📝 src/renderer/inc/DummyRenderTarget.hpp (+1 -0)
📝 src/renderer/inc/IRenderEngine.hpp (+1 -0)
📝 src/renderer/inc/IRenderTarget.hpp (+2 -0)
📝 src/renderer/inc/RenderEngineBase.hpp (+2 -0)

...and 3 more files

📄 Description

Summary of the Pull Request

This change makes Windows Terminal raise a RaiseNotificationEvent() (docs) for new text output to the buffer.

This is intended to help Narrator identify what new output appears and reduce the workload of diffing the buffer when a TextChanged event occurs.

Detailed Description of the Pull Request / Additional comments

The flow of the event occurs as follows:

  • Terminal::_WriteBuffer()
    • New text is output to the text buffer. Notify the renderer that we have new text (and what that text is).
  • Renderer::TriggerNewTextNotification()
    • Cycle through all the rendering engines and tell them to notify handle the new text output.
    • None of the rendering engines except UiaEngine has it implemented, so really we're just notifying UIA.
  • UiaEngine::NotifyNewText()
    • Concatenate any new output into a string.
    • When we're done painting, tell the notification system to actually notify of new events occurring and clear any stored output text. That way, we're ready for the next renderer frame.
  • InteractivityAutomationPeer::NotifyNewOutput() --> TermControlAutomationPeer::NotifyNewOutput
    • NOTE: these are split because of the in-proc and out-of-proc separation of the buffer.
    • Actually RaiseNotificationEvent() for the new text output.

Additionally, we had to handle the "local echo" problem: when a key is pressed, the character is said twice (once for the keyboard event, and again for the character being written to the buffer). To accomplish this, we did the following:

  • TermControl:
    • here, we already handle keyboard events, so I added a line saying "if we have an automation peer attached, record the keyboard event in the automation peer".
  • TermControlAutomationPeer:
    • just before the notification is dispatched, check if the string of recent keyboard events match the beginning of the string of new output. If that's the case, we can assume that the common prefix was the "local echo".

This is a fairly naive heuristic, but it's been working.

Closes the following ADO bugs:

Test cases

  • Base case: "echo hello"
  • Partial line change
  • Scrolling (should be unaffected)
  • Large output
  • "local echo": keyboard events read input character twice

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/12358 **Author:** [@carlos-zamora](https://github.com/carlos-zamora) **Created:** 2/3/2022 **Status:** ✅ Merged **Merged:** 3/11/2022 **Merged by:** [@undefined](undefined) **Base:** `main` ← **Head:** `dev/cazamor/a11y/uia-notification-event` --- ### 📝 Commits (10+) - [`91eeb59`](https://github.com/microsoft/terminal/commit/91eeb594a34b16a454925e389ff15d6701a592f9) [Prototype] Use UIA notifications for text output - [`2108d08`](https://github.com/microsoft/terminal/commit/2108d08fd805bc0e8c894ba1246c45e6f2f31d4b) fix audit mode - [`320b1f8`](https://github.com/microsoft/terminal/commit/320b1f86ca71768c3f5365b8e2c9c1bcc670f856) update other fake renderers for testing - [`a369772`](https://github.com/microsoft/terminal/commit/a369772d3af21ad35c00704091e92d431dfffc78) make events synchronous; notify text line-by-line - [`e2373d1`](https://github.com/microsoft/terminal/commit/e2373d1de18308ea975a0b6c278b0831addea691) update class name for 'versioning' - [`aa7ecb4`](https://github.com/microsoft/terminal/commit/aa7ecb4d01175fce9aa94b6120c8a18b1d1ce0be) fix large output handling (for accevent) - [`31762fc`](https://github.com/microsoft/terminal/commit/31762fc36b3847151d01e5c055b305354e1d964d) sapi doesn't exist - [`551d648`](https://github.com/microsoft/terminal/commit/551d648f8dbe46ad7f0238688021533a55bb9b77) std::move - [`768dd7c`](https://github.com/microsoft/terminal/commit/768dd7cdf4701d20f8147a5b7d19bea50530701e) suppress 'local echo' from keyboard input - [`facc78c`](https://github.com/microsoft/terminal/commit/facc78c7d8d118c8c666b119be90d107b0a4286c) add sapi to spellcheck ### 📊 Changes **23 files changed** (+232 additions, -21 deletions) <details> <summary>View changed files</summary> 📝 `.github/actions/spelling/expect/expect.txt` (+1 -0) 📝 `src/cascadia/TerminalControl/InteractivityAutomationPeer.cpp` (+5 -0) 📝 `src/cascadia/TerminalControl/InteractivityAutomationPeer.h` (+2 -0) 📝 `src/cascadia/TerminalControl/InteractivityAutomationPeer.idl` (+1 -0) 📝 `src/cascadia/TerminalControl/TermControl.cpp` (+5 -0) 📝 `src/cascadia/TerminalControl/TermControlAutomationPeer.cpp` (+107 -0) 📝 `src/cascadia/TerminalControl/TermControlAutomationPeer.h` (+3 -0) 📝 `src/cascadia/TerminalCore/Terminal.cpp` (+5 -0) 📝 `src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp` (+1 -0) 📝 `src/host/ScreenBufferRenderTarget.cpp` (+10 -0) 📝 `src/host/ScreenBufferRenderTarget.hpp` (+1 -0) 📝 `src/renderer/atlas/AtlasEngine.api.cpp` (+5 -0) 📝 `src/renderer/atlas/AtlasEngine.h` (+1 -0) 📝 `src/renderer/base/RenderEngineBase.cpp` (+5 -0) 📝 `src/renderer/base/renderer.cpp` (+8 -0) 📝 `src/renderer/base/renderer.hpp` (+2 -0) 📝 `src/renderer/inc/DummyRenderTarget.hpp` (+1 -0) 📝 `src/renderer/inc/IRenderEngine.hpp` (+1 -0) 📝 `src/renderer/inc/IRenderTarget.hpp` (+2 -0) 📝 `src/renderer/inc/RenderEngineBase.hpp` (+2 -0) _...and 3 more files_ </details> ### 📄 Description ## Summary of the Pull Request This change makes Windows Terminal raise a `RaiseNotificationEvent()` ([docs](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.automation.peers.automationpeer.raisenotificationevent?view=winrt-22000)) for new text output to the buffer. This is intended to help Narrator identify what new output appears and reduce the workload of diffing the buffer when a `TextChanged` event occurs. ## Detailed Description of the Pull Request / Additional comments The flow of the event occurs as follows: - `Terminal::_WriteBuffer()` - New text is output to the text buffer. Notify the renderer that we have new text (and what that text is). - `Renderer::TriggerNewTextNotification()` - Cycle through all the rendering engines and tell them to notify handle the new text output. - None of the rendering engines _except_ `UiaEngine` has it implemented, so really we're just notifying UIA. - `UiaEngine::NotifyNewText()` - Concatenate any new output into a string. - When we're done painting, tell the notification system to actually notify of new events occurring and clear any stored output text. That way, we're ready for the next renderer frame. - `InteractivityAutomationPeer::NotifyNewOutput()` --> `TermControlAutomationPeer::NotifyNewOutput` - NOTE: these are split because of the in-proc and out-of-proc separation of the buffer. - Actually `RaiseNotificationEvent()` for the new text output. Additionally, we had to handle the "local echo" problem: when a key is pressed, the character is said twice (once for the keyboard event, and again for the character being written to the buffer). To accomplish this, we did the following: - `TermControl`: - here, we already handle keyboard events, so I added a line saying "if we have an automation peer attached, record the keyboard event in the automation peer". - `TermControlAutomationPeer`: - just before the notification is dispatched, check if the string of recent keyboard events match the beginning of the string of new output. If that's the case, we can assume that the common prefix was the "local echo". This is a fairly naive heuristic, but it's been working. Closes the following ADO bugs: - https://dev.azure.com/microsoft/OS/_workitems/edit/36506838 - (Probably) https://dev.azure.com/microsoft/OS/_workitems/edit/38011453 ## Test cases - [x] Base case: "echo hello" - [x] Partial line change - [x] Scrolling (should be unaffected) - [x] Large output - [x] "local echo": keyboard events read input character twice --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:32:11 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#29003