Bug 764686 - Always check if point are in match's bounds in Accessible::ChildAtPoint(). r=davidb

This commit is contained in:
Eitan Isaacson 2012-06-18 16:07:56 -07:00
parent bcfc7149dc
commit a9fc03b503
2 changed files with 56 additions and 32 deletions

View File

@ -799,38 +799,11 @@ Accessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
if (!accessible)
return fallbackAnswer;
if (accessible == this) {
// Manually walk through accessible children and see if the are within this
// point. Skip offscreen or invisible accessibles. This takes care of cases
// where layout won't walk into things for us, such as image map areas and
// sub documents (XXX: subdocuments should be handled by methods of
// OuterDocAccessibles).
PRUint32 childCount = ChildCount();
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
Accessible* child = GetChildAt(childIdx);
PRInt32 childX, childY, childWidth, childHeight;
child->GetBounds(&childX, &childY, &childWidth, &childHeight);
if (aX >= childX && aX < childX + childWidth &&
aY >= childY && aY < childY + childHeight &&
(child->State() & states::INVISIBLE) == 0) {
if (aWhichChild == eDeepestChild)
return child->ChildAtPoint(aX, aY, eDeepestChild);
return child;
}
}
// The point is in this accessible but not in a child. We are allowed to
// return |this| as the answer.
return accessible;
}
// Hurray! We have an accessible for the frame that layout gave us.
// Since DOM node of obtained accessible may be out of flow then we should
// ensure obtained accessible is a child of this accessible.
Accessible* child = accessible;
while (true) {
while (child != this) {
Accessible* parent = child->Parent();
if (!parent) {
// Reached the top of the hierarchy. These bounds were inside an
@ -838,13 +811,37 @@ Accessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
return fallbackAnswer;
}
if (parent == this)
return aWhichChild == eDeepestChild ? accessible : child;
// If we landed on a legitimate child of |this|, and we want the direct
// child, return it here.
if (parent == this && aWhichChild == eDirectChild)
return child;
child = parent;
}
return nsnull;
// Manually walk through accessible children and see if the are within this
// point. Skip offscreen or invisible accessibles. This takes care of cases
// where layout won't walk into things for us, such as image map areas and
// sub documents (XXX: subdocuments should be handled by methods of
// OuterDocAccessibles).
PRUint32 childCount = accessible->ChildCount();
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
Accessible* child = accessible->GetChildAt(childIdx);
PRInt32 childX, childY, childWidth, childHeight;
child->GetBounds(&childX, &childY, &childWidth, &childHeight);
if (aX >= childX && aX < childX + childWidth &&
aY >= childY && aY < childY + childHeight &&
(child->State() & states::INVISIBLE) == 0) {
if (aWhichChild == eDeepestChild)
return child->ChildAtPoint(aX, aY, eDeepestChild);
return child;
}
}
return accessible;
}
// nsIAccessible getChildAtPoint(in long x, in long y)

View File

@ -6,6 +6,8 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
@ -54,6 +56,20 @@ if (!MAC) {
testChildAtPoint("area", 1, 1, "area", "area");
var container = getAccessible("container");
var paragraph = getAccessible("paragraph");
var [tx, ty, tw, th] = getBounds(paragraph);
var [cx, cy, cw, ch] = getBounds(container);
// Test the point in the vertical center of the paragraph, between the two lines.
testChildAtPoint("container", tx - cx + 1, ty - cy + Math.round(tw/2), paragraph, paragraph.firstChild);
// Test image maps. Their children are not in the layout tree.
ensureImageMapTree("imgmap");
var theLetterA = getAccessible("imgmap").firstChild;
hitTest("imgmap", theLetterA, theLetterA);
hitTest("container", "imgmap", theLetterA);
SimpleTest.finish();
}
@ -82,5 +98,16 @@ if (!MAC) {
<div id="outofflow" style="width: 10px; height: 10px; position: absolute; left: 0px; top: 0px; background-color: yellow;">
</div>
<div id="area" style="width: 100px; height: 100px; background-color: blue;"></div>
<map name="atoz_map">
<area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
coords="0,0,15,15" alt="thelettera" shape="rect"/>
</map>
<div id="container">
<p id="paragraph" style="width: 5em; line-height: 3em;">Hello World</p>
<img id="imgmap" width="447" height="15" usemap="#atoz_map" src="../letters.gif"/>
</div>
</body>
</html>