зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1263357 - When the caret is placed after visible line break, associate caret with frame on the next line instead. r=mats
--HG-- extra : amend_source : a0068b0c841189204e07cc6c0a19f83d5dac8da3
This commit is contained in:
Родитель
e6f4f137d8
Коммит
4bb58198d9
|
@ -49,9 +49,7 @@
|
|||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -324,85 +322,6 @@ nsDocumentEncoder::IncludeInContext(nsINode *aNode)
|
|||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LineHasNonEmptyContentWorker(nsIFrame* aFrame)
|
||||
{
|
||||
// Look for non-empty frames, but ignore inline and br frames.
|
||||
// For inline frames, descend into the children, if any.
|
||||
if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
|
||||
for (nsIFrame* child : aFrame->PrincipalChildList()) {
|
||||
if (LineHasNonEmptyContentWorker(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aFrame->GetType() != nsGkAtoms::brFrame &&
|
||||
!aFrame->IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LineHasNonEmptyContent(nsLineBox* aLine)
|
||||
{
|
||||
int32_t count = aLine->GetChildCount();
|
||||
for (nsIFrame* frame = aLine->mFirstChild; count > 0;
|
||||
--count, frame = frame->GetNextSibling()) {
|
||||
if (LineHasNonEmptyContentWorker(frame)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
IsInvisibleBreak(nsINode *aNode)
|
||||
{
|
||||
if (!aNode->IsElement() || !aNode->IsEditable()) {
|
||||
return false;
|
||||
}
|
||||
nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame();
|
||||
if (!frame || frame->GetType() != nsGkAtoms::brFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsContainerFrame* f = frame->GetParent();
|
||||
while (f && f->IsFrameOfType(nsBox::eLineParticipant)) {
|
||||
f = f->GetParent();
|
||||
}
|
||||
nsBlockFrame* blockAncestor = do_QueryFrame(f);
|
||||
if (!blockAncestor) {
|
||||
// The container frame doesn't support line breaking.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
nsBlockInFlowLineIterator iter(blockAncestor, frame, &valid);
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lineNonEmpty = LineHasNonEmptyContent(iter.GetLine());
|
||||
|
||||
while (iter.Next()) {
|
||||
auto currentLine = iter.GetLine();
|
||||
// Completely skip empty lines.
|
||||
if (!currentLine->IsEmpty()) {
|
||||
// If we come across an inline line, the BR has caused a visible line break.
|
||||
if (currentLine->IsInline()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lineNonEmpty;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
||||
int32_t aStartOffset,
|
||||
|
@ -437,7 +356,7 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
|||
if (node->IsElement()) {
|
||||
if ((mFlags & (nsIDocumentEncoder::OutputPreformatted |
|
||||
nsIDocumentEncoder::OutputDropInvisibleBreak)) &&
|
||||
IsInvisibleBreak(node)) {
|
||||
nsLayoutUtils::IsInvisibleBreak(node)) {
|
||||
return NS_OK;
|
||||
}
|
||||
Element* originalElement =
|
||||
|
|
|
@ -9370,3 +9370,92 @@ nsLayoutUtils::SupportsServoStyleBackend(nsIDocument* aDocument)
|
|||
aDocument->IsHTMLOrXHTML() &&
|
||||
static_cast<nsDocument*>(aDocument)->IsContentDocument();
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LineHasNonEmptyContentWorker(nsIFrame* aFrame)
|
||||
{
|
||||
// Look for non-empty frames, but ignore inline and br frames.
|
||||
// For inline frames, descend into the children, if any.
|
||||
if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
|
||||
for (nsIFrame* child : aFrame->PrincipalChildList()) {
|
||||
if (LineHasNonEmptyContentWorker(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aFrame->GetType() != nsGkAtoms::brFrame &&
|
||||
!aFrame->IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LineHasNonEmptyContent(nsLineBox* aLine)
|
||||
{
|
||||
int32_t count = aLine->GetChildCount();
|
||||
for (nsIFrame* frame = aLine->mFirstChild; count > 0;
|
||||
--count, frame = frame->GetNextSibling()) {
|
||||
if (LineHasNonEmptyContentWorker(frame)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsLayoutUtils::IsInvisibleBreak(nsINode* aNode, nsIFrame** aNextLineFrame)
|
||||
{
|
||||
if (aNextLineFrame) {
|
||||
*aNextLineFrame = nullptr;
|
||||
}
|
||||
|
||||
if (!aNode->IsElement() || !aNode->IsEditable()) {
|
||||
return false;
|
||||
}
|
||||
nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame();
|
||||
if (!frame || frame->GetType() != nsGkAtoms::brFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsContainerFrame* f = frame->GetParent();
|
||||
while (f && f->IsFrameOfType(nsBox::eLineParticipant)) {
|
||||
f = f->GetParent();
|
||||
}
|
||||
nsBlockFrame* blockAncestor = do_QueryFrame(f);
|
||||
if (!blockAncestor) {
|
||||
// The container frame doesn't support line breaking.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
nsBlockInFlowLineIterator iter(blockAncestor, frame, &valid);
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lineNonEmpty = LineHasNonEmptyContent(iter.GetLine());
|
||||
if (!lineNonEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (iter.Next()) {
|
||||
auto currentLine = iter.GetLine();
|
||||
// Completely skip empty lines.
|
||||
if (!currentLine->IsEmpty()) {
|
||||
// If we come across an inline line, the BR has caused a visible line break.
|
||||
if (currentLine->IsInline()) {
|
||||
if (aNextLineFrame) {
|
||||
*aNextLineFrame = currentLine->mFirstChild;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lineNonEmpty;
|
||||
}
|
||||
|
|
|
@ -2856,6 +2856,19 @@ public:
|
|||
*/
|
||||
static bool SupportsServoStyleBackend(nsIDocument* aDocument);
|
||||
|
||||
/*
|
||||
* Checks whether a node is an invisible break.
|
||||
* If not, returns the first frame on the next line if such a next line exists.
|
||||
*
|
||||
* @return true if the node is an invisible break.
|
||||
* aNextLineFrame is returned null in this case.
|
||||
* false if the node causes a visible break or if the node is no break.
|
||||
*
|
||||
* @param aNextLineFrame assigned to first frame on the next line if such a
|
||||
* next line exists, null otherwise.
|
||||
*/
|
||||
static bool IsInvisibleBreak(nsINode* aNode, nsIFrame** aNextLineFrame = nullptr);
|
||||
|
||||
private:
|
||||
static uint32_t sFontSizeInflationEmPerLine;
|
||||
static uint32_t sFontSizeInflationMinTwips;
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #1 for bug 1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p id="theP"><tt>xyz<br></tt><br></p></div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theP = document.getElementById("theP");
|
||||
theDiv.focus();
|
||||
sel.collapse(theP, 1);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #1 for bug1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p><tt>xyz</tt><br></p></div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 0);
|
||||
if (navigator.platform.indexOf("Win") == 0) {
|
||||
synthesizeKey("VK_END", {});
|
||||
} else {
|
||||
// End key doesn't work as expected on Mac and Linux.
|
||||
sel.modify("move", "right", "lineboundary");
|
||||
}
|
||||
synthesizeKey("VK_RETURN", {shiftKey: true});
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #2 for bug 1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p id="theP"><font color=red><span>xyz<br></span></font><br></p></div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theP = document.getElementById("theP");
|
||||
theDiv.focus();
|
||||
sel.collapse(theP, 1);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #2 for bug 1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><p><font color=red><span>xyz</span></font><br></p></div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 0);
|
||||
if (navigator.platform.indexOf("Win") == 0) {
|
||||
synthesizeKey("VK_END", {});
|
||||
} else {
|
||||
// End key doesn't work as expected on Mac and Linux.
|
||||
sel.modify("move", "right", "lineboundary");
|
||||
}
|
||||
synthesizeKey("VK_RETURN", {shiftKey: true});
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #3 for bug 1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span><br>more</div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 1);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #3 for bug1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span><br>more</div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theSpan = document.getElementById("theSpan");
|
||||
theDiv.focus();
|
||||
sel.collapse(theSpan, 2);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #4 for bug 1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span>more</div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 1);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #4 for bug1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span>more</div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theSpan = document.getElementById("theSpan");
|
||||
theDiv.focus();
|
||||
sel.collapse(theSpan, 2);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #5 for bug 1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span> more</div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 1);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE HTML><html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=bug1263357
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testcase #5 for bug1263357</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="editable" contenteditable='true' spellcheck=false style="outline: 1px solid;"><span id="theSpan">text<br></span> more</div>
|
||||
<script>
|
||||
|
||||
function start() {
|
||||
var sel = window.getSelection();
|
||||
// Focus on editable block.
|
||||
theDiv = document.getElementById("editable");
|
||||
theSpan = document.getElementById("theSpan");
|
||||
theDiv.focus();
|
||||
sel.collapse(theSpan, 2);
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(start);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -173,6 +173,16 @@ support-files =
|
|||
bug1082486-1-ref.html
|
||||
bug1082486-2.html
|
||||
bug1082486-2-ref.html
|
||||
bug1263357-1.html
|
||||
bug1263357-1-ref.html
|
||||
bug1263357-2.html
|
||||
bug1263357-2-ref.html
|
||||
bug1263357-3.html
|
||||
bug1263357-3-ref.html
|
||||
bug1263357-4.html
|
||||
bug1263357-4-ref.html
|
||||
bug1263357-5.html
|
||||
bug1263357-5-ref.html
|
||||
input-maxlength-valid-before-change.html
|
||||
input-maxlength-valid-change.html
|
||||
input-maxlength-invalid-change.html
|
||||
|
|
|
@ -181,6 +181,11 @@ var tests = [
|
|||
[ 'bug1259949-1.html' , 'bug1259949-1-ref.html'] ,
|
||||
[ 'bug1259949-2.html' , 'bug1259949-2-ref.html'] ,
|
||||
[ 'bug1263288.html' , 'bug1263288-ref.html'] ,
|
||||
[ 'bug1263357-1.html' , 'bug1263357-1-ref.html'] ,
|
||||
[ 'bug1263357-2.html' , 'bug1263357-2-ref.html'] ,
|
||||
[ 'bug1263357-3.html' , 'bug1263357-3-ref.html'] ,
|
||||
[ 'bug1263357-4.html' , 'bug1263357-4-ref.html'] ,
|
||||
[ 'bug1263357-5.html' , 'bug1263357-5-ref.html'] ,
|
||||
function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled']]}, nextTest);} ,
|
||||
];
|
||||
|
||||
|
|
|
@ -1992,7 +1992,7 @@ nsFrameSelection::RepaintSelection(SelectionType aSelectionType)
|
|||
#endif
|
||||
return mDomSelections[index]->Repaint(mShell->GetPresContext());
|
||||
}
|
||||
|
||||
|
||||
nsIFrame*
|
||||
nsFrameSelection::GetFrameForNodeOffset(nsIContent* aNode,
|
||||
int32_t aOffset,
|
||||
|
@ -2011,11 +2011,12 @@ nsFrameSelection::GetFrameForNodeOffset(nsIContent* aNode,
|
|||
}
|
||||
|
||||
nsIFrame* returnFrame = nullptr;
|
||||
nsCOMPtr<nsIContent> theNode;
|
||||
|
||||
while (true) {
|
||||
*aReturnOffset = aOffset;
|
||||
|
||||
nsCOMPtr<nsIContent> theNode = aNode;
|
||||
theNode = aNode;
|
||||
|
||||
if (aNode->IsElement()) {
|
||||
int32_t childIndex = 0;
|
||||
|
@ -2135,6 +2136,18 @@ nsFrameSelection::GetFrameForNodeOffset(nsIContent* aNode,
|
|||
if (!returnFrame)
|
||||
return nullptr;
|
||||
|
||||
// If we ended up here and were asked to position the caret after a visible
|
||||
// break, let's return the frame on the next line instead if it exists.
|
||||
if (aOffset > 0 && (uint32_t) aOffset >= aNode->Length() &&
|
||||
theNode == aNode->GetLastChild()) {
|
||||
nsIFrame* newFrame;
|
||||
nsLayoutUtils::IsInvisibleBreak(theNode, &newFrame);
|
||||
if (newFrame) {
|
||||
returnFrame = newFrame;
|
||||
*aReturnOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// find the child frame containing the offset we want
|
||||
returnFrame->GetChildFrameContainingOffset(*aReturnOffset, aHint == CARET_ASSOCIATE_AFTER,
|
||||
&aOffset, &returnFrame);
|
||||
|
|
Загрузка…
Ссылка в новой задаче