Commit 80b5e13b authored by Hiroki Sato's avatar Hiroki Sato Committed by Commit Bot

Handle VIEW_SELECTED event from list item in ArcA11yHelperBridge

Previously, Android's AccessibilityEvent.TYPE_VIEW_SELECTED is handled
as an event of changing value in ProgressBar or Slider in ARC++.
However, this event is usually used when selecting an item in
AdapterView (like ListView or GridView).

This CL modifies to handle both patterns of the event.

      app that ListView items can be selected and read by ChromeVox

Bug: b:130187244
Test: unit_tests --gtest_filter="ArcAccessibilityHelperBridgeTest.*"
Test: unit_tests --gtest_filter="AXTreeSourceArcTest.*"
Test: manually test with ag/9191465 using PlayStore and TalkBack test
Change-Id: If3af1bdc28490d00399fa89bd18258ff89731d19
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1746326
Commit-Queue: Hiroki Sato <hirokisato@chromium.org>
Reviewed-by: default avatarAlice Boxhall <aboxhall@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarSara Kato <sarakato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695041}
parent 33457ed0
......@@ -366,8 +366,8 @@ void AccessibilityNodeInfoDataWrapper::Serialize(
}
// Range info.
AXRangeInfoData* range_info = node_ptr_->range_info.get();
if (range_info) {
if (node_ptr_->range_info) {
AXRangeInfoData* range_info = node_ptr_->range_info.get();
out_data->AddFloatAttribute(ax::mojom::FloatAttribute::kValueForRange,
range_info->current);
out_data->AddFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange,
......
......@@ -9,7 +9,9 @@
namespace arc {
ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type) {
ax::mojom::Event ToAXEvent(
mojom::AccessibilityEventType arc_event_type,
mojom::AccessibilityNodeInfoData* focused_node_info_data) {
switch (arc_event_type) {
case mojom::AccessibilityEventType::VIEW_FOCUSED:
case mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED:
......@@ -32,8 +34,18 @@ ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type) {
return ax::mojom::Event::kAlert;
case mojom::AccessibilityEventType::VIEW_SCROLLED:
return ax::mojom::Event::kScrollPositionChanged;
case mojom::AccessibilityEventType::VIEW_SELECTED:
return ax::mojom::Event::kValueChanged;
case mojom::AccessibilityEventType::VIEW_SELECTED: {
// In Android, VIEW_SELECTED event is fired in the two cases below:
// 1. Changing a value in ProgressBar or TimePicker.
// (this usage is NOT documented)
// 2. Selecting an item in the context of an AdapterView.
// (officially documented in Android Developer doc below)
// https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent#TYPE_VIEW_SELECTED
if (focused_node_info_data && focused_node_info_data->range_info)
return ax::mojom::Event::kValueChanged;
else
return ax::mojom::Event::kSelection;
}
case mojom::AccessibilityEventType::VIEW_HOVER_EXIT:
case mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_START:
case mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_END:
......
......@@ -12,9 +12,11 @@
namespace arc {
namespace mojom {
enum class AccessibilityEventType;
class AccessibilityNodeInfoData;
} // namespace mojom
ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type);
ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type,
mojom::AccessibilityNodeInfoData* node_info_data);
} // namespace arc
......
......@@ -189,7 +189,12 @@ void AXTreeSourceArc::NotifyAccessibilityEvent(AXEventData* event_data) {
event_bundle.events.emplace_back();
ui::AXEvent& event = event_bundle.events.back();
event.event_type = ToAXEvent(event_data->event_type);
// When the focused node exists, give it as a hint to decide a Chrome
// automation event type.
AXNodeInfoData* opt_focused_node = nullptr;
if (tree_map_.find(focused_id_) != tree_map_.end())
opt_focused_node = tree_map_[focused_id_]->GetNode();
event.event_type = ToAXEvent(event_data->event_type, opt_focused_node);
event.id = event_data->source_id;
event_bundle.updates.emplace_back();
......@@ -200,22 +205,18 @@ void AXTreeSourceArc::NotifyAccessibilityEvent(AXEventData* event_data) {
current_tree_serializer_->SerializeChanges(GetFromId(event_data->source_id),
&event_bundle.updates.back());
extensions::AutomationEventRouter* router =
extensions::AutomationEventRouter::GetInstance();
router->DispatchAccessibilityEvents(event_bundle);
GetAutomationEventRouter()->DispatchAccessibilityEvents(event_bundle);
}
void AXTreeSourceArc::NotifyActionResult(const ui::AXActionData& data,
bool result) {
extensions::AutomationEventRouter::GetInstance()->DispatchActionResult(
data, result);
GetAutomationEventRouter()->DispatchActionResult(data, result);
}
void AXTreeSourceArc::NotifyGetTextLocationDataResult(
const ui::AXActionData& data,
const base::Optional<gfx::Rect>& rect) {
extensions::AutomationEventRouter::GetInstance()
->DispatchGetTextLocationDataResult(data, rect);
GetAutomationEventRouter()->DispatchGetTextLocationDataResult(data, rect);
}
bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const {
......@@ -443,12 +444,17 @@ void AXTreeSourceArc::Reset() {
current_tree_serializer_.reset(new AXTreeArcSerializer(this));
root_id_ = -1;
focused_id_ = -1;
extensions::AutomationEventRouter* router =
extensions::AutomationEventRouter::GetInstance();
extensions::AutomationEventRouterInterface* router =
GetAutomationEventRouter();
if (!router)
return;
router->DispatchTreeDestroyedEvent(ax_tree_id(), nullptr);
}
extensions::AutomationEventRouterInterface*
AXTreeSourceArc::GetAutomationEventRouter() const {
return extensions::AutomationEventRouter::GetInstance();
}
} // namespace arc
......@@ -11,6 +11,7 @@
#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h"
#include "components/arc/mojom/accessibility_helper.mojom.h"
#include "extensions/browser/api/automation_internal/automation_event_router.h"
#include "ui/accessibility/ax_action_handler.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_node_data.h"
......@@ -88,6 +89,10 @@ class AXTreeSourceArc : public ui::AXTreeSource<ArcAccessibilityInfoData*,
bool is_input_method_window() { return is_input_method_window_; }
protected:
virtual extensions::AutomationEventRouterInterface* GetAutomationEventRouter()
const;
private:
friend class arc::AXTreeSourceArcTest;
class FocusStealer;
......
......@@ -73,8 +73,9 @@ class AutomationEventRouter : public ui::AXEventBundleSink,
content::BrowserContext* browser_context = nullptr) override;
// Notify the source extension of the result to getTextLocation.
void DispatchGetTextLocationDataResult(const ui::AXActionData& data,
const base::Optional<gfx::Rect>& rect);
void DispatchGetTextLocationDataResult(
const ui::AXActionData& data,
const base::Optional<gfx::Rect>& rect) override;
private:
struct AutomationListener {
......
......@@ -51,6 +51,11 @@ class AutomationEventRouterInterface {
bool result,
content::BrowserContext* browser_context = nullptr) = 0;
// Notify the source extension of the result to getTextLocation.
virtual void DispatchGetTextLocationDataResult(
const ui::AXActionData& data,
const base::Optional<gfx::Rect>& rect) {}
AutomationEventRouterInterface() {}
virtual ~AutomationEventRouterInterface() {}
......
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