--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -3604,16 +3604,49 @@ AddNewFlexLineToList(LinkedList<FlexLine
if (aShouldInsertAtFront) {
aLines.insertFront(newLine);
} else {
aLines.insertBack(newLine);
}
return newLine;
}
+bool
+nsFlexContainerFrame::ShouldUseMozBoxCollapseBehavior(
+ const nsStyleDisplay* aThisStyleDisp)
+{
+ MOZ_ASSERT(StyleDisplay() == aThisStyleDisp, "wrong StyleDisplay passed in");
+
+ // Quick filter to screen out *actual* (not-coopted-for-emulation)
+ // flex containers, using state bit:
+ if (!IsLegacyBox(this)) {
+ return false;
+ }
+
+ // Check our own display value:
+ if (aThisStyleDisp->mDisplay == mozilla::StyleDisplay::MozBox ||
+ aThisStyleDisp->mDisplay == mozilla::StyleDisplay::MozInlineBox) {
+ return true;
+ }
+
+ // Check our parent's display value, if we're an anonymous box (with a
+ // potentially-untrustworthy display value):
+ auto pseudoType = StyleContext()->GetPseudo();
+ if (pseudoType == nsCSSAnonBoxes::scrolledContent ||
+ pseudoType == nsCSSAnonBoxes::buttonContent) {
+ const nsStyleDisplay* disp = GetParent()->StyleDisplay();
+ if (disp->mDisplay == mozilla::StyleDisplay::MozBox ||
+ disp->mDisplay == mozilla::StyleDisplay::MozInlineBox) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void
nsFlexContainerFrame::GenerateFlexLines(
nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
const nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker,
@@ -3680,34 +3713,42 @@ nsFlexContainerFrame::GenerateFlexLines(
OrderingPropertyForIter(this));
if (iter.ItemsAreAlreadyInOrder()) {
AddStateBits(NS_STATE_FLEX_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER);
} else {
RemoveStateBits(NS_STATE_FLEX_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER);
}
+ const bool useMozBoxCollapseBehavior =
+ ShouldUseMozBoxCollapseBehavior(aReflowInput.mStyleDisplay);
+
for (; !iter.AtEnd(); iter.Next()) {
nsIFrame* childFrame = *iter;
// Don't create flex items / lines for placeholder frames:
if (childFrame->IsPlaceholderFrame()) {
aPlaceholders.AppendElement(childFrame);
continue;
}
// Honor "page-break-before", if we're multi-line and this line isn't empty:
if (!isSingleLine && !curLine->IsEmpty() &&
childFrame->StyleDisplay()->mBreakBefore) {
curLine = AddNewFlexLineToList(aLines, shouldInsertAtFront);
}
UniquePtr<FlexItem> item;
- if (nextStrutIdx < aStruts.Length() &&
- aStruts[nextStrutIdx].mItemIdx == itemIdxInContainer) {
-
+ if (useMozBoxCollapseBehavior &&
+ (NS_STYLE_VISIBILITY_COLLAPSE ==
+ childFrame->StyleVisibility()->mVisible)) {
+ // Legacy visibility:collapse behavior: make a 0-sized strut. (No need to
+ // bother with aStruts and remembering cross size.)
+ item = MakeUnique<FlexItem>(childFrame, 0, aReflowInput.GetWritingMode());
+ } else if (nextStrutIdx < aStruts.Length() &&
+ aStruts[nextStrutIdx].mItemIdx == itemIdxInContainer) {
// Use the simplified "strut" FlexItem constructor:
item = MakeUnique<FlexItem>(childFrame, aStruts[nextStrutIdx].mStrutCrossSize,
aReflowInput.GetWritingMode());
nextStrutIdx++;
} else {
item = GenerateFlexItemForChild(aPresContext, childFrame,
aReflowInput, aAxisTracker);
}
@@ -4469,17 +4510,18 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
crossAxisPosnTracker(lines.getFirst(),
aReflowInput, contentBoxCrossSize,
isCrossSizeDefinite, aAxisTracker);
// Now that we know the cross size of each line (including
// "align-content:stretch" adjustments, from the CrossAxisPositionTracker
// constructor), we can create struts for any flex items with
// "visibility: collapse" (and restart flex layout).
- if (aStruts.IsEmpty()) { // (Don't make struts if we already did)
+ if (aStruts.IsEmpty() && // (Don't make struts if we already did)
+ !ShouldUseMozBoxCollapseBehavior(aReflowInput.mStyleDisplay)) {
BuildStrutInfoFromCollapsedItems(lines.getFirst(), aStruts);
if (!aStruts.IsEmpty()) {
// Restart flex layout, using our struts.
return;
}
}
// If the container should derive its baseline from the first FlexLine,
@@ -4915,30 +4957,39 @@ nsFlexContainerFrame::GetMinISize(gfxCon
nscoord minISize = 0;
DISPLAY_MIN_WIDTH(this, minISize);
RenumberList();
const nsStylePosition* stylePos = StylePosition();
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
+ const bool useMozBoxCollapseBehavior =
+ ShouldUseMozBoxCollapseBehavior(StyleDisplay());
+
for (nsIFrame* childFrame : mFrames) {
- nscoord childMinISize =
- nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
- nsLayoutUtils::MIN_ISIZE);
- // For a horizontal single-line flex container, the intrinsic min
- // isize is the sum of its items' min isizes.
- // For a column-oriented flex container, or for a multi-line row-
- // oriented flex container, the intrinsic min isize is the max of
- // its items' min isizes.
- if (axisTracker.IsRowOriented() &&
- NS_STYLE_FLEX_WRAP_NOWRAP == stylePos->mFlexWrap) {
- minISize += childMinISize;
- } else {
- minISize = std::max(minISize, childMinISize);
+ // If we're using legacy "visibility:collapse" behavior, then we don't
+ // care about the sizes of any collapsed children.
+ if (!useMozBoxCollapseBehavior ||
+ (NS_STYLE_VISIBILITY_COLLAPSE !=
+ childFrame->StyleVisibility()->mVisible)) {
+ nscoord childMinISize =
+ nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
+ nsLayoutUtils::MIN_ISIZE);
+ // For a horizontal single-line flex container, the intrinsic min
+ // isize is the sum of its items' min isizes.
+ // For a column-oriented flex container, or for a multi-line row-
+ // oriented flex container, the intrinsic min isize is the max of
+ // its items' min isizes.
+ if (axisTracker.IsRowOriented() &&
+ NS_STYLE_FLEX_WRAP_NOWRAP == stylePos->mFlexWrap) {
+ minISize += childMinISize;
+ } else {
+ minISize = std::max(minISize, childMinISize);
+ }
}
}
return minISize;
}
/* virtual */ nscoord
nsFlexContainerFrame::GetPrefISize(gfxContext* aRenderingContext)
{
@@ -4949,20 +5000,29 @@ nsFlexContainerFrame::GetPrefISize(gfxCo
// XXXdholbert Optimization: We could cache our intrinsic widths like
// nsBlockFrame does (and return it early from this function if it's set).
// Whenever anything happens that might change it, set it to
// NS_INTRINSIC_WIDTH_UNKNOWN (like nsBlockFrame::MarkIntrinsicISizesDirty
// does)
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
+ const bool useMozBoxCollapseBehavior =
+ ShouldUseMozBoxCollapseBehavior(StyleDisplay());
+
for (nsIFrame* childFrame : mFrames) {
- nscoord childPrefISize =
- nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
- nsLayoutUtils::PREF_ISIZE);
- if (axisTracker.IsRowOriented()) {
- prefISize += childPrefISize;
- } else {
- prefISize = std::max(prefISize, childPrefISize);
+ // If we're using legacy "visibility:collapse" behavior, then we don't
+ // care about the sizes of any collapsed children.
+ if (!useMozBoxCollapseBehavior ||
+ (NS_STYLE_VISIBILITY_COLLAPSE !=
+ childFrame->StyleVisibility()->mVisible)) {
+ nscoord childPrefISize =
+ nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
+ nsLayoutUtils::PREF_ISIZE);
+ if (axisTracker.IsRowOriented()) {
+ prefISize += childPrefISize;
+ } else {
+ prefISize = std::max(prefISize, childPrefISize);
+ }
}
}
return prefISize;
}
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -295,16 +295,27 @@ protected:
* (Helper for GenerateFlexItemForChild().)
*/
void ResolveAutoFlexBasisAndMinSize(nsPresContext* aPresContext,
FlexItem& aFlexItem,
const ReflowInput& aItemReflowInput,
const FlexboxAxisTracker& aAxisTracker);
/**
+ * Returns true if "this" is the nsFlexContainerFrame for a -moz-box or
+ * a -moz-inline-box -- these boxes have special behavior for flex items with
+ * "visibility:collapse".
+ *
+ * @param aFlexStyleDisp This frame's StyleDisplay(). (Just an optimization to
+ * avoid repeated lookup; some callers already have it.)
+ * @return true if "this" is the nsFlexContainerFrame for a -moz-{inline}box.
+ */
+ bool ShouldUseMozBoxCollapseBehavior(const nsStyleDisplay* aFlexStyleDisp);
+
+ /**
* This method:
* - Creates FlexItems for all of our child frames (except placeholders).
* - Groups those FlexItems into FlexLines.
* - Returns those FlexLines in the outparam |aLines|.
*
* For any child frames which are placeholders, this method will instead just
* append that child to the outparam |aPlaceholders| for separate handling.
* (Absolutely positioned children of a flex container are *not* flex items.)