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;
|
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) {
|
static void AdjustCaretFrameForLineEnd(nsIFrame** aFrame, int32_t* aOffset) {
|
||||||
nsLineBox* line = FindContainingLine(*aFrame);
|
nsLineBox* line = FindContainingLine(*aFrame);
|
||||||
if (!line) return;
|
if (!line) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int32_t count = line->GetChildCount();
|
int32_t count = line->GetChildCount();
|
||||||
for (nsIFrame* f = line->mFirstChild; count > 0;
|
for (nsIFrame* f = line->mFirstChild; count > 0;
|
||||||
--count, f = f->GetNextSibling()) {
|
--count, f = f->GetNextSibling()) {
|
||||||
@@ -636,11 +664,16 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
|
|||||||
*aReturnUnadjustedFrame = theFrame;
|
*aReturnUnadjustedFrame = theFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if theFrame is after a text frame that's logically at the end of the line
|
// if theFrame is a text frame with a significant terminal character, use the
|
||||||
// (e.g. if theFrame is a <br> frame), then put the caret at the end of
|
// next frame instead
|
||||||
// that text frame instead. This way, the caret will be positioned as if
|
if (!AdjustCaretFrameForLineStart(theFrame, theFrameOffset,
|
||||||
// trailing whitespace was not trimmed.
|
*aFrameSelection)) {
|
||||||
AdjustCaretFrameForLineEnd(&theFrame, &theFrameOffset);
|
// 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
|
// 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;
|
*aPosition = 0;
|
||||||
} else if (textNode) {
|
} else if (textNode) {
|
||||||
uint32_t textLength = textNode->Length();
|
uint32_t textLength = textNode->Length();
|
||||||
if (length == 2 && aOffset == textLength) {
|
firstNode.forget(aResult);
|
||||||
// If we're at the end of the text node and we have a trailing BR node,
|
*aPosition = std::min(aOffset, textLength);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rootNode.forget(aResult);
|
rootNode.forget(aResult);
|
||||||
*aPosition = 0;
|
*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