Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,39 @@ 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-like view (an actual WebView or a browser) has focus:
// Check the web content'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 firstWebNode = WebInterfaceUtils.supportsWebActions(node)
&& !WebInterfaceUtils.supportsWebActions(node.getParent());
boolean firstWebNodeWantsKeyEvents = firstWebNode
&& node.getChildCount() > 0
&& hasApplicationWebRole(node.getChild(0));

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

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