Bug 1714640 - Add AdjustFrameForLineStart call in Selection::ScrollIntoView r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D117009
This commit is contained in:
Kagami Sascha Rosylight 2021-06-08 16:21:36 +00:00
parent 529c78906f
commit 41fc1feef9
6 changed files with 69 additions and 31 deletions

View File

@ -2865,6 +2865,8 @@ nsIFrame* Selection::GetSelectionEndPointGeometry(SelectionRegion aRegion,
content, nodeOffset, mFrameSelection->GetHint(), &frameOffset);
if (!frame) return nullptr;
nsFrameSelection::AdjustFrameForLineStart(frame, frameOffset);
// Figure out what node type we have, then get the
// appropriate rect for it's nodeOffset.
bool isText = node->IsText();

View File

@ -81,32 +81,6 @@ 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) {
@ -664,16 +638,15 @@ nsIFrame* nsCaret::GetCaretFrameForNodeOffset(
*aReturnUnadjustedFrame = theFrame;
}
// if theFrame is a text frame with a significant terminal character, use the
// next frame instead
if (!AdjustCaretFrameForLineStart(theFrame, theFrameOffset,
*aFrameSelection)) {
if (nsFrameSelection::AdjustFrameForLineStart(theFrame, theFrameOffset)) {
aFrameSelection->SetHint(CARET_ASSOCIATE_AFTER);
} else {
// 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

@ -143,6 +143,7 @@ support-files = bug1226904.html
support-files = bug1448730.html
[test_bug1515822.html]
[test_bug1550869_video.html]
[test_bug1714640.html]
[test_dynamic_toolbar_max_height.html]
support-files = file_dynamic_toolbar_max_height.html
[test_emulateMedium.html]

View File

@ -0,0 +1,36 @@
<!DOCTYPE HTML>
<meta charset="utf-8">
<title>Bug NNN</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
<style type="text/css">
@font-face {
font-family: Ahem;
src: url("Ahem.ttf");
}
pre {
font: 14px/1 Ahem;
height: 50px;
overflow-y: scroll;
}
</style>
<pre id=target contenteditable>ABC
<br></pre>
<script>
getSelection().collapse(target.childNodes[0], 9);
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(() => {
const sel = SpecialPowers.wrap(getSelection());
sel.scrollIntoView(0, true, 100, 0);
is(target.scrollTop, target.scrollTopMax);
SimpleTest.finish();
});
</script>

View File

@ -1605,6 +1605,30 @@ static bool IsDisplayContents(const nsIContent* aContent) {
return aContent->IsElement() && aContent->AsElement()->IsDisplayContents();
}
bool nsFrameSelection::AdjustFrameForLineStart(nsIFrame*& aFrame,
int32_t& aFrameOffset) {
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;
return true;
}
// static
nsIFrame* nsFrameSelection::GetFrameForNodeOffset(nsIContent* aNode,
int32_t aOffset,

View File

@ -428,6 +428,8 @@ class nsFrameSelection final {
bool IsValidSelectionPoint(nsINode* aNode) const;
static bool AdjustFrameForLineStart(nsIFrame*& aFrame, int32_t& aFrameOffset);
/**
* Given a node and its child offset, return the nsIFrame and the offset into
* that frame.