Commit ea553f7a authored by Hiroki Sato's avatar Hiroki Sato Committed by Commit Bot

Adjust focus when it is set to entire List in ARC

Sometimes Android sets the focus (via a11y event of VIEW_FOCUSED) to
the collection (list/grid). This invokes ChromeVox to read entire
content of the collection.

This CL adds following logic to handle the situation:
1. If a role of a node is kList or kGrid, CanBeAccessibilityFocused returns
   false.
2. When a11y event of VIEW_FOCUSED is dispatched, instead of directly
   assigning event source as a focus, try to find the first focusable
   node under the event source.

element of the node gets ChromeVox focus.

Bug: b:130185621
Test: unit_tests --gtest_filter="AXTreeSourceArcTest.*"
Test: manual. Open PlayStore/Hangouts and open drawer menu. The fist
Change-Id: Ic85f05711fbd9cff2e2e074a01daa37c09d71bff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1942902
Commit-Queue: Hiroki Sato <hirokisato@chromium.org>
Reviewed-by: default avatarSara Kato <sarakato@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721876}
parent 5656d811
......@@ -71,7 +71,9 @@ bool AccessibilityNodeInfoDataWrapper::CanBeAccessibilityFocused() const {
bool important = GetProperty(AXBooleanProperty::IMPORTANCE) ||
IsFocusableNativeWeb(data.role);
bool non_generic_role = data.role != ax::mojom::Role::kGenericContainer &&
data.role != ax::mojom::Role::kGroup;
data.role != ax::mojom::Role::kGroup &&
data.role != ax::mojom::Role::kList &&
data.role != ax::mojom::Role::kGrid;
bool actionable = is_clickable_leaf_ ||
GetProperty(AXBooleanProperty::FOCUSABLE) ||
GetProperty(AXBooleanProperty::CHECKABLE);
......
......@@ -117,8 +117,13 @@ void AXTreeSourceArc::NotifyAccessibilityEvent(AXEventData* event_data) {
if (event_data->event_type == AXEventType::VIEW_FOCUSED) {
AccessibilityInfoDataWrapper* focused_node =
GetFromId(event_data->source_id);
if (focused_node)
focused_id_ = event_data->source_id;
if (focused_node) {
// Sometimes Android sets focus on unfocusable node, e.g. ListView.
AccessibilityInfoDataWrapper* adjusted_node =
FindFirstFocusableNode(focused_node);
focused_id_ = IsValid(adjusted_node) ? adjusted_node->GetId()
: event_data->source_id;
}
} else if (event_data->event_type == AXEventType::WINDOW_STATE_CHANGED) {
// When accessibility window changed, a11y event of WINDOW_CONTENT_CHANGED
// is fired from Android multiple times.
......
......@@ -919,7 +919,6 @@ TEST_F(AXTreeSourceArcTest, OnWindowStateChangedEvent) {
TEST_F(AXTreeSourceArcTest, OnFocusEvent) {
auto event = AXEventData::New();
event->source_id = 2; // node2.
event->task_id = 1;
event->event_type = AXEventType::VIEW_FOCUSED;
......@@ -936,28 +935,41 @@ TEST_F(AXTreeSourceArcTest, OnFocusEvent) {
SetProperty(root, AXIntListProperty::CHILD_NODE_IDS,
std::vector<int>({1, 2}));
SetProperty(root, AXBooleanProperty::IMPORTANCE, true);
root->collection_info = AXCollectionInfoData::New();
root->collection_info->row_count = 2;
root->collection_info->column_count = 1;
event->node_data.emplace_back(AXNodeInfoData::New());
AXNodeInfoData* node1 = event->node_data.back().get();
node1->id = 1;
SetProperty(node1, AXBooleanProperty::IMPORTANCE, true);
SetProperty(node1, AXBooleanProperty::ACCESSIBILITY_FOCUSED, true);
SetProperty(node1, AXBooleanProperty::VISIBLE_TO_USER, true);
SetProperty(node1, AXStringProperty::TEXT, "sample string1.");
event->node_data.emplace_back(AXNodeInfoData::New());
AXNodeInfoData* node2 = event->node_data.back().get();
node2->id = 2;
SetProperty(node2, AXBooleanProperty::IMPORTANCE, true);
SetProperty(node1, AXBooleanProperty::VISIBLE_TO_USER, true);
SetProperty(node2, AXStringProperty::TEXT, "sample string2.");
// Chrome should focus to node2, even if node1 has 'focus' in Android.
event->source_id = node2->id;
CallNotifyAccessibilityEvent(event.get());
ui::AXTreeData data;
// Chrome should focus to node2, even if node1 has 'focus' in Android.
ui::AXTreeData data;
EXPECT_TRUE(CallGetTreeData(&data));
EXPECT_EQ(node2->id, data.focus_id);
EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus));
// Chrome should focus to node2, even if Android sends focus on List.
event->source_id = root->id;
CallNotifyAccessibilityEvent(event.get());
EXPECT_TRUE(CallGetTreeData(&data));
EXPECT_EQ(node1->id, data.focus_id);
EXPECT_EQ(2, GetDispatchedEventCount(ax::mojom::Event::kFocus));
}
TEST_F(AXTreeSourceArcTest, SerializeAndUnserialize) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment