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:
@@ -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
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
|
||||
1
testing/web-platform/meta/selection/caret/__dir__.ini
Normal file
1
testing/web-platform/meta/selection/caret/__dir__.ini
Normal file
@@ -0,0 +1 @@
|
||||
prefs: [ui.caretBlinkTime:-1]
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user