mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1504053 - Reframe multi-column container if inserting a subtree with a column-span child. r=dbaron
Differential Revision: https://phabricator.services.mozilla.com/D16077 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6df4e561ff
commit
5ec0177dc3
@ -5932,7 +5932,7 @@ void nsCSSFrameConstructor::AppendFramesToParent(
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're appending a list of frames at the last continuations of a
|
||||
// If we're appending a list of frames to the last continuations of a
|
||||
// ::-moz-column-content, we may need to create column-span siblings for them.
|
||||
if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
|
||||
// Extract any initial non-column-span kids, and append them to
|
||||
@ -6871,6 +6871,14 @@ void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
|
||||
AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
|
||||
}
|
||||
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
if (StaticPrefs::layout_css_column_span_enabled() &&
|
||||
MaybeRecreateForColumnSpan(state, parentFrame, frameItems, prevSibling)) {
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
return;
|
||||
}
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
|
||||
if (frameItems.NotEmpty()) { // append the in-flow kids
|
||||
AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
|
||||
}
|
||||
@ -7326,6 +7334,15 @@ void nsCSSFrameConstructor::ContentRangeInserted(
|
||||
}
|
||||
}
|
||||
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
if (StaticPrefs::layout_css_column_span_enabled() &&
|
||||
MaybeRecreateForColumnSpan(state, insertion.mParentFrame, frameItems,
|
||||
prevSibling)) {
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
return;
|
||||
}
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
|
||||
if (frameItems.NotEmpty()) {
|
||||
// Notify the parent frame
|
||||
if (isAppend) {
|
||||
@ -10857,6 +10874,61 @@ nsFrameItems nsCSSFrameConstructor::CreateColumnSpanSiblings(
|
||||
return siblings;
|
||||
}
|
||||
|
||||
bool nsCSSFrameConstructor::MaybeRecreateForColumnSpan(
|
||||
nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
|
||||
nsFrameList& aFrameList, nsIFrame* aPrevSibling) {
|
||||
MOZ_ASSERT(StaticPrefs::layout_css_column_span_enabled(),
|
||||
"Call this only when layout.css.column-span.enabled is true!");
|
||||
|
||||
if (!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!IsFramePartOfIBSplit(aParentFrame),
|
||||
"We should have wiped aParentFrame in WipeContainingBlock if it's "
|
||||
"part of IB split!");
|
||||
|
||||
nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
|
||||
if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
|
||||
// We are appending a list of frames to the last continuation of a
|
||||
// ::-moz-column-content. This is the case where we can fix the frame tree
|
||||
// instead of reframing the containing block. Return false and let
|
||||
// AppendFramesToParent() deal with this.
|
||||
return false;
|
||||
}
|
||||
|
||||
auto HasColumnSpan = [](const nsFrameList& aList) {
|
||||
for (nsIFrame* f : aList) {
|
||||
if (f->IsColumnSpan()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (HasColumnSpan(aFrameList)) {
|
||||
// If any frame in the frame list has "column-span:all" style, i.e. a
|
||||
// -moz-column-span-wrapper frame, we need to reframe the multi-column
|
||||
// containing block.
|
||||
//
|
||||
// We can only be here if none of the new inserted nsIContent* nodes (via
|
||||
// ContentAppended or ContentRangeInserted) have column-span:all style, yet
|
||||
// some of them have column-span:all descendants. Sadly, there's no way to
|
||||
// detect this by checking FrameConstructionItems in WipeContainingBlock().
|
||||
// Otherwise, we would have already wiped the multi-column containing block.
|
||||
PROFILER_TRACING("Layout",
|
||||
"Reframe multi-column after constructing frame list",
|
||||
LAYOUT, TRACING_EVENT);
|
||||
aFrameList.DestroyFrames();
|
||||
RecreateFramesForContent(
|
||||
GetMultiColumnContainingBlockFor(aParentFrame)->GetContent(),
|
||||
InsertionKind::Async);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIFrame* nsCSSFrameConstructor::ConstructInline(
|
||||
nsFrameConstructorState& aState, FrameConstructionItem& aItem,
|
||||
nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
|
||||
|
@ -1891,6 +1891,23 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
||||
nsFrameList& aChildList,
|
||||
nsIFrame* aPositionedFrame);
|
||||
|
||||
// Reconstruct the multi-column containing block of aParentFrame when we want
|
||||
// to insert aFrameList into aParentFrame immediately after aPrevSibling but
|
||||
// cannot fix the frame tree because aFrameList contains some column-spans.
|
||||
//
|
||||
// @param aParentFrame the to-be parent frame for aFrameList.
|
||||
// @param aFrameList the frames to be inserted. It will be cleared if we need
|
||||
// reconstruction.
|
||||
// @param aPrevSibling the position where the frames in aFrameList are going
|
||||
// to be inserted. Nullptr means aFrameList is being inserted at
|
||||
// the beginning.
|
||||
// @return true if the multi-column containing block of aParentFrame is
|
||||
// reconstructed; false otherwise.
|
||||
bool MaybeRecreateForColumnSpan(nsFrameConstructorState& aState,
|
||||
nsContainerFrame* aParentFrame,
|
||||
nsFrameList& aFrameList,
|
||||
nsIFrame* aPrevSibling);
|
||||
|
||||
nsIFrame* ConstructInline(nsFrameConstructorState& aState,
|
||||
FrameConstructionItem& aItem,
|
||||
nsContainerFrame* aParentFrame,
|
||||
|
@ -0,0 +1,2 @@
|
||||
[multicol-span-all-dynamic-add-011.html]
|
||||
prefs: [layout.css.column-span.enabled:true]
|
@ -0,0 +1,2 @@
|
||||
[multicol-span-all-dynamic-add-012.html]
|
||||
prefs: [layout.css.column-span.enabled:true]
|
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test: Insert a block containing a spanner kid. The spanner kid should correctly span across all columns</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
|
||||
<link rel="match" href="multicol-span-all-dynamic-add-003-ref.html">
|
||||
<meta name="assert" content="This test checks that an inserted block containing 'column-span' element should be rendered correctly.">
|
||||
|
||||
<script>
|
||||
function runTest() {
|
||||
document.body.offsetHeight;
|
||||
|
||||
// Create a subtree like the following, and insert it into column as the
|
||||
// first child.
|
||||
// <div>
|
||||
// block1
|
||||
// <h3>spanner</h3>
|
||||
// </div>
|
||||
var spanner = document.createElement("h3");
|
||||
var spannerText = document.createTextNode("spanner");
|
||||
spanner.appendChild(spannerText);
|
||||
|
||||
var block1 = document.createElement("div");
|
||||
var block1Text = document.createTextNode("block1");
|
||||
block1.appendChild(block1Text)
|
||||
block1.appendChild(spanner);
|
||||
|
||||
var column = document.getElementById("column");
|
||||
column.insertBefore(block1, column.children[0]);
|
||||
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#column {
|
||||
column-count: 3;
|
||||
column-rule: 6px solid;
|
||||
width: 400px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
column-span: all;
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body onload="runTest();">
|
||||
<article id="column">
|
||||
<div>block2</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test Reference: Append a block containing a spanner kid. The spanner kid should correctly span across all columns</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
|
||||
<style>
|
||||
#column {
|
||||
column-count: 3;
|
||||
column-rule: 6px solid;
|
||||
width: 400px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
column-span: all;
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<article id="column">
|
||||
<div>block1
|
||||
<div>
|
||||
<h3>spanner</h3>
|
||||
block2
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test: Append a block containing a spanner kid. The spanner kid should correctly span across all columns</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
|
||||
<link rel="match" href="multicol-span-all-dynamic-add-012-ref.html">
|
||||
<meta name="assert" content="This test checks that an appended block containing 'column-span' element should be rendered correctly.">
|
||||
|
||||
<script>
|
||||
function runTest() {
|
||||
document.body.offsetHeight;
|
||||
|
||||
// Create a subtree like the following, and append it to block1.
|
||||
// <div>
|
||||
// <h3>spanner</h3>
|
||||
// block2
|
||||
// </div>
|
||||
var spanner = document.createElement("h3");
|
||||
var spannerText = document.createTextNode("spanner");
|
||||
spanner.appendChild(spannerText);
|
||||
|
||||
var block2 = document.createElement("div");
|
||||
var block2Text = document.createTextNode("block2");
|
||||
block2.appendChild(spanner);
|
||||
block2.appendChild(block2Text)
|
||||
|
||||
var block1 = document.getElementById("block1");
|
||||
block1.appendChild(block2);
|
||||
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#column {
|
||||
column-count: 3;
|
||||
column-rule: 6px solid;
|
||||
width: 400px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
column-span: all;
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body onload="runTest();">
|
||||
<article id="column">
|
||||
<div id="block1">block1</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user