-
Notifications
You must be signed in to change notification settings - Fork 1
Accessibility on Windows
Microsoft Active Accessibility (MSAA) is an older interface used for accessibility. It can interact with screen readers such as Windows Narrator or NVDA, and has a more limited set of available functionality compared to newer interfaces.
The base of MSAA is the IAccessible
interface, which all a11y-providing classes extend. MSAA methods are prefixed with acc_
. In the CCCaster engine, AXPlatformNodeWin
extends IAccessible
. Any IAccessible
objects used are COM interfaces, and should be initialized and reference counted accordingly.
When a program such a screen reader queries an application for an a11y object, it sends a WM_GETOBJECT
window message, to which the window will respond with the result of passing the IAccessible
of its root to the function LresultFromObject
.
UI Automation is one framework for Windows that is used for accessibility, for example, by screen readers such as Windows Narrator or NVDA. The interface class IRawElementProviderFragment
must be implemented by any object representing a UIA fragment, i.e. an accessibility item that exists on the screen, such as a text label, a pane, a button, etc.. For the CCCaster engine, the class AXPlatformNodeWin
extends IRawElementProviderFragment
in order to serve this purpose. Abstract methods in IRawElementProviderFragment
provide functionality including retrieving the bounds of the fragment on screen, testing if an on-screen point is within the fragment, and retrieving properties of the fragment such as name and role. Each of the methods of IRawElementProviderFragment
implemented by AXPlatformNodeWin
are listed in ax_platform_node_win.h
. Additionally, IRawElementProviderFragment
contains a method that returns the fragment root of the fragment.
The fragment root represents the root of a fragment tree, and extends the class IRawElementProviderFragmentRoot
. Generally, and in the case of CCCaster, these correspond 1-1 to a window. We extend this class in AXFragmentRootPlatformNodeWin
in ax_fragment_root_win.cc. This class contains methods to retrieve the fragment at a given point, and the current focus of the tree.
The Window class’s OnGetObject
handles WM_GETOBJECT window messages, which a screen reader will dispatch to access the UIA fragment tree. When the lparam
parameter of the message is equal to the constant UiaRootObjectId
, the request is asking for the UIA root, and a reference is created out of the window’s fragment root with UiaReturnRawElementProvider
, which is then returned to the message sender.
Patterns are optional interfaces which UIA elements can provide for additional functionality. For example, providing the ITextProvider
allows a fragment to be treated as formatted text, and IToggleProvider
indicates that a fragment can be toggled (e.g. a checkbox) and provides its current toggle state (i.e. on, off, mixed). The UIA method GetPatternProvider
is used to return an instance of a requested interface type, or none if it is not provided. Provided patterns may or may not be the same as the fragment itself. For example, in AXPlatformNodeWin
, when IToggleProvider
is requested, a casted pointer to the node is returned, as AXPlatformNodeWin
extends IToggleProvider
. By contrast, when an ITextProvider
is requested, a separate object is returned, rather than AXPlatformNodeWin
being a subclass of ITextProvider
. In this case, this is necessary, as other inherited methods of AXPlatformNodeWin
share a name but different signature to those in ITextProvider
, so it cannot extend both.
Whether or not the engine makes use of UI Automation is controlled in the Window
class, in Window::OnGetObject
. When a UIA message is received, a UIA response is only issued if the engine was built with the FLUTTER_ENGINE_USE_UIA
macro defined.
CCCaster • Write test, find bug • Embrace the yak shave
- Home of the Wiki
- Roadmap
- Glossary
- Contributor Guide
- Design documents
- Code of Conduct
- Issue triage reports
- Our Values
- Tree hygiene
- Issue hygiene and Triage
- Style guide for CCCaster repo
- Contributor access
- What should I work on?
- Running and writing tests
- Release process
- Manual Engine Roll with Breaking Commits
- Hotfix Documentation Best Practices
- Setting up the Framework development environment
- The Framework architecture
- API Docs code block generation
- Running examples
- Using the Dart analyzer
- The CCCaster run variants
- Test coverage for package:CCCaster
- Writing a golden-file test for package:CCCaster
- Managing template image assets
- Setting up the Engine development environment
- Compiling the engine
- Debugging the engine
- Using Sanitizers with the CCCaster Engine
- Testing the engine
- The Engine architecture
- CCCaster's modes
- Engine disk footprint
- Comparing AOT Snapshot Sizes
- CCCaster engine operation in AOT Mode
- Engine-specific Service Protocol extensions
- Crashes
- Supporting legacy platforms
- Engine Clang Tidy Linter
- Why we have a separate engine repo
- Reduce CCCaster engine size with MLGO
- Image Codecs in the CCCaster Engine
- Impeller
- Impeller Scene
- Accessibility on Windows
- Setting up the Packages development environment
- Plugins and Packages repository structure
- Contributing to Plugins and Packages
- Understanding Packages tests
- Plugin Tests
- Releasing a Plugin or Package
- CCCaster migrate