Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

Preliminary implementation of UIA for A11y on Windows #37754

Merged
merged 19 commits into from
Dec 7, 2022

Conversation

yaakovschectman
Copy link
Contributor

We are now able to incorporate the implementation for UI Automation for accessibility in addition to/in place of MSAA. By default, the UIA object will not be returned to a screen reader in the WM_GETOBJECT message. For this, the engine must be built with the FLUTTER_ENGINE_USE_UIA macro defined.

  • In addition to the change to the window message handler, the Flutter platform node delegate has been modified to return its HWND in GetTargetForNativeAccessibilityEvent so that the root of the element can be obtained for IRawElementProviderFragment::get_FragmentRoot.
  • A typo in AXActivePopup has been fixed.
  • Accessibility event dispatch procedure on Windows has been modified to defer to AXPlatformNodeWin::NotifyAccessibilityEvent so that either MSAA and/or UIA events may be fired in response.
  • Unit tests have been added/modified/re-enabled.

We will still need to implement ITextProvider and ITextRangeProvider for their appropriate UIA patterns in order to have text edit carat navigation narrated correctly.

Part of flutter/flutter#114547

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See testing the engine for instructions on writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

// Retrieve UIA object for the root view.
Microsoft::WRL::ComPtr<IRawElementProviderSimple> root;
if (SUCCEEDED(ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
IID_PPV_ARGS(&root)))) {
Copy link
Member

Choose a reason for hiding this comment

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

I see that Chrome doesn't have this SUCCEEDED check. Just curious, why did you add this? Feel free to keep as is, just asking for knowledge :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do not know for sure why they do not use the check, but QueryInterface can return failure

Copy link
Member

Choose a reason for hiding this comment

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

Can we not guarantee that QueryInterface will succeed here since we entirely own the logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know how accurate it is to say we entirely own the logic. ATL provides a default QueryInterface which calls InternalQueryInterface, which we own, which then calls, CComObjectRootBase::InternalQueryInterface, which is also a provided ATL implementation.

@skia-gold
Copy link

Gold has detected about 1 new digest(s) on patchset 16.
View them at https://flutter-engine-gold.skia.org/cl/github/37754

// common function names. To work around that, windowsx.h is not to be
// included directly, and instead this file should be included. If one
// of the removed Win32 macros is wanted, use the expanded form
// manually instead.
Copy link
Member

Choose a reason for hiding this comment

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

Thank you for cleaning this up. Much nicer.

Copy link
Member

@loic-sharma loic-sharma left a comment

Choose a reason for hiding this comment

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

LGTM, nice work!

@@ -135,6 +136,9 @@ class WindowBindingHandlerDelegate {

// Update the status of the high contrast feature
virtual void UpdateHighContrastEnabled(bool enabled) = 0;

// Obtain a pointer to the fragment root delegate.
Copy link
Member

Choose a reason for hiding this comment

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

It may be useful to add a little detail on how this is used by UIA, since it's not something that was required in MSAA.

@@ -5205,6 +5218,10 @@ std::optional<DWORD> AXPlatformNodeWin::MojoEventToMSAAEvent(
return EVENT_OBJECT_SHOW;
case ax::mojom::Event::kValueChanged:
return EVENT_OBJECT_VALUECHANGE;
#ifdef EVENT_OBJECT_TEXTSELECTIONCHANGED
Copy link
Member

Choose a reason for hiding this comment

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

I'm assuming this was added in Win 8 or 10 maybe? Consider adding a doc comment pointing out why it's ifdefed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually on second look we probably do not need it. This macro should be defined from Windows Server 2008 onwards.

@@ -54,9 +54,14 @@ std::map<AXNode::AXID, AXNode::AXID> g_hit_test_result;
class TestAXTreeObserver : public AXTreeObserver {
private:
void OnNodeDeleted(AXTree* tree, int32_t node_id) override {
const auto iter = g_node_id_to_wrapper_map.find(node_id);
const auto& iter = g_node_id_to_wrapper_map.find(node_id);
Copy link
Member

Choose a reason for hiding this comment

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

Nice.

Copy link
Member

@cbracken cbracken left a comment

Choose a reason for hiding this comment

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

LGTM stamp from a Japanese personal seal

@yaakovschectman yaakovschectman merged commit dec8b52 into flutter:main Dec 7, 2022
@yaakovschectman yaakovschectman deleted the uia branch December 7, 2022 16:12
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 9, 2022
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Dec 9, 2022
…116802)

* bd8bcf956 Roll Fuchsia Mac SDK from crEcyXdyZ686cAqMV... to pMV6A0ykZQ8aA3NG2... (flutter/engine#38120)

* dec8b5221 Preliminary implementation of UIA for A11y on Windows (flutter/engine#37754)

* 5545ccf87 Roll Fuchsia Linux SDK from NlJGkMbtZqQ6_BCpu... to xn8ztWtp-zww-jObz... (flutter/engine#38122)

* 80a15a419 Create FlutterActivity/FlutterFragment using light weight engine with FlutterEngineGroup (flutter/engine#36963)

* 5caef8585 Full implementation of text-input-test (flutter/engine#37986)

* 8f6036e58 Reland fix wrong VSYNC event (flutter/engine#37865)

* 4101c363c [iOS] Change locale format for spell check (flutter/engine#38080)

* 2f5b67e4d [embedder] Ensure destruction called on present (flutter/engine#38078)

* 0bddc6045 [Impeller Scene] Depth attachment; baked lighting example (flutter/engine#38118)

* 6aa4ccd60 Remove dlCanvasRecorder from flutter::PictureRecorder (flutter/engine#38127)

* dbb5284f2 [Windows] Add more cursor plugin tests (flutter/engine#38112)

* 6e91204d9 Roll Fuchsia Mac SDK from pMV6A0ykZQ8aA3NG2... to 9SnrQ0vbR8IC7UIoP... (flutter/engine#38135)

* 3140ad924 [Impeller] order metal samplers according to declared order and not usage order (flutter/engine#38115)

* 84abf21d4 Remove autoninja. (flutter/engine#38136)

* 8a113d328 [embedder] Expose metal surface from test context (flutter/engine#38133)

* 1ef25b63f Roll Fuchsia Mac SDK from 9SnrQ0vbR8IC7UIoP... to aMW0DjntzFJj4RoR3... (flutter/engine#38139)

* 748b3bc15 Revert "Remove dlCanvasRecorder from flutter::PictureRecorder (#38127)" (flutter/engine#38137)

* b6daf3d06 [embedder] Consistent naming for GL/Metal tests (flutter/engine#38141)

* 339d04baf [web] Trivial fix for non-static interop JS interop class. (flutter/engine#38126)

* 1fcbb9c11 [tools] Eliminate version on Obj-C docs (flutter/engine#38145)

* 71928b6a4 [Impeller] Use DrawPath instead of Rect geometry when the paint style is stroke (flutter/engine#38146)

* 23ce8fdbc Roll Skia from dd3285a80b23 to f84dc9303045 (4 revisions) (flutter/engine#38123)

* 366f8663b Roll Skia from f84dc9303045 to 2691cd7b4110 (40 revisions) (flutter/engine#38151)

* 447e7013e Roll Skia from 2691cd7b4110 to 711396b81248 (1 revision) (flutter/engine#38152)

* cd5d91bf9 Pylint testing/run_tests.py (flutter/engine#38016)

* aafac083b Roll Skia from 711396b81248 to b253b10374e7 (7 revisions) (flutter/engine#38157)

* 799dc78e8 Roll Fuchsia Linux SDK from xn8ztWtp-zww-jObz... to rRJIjuO-dPNCpCTd9... (flutter/engine#38134)

* 3aa3d2a8f Massage the JS interop around `didCreateEngineInitializer` (flutter/engine#38147)

* 030950f30 Roll Skia from b253b10374e7 to ec407902999b (3 revisions) (flutter/engine#38158)
gspencergoog pushed a commit to gspencergoog/flutter that referenced this pull request Jan 19, 2023
…lutter#116802)

* bd8bcf956 Roll Fuchsia Mac SDK from crEcyXdyZ686cAqMV... to pMV6A0ykZQ8aA3NG2... (flutter/engine#38120)

* dec8b5221 Preliminary implementation of UIA for A11y on Windows (flutter/engine#37754)

* 5545ccf87 Roll Fuchsia Linux SDK from NlJGkMbtZqQ6_BCpu... to xn8ztWtp-zww-jObz... (flutter/engine#38122)

* 80a15a419 Create FlutterActivity/FlutterFragment using light weight engine with FlutterEngineGroup (flutter/engine#36963)

* 5caef8585 Full implementation of text-input-test (flutter/engine#37986)

* 8f6036e58 Reland fix wrong VSYNC event (flutter/engine#37865)

* 4101c363c [iOS] Change locale format for spell check (flutter/engine#38080)

* 2f5b67e4d [embedder] Ensure destruction called on present (flutter/engine#38078)

* 0bddc6045 [Impeller Scene] Depth attachment; baked lighting example (flutter/engine#38118)

* 6aa4ccd60 Remove dlCanvasRecorder from flutter::PictureRecorder (flutter/engine#38127)

* dbb5284f2 [Windows] Add more cursor plugin tests (flutter/engine#38112)

* 6e91204d9 Roll Fuchsia Mac SDK from pMV6A0ykZQ8aA3NG2... to 9SnrQ0vbR8IC7UIoP... (flutter/engine#38135)

* 3140ad924 [Impeller] order metal samplers according to declared order and not usage order (flutter/engine#38115)

* 84abf21d4 Remove autoninja. (flutter/engine#38136)

* 8a113d328 [embedder] Expose metal surface from test context (flutter/engine#38133)

* 1ef25b63f Roll Fuchsia Mac SDK from 9SnrQ0vbR8IC7UIoP... to aMW0DjntzFJj4RoR3... (flutter/engine#38139)

* 748b3bc15 Revert "Remove dlCanvasRecorder from flutter::PictureRecorder (flutter#38127)" (flutter/engine#38137)

* b6daf3d06 [embedder] Consistent naming for GL/Metal tests (flutter/engine#38141)

* 339d04baf [web] Trivial fix for non-static interop JS interop class. (flutter/engine#38126)

* 1fcbb9c11 [tools] Eliminate version on Obj-C docs (flutter/engine#38145)

* 71928b6a4 [Impeller] Use DrawPath instead of Rect geometry when the paint style is stroke (flutter/engine#38146)

* 23ce8fdbc Roll Skia from dd3285a80b23 to f84dc9303045 (4 revisions) (flutter/engine#38123)

* 366f8663b Roll Skia from f84dc9303045 to 2691cd7b4110 (40 revisions) (flutter/engine#38151)

* 447e7013e Roll Skia from 2691cd7b4110 to 711396b81248 (1 revision) (flutter/engine#38152)

* cd5d91bf9 Pylint testing/run_tests.py (flutter/engine#38016)

* aafac083b Roll Skia from 711396b81248 to b253b10374e7 (7 revisions) (flutter/engine#38157)

* 799dc78e8 Roll Fuchsia Linux SDK from xn8ztWtp-zww-jObz... to rRJIjuO-dPNCpCTd9... (flutter/engine#38134)

* 3aa3d2a8f Massage the JS interop around `didCreateEngineInitializer` (flutter/engine#38147)

* 030950f30 Roll Skia from b253b10374e7 to ec407902999b (3 revisions) (flutter/engine#38158)
@nicerloop nicerloop mentioned this pull request Jun 28, 2024
8 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants