Bug 1712834 - Adjust caret frame for a significant terminal newline r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D116155
This commit is contained in:
Kagami Sascha Rosylight
2021-05-29 12:01:30 +00:00
parent 7671862509
commit d6840d901b
6 changed files with 75 additions and 16 deletions

View File

@@ -81,9 +81,37 @@ static nsLineBox* FindContainingLine(nsIFrame* aFrame) {
return nullptr;
}
static bool AdjustCaretFrameForLineStart(nsIFrame*& aFrame,
int32_t& aFrameOffset,
nsFrameSelection& aFrameSelection) {
if (!aFrame->HasSignificantTerminalNewline()) {
return false;
}
int32_t start;
int32_t end;
aFrame->GetOffsets(start, end);
if (aFrameOffset != end) {
return false;
}
nsIFrame* nextSibling = aFrame->GetNextSibling();
if (!nextSibling) {
return false;
}
aFrame = nextSibling;
aFrame->GetOffsets(start, end);
aFrameOffset = start;
aFrameSelection.SetHint(CARET_ASSOCIATE_AFTER);
return true;
}
static void AdjustCaretFrameForLineEnd(nsIFrame** aFrame, int32_t* aOffset) {
nsLineBox* line = FindContainingLine(*aFrame);
if (!line) return;
if (!line) {
return;
}
int32_t count = line->GetChildCount();
for (nsIFrame* f = line->mFirstChild; count > 0;
--count, f = f->GetNextSibling()) {
@@ -636,11 +664,16 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
*aReturnUnadjustedFrame = theFrame;
}
// if theFrame is after a text frame that's logically at the end of the line
// (e.g. if theFrame is a <br> frame), then put the caret at the end of
// that text frame instead. This way, the caret will be positioned as if
// trailing whitespace was not trimmed.
AdjustCaretFrameForLineEnd(&theFrame, &theFrameOffset);
// if theFrame is a text frame with a significant terminal character, use the
// next frame instead
if (!AdjustCaretFrameForLineStart(theFrame, theFrameOffset,
*aFrameSelection)) {
// if theFrame is after a text frame that's logically at the end of the line
// (e.g. if theFrame is a <br> frame), then put the caret at the end of
// that text frame instead. This way, the caret will be positioned as if
// trailing whitespace was not trimmed.
AdjustCaretFrameForLineEnd(&theFrame, &theFrameOffset);
};
// Mamdouh : modification of the caret to work at rtl and ltr with Bidi
//

View File

@@ -1028,16 +1028,8 @@ nsresult nsTextControlFrame::OffsetToDOMPoint(uint32_t aOffset,
*aPosition = 0;
} else if (textNode) {
uint32_t textLength = textNode->Length();
if (length == 2 && aOffset == textLength) {
// If we're at the end of the text node and we have a trailing BR node,
// set the selection on the BR node.
rootNode.forget(aResult);
*aPosition = 1;
} else {
// Otherwise, set the selection on the textnode itself.
firstNode.forget(aResult);
*aPosition = std::min(aOffset, textLength);
}
firstNode.forget(aResult);
*aPosition = std::min(aOffset, textLength);
} else {
rootNode.forget(aResult);
*aPosition = 0;

View File

@@ -0,0 +1 @@
prefs: [ui.caretBlinkTime:-1]

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>selection.collapse() to line start</title>
<link rel="author" title="Kagami Sascha Rosylight" href="mailto:krosylight@mozilla.com">
<link rel="help" href="https://w3c.github.io/selection-api/#dom-selection-collapse">
<link rel="match" href="collapse-pre-linestart-ref.html">
<meta name="assert" content="The caret must appear at the start of the second line.">
<pre id=target contenteditable>ABC
<br></pre>
<script>
getSelection().collapse(target.childNodes[0], 4);
</script>

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>selection.collapse() to line start</title>
<link rel="author" title="Kagami Sascha Rosylight" href="mailto:krosylight@mozilla.com">
<link rel="help" href="https://w3c.github.io/selection-api/#dom-selection-collapse">
<link rel="match" href="collapse-pre-linestart-ref.html">
<meta name="assert" content="The caret must appear at the start of the second line.">
<pre id=target contenteditable>ABC
</pre>
<script>
getSelection().collapse(target.childNodes[0], 4);
</script>

View File

@@ -0,0 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>selection.collapse() to line start</title>
<pre id=target contenteditable>ABC<br><br></pre>
<script>
target.focus();
getSelection().collapse(target, 3);
</script>