зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1670541 - Return the parent line end offset if an embedded character contains a line break, r=Jamie
If the offset for an embedded character is queried, and it is an inline element, such as a link, and it contains a line break, return the full parent line. Likewise, if querying character offsets before that embedded character, include its line break in the end offset. Differential Revision: https://phabricator.services.mozilla.com/D94024
This commit is contained in:
Родитель
555178bed2
Коммит
92ae4518de
|
@ -745,9 +745,51 @@ uint32_t HyperTextAccessible::FindLineBoundary(
|
|||
// Move to begin of the next line if any (arrow down and home keys),
|
||||
// otherwise end of the current line (arrow down only).
|
||||
uint32_t tmpOffset = FindOffset(aOffset, eDirNext, eSelectLine);
|
||||
if (tmpOffset == CharacterCount()) return tmpOffset;
|
||||
uint32_t characterCount = CharacterCount();
|
||||
if (tmpOffset == characterCount) {
|
||||
return tmpOffset;
|
||||
}
|
||||
|
||||
return FindOffset(tmpOffset, eDirPrevious, eSelectBeginLine);
|
||||
// Now, simulate the Home key on the next line to get its real offset.
|
||||
uint32_t nextLineBeginOffset =
|
||||
FindOffset(tmpOffset, eDirPrevious, eSelectBeginLine);
|
||||
// Sometimes, there are line breaks inside embedded characters. If this
|
||||
// is the case, the cursor is after the line break, but the offset will
|
||||
// be that of the embedded character, which points to before the line
|
||||
// break. We definitely want the line break included.
|
||||
if (IsCharAt(nextLineBeginOffset, kEmbeddedObjectChar)) {
|
||||
// We can determine if there is a line break by pressing End from
|
||||
// the queried offset. If there is a line break, the offset will be 1
|
||||
// greater, since this line ends with the embed. If there is not, the
|
||||
// value will be different even if a line break follows right after the
|
||||
// embed.
|
||||
uint32_t thisLineEndOffset =
|
||||
FindOffset(aOffset, eDirNext, eSelectEndLine);
|
||||
if (thisLineEndOffset == nextLineBeginOffset + 1) {
|
||||
// If we're querying the offset of the embedded character, we want
|
||||
// the end offset of the parent line instead. Press End
|
||||
// once more from the current position, which is after the embed.
|
||||
if (nextLineBeginOffset == aOffset) {
|
||||
uint32_t thisLineEndOffset2 =
|
||||
FindOffset(thisLineEndOffset, eDirNext, eSelectEndLine);
|
||||
// The above returns an offset exclusive the final line break, so we
|
||||
// need to add 1 to it to return an inclusive end offset. Make sure
|
||||
// we don't overshoot if we've started from another embedded
|
||||
// character that has a line break, or landed on another embedded
|
||||
// character, or if the result is the very end.
|
||||
return (thisLineEndOffset2 == characterCount ||
|
||||
(IsCharAt(thisLineEndOffset, kEmbeddedObjectChar) &&
|
||||
thisLineEndOffset2 == thisLineEndOffset + 1) ||
|
||||
IsCharAt(thisLineEndOffset2, kEmbeddedObjectChar))
|
||||
? thisLineEndOffset2
|
||||
: thisLineEndOffset2 + 1;
|
||||
}
|
||||
|
||||
return thisLineEndOffset;
|
||||
}
|
||||
}
|
||||
|
||||
return nextLineBeginOffset;
|
||||
}
|
||||
|
||||
case eNextLineEnd: {
|
||||
|
|
|
@ -171,6 +171,41 @@
|
|||
[ [ 0, 0, kEmbedChar, 0, 1 ],
|
||||
[ 1, 1, kEmbedChar, 1, 2 ] ]);
|
||||
|
||||
// Embedded char containing a line break breaks line offsets in parent.
|
||||
testTextAtOffset([ "brInEmbed" ], BOUNDARY_LINE_START,
|
||||
[ [0, 1, "a " + kEmbedChar, 0, 3],
|
||||
[2, 2, "a " + kEmbedChar + " d", 0, 5],
|
||||
[3, 5, kEmbedChar + " d", 2, 5] ]);
|
||||
testTextAtOffset([ "brInEmbedAndBefore" ], BOUNDARY_LINE_START,
|
||||
[ [0, 1, "a\n", 0, 2],
|
||||
[2, 3, "b " + kEmbedChar, 2, 5],
|
||||
[4, 4, "b " + kEmbedChar + " e", 2, 7],
|
||||
[5, 7, kEmbedChar + " e", 4, 7] ]);
|
||||
testTextAtOffset([ "brInEmbedAndAfter" ], BOUNDARY_LINE_START,
|
||||
[ [0, 1, "a " + kEmbedChar, 0, 3],
|
||||
[2, 2, "a " + kEmbedChar + " d\n", 0, 6],
|
||||
[3, 5, kEmbedChar + " d\n", 2, 6],
|
||||
[6, 7, "e", 6, 7] ]);
|
||||
testTextAtOffset([ "brInEmbedAndBlockElementAfter" ], BOUNDARY_LINE_START,
|
||||
[ [0, 2, "a " + kEmbedChar, 0, 3],
|
||||
[3, 4, kEmbedChar, 3, 4] ]);
|
||||
testTextAtOffset([ "brInEmbedThenTextThenBlockElement" ], BOUNDARY_LINE_START,
|
||||
[ [0, 1, "a " + kEmbedChar, 0, 3],
|
||||
[2, 2, "a " + kEmbedChar + " d", 0, 5],
|
||||
[3, 4, kEmbedChar + " d", 2, 5],
|
||||
[5, 6, kEmbedChar, 5, 6] ]);
|
||||
testTextAtOffset([ "noBrInEmbedButOneBefore" ], BOUNDARY_LINE_START,
|
||||
[ [0, 1, "a\n", 0, 2],
|
||||
[2, 7, "b " + kEmbedChar + " d", 2, 7] ]);
|
||||
testTextAtOffset([ "noBrInEmbedButOneAfter" ], BOUNDARY_LINE_START,
|
||||
[ [0, 3, "a " + kEmbedChar + "\n", 0, 4],
|
||||
[4, 5, "c", 4, 5] ]);
|
||||
testTextAtOffset([ "twoEmbedsWithBRs" ], BOUNDARY_LINE_START,
|
||||
[ [0, 1, "a " + kEmbedChar, 0, 3],
|
||||
[2, 2, "a " + kEmbedChar + kEmbedChar, 0, 4],
|
||||
[3, 3, kEmbedChar + kEmbedChar + " f", 2, 6],
|
||||
[4, 6, kEmbedChar + " f", 3, 6] ]);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -270,6 +305,13 @@ two words
|
|||
<p>Block</p>
|
||||
<ul><li>Li</li></ul>
|
||||
</div>
|
||||
</body>
|
||||
<div id="brInEmbed" contenteditable>a <a href="https://mozilla.org/">b<br>c</a> d</div>
|
||||
<div id="brInEmbedAndBefore">a<br>b <a href="https://mozilla.org/">c<br>d</a> e</div>
|
||||
<div id="brInEmbedAndAfter">a <a href="https://mozilla.org/">b<br>c</a> d<br>e</div>
|
||||
<div id="brInEmbedAndBlockElementAfter">a <a href="https://mozilla.org/">b<br>c</a><p>d</p></div>
|
||||
<div id="brInEmbedThenTextThenBlockElement">a <a href="https://mozilla.org/">b<br>c</a> d<p>e</p></div>
|
||||
<div id="noBrInEmbedButOneBefore">a<br>b <a href="https://mozilla.org/">c</a> d</div>
|
||||
<div id="noBrInEmbedButOneAfter">a <a href="https://mozilla.org/">b</a><br>c</div>
|
||||
<div id="twoEmbedsWithBRs">a <a href="https://mozilla.org">b<br>c</a><a href="https://mozilla.org">d<br>e</a> f</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Загрузка…
Ссылка в новой задаче