Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessibility: TermControl Automation Peer #2083

Merged
merged 28 commits into from
Jul 30, 2019

Conversation

carlos-zamora
Copy link
Member

Summary of the Pull Request

Adds accessibility patterns to the Terminal Control using ConHost's accessibility model.

References

Builds on the work of #1691 and #1915

Detailed Description of the Pull Request / Additional comments

Let's start with the easy change:

  • TermControl's controlRoot was removed. TermControl is a UserControl now.

Ok. Now we've got a story to tell here....

TermControlAP - the Automation Peer

Here's an in-depth guide on custom automation peers.

We have a custom XAML element (TermControl). So XAML can't really hold our hands and determine an accessible behavior for us. So this automation peer is responsible for enabling that interaction.

We made it a FrameworkElementAutomationPeer to get as much accessibility as possible from it just being a XAML element (i.e.: where are we on the screen? what are my dimensions?). This is recommended. Any functions with "Core" at the end, are overwritten here to tweak this automation peer into what we really need.

But what kind of interactions can a user expect from this XAML element? Introducing ControlPatterns! There's a ton of interfaces that just define "what can I do". Thankfully, we already know that we're supposed to be ScreenInfoUiaProvider and that was an ITextProvider, so let's just make the TermControlAP an ITextProvider too.

So now we have a way to define what accessible actions can be performed on us, but what should those actions do? Well let's just use the automation providers from ConHost that are now in a shared space! (Note: this is a great place to stop and get some coffee. We're about to hop into the .cpp file in the next section)

Wrapping our shared Automation Providers

Unfortunately, we can't just use the automation providers from ConHost. Or, at least not just hook them up as easily as we wish. ConHost's UIA Providers were written using UIAutomationCore's ITextProvider and ITextRangeProvider. XAML's interfaces (ITextProvider and ITextRangeProvider) are lined up to be exactly the same.

So we need to wrap our ConHost UIA Providers (UIAutomationCore) with the XAML ones. We had two providers, so that means we have two wrappers.

TermControlAP (XAML) <----> ScreenInfoUiaProvider (UIAutomationCore)

Each of the functions in the pragma region ITextProvider for TermControlAP.cpp is just wrapping what we do in ScreenInfoUiaProvider, and returning an acceptable version of it.

Most of ScreenInfoUiaProvider's functions return UiaTextRanges. So we need to wrap that too. That's this next section...

XamlUiaTextRange (XAML) <----> UiaTextRange (UIAutomationCore)

Same idea. We're wrapping everything that we could do with UiaTextRange and putting it inside of XamlUiaTextRange.

Additional changes to UiaTextRange and ScreenInfoUiaProvider

If you don't know what I just said, please read this background:

TL;DR: ScreenInfoUiaProvider lets you interact with the displayed text. UiaTextRange is specific ranges of text in the display and navigate the text.

Thankfully, we didn't do many changes here. I feel like some of it is hacked together but now that we have a somewhat working system, making changes shouldn't be too hard...I hope.

UiaTextRange

We don't have access to the window handle. We really only need it to draw the bounding rects using WinUser's ScreenToClient() and ClientToScreen(). I need to figure out how to get around this.

In the meantime, I made the window handle optional. And if we don't have one....well, we need to figure that out. But other than that, we have a UiaTextRange.

ScreenInfoUiaProvider

At some point, we need to hook up this automation provider to the WindowUiaProvider. This should help with navigation of the UIA Tree and make everything just look waaaay better. For now, let's just do the same approach and make the pUiaParent optional.

This one's the one I'm not that proud of, but it works. We need the parent to get a bounding rect of the terminal. While we figure out how to attach the WindowUiaProvider, we should at the very least be able to get a bunch of info from our xaml automation peer. So, I've added a _getBoundingRect optional function. This is what's called when we don't have a WindowUiaProvider as our parent.

Validation Steps Performed

I've been using inspect.exe to see the UIA tree. I was able to interact with the terminal mostly fine. A few known issues below.

Unfortunately, I tried running Narrator on this and it didn't seem to like it (by that I mean WT crashed). Then again, I don't really know how to use narrator other than "click on object" --> "listen voice". I feel like there's a way to get the other interactions with narrator, but I'll be looking into more of that soon. I bet if I fix the two issues below, Narrator will be happy.

Miscellaneous Known Issues

  • GetSelection() and GetVisibleRanges() crashes. I need to debug through these. I want to include them in this PR.

carlos-zamora and others added 17 commits July 16, 2019 18:25
- Moved WindowUiaProvider to Types (Shared)
- Hooked up WindowUiaProvider to BaseWindow (WT)

UIATree is now accessible in WT
…g used.

TODO:
- replace IWindow with IConsoleWindow (for my own sanity)
- turn SIUP into an abstract class where any use of ServiceLocator and Selection is abstracted out
- Made IslandWindow inherit IConsoleWindow
- Moved some UIATree logic to IslandWindow
- Fixed ConHost to work with UIATree (sorta)

At the moment, ConHost is using a temp ScreenInfoUIAProvider. This will be fixed with next inheritance patch.

TODO:
- turn SIUP into an abstract class where any use of ServiceLocator and Selection is abstracted out
Added correct strings to WindowUiaProvider description fields
Created TermControlAP (AutomationPeer)
Created XamlUiaTextRange to wrap UiaTextRange

Need to fix...
- GetSelection()
- GetVisibleRanges()
- Compare() (A few other minor ones too)
- Moved WindowUiaProvider to Types (Shared)
- Hooked up WindowUiaProvider to BaseWindow (WT)

UIATree is now accessible in WT
…g used.

TODO:
- replace IWindow with IConsoleWindow (for my own sanity)
- turn SIUP into an abstract class where any use of ServiceLocator and Selection is abstracted out
- Made IslandWindow inherit IConsoleWindow
- Moved some UIATree logic to IslandWindow
- Fixed ConHost to work with UIATree (sorta)

At the moment, ConHost is using a temp ScreenInfoUIAProvider. This will be fixed with next inheritance patch.

TODO:
- turn SIUP into an abstract class where any use of ServiceLocator and Selection is abstracted out
Added correct strings to WindowUiaProvider description fields
@carlos-zamora carlos-zamora self-assigned this Jul 25, 2019
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just leaving some preliminary comments here. There's so much TODO CARLOS in it that I'll make another pass when there's less TODO.

src/cascadia/TerminalControl/TermControl.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControl.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControl.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControl.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAP.idl Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.cpp Outdated Show resolved Hide resolved
src/types/lib/types.vcxproj.filters Show resolved Hide resolved
@carlos-zamora
Copy link
Member Author

carlos-zamora commented Jul 25, 2019

So, there's a big set of "TODO CARLOS" in the changes I made. It's all one issue: hwnd is now optional. Should we ship with this and worry about it later?

Edit: just threw them into separate work items. Need to do some refactoring anyways.

@carlos-zamora carlos-zamora marked this pull request as ready for review July 25, 2019 18:54
src/cascadia/TerminalControl/TermControlAutomationPeer.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.h Outdated Show resolved Hide resolved
src/types/ScreenInfoUiaProvider.cpp Outdated Show resolved Hide resolved
src/types/ScreenInfoUiaProvider.cpp Outdated Show resolved Hide resolved
src/types/ScreenInfoUiaProvider.cpp Outdated Show resolved Hide resolved
@ghost ghost added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jul 25, 2019
Attached TODO CARLOS to actual github issue
@ghost ghost added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jul 26, 2019
src/types/UiaTextRange.cpp Outdated Show resolved Hide resolved
src/types/UiaTextRange.cpp Outdated Show resolved Hide resolved
Fixed ownership issue with SAFEARRAYs
src/cascadia/inc/cppwinrt_utils.h Outdated Show resolved Hide resolved
src/cascadia/inc/cppwinrt_utils.h Outdated Show resolved Hide resolved
# Conflicts:
#	src/cascadia/WindowsTerminal/WindowUiaProvider.cpp
#	src/host/tracing.cpp
#	src/host/tracing.hpp
#	src/interactivity/win32/WindowMetrics.cpp
#	src/interactivity/win32/window.cpp
#	src/types/IUiaWindow.h
#	src/types/ScreenInfoUiaProvider.cpp
#	src/types/ScreenInfoUiaProvider.h
#	src/types/UiaTextRange.cpp
#	src/types/WindowUiaProviderBase.cpp
#	src/types/WindowUiaProviderBase.hpp
#	src/types/lib/types.vcxproj.filters
@carlos-zamora carlos-zamora changed the base branch from dev/cazamor/accessibility to master July 30, 2019 00:18
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I have anything worth blocking over, but I certainly have questions. Judging based on this PR, #2120 is going to help me feel a lot more comfortable with this change - I really didn't love having to check _pUiaParent all over the ScreenInfoUiaProvider, but if that's getting done in #2120 I'll just deal with it for now.

src/interactivity/win32/windowUiaProvider.cpp Outdated Show resolved Hide resolved
src/interactivity/win32/window.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/TermControlAutomationPeer.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.h Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.h Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/BaseWindow.h Outdated Show resolved Hide resolved
src/cascadia/inc/cppwinrt_utils.h Outdated Show resolved Hide resolved
src/cascadia/inc/cppwinrt_utils.h Show resolved Hide resolved
@ghost ghost added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jul 30, 2019
@ghost ghost added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jul 30, 2019
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I have no reason left to block this.

src/cascadia/TerminalControl/XamlUiaTextRange.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalControl/XamlUiaTextRange.cpp Outdated Show resolved Hide resolved
@ghost ghost added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jul 30, 2019
and a minor bugfix on compare
@ghost ghost removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jul 30, 2019
Copy link
Contributor

@DHowett-MSFT DHowett-MSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Y E S

@DHowett-MSFT
Copy link
Contributor

🎆

@DHowett-MSFT DHowett-MSFT merged commit a08666b into master Jul 30, 2019
@DHowett-MSFT DHowett-MSFT deleted the dev/cazamor/acc/text_buffer branch July 30, 2019 23:43
@ghost
Copy link

ghost commented Aug 3, 2019

🎉Windows Terminal Preview v0.3.2142.0 has been released which incorporates this pull request.:tada:

Handy links:

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.

4 participants