Bug 1869966 part 3: When calculating a DOM point from a TextLeafPoint for a non-text node, use the child index within the parent, not an offset within the node itself. r=eeejay
For text nodes, DOM points use the character offset within the node itself, just like accessibility does. For non-text nodes, DOM points use the child index within the parent to specify the position before or after the node. Previously, TextLeafPoint::ToDOMPoint always used an offset within the node itself. This meant that when the (exclusive) end point of a range was an image, we converted to a DOM point of offset 0 within the image. As far as DOM is concerned, this includes the image. This patch adjusts ToDOMPoint as appropriate. As part of this, ToDOMPoint now returns a uint32_t instead of an int32_t. This is because DOM offsets are actually uint32_t and calculating int32_t child indices is deprecated. Differential Revision: https://phabricator.services.mozilla.com/D247873
This commit is contained in:
committed by
jteh@mozilla.com
parent
5c140ae138
commit
123bc5b115
@@ -536,7 +536,7 @@ static dom::Selection* GetDOMSelection(const nsIContent* aStartContent,
|
||||
return startFrameSel ? &startFrameSel->NormalSelection() : nullptr;
|
||||
}
|
||||
|
||||
std::pair<nsIContent*, int32_t> TextLeafPoint::ToDOMPoint(
|
||||
std::pair<nsIContent*, uint32_t> TextLeafPoint::ToDOMPoint(
|
||||
bool aIncludeGenerated) const {
|
||||
if (!(*this) || !mAcc->IsLocal()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid point");
|
||||
@@ -573,9 +573,23 @@ std::pair<nsIContent*, int32_t> TextLeafPoint::ToDOMPoint(
|
||||
}
|
||||
}
|
||||
|
||||
if (!mAcc->IsTextLeaf() && !mAcc->IsHTMLBr() && !mAcc->HasChildren()) {
|
||||
// If this is not a text leaf it can be an empty editable container,
|
||||
// whitespace, or an empty doc. In any case, the offset inside should be 0.
|
||||
if (mAcc->IsTextLeaf()) {
|
||||
// For text nodes, DOM uses a character offset within the node.
|
||||
return {content, RenderedToContentOffset(mAcc->AsLocal(), mOffset)};
|
||||
}
|
||||
|
||||
if (!mAcc->IsHyperText()) {
|
||||
// For non-text nodes (e.g. images), DOM points use the child index within
|
||||
// the parent.
|
||||
nsIContent* parent = content->GetParent();
|
||||
MOZ_ASSERT(parent);
|
||||
auto childIndex = parent->ComputeIndexOf(content);
|
||||
MOZ_ASSERT(childIndex);
|
||||
return {parent, *childIndex};
|
||||
}
|
||||
|
||||
// This could be an empty editable container, whitespace or an empty doc. In
|
||||
// any case, the offset inside should be 0.
|
||||
MOZ_ASSERT(mOffset == 0);
|
||||
|
||||
if (RefPtr<TextControlElement> textControlElement =
|
||||
@@ -592,9 +606,6 @@ std::pair<nsIContent*, int32_t> TextLeafPoint::ToDOMPoint(
|
||||
return {content, 0};
|
||||
}
|
||||
|
||||
return {content, RenderedToContentOffset(mAcc->AsLocal(), mOffset)};
|
||||
}
|
||||
|
||||
static bool IsLineBreakContinuation(nsTextFrame* aContinuation) {
|
||||
// A fluid continuation always means a new line.
|
||||
if (aContinuation->HasAnyStateBits(NS_FRAME_IS_FLUID_CONTINUATION)) {
|
||||
|
||||
@@ -188,7 +188,7 @@ class TextLeafPoint final {
|
||||
/**
|
||||
* Translate given TextLeafPoint into a DOM point.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT std::pair<nsIContent*, int32_t> ToDOMPoint(
|
||||
MOZ_CAN_RUN_SCRIPT std::pair<nsIContent*, uint32_t> ToDOMPoint(
|
||||
bool aIncludeGenerated = true) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -21,7 +21,7 @@ function checkSelection(root, ranges) {
|
||||
* Test IAccessibleTextSelectionContainer::setSelections.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`<p id="p">ab<a id="link" href="/">cd</a>ef</p>`,
|
||||
`<p id="p">ab<a id="link" href="/">cd</a>ef<img id="img" src="https://example.com/a11y/accessible/tests/mochitest/moz.png" alt="g"></p>`,
|
||||
async function testSetSelections(browser, docAcc) {
|
||||
docAcc.QueryInterface(nsIAccessibleText);
|
||||
await runPython(`
|
||||
@@ -66,6 +66,21 @@ addAccessibleTask(
|
||||
await selected;
|
||||
checkSelection(docAcc, [[link, 1, p, 4]]);
|
||||
|
||||
info("Selecting f");
|
||||
selected = waitForEvent(EVENT_TEXT_SELECTION_CHANGED, p);
|
||||
await runPython(`
|
||||
docSel.setSelections(1, byref(IA2TextSelection(p, 4, p, 5, False)))
|
||||
`);
|
||||
await selected;
|
||||
checkSelection(docAcc, [[p, 4, p, 5]]);
|
||||
// DOM treats an end point of (img, 0) as including the image. Ensure we
|
||||
// used a DOM child index.
|
||||
await invokeContentTask(browser, [], () => {
|
||||
const sel = content.getSelection();
|
||||
is(sel.focusNode.id, "p", "DOM selection focus node correct");
|
||||
is(sel.focusOffset, 3, "DOM selection focus offset correct");
|
||||
});
|
||||
|
||||
info("Selecting a, c");
|
||||
selected = waitForEvent(EVENT_TEXT_SELECTION_CHANGED, link);
|
||||
await runPython(`
|
||||
|
||||
Reference in New Issue
Block a user