Bug 1269045 part 2: Separate out abspos placeholders when creating FlexItems, and give them a trivial reflow at container's content-box origin. r=mats
MozReview-Commit-ID: 5lXUsusLryC
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -3398,17 +3398,18 @@ AddNewFlexLineToList(LinkedList<FlexLine
void
nsFlexContainerFrame::GenerateFlexLines(
nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
const nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker,
- LinkedList<FlexLine>& aLines)
+ nsTArray<nsIFrame*>& aPlaceholders, /* out */
+ LinkedList<FlexLine>& aLines /* out */)
{
MOZ_ASSERT(aLines.isEmpty(), "Expecting outparam to start out empty");
const bool isSingleLine =
NS_STYLE_FLEX_WRAP_NOWRAP == aReflowInput.mStylePosition->mFlexWrap;
// If we're transparently reversing axes, then we'll need to link up our
// FlexItems and FlexLines in the reverse order, so that the rest of flex
@@ -3455,16 +3456,22 @@ nsFlexContainerFrame::GenerateFlexLines(
// aStruts.Length(), that means there are no more struts):
uint32_t nextStrutIdx = 0;
// Overall index of the current flex item in the flex container. (This gets
// checked against entries in aStruts.)
uint32_t itemIdxInContainer = 0;
for (nsIFrame* childFrame : mFrames) {
+ // Don't create flex items / lines for placeholder frames:
+ if (childFrame->GetType() == nsGkAtoms::placeholderFrame) {
+ 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() &&
@@ -4030,22 +4037,24 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker)
{
aStatus = NS_FRAME_COMPLETE;
LinkedList<FlexLine> lines;
+ nsTArray<nsIFrame*> placeholderKids;
AutoFlexLineListClearer cleanupLines(lines);
GenerateFlexLines(aPresContext, aReflowInput,
aContentBoxMainSize,
aAvailableBSizeForContent,
- aStruts, aAxisTracker, lines);
+ aStruts, aAxisTracker,
+ placeholderKids, lines);
aContentBoxMainSize =
ResolveFlexContainerMainSize(aReflowInput, aAxisTracker,
aContentBoxMainSize, aAvailableBSizeForContent,
lines.getFirst(), aStatus);
for (FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
line->ResolveFlexibleLengths(aContentBoxMainSize);
@@ -4264,16 +4273,22 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
// children), then use this child's baseline as the container's baseline.
if (item == firstItem &&
flexContainerAscent == nscoord_MIN) {
flexContainerAscent = itemNormalBPos + item->ResolvedAscent();
}
}
}
+ if (!placeholderKids.IsEmpty()) {
+ ReflowPlaceholders(aPresContext, aReflowInput,
+ placeholderKids, containerContentBoxOrigin,
+ containerSize);
+ }
+
// Compute flex container's desired size (in its own writing-mode),
// starting w/ content-box size & growing from there:
LogicalSize desiredSizeInFlexWM =
aAxisTracker.LogicalSizeFromFlexRelativeSizes(aContentBoxMainSize,
contentBoxCrossSize);
// Add border/padding (w/ skipSides already applied):
desiredSizeInFlexWM.ISize(flexWM) += containerBP.IStartEnd(flexWM);
desiredSizeInFlexWM.BSize(flexWM) += containerBP.BStartEnd(flexWM);
@@ -4465,16 +4480,48 @@ nsFlexContainerFrame::ReflowFlexItem(nsP
FinishReflowChild(aItem.Frame(), aPresContext,
childDesiredSize, &childReflowInput,
outerWM, aFramePos, aContainerSize, 0);
aItem.SetAscent(childDesiredSize.BlockStartAscent());
}
+void
+nsFlexContainerFrame::ReflowPlaceholders(nsPresContext* aPresContext,
+ const ReflowInput& aReflowInput,
+ nsTArray<nsIFrame*>& aPlaceholders,
+ const LogicalPoint& aContentBoxOrigin,
+ const nsSize& aContainerSize)
+{
+ WritingMode outerWM = aReflowInput.GetWritingMode();
+
+ // As noted in this method's documentation, we'll reflow every entry in
+ // |aPlaceholders| at the container's content-box origin.
+ for (nsIFrame* placeholder : aPlaceholders) {
+ MOZ_ASSERT(placeholder->GetType() == nsGkAtoms::placeholderFrame,
+ "placeholders array should only contain placeholder frames");
+ WritingMode wm = placeholder->GetWritingMode();
+ LogicalSize availSize = aReflowInput.ComputedSize(wm);
+ ReflowInput childReflowInput(aPresContext, aReflowInput,
+ placeholder, availSize);
+ ReflowOutput childDesiredSize(childReflowInput);
+ nsReflowStatus childReflowStatus;
+ ReflowChild(placeholder, aPresContext,
+ childDesiredSize, childReflowInput,
+ outerWM, aContentBoxOrigin, aContainerSize, 0,
+ childReflowStatus);
+
+ FinishReflowChild(placeholder, aPresContext,
+ childDesiredSize, &childReflowInput,
+ outerWM, aContentBoxOrigin, aContainerSize, 0);
+
+ }
+}
+
/* virtual */ nscoord
nsFlexContainerFrame::GetMinISize(nsRenderingContext* aRenderingContext)
{
nscoord minISize = 0;
DISPLAY_MIN_WIDTH(this, minISize);
RenumberList();
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -188,26 +188,33 @@ protected:
* on aFlexItem, if needed.
* (Helper for GenerateFlexItemForChild().)
*/
void ResolveAutoFlexBasisAndMinSize(nsPresContext* aPresContext,
FlexItem& aFlexItem,
const ReflowInput& aItemReflowInput,
const FlexboxAxisTracker& aAxisTracker);
- // Creates FlexItems for all of our child frames, arranged in a list of
- // FlexLines. These are returned by reference in |aLines|. Our actual
- // return value has to be |nsresult|, in case we have to reflow a child
- // to establish its flex base size and that reflow fails.
+ /**
+ * 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.)
+ */
void GenerateFlexLines(nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent,
const nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker,
+ nsTArray<nsIFrame*>& aPlaceholders,
mozilla::LinkedList<FlexLine>& aLines);
nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput,
const FlexboxAxisTracker& aAxisTracker);
nscoord ComputeCrossSize(const ReflowInput& aReflowInput,
const FlexboxAxisTracker& aAxisTracker,
nscoord aSumLineCrossSizes,
@@ -254,15 +261,45 @@ protected:
*/
void ReflowFlexItem(nsPresContext* aPresContext,
const FlexboxAxisTracker& aAxisTracker,
const ReflowInput& aReflowInput,
const FlexItem& aItem,
mozilla::LogicalPoint& aFramePos,
const nsSize& aContainerSize);
+ /**
+ * Helper-function to perform a "dummy reflow" on all our nsPlaceholderFrame
+ * children, at the container's content-box origin.
+ *
+ * This doesn't actually represent the static position of the placeholders'
+ * out-of-flow (OOF) frames -- we can't compute that until we've reflowed the
+ * OOF, because (depending on the CSS Align properties) the static position
+ * may be influenced by the OOF's size. So for now, we just co-opt the
+ * placeholder to store the flex container's logical content-box origin, and
+ * we defer to nsAbsoluteContainingBlock to determine the OOF's actual static
+ * position (using this origin, the OOF's size, and the CSS Align
+ * properties).
+ *
+ * XXXdholbert The nsAbsoluteContainingBlock stuff is coming in bug 1269046.
+ *
+ * @param aPresContext The presentation context being used in reflow.
+ * @param aReflowInput The flex container's reflow input.
+ * @param aPlaceholders An array of all the flex container's
+ * nsPlaceholderFrame children.
+ * @param aContentBoxOrigin The flex container's logical content-box
+ * origin (in its own coordinate space).
+ * @param aContainerSize The flex container's size (required by some
+ * reflow methods to interpret positions correctly).
+ */
+ void ReflowPlaceholders(nsPresContext* aPresContext,
+ const ReflowInput& aReflowInput,
+ nsTArray<nsIFrame*>& aPlaceholders,
+ const mozilla::LogicalPoint& aContentBoxOrigin,
+ const nsSize& aContainerSize);
+
bool mChildrenHaveBeenReordered; // Have we ever had to reorder our kids
// to satisfy their 'order' values?
nscoord mBaselineFromLastReflow;
};
#endif /* nsFlexContainerFrame_h___ */