forked from mirrors/gecko-dev
Bug 1816601: HyperTextAccessibleBase::OffsetAtPoint: Return 0 if the point is within the container but before the rect at offset 0. r=nlapre
This perpetuates a bug in (local) HyperTextAccessible that some users have unfortunately come to rely on. Differential Revision: https://phabricator.services.mozilla.com/D169802
This commit is contained in:
parent
21d3624930
commit
e425f02438
2 changed files with 44 additions and 4 deletions
|
|
@ -279,7 +279,7 @@ int32_t HyperTextAccessibleBase::OffsetAtPoint(int32_t aX, int32_t aY,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextLeafPoint point = ToTextLeafPoint(0, false);
|
TextLeafPoint startPoint = ToTextLeafPoint(0, false);
|
||||||
// As with TextBounds, we walk to the very end of the text contained in this
|
// As with TextBounds, we walk to the very end of the text contained in this
|
||||||
// hypertext and then step backwards to make our endPoint inclusive.
|
// hypertext and then step backwards to make our endPoint inclusive.
|
||||||
TextLeafPoint endPoint =
|
TextLeafPoint endPoint =
|
||||||
|
|
@ -287,18 +287,27 @@ int32_t HyperTextAccessibleBase::OffsetAtPoint(int32_t aX, int32_t aY,
|
||||||
endPoint =
|
endPoint =
|
||||||
endPoint.FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious,
|
endPoint.FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious,
|
||||||
/* aIncludeOrigin */ false);
|
/* aIncludeOrigin */ false);
|
||||||
|
TextLeafPoint point = startPoint;
|
||||||
// XXX: We should create a TextLeafRange object for this hypertext and move
|
// XXX: We should create a TextLeafRange object for this hypertext and move
|
||||||
// this search inside the TextLeafRange class.
|
// this search inside the TextLeafRange class.
|
||||||
// If there are no characters in this container, we might have moved endPoint
|
// If there are no characters in this container, we might have moved endPoint
|
||||||
// before point. In that case, we shouldn't try to move further forward, as
|
// before startPoint. In that case, we shouldn't try to move further forward,
|
||||||
// that might result in an infinite loop.
|
// as that might result in an infinite loop.
|
||||||
if (point <= endPoint) {
|
if (startPoint <= endPoint) {
|
||||||
for (; !point.ContainsPoint(coords.x, coords.y) && point != endPoint;
|
for (; !point.ContainsPoint(coords.x, coords.y) && point != endPoint;
|
||||||
point = point.FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirNext,
|
point = point.FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirNext,
|
||||||
/* aIncludeOrigin */ false)) {
|
/* aIncludeOrigin */ false)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!point.ContainsPoint(coords.x, coords.y)) {
|
if (!point.ContainsPoint(coords.x, coords.y)) {
|
||||||
|
LayoutDeviceIntRect startRect = startPoint.CharBounds();
|
||||||
|
if (coords.x < startRect.x || coords.y < startRect.y) {
|
||||||
|
// Bug 1816601: The point is within the container but above or to the left
|
||||||
|
// of the rectangle at offset 0. We should really return -1, but we've
|
||||||
|
// returned 0 for many years due to a bug. Some users have unfortunately
|
||||||
|
// come to rely on this, so perpetuate this here.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
DebugOnly<bool> ok = false;
|
DebugOnly<bool> ok = false;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,13 @@ a
|
||||||
a
|
a
|
||||||
<iframe width="1" height="1"></iframe>
|
<iframe width="1" height="1"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
<button id="pointBeforeText">
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div style="width: 100px; background-color: red;" role="none"></div>
|
||||||
|
test
|
||||||
|
<div style="width: 100px; background-color: blue;" role="none"></div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
`,
|
`,
|
||||||
async function(browser, docAcc) {
|
async function(browser, docAcc) {
|
||||||
const dpr = await getContentDPR(browser);
|
const dpr = await getContentDPR(browser);
|
||||||
|
|
@ -43,6 +50,30 @@ a
|
||||||
x += width - 1;
|
x += width - 1;
|
||||||
y += height - 1;
|
y += height - 1;
|
||||||
await testOffsetAtPoint(iframeAtEnd, x, y, COORDTYPE_SCREEN_RELATIVE, -1);
|
await testOffsetAtPoint(iframeAtEnd, x, y, COORDTYPE_SCREEN_RELATIVE, -1);
|
||||||
|
|
||||||
|
// Test that 0 is returned if the point is within the container but before
|
||||||
|
// the rectangle at offset 0. This is buggy behavior that some users have
|
||||||
|
// unfortunately come to rely on (bug 1816601).
|
||||||
|
const pointBeforeText = findAccessibleChildByID(docAcc, "pointBeforeText", [
|
||||||
|
Ci.nsIAccessibleText,
|
||||||
|
]);
|
||||||
|
[x, y, width, height] = Layout.getBounds(pointBeforeText, dpr);
|
||||||
|
await testOffsetAtPoint(
|
||||||
|
pointBeforeText,
|
||||||
|
x + 1,
|
||||||
|
y + 1,
|
||||||
|
COORDTYPE_SCREEN_RELATIVE,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
// But this buggy behavior only applies for a point before offset 0, not
|
||||||
|
// a point after the last offset. So it's asymmetrically buggy. :(
|
||||||
|
await testOffsetAtPoint(
|
||||||
|
pointBeforeText,
|
||||||
|
x + width - 1,
|
||||||
|
y + height - 1,
|
||||||
|
COORDTYPE_SCREEN_RELATIVE,
|
||||||
|
-1
|
||||||
|
);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
topLevel: true,
|
topLevel: true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue