Bug 1958639 - Ignore anonymous boxes and NAC for paragraph selection code. r=masayuki
The inner block of a scroller for example (::-moz-scrolled-content) shouldn't be considered a line break. Same for scrollbar nodes, we don't want to break on scrollbars (or native anonymous content in general), since we can't position the caret and such there anyways. Differential Revision: https://phabricator.services.mozilla.com/D244519
This commit is contained in:
@@ -31,13 +31,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=578771
|
||||
ce.focus();
|
||||
|
||||
synthesizeMouse(elem, 5, 5, {clickCount: 2 });
|
||||
ok(elem.selectionStart == 0 && elem.selectionEnd == 7,
|
||||
" Double-clicking on another " + elemTag + " works correctly");
|
||||
is(elem.selectionStart, 0, `${elemTag} selectionStart after double-click`);
|
||||
is(elem.selectionEnd, 7, `${elemTag} selectionEnd after double-click`);
|
||||
|
||||
ce.focus();
|
||||
synthesizeMouse(elem, 5, 5, {clickCount: 3 });
|
||||
ok(elem.selectionStart == 0 && elem.selectionEnd == 14,
|
||||
"Triple-clicking on another " + elemTag + " works correctly");
|
||||
is(elem.selectionStart, 0, `${elemTag} selectionStart after triple-click`);
|
||||
is(elem.selectionEnd, 14, `${elemTag} selectionEnd after triple-click`);
|
||||
}
|
||||
// Avoid platform selection differences
|
||||
SimpleTest.waitForFocus(function() {
|
||||
|
||||
@@ -4615,6 +4615,10 @@ nsresult nsIFrame::GetDataForTableSelection(
|
||||
}
|
||||
|
||||
static bool IsEditingHost(const nsIFrame* aFrame) {
|
||||
if (aFrame->Style()->GetPseudoType() ==
|
||||
PseudoStyleType::mozTextControlEditingRoot) {
|
||||
return true;
|
||||
}
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
return content && content->IsEditingHost();
|
||||
}
|
||||
@@ -4666,8 +4670,6 @@ bool nsIFrame::ShouldHaveLineIfEmpty() const {
|
||||
break;
|
||||
case PseudoStyleType::scrolledContent:
|
||||
return GetParent()->ShouldHaveLineIfEmpty();
|
||||
case PseudoStyleType::mozTextControlEditingRoot:
|
||||
return true;
|
||||
case PseudoStyleType::buttonContent:
|
||||
// HTML quirk.
|
||||
return GetContent()->IsHTMLElement(nsGkAtoms::input);
|
||||
@@ -5460,6 +5462,22 @@ struct MOZ_STACK_CLASS FrameContentRange {
|
||||
int32_t end;
|
||||
};
|
||||
|
||||
static bool IsRelevantBlockFrame(const nsIFrame* aFrame) {
|
||||
if (!aFrame->IsBlockOutside()) {
|
||||
return false;
|
||||
}
|
||||
if (aFrame->Style()->IsAnonBox()) {
|
||||
// This helps skipping things like ::-moz-scrolled-content on an
|
||||
// inline-block.
|
||||
return false;
|
||||
}
|
||||
if (aFrame->GetContent()->IsInNativeAnonymousSubtree()) {
|
||||
// This helps skipping things like scrollbar parts.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retrieve the content offsets of a frame
|
||||
static FrameContentRange GetRangeForFrame(const nsIFrame* aFrame) {
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
@@ -5486,7 +5504,7 @@ static FrameContentRange GetRangeForFrame(const nsIFrame* aFrame) {
|
||||
|
||||
MOZ_ASSERT(!content->IsBeingRemoved());
|
||||
nsIContent* parent = content->GetParent();
|
||||
if (aFrame->IsBlockOutside() || !parent) {
|
||||
if (IsRelevantBlockFrame(aFrame) || !parent) {
|
||||
return FrameContentRange(content, 0, content->GetChildCount());
|
||||
}
|
||||
|
||||
@@ -9385,7 +9403,7 @@ static nsContentAndOffset FindLineBreakingFrame(nsIFrame* aFrame,
|
||||
// the content of the inline frames they were created from. The
|
||||
// first/last child of such frames is the real block frame we're
|
||||
// looking for.
|
||||
if ((aFrame->IsBlockOutside() &&
|
||||
if ((IsRelevantBlockFrame(aFrame) &&
|
||||
!aFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) ||
|
||||
aFrame->IsBrFrame()) {
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
@@ -9427,7 +9445,7 @@ nsresult nsIFrame::PeekOffsetForParagraph(PeekOffsetStruct* aPos) {
|
||||
nsIFrame* frame = this;
|
||||
nsContentAndOffset blockFrameOrBR;
|
||||
blockFrameOrBR.mContent = nullptr;
|
||||
bool reachedLimit = frame->IsBlockOutside() || IsEditingHost(frame);
|
||||
bool reachedLimit = IsRelevantBlockFrame(frame) || IsEditingHost(frame);
|
||||
|
||||
auto traverse = [&aPos](nsIFrame* current) {
|
||||
return aPos->mDirection == eDirPrevious ? current->GetPrevSibling()
|
||||
@@ -9463,7 +9481,8 @@ nsresult nsIFrame::PeekOffsetForParagraph(PeekOffsetStruct* aPos) {
|
||||
break;
|
||||
}
|
||||
frame = parent;
|
||||
reachedLimit = frame && (frame->IsBlockOutside() || IsEditingHost(frame));
|
||||
reachedLimit =
|
||||
frame && (IsRelevantBlockFrame(frame) || IsEditingHost(frame));
|
||||
}
|
||||
|
||||
if (reachedLimit) { // no "stop frame" found
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<style>
|
||||
body { margin: 0; font: 16px/1 sans-serif; }
|
||||
code { display: inline-block }
|
||||
#d code { overflow: auto }
|
||||
</style>
|
||||
<p id="a">Some <code>code</code> with <span>text</span> with <code>code</code> in it</p>
|
||||
|
||||
@@ -15,6 +16,8 @@ some <span>more</span> code <span>with</span> pre-formatted
|
||||
whitespace <span>that</span> should be selected
|
||||
line <span>by</span> line</pre>
|
||||
|
||||
<p id="d">Some <code>code</code> with <span>text</span> with <code>code</code> in <span>it</span></p>
|
||||
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
@@ -25,7 +28,7 @@ line <span>by</span> line</pre>
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(function () {
|
||||
for (let child of document.querySelectorAll("#a span, #a code"))
|
||||
for (let child of document.querySelectorAll(":is(#a, #d) :is(span, code)"))
|
||||
testTripleClick(child, "Some code with text with code in it");
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user