summaryrefslogtreecommitdiffstats
path: root/layout/generic/nsAbsoluteContainingBlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/nsAbsoluteContainingBlock.h')
-rw-r--r--layout/generic/nsAbsoluteContainingBlock.h182
1 files changed, 182 insertions, 0 deletions
diff --git a/layout/generic/nsAbsoluteContainingBlock.h b/layout/generic/nsAbsoluteContainingBlock.h
new file mode 100644
index 0000000000..fffed04dca
--- /dev/null
+++ b/layout/generic/nsAbsoluteContainingBlock.h
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * code for managing absolutely positioned children of a rendering
+ * object that is a containing block for them
+ */
+
+#ifndef nsAbsoluteContainingBlock_h___
+#define nsAbsoluteContainingBlock_h___
+
+#include "nsFrameList.h"
+#include "nsIFrame.h"
+#include "mozilla/TypedEnumBits.h"
+
+class nsContainerFrame;
+class nsPresContext;
+
+/**
+ * This class contains the logic for being an absolute containing block. This
+ * class is used within viewport frames (for frames representing content with
+ * fixed position) and blocks (for frames representing absolutely positioned
+ * content), since each set of frames is absolutely positioned with respect to
+ * its parent.
+ *
+ * There is no principal child list, just a named child list which contains
+ * the absolutely positioned frames (FrameChildListID::Absolute or
+ * FrameChildListID::Fixed).
+ *
+ * All functions include as the first argument the frame that is delegating
+ * the request.
+ */
+class nsAbsoluteContainingBlock {
+ using ReflowInput = mozilla::ReflowInput;
+
+ public:
+ explicit nsAbsoluteContainingBlock(mozilla::FrameChildListID aChildListID)
+#ifdef DEBUG
+ : mChildListID(aChildListID)
+#endif
+ {
+ MOZ_ASSERT(mChildListID == mozilla::FrameChildListID::Absolute ||
+ mChildListID == mozilla::FrameChildListID::Fixed,
+ "should either represent position:fixed or absolute content");
+ }
+
+ const nsFrameList& GetChildList() const { return mAbsoluteFrames; }
+ void AppendChildList(nsTArray<mozilla::FrameChildList>* aLists,
+ mozilla::FrameChildListID aListID) const {
+ NS_ASSERTION(aListID == mChildListID, "wrong list ID");
+ GetChildList().AppendIfNonempty(aLists, aListID);
+ }
+
+ void SetInitialChildList(nsIFrame* aDelegatingFrame,
+ mozilla::FrameChildListID aListID,
+ nsFrameList&& aChildList);
+ void AppendFrames(nsIFrame* aDelegatingFrame,
+ mozilla::FrameChildListID aListID,
+ nsFrameList&& aFrameList);
+ void InsertFrames(nsIFrame* aDelegatingFrame,
+ mozilla::FrameChildListID aListID, nsIFrame* aPrevFrame,
+ nsFrameList&& aFrameList);
+ void RemoveFrame(mozilla::FrameDestroyContext&, mozilla::FrameChildListID,
+ nsIFrame*);
+
+ enum class AbsPosReflowFlags {
+ ConstrainHeight = 0x1,
+ CBWidthChanged = 0x2,
+ CBHeightChanged = 0x4,
+ CBWidthAndHeightChanged = CBWidthChanged | CBHeightChanged,
+ IsGridContainerCB = 0x8,
+ };
+
+ /**
+ * Called by the delegating frame after it has done its reflow first. This
+ * function will reflow any absolutely positioned child frames that need to
+ * be reflowed, e.g., because the absolutely positioned child frame has
+ * 'auto' for an offset, or a percentage based width or height.
+ *
+ * @param aOverflowAreas, if non-null, is unioned with (in the local
+ * coordinate space) the overflow areas of the absolutely positioned
+ * children.
+ *
+ * @param aReflowStatus is assumed to be already-initialized, e.g. with the
+ * status of the delegating frame's main reflow. This function merges in the
+ * statuses of the absolutely positioned children's reflows.
+ *
+ * @param aFlags zero or more AbsPosReflowFlags
+ */
+ void Reflow(nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext,
+ const ReflowInput& aReflowInput, nsReflowStatus& aReflowStatus,
+ const nsRect& aContainingBlock, AbsPosReflowFlags aFlags,
+ mozilla::OverflowAreas* aOverflowAreas);
+
+ using DestroyContext = nsIFrame::DestroyContext;
+ void DestroyFrames(DestroyContext&);
+
+ bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); }
+
+ /**
+ * Mark our size-dependent absolute frames with NS_FRAME_HAS_DIRTY_CHILDREN
+ * so that we'll make sure to reflow them.
+ */
+ void MarkSizeDependentFramesDirty();
+
+ /**
+ * Mark all our absolute frames with NS_FRAME_IS_DIRTY.
+ */
+ void MarkAllFramesDirty();
+
+ protected:
+ /**
+ * Returns true if the position of aFrame depends on the position of
+ * its placeholder or if the position or size of aFrame depends on a
+ * containing block dimension that changed.
+ */
+ bool FrameDependsOnContainer(nsIFrame* aFrame, bool aCBWidthChanged,
+ bool aCBHeightChanged);
+
+ /**
+ * After an abspos child's size is known, this method can be used to
+ * resolve size-dependent values in the ComputedLogicalOffsets on its
+ * reflow input. (This may involve resolving the inline dimension of
+ * aLogicalCBSize, too; hence, that variable is an in/outparam.)
+ *
+ * aKidSize, aMargin, aOffsets, and aLogicalCBSize are all expected to be
+ * represented in terms of the absolute containing block's writing-mode.
+ */
+ void ResolveSizeDependentOffsets(nsPresContext* aPresContext,
+ ReflowInput& aKidReflowInput,
+ const mozilla::LogicalSize& aKidSize,
+ const mozilla::LogicalMargin& aMargin,
+ mozilla::LogicalMargin* aOffsets,
+ mozilla::LogicalSize* aLogicalCBSize);
+
+ /**
+ * For frames that have intrinsic block sizes, since we want to use the
+ * frame's actual instrinsic block-size, we don't compute margins in
+ * InitAbsoluteConstraints because the block-size isn't computed yet. This
+ * method computes the margins for them after layout.
+ * aMargin and aOffsets are both outparams (though we only touch aOffsets if
+ * the position is overconstrained)
+ */
+ void ResolveAutoMarginsAfterLayout(ReflowInput& aKidReflowInput,
+ const mozilla::LogicalSize* aLogicalCBSize,
+ const mozilla::LogicalSize& aKidSize,
+ mozilla::LogicalMargin& aMargin,
+ mozilla::LogicalMargin& aOffsets);
+
+ void ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame,
+ nsPresContext* aPresContext,
+ const ReflowInput& aReflowInput,
+ const nsRect& aContainingBlockRect,
+ AbsPosReflowFlags aFlags, nsIFrame* aKidFrame,
+ nsReflowStatus& aStatus,
+ mozilla::OverflowAreas* aOverflowAreas);
+
+ /**
+ * Mark our absolute frames dirty.
+ * @param aMarkAllDirty if true, all will be marked with NS_FRAME_IS_DIRTY.
+ * Otherwise, the size-dependant ones will be marked with
+ * NS_FRAME_HAS_DIRTY_CHILDREN.
+ */
+ void DoMarkFramesDirty(bool aMarkAllDirty);
+
+ protected:
+ nsFrameList mAbsoluteFrames; // additional named child list
+
+#ifdef DEBUG
+ mozilla::FrameChildListID const
+ mChildListID; // FrameChildListID::Fixed or FrameChildListID::Absolute
+#endif
+};
+
+namespace mozilla {
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(
+ nsAbsoluteContainingBlock::AbsPosReflowFlags)
+}
+#endif /* nsnsAbsoluteContainingBlock_h___ */