Skip to content

Commit

Permalink
T48742457: Support role=application web widgets
Browse files Browse the repository at this point in the history
After: The green rect follows web focus.
Before: TalkBack tries to read the TV apps as a
textual documents.

Background:
Within <xxx role=application>...</xxx>, screen readers
should not consume DPAD (arrow key) events. Web apps or
widgets with role=application have, per the WAI-ARIA
spec's contract, their own JavaScript logic for moving
focus.

I learned this through:
w3c/aria#1049

Problem:
TalkBack completely neglects role=application.

Solution:
Whenever accessibility focus (the green rect) goes to a
WebView with <body role=application> or anywhere within
such a document, don't consume the DPAD events; let them
through.

Testing done:
Open a simple TV web app that has <body role=application>.
Notice:
 Once the web view gets accessibilty focus, TalkBack
 won't eat (consume) DPAD key events and the the key
 events reach the web page's key handler in JavaScript.

Signed-off-by: Hugo Holgersson <[email protected]>
  • Loading branch information
hugoholgersson committed Dec 3, 2021
1 parent 9db811a commit 650ba28
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,13 @@ private boolean shouldHandleEvent(AccessibilityNodeInfoCompat cursor, KeyEvent e
return false;
}
}

// Web applications and web widgets with role=application have, per the
// WAI-ARIA spec's contract, their own JavaScript logic for moving focus.
// TalkBack should not consume key events when such an app has accessibility focus.
boolean shouldProcessDPadKeyEvent = this.shouldProcessDPadKeyEvent &&
!AccessibilityNodeInfoUtils.isWebApplication(cursor);

// TalkBack should always consume up/down/left/right on the d-pad, unless
// shouldProcessDPadKeyEvent is false. Otherwise, strange things will happen when TalkBack
// cannot navigate further.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,37 @@ public boolean accept(AccessibilityNodeInfoCompat node) {
|| (node != null && node.getCollectionInfo() != null);
});

public static boolean hasApplicationWebRole(AccessibilityNodeInfoCompat node) {
return node != null && node.getExtras() != null
&& node.getExtras().containsKey("AccessibilityNodeInfo.chromeRole")
&& node.getExtras().get("AccessibilityNodeInfo.chromeRole").equals("application");
}

private static final Filter<AccessibilityNodeInfoCompat> FILTER_IN_WEB_APPLICATION =
new Filter<AccessibilityNodeInfoCompat>() {
@Override
public boolean accept(AccessibilityNodeInfoCompat node) {
return hasApplicationWebRole(node);
}
};

/**
* Returns true if |node| has role=application, i.e. |node| has JavaScript
* that handles key events.
*/
public static boolean isWebApplication(AccessibilityNodeInfoCompat node) {
// When a WebView has focus: Check Chromium's accessibility tree's first node.
// If that node wants raw key event, instead of first "tabbing" the green
// rect to it, skip ahead and let the web app directly decide where to go.
boolean firstChromiumNodeWantsKeyEvents =
Role.getRole(node) == Role.ROLE_WEB_VIEW
&& node.getChildCount() > 0
&& hasApplicationWebRole(node.getChild(0));

return firstChromiumNodeWantsKeyEvents ||
getSelfOrMatchingAncestor(node, FILTER_IN_WEB_APPLICATION) != null;
}

private AccessibilityNodeInfoUtils() {
// This class is not instantiable.
}
Expand Down

0 comments on commit 650ba28

Please sign in to comment.