Commit 9b8d378a authored by Yuki Awano's avatar Yuki Awano Committed by Commit Bot

Fix accessibility location

- Fix GetBounds to return bounds which can be passed to
  AXNodeData.location. Bounds are returned in the following coordinates.
- Bounds of root node are relative to its container, i.e. focused
  window.
- Bounds of non-root node are relative to its tree's root.
- Bounds are returned in non-dip value.

      Android window with ChromeVox. Confirm that focus rectangle is
      shown on right location.

Bug: 764870
Test: enable --enable-chromevox-arc-support and navigate elements on
Change-Id: I052c3da643cd3e017b6256372221a6947410da65
Reviewed-on: https://chromium-review.googlesource.com/671168
Commit-Queue: Yuki Awano <yawano@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#505284}
parent 115ef964
......@@ -60,22 +60,6 @@ ui::AXEvent ToAXEvent(arc::mojom::AccessibilityEventType arc_event_type) {
return ui::AX_EVENT_CHILDREN_CHANGED;
}
const gfx::Rect GetBounds(arc::mojom::AccessibilityNodeInfoData* node) {
exo::WMHelper* wm_helper = exo::WMHelper::GetInstance();
if (!wm_helper)
return gfx::Rect();
aura::Window* focused_window = wm_helper->GetFocusedWindow();
gfx::Rect bounds_in_screen = node->bounds_in_screen;
if (focused_window) {
aura::Window* toplevel_window = focused_window->GetToplevelWindow();
return gfx::ScaleToEnclosingRect(
bounds_in_screen,
1.0f / toplevel_window->layer()->device_scale_factor());
}
return bounds_in_screen;
}
bool GetBooleanProperty(arc::mojom::AccessibilityNodeInfoData* node,
arc::mojom::AccessibilityBooleanProperty prop) {
if (!node->boolean_properties)
......@@ -513,10 +497,20 @@ void AXTreeSourceArc::SerializeNode(mojom::AccessibilityNodeInfoData* node,
out_data->AddBoolAttribute(ui::AX_ATTR_SCROLLABLE, true);
}
const gfx::Rect bounds_in_screen = GetBounds(node);
out_data->location.SetRect(bounds_in_screen.x(), bounds_in_screen.y(),
bounds_in_screen.width(),
bounds_in_screen.height());
exo::WMHelper* wm_helper = exo::WMHelper::GetInstance();
// To get bounds of a node which can be passed to AXNodeData.location,
// - Root node must exist.
// - Window where this tree is attached to need to be focused.
if (root_id_ != -1 && wm_helper) {
aura::Window* focused_window = wm_helper->GetFocusedWindow();
if (focused_window) {
const gfx::Rect bounds_in_screen = GetBounds(node, focused_window);
out_data->location.SetRect(bounds_in_screen.x(), bounds_in_screen.y(),
bounds_in_screen.width(),
bounds_in_screen.height());
}
}
if (out_data->role == ui::AX_ROLE_TEXT_FIELD && !text.empty())
out_data->AddStringAttribute(ui::AX_ATTR_VALUE, text);
......@@ -550,6 +544,35 @@ void AXTreeSourceArc::SerializeNode(mojom::AccessibilityNodeInfoData* node,
}
}
const gfx::Rect AXTreeSourceArc::GetBounds(
mojom::AccessibilityNodeInfoData* node,
aura::Window* focused_window) const {
DCHECK(focused_window);
DCHECK(root_id_ != -1);
gfx::Rect node_bounds = node->bounds_in_screen;
if (node->id == root_id_) {
// Top level window returns its bounds in dip.
aura::Window* toplevel_window = focused_window->GetToplevelWindow();
float scale = toplevel_window->layer()->device_scale_factor();
// Bounds of root node is relative to its container, i.e. focused window.
node_bounds.Offset(
static_cast<int>(-1.0f * scale *
static_cast<float>(toplevel_window->bounds().x())),
static_cast<int>(-1.0f * scale *
static_cast<float>(toplevel_window->bounds().y())));
return node_bounds;
}
// Bounds of non-root node is relative to its tree's root.
gfx::Rect root_bounds = GetFromId(root_id_)->bounds_in_screen;
node_bounds.Offset(-1 * root_bounds.x(), -1 * root_bounds.y());
return node_bounds;
}
void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) {
delegate_->OnAction(data);
}
......
......@@ -75,6 +75,14 @@ class AXTreeSourceArc
void SerializeNode(mojom::AccessibilityNodeInfoData* node,
ui::AXNodeData* out_data) const override;
// Returns bounds of a node which can be passed to AXNodeData.location. Bounds
// are returned in the following coordinates depending on whether it's root or
// not.
// - Root node is relative to its container, i.e. focused window.
// - Non-root node is relative to the root node of this tree.
const gfx::Rect GetBounds(mojom::AccessibilityNodeInfoData* node,
aura::Window* focused_window) const;
// AXHostDelegate overrides.
void PerformAction(const ui::AXActionData& data) override;
......
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