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

Announce alerts through SemanticsService on Windows #36966

Merged
merged 21 commits into from
Oct 27, 2022

Conversation

yaakovschectman
Copy link
Contributor

The platform message used to trigger announcements/alerts by the Framework was previously ignored on Windows, as there was no channel to accept it, nor method to announce it. This PR receives the message to announce a message to the screen reader. The former root node of the Window is now wrapped by a parent node which may also create an alert node as a sibling, and can then notify a EVENT_SYSTEM_ALERT event pointing to this alert node to read out an alert.

You may test this by running the code sample in the linked issue with either Windows Narrator or NVDA.

Addresses flutter/flutter#113059

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.

Sorry, something went wrong.

@yaakovschectman yaakovschectman marked this pull request as ready for review October 24, 2022 18:30
return nullptr;
}
if (child_id == CHILDID_SELF || child_id == kWindowChildId) {
child_id = CHILDID_SELF;
Copy link
Member

Choose a reason for hiding this comment

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

What's the value of setting child_id on this line and line 38 below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

child_id is a reference to var_id->lVal. Setting it updates the value in the VARIANT passed to the function, so for example, if a method is called in the root node with var_id.lVal == 1 pointing to the window node child, var_id.lVal is set to CHILDID_SELF = 0 and the method is called on the window node.

Copy link
Member

Choose a reason for hiding this comment

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

Ah I missed the reference, thanks!

Copy link
Member

Choose a reason for hiding this comment

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

I should make stronger coffee 😂

Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this method would be clearer if it returned the target and child ID instead of mutating the input var_id. Perhaps it could return a std::optional<std::pair<IAccessible*, VARIANT>>? This would be more verbose but also make its behavior more apparent. Thoughts?

@loic-sharma loic-sharma requested a review from chunhtai October 24, 2022 22:06
@loic-sharma
Copy link
Member

@yaakovschectman Just curious, how did you make the decision between implementing this at the Windows native layer versus at the accessibility bridge layer? It seems we could make the AccessibilityBridge generate an AXTreeUpdate containing a node with an alert. Generating an Event::ALERT event seems to notify Windows as expected.

@yaakovschectman
Copy link
Contributor Author

@yaakovschectman Just curious, how did you make the decision between implementing this at the Windows native layer versus at the accessibility bridge layer?

When trying to research how to go about implementing this, I saw Chromium does this by attaching an optional alert node to whatever AX view node the alert is associated with. This would not be easily translated to our project as we do not use the AX view architecture they do, and our alerts from the framework are not associated with any particular node. Adding a new sibling to the existing root node via generating an update looks like it would require recreating the FlutterSemanticsNode from only the AXNode/AXPlatformNode, which seems easily error-prone. So I spoke with Chris, Nektarios, and Chun-Heng and received the suggestion to wrap the root node in a separate implementation of IAccessible.

@loic-sharma
Copy link
Member

I chatted with Yaakov offline on #36966 (comment). It seems the concerns with the accessibility bridge approach are surmountable. Here are pro/cons on the accessibility bridge approach over the native MSAA approach for announcing alerts:

Pros:

  • If macOS and Linux needs similar announce alerts work, we might be able to reuse this logic (instead of doing 3 native accessibility announcement implementations)
  • Accessibility logic is kept within AccessibilityBridge which may make testing easier

Cons:

  • We know the native approach works, whereas the AccessibilityBridge approach may have blockers
  • This is pivot, which will push back when we can release this

Verified

This commit was signed with the committer’s verified signature.
pablogsal Pablo Galindo Salgado
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.

Overall looks good, just a few nits.

Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

LGTM, once comments from other reviewers are addressed

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.

Please take another look at the open comments, but other than that looks good!

@yaakovschectman yaakovschectman merged commit 9915434 into flutter:main Oct 27, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 27, 2022
yaakovschectman added a commit that referenced this pull request Oct 28, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 28, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 28, 2022
yaakovschectman added a commit to yaakovschectman/flutter-engine that referenced this pull request Oct 31, 2022
bourdakos1 pushed a commit to bourdakos1/engine that referenced this pull request Nov 2, 2022
yaakovschectman added a commit that referenced this pull request Nov 3, 2022
* Corresponds to changes by reverted PR #36966.

* Changes on top of original reverted PR that add IServiceProvider and COM_INTERFACE_ENTRY's to the new node classes.

* self_com_ unused
schwa423 pushed a commit to schwa423/engine that referenced this pull request Nov 16, 2022
schwa423 pushed a commit to schwa423/engine that referenced this pull request Nov 16, 2022
* Corresponds to changes by reverted PR flutter#36966.

* Changes on top of original reverted PR that add IServiceProvider and COM_INTERFACE_ENTRY's to the new node classes.

* self_com_ unused
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.

None yet

4 participants