Commit 3a75d1cf authored by dmazzoni@chromium.org's avatar dmazzoni@chromium.org

Improve accessible hit testing heuristic.

When doing recursive hit testing and the point falls within two children
of the same element, prefer the one that has an indirect descendant
(i.e. grandchild) match.

A better fix would be to send an IPC to the renderer and let Blink do
the hit testing, I filed another bug (357371) for that. This is a stopgap.

Note, though, that we still need this hit testing algorithm for
synchronous APIs (like on Windows), so it's worth improving this.

BUG=357247
R=aboxhall@chromium.org

Review URL: https://codereview.chromium.org/215633003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260161 0039d316-1c4b-4281-b951-d872f2087c98
parent 0a9ef3ea
......@@ -314,8 +314,15 @@ gfx::Rect BrowserAccessibility::GetGlobalBoundsForRange(int start, int len)
BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
const gfx::Point& point) {
// The best result found that's a child of this object.
BrowserAccessibility* child_result = NULL;
// The best result that's an indirect descendant like grandchild, etc.
BrowserAccessibility* descendant_result = NULL;
// Walk the children recursively looking for the BrowserAccessibility that
// most tightly encloses the specified point.
// most tightly encloses the specified point. Walk backwards so that in
// the absence of any other information, we assume the object that occurs
// later in the tree is on top of one that comes before it.
for (int i = static_cast<int>(PlatformChildCount()) - 1; i >= 0; --i) {
BrowserAccessibility* child = PlatformGetChild(i);
......@@ -324,9 +331,29 @@ BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
if (child->role() == ui::AX_ROLE_COLUMN)
continue;
if (child->GetGlobalBoundsRect().Contains(point))
return child->BrowserAccessibilityForPoint(point);
if (child->GetGlobalBoundsRect().Contains(point)) {
BrowserAccessibility* result = child->BrowserAccessibilityForPoint(point);
if (result == child && !child_result)
child_result = result;
if (result != child && !descendant_result)
descendant_result = result;
}
if (child_result && descendant_result)
break;
}
// Explanation of logic: it's possible that this point overlaps more than
// one child of this object. If so, as a heuristic we prefer if the point
// overlaps a descendant of one of the two children and not the other.
// As an example, suppose you have two rows of buttons - the buttons don't
// overlap, but the rows do. Without this heuristic, we'd greedily only
// consider one of the containers.
if (descendant_result)
return descendant_result;
if (child_result)
return child_result;
return this;
}
......
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