Skip to content

Edge with UIA: allow activating buttons in browse mode by walking ancestors until an action succeeds#15748

Merged
seanbudd merged 9 commits intomasterfrom
edgeAncestorDoAction
Nov 22, 2023
Merged

Edge with UIA: allow activating buttons in browse mode by walking ancestors until an action succeeds#15748
seanbudd merged 9 commits intomasterfrom
edgeAncestorDoAction

Conversation

@michaelDCurran
Copy link
Copy Markdown
Member

Link to issue number:

Fixes #14612

Summary of the issue:

when accessing Microsoft Edge with UI Automation, NVDA is unable to activate most buttons and controls in browse mode.
This is because NvDA only tries to invoke/select/toggle the deepest element at the browse mode caret position, which may be a text leaf, or span within the interactive control, and not the control itself.

Description of user facing changes

Microsoft Edge via UI Automation: NVDA can now activate buttons and other controls in browse mode.

Description of development approach

  • UIA NVDAObject's doAction method: if the element cannot be invoked or selected or toggled, then NotImplementedError is raised.
  • UIA BrowseMode document's _activateNVDAObject method: Rather than just trying to activate the given object with its doAction method, instead start at the given object and move up its ancestors, until a call to doAction succeeds. I.e. activates the given object or its closest ancestor that supports performing actions.

Testing strategy:

  • Ensure NVDA's use UI Automation to access Edge / chromium is set to yes.
  • Open Microsoft Edge and navigate to https://www.youtube.com/
  • Tab to the Guide button and press enter, and ensure that it activates.

Known issues with pull request:

None known.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

…ement cannot be invoked, toggled or selected.
… with the NVDAObject's doAction method, keep going up the ancestors until DoAction succeeds.
@michaelDCurran michaelDCurran requested a review from a team as a code owner November 6, 2023 08:35
@jcsteh
Copy link
Copy Markdown
Contributor

jcsteh commented Nov 7, 2023

Unless I'm missing something, this is not going to work well for non-semantic clickable controls. Obviously, those are authoring error, but there are plenty of them. This might also result in a click potentially getting routed to a far away, irrelevant ancestor that happens to have a click handler for event listening purposes.

With gecko_ia2, when walking ancestors, if doAction fails, NVDA simulates a mouse click if the ancestor has a relevant location and considers that a success. This does occasionally fail and click the wrong place, since location might not be perfect due to bugs, pop-ups obscuring things, etc. That's why Chrome and Firefox implemented click ancestor, but I guess we can't access that with UIA, so click simulation is probably the best we can do.

@michaelDCurran michaelDCurran marked this pull request as draft November 7, 2023 21:09
…the base BrowseMode's _activateNvDAObject, and remove UIA browseMode's implementation.

All browse mode documents will now use gecko_ia2's approach to activating which is to first try doAction, and if that fails, then perform a click if the object is visible, otherwise, go up the ancestors doing the same thing until one of those succeeds.
@michaelDCurran michaelDCurran marked this pull request as ready for review November 8, 2023 01:39
@michaelDCurran michaelDCurran requested a review from jcsteh November 8, 2023 01:41
@michaelDCurran
Copy link
Copy Markdown
Member Author

@jcsteh I've now moved that gecko_ia2 logic into the base browse mode _activateNVDAObject. I can't see any reason why all implementations can't use that then if we are happy with it.

Copy link
Copy Markdown
Contributor

@jcsteh jcsteh left a comment

Choose a reason for hiding this comment

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

"Happy with it" is probably a stretch. As I noted, it can result in clicking the wrong thing in some cases. However, I think this is probably the most pragmatic solution given the prevalence of non-semantic clickables with ancestor click handlers.

Could this be a problem for non-web contexts; Microsoft Word, etc.?

return
elif self.UIASelectionItemPattern:
self.UIASelectionItemPattern.select()
return
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why this change? I don't think there's a functional difference, but having elif + return is redundant. If you want to keep the early returns in each branch, I'd change the elifs to ifs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Previously it would raise NotImplementedError only if actionIndex was not 0. Now it also raises NotImplementedError if neither invoking, toggling or selecting is possible. At least, that was what I was trying to go for...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah gotcha. Sorry, missed that subtlety. In that case, please change the elifs to ifs and we're good here.

@AppVeyorBot
Copy link
Copy Markdown

See test results for failed build of commit 5dc72b2c99

@michaelDCurran
Copy link
Copy Markdown
Member Author

@jcsteh Some quick tests with MS Word seems to suggest things are working okay. It is possibly now more accurate when jumping to references.

return
elif self.UIASelectionItemPattern:
self.UIASelectionItemPattern.select()
return
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah gotcha. Sorry, missed that subtlety. In that case, please change the elifs to ifs and we're good here.

@AppVeyorBot
Copy link
Copy Markdown

See test results for failed build of commit 2bc1100bfa

Copy link
Copy Markdown
Member

@seanbudd seanbudd left a comment

Choose a reason for hiding this comment

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

Please fix the failing lint check before merging

@seanbudd seanbudd added the conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. label Nov 21, 2023
@seanbudd seanbudd merged commit 4c36700 into master Nov 22, 2023
@seanbudd seanbudd deleted the edgeAncestorDoAction branch November 22, 2023 00:57
@nvaccessAuto nvaccessAuto added this to the 2024.1 milestone Nov 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NVDA fails to interact with some web controls on Google pages if using UIA for Microsoft Edge

5 participants