Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(902)

Unified Diff: content/browser/accessibility/browser_accessibility_manager.cc

Issue 2393123002: Implement caching asynchronous accessibility hit testing. (Closed)
Patch Set: Made test more robust Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/accessibility/browser_accessibility_manager.cc
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index b3d3668035e6477cb81ac81b34f3abb576c2f3bc..f5f8808b0f952d174dcba7053edcb2c4ec7c7cf0 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -398,6 +398,9 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Fire the native event.
BrowserAccessibility* event_target = GetFromAXNode(node);
if (event_target) {
+ if (event_type == ui::AX_EVENT_HOVER)
+ GetRootManager()->CacheHitTestResult(event_target);
+
NotifyAccessibilityEvent(
BrowserAccessibilityEvent::FromBlink,
event_type,
@@ -1095,4 +1098,56 @@ BrowserAccessibilityManager::SnapshotAXTreeForTesting() {
return update;
}
+BrowserAccessibility* BrowserAccessibilityManager::CachingAsyncHitTest(
+ const gfx::Point& screen_point) {
+ BrowserAccessibilityManager* root_manager = GetRootManager();
+ if (root_manager && root_manager != this)
+ return root_manager->CachingAsyncHitTest(screen_point);
+
+ if (delegate()) {
+ // This triggers an asynchronous request to compute the true object that's
+ // under |screen_point|.
+ gfx::Point local_point = screen_point - GetViewBounds().OffsetFromOrigin();
+ delegate()->AccessibilityHitTest(local_point);
+
+ // Unfortunately we still have to return an answer synchronously because
+ // the APIs were designed that way. The best case scenario is that the
+ // screen point is within the bounds of the last result we got from a
+ // call to AccessibilityHitTest - in that case, we can return that object!
+ if (last_hover_bounds_.Contains(screen_point)) {
+ BrowserAccessibilityManager* manager =
+ BrowserAccessibilityManager::FromID(last_hover_ax_tree_id_);
+ if (manager) {
+ BrowserAccessibility* node = manager->GetFromID(last_hover_node_id_);
+ if (node)
+ return node;
+ }
+ }
+ }
+
+ // If that test failed we have to fall back on searching the accessibility
+ // tree locally for the best bounding box match. This is generally right
+ // for simple pages but wrong in cases of z-index, overflow, and other
+ // more complicated layouts. The hope is that if the user is moving the
+ // mouse, this fallback will only be used transiently, and the asynchronous
+ // result will be used for the next call.
+ return GetRoot()->ApproximateHitTest(screen_point);
+}
+
+void BrowserAccessibilityManager::CacheHitTestResult(
+ BrowserAccessibility* hit_test_result) {
+ // Walk up to the highest ancestor that's a leaf node; we don't want to
+ // return a node that's hidden from the tree.
+ BrowserAccessibility* parent = hit_test_result->GetParent();
+ while (parent) {
+ if (parent->PlatformChildCount() == 0)
+ hit_test_result = parent;
+ parent = parent->GetParent();
+ }
+
+ last_hover_ax_tree_id_ = hit_test_result->manager()->ax_tree_id();
+ last_hover_node_id_ = hit_test_result->GetId();
+ last_hover_bounds_ = hit_test_result->GetScreenBoundsRect();
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698