AbsoluteContainingBlock.h (8643B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 * code for managing absolutely positioned children of a rendering 9 * object that is a containing block for them 10 */ 11 12 #ifndef LAYOUT_GENERIC_ABSOLUTE_CONTAINING_BLOCK_H_ 13 #define LAYOUT_GENERIC_ABSOLUTE_CONTAINING_BLOCK_H_ 14 15 #include "nsFrameList.h" 16 #include "nsIFrame.h" 17 18 class nsContainerFrame; 19 class nsPresContext; 20 21 namespace mozilla { 22 enum class AbsPosReflowFlag : uint8_t { 23 // Allow the children in the absolute containing block to fragment. Without 24 // this flag, the children will be monolithic. 25 AllowFragmentation, 26 CBWidthChanged, 27 CBHeightChanged, 28 IsGridContainerCB, 29 }; 30 using AbsPosReflowFlags = EnumSet<AbsPosReflowFlag>; 31 struct StylePositionArea; 32 33 /** 34 * This class contains the logic for being an absolute containing block. This 35 * class is used within viewport frames (for frames representing content with 36 * fixed position) and blocks (for frames representing absolutely positioned 37 * content), since each set of frames is absolutely positioned with respect to 38 * its parent. 39 * 40 * There is no principal child list, just a named child list which contains 41 * the absolutely positioned frames (FrameChildListID::Absolute or 42 * FrameChildListID::Fixed). 43 * 44 * All functions include as the first argument the frame that is delegating 45 * the request. 46 */ 47 class AbsoluteContainingBlock { 48 public: 49 explicit AbsoluteContainingBlock(FrameChildListID aChildListID) 50 #ifdef DEBUG 51 : mChildListID(aChildListID) 52 #endif 53 { 54 MOZ_ASSERT(mChildListID == FrameChildListID::Absolute || 55 mChildListID == FrameChildListID::Fixed, 56 "should either represent position:fixed or absolute content"); 57 } 58 59 const nsFrameList& GetChildList() const { return mAbsoluteFrames; } 60 const nsFrameList& GetPushedChildList() const { 61 return mPushedAbsoluteFrames; 62 } 63 64 void SetInitialChildList(nsIFrame* aDelegatingFrame, FrameChildListID aListID, 65 nsFrameList&& aChildList); 66 void AppendFrames(nsIFrame* aDelegatingFrame, FrameChildListID aListID, 67 nsFrameList&& aFrameList); 68 void InsertFrames(nsIFrame* aDelegatingFrame, FrameChildListID aListID, 69 nsIFrame* aPrevFrame, nsFrameList&& aFrameList); 70 void RemoveFrame(FrameDestroyContext&, FrameChildListID, nsIFrame*); 71 72 /** 73 * Return the pushed absolute frames. The caller is responsible for passing 74 * the ownership of the frames to someone else, or destroying them. 75 */ 76 [[nodiscard]] nsFrameList StealPushedChildList(); 77 78 /** 79 * Prepare our absolute child list so that it is ready to reflow by moving all 80 * the pushed absolute frames in aDelegatingFrame's prev-in-flow's absCB, and 81 * some in our own pushed absolute child list, to our absolute child list. 82 * 83 * @return true if we have absolute frames after we return. 84 */ 85 bool PrepareAbsoluteFrames(nsContainerFrame* aDelegatingFrame); 86 87 /** 88 * Return true if we have absolute frames. 89 * 90 * Note: During reflow, consider calling PrepareAbsoluteFrames() rather than 91 * this method; it moves absolute frames from other lists to mAbsoluteFrames, 92 * which may be needed to get the correct result. 93 */ 94 bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); } 95 96 /** 97 * Called by the delegating frame after it has done its reflow first. This 98 * function will reflow any absolutely positioned child frames that need to 99 * be reflowed, e.g., because the absolutely positioned child frame has 100 * 'auto' for an offset, or a percentage based width or height. 101 * 102 * @param aOverflowAreas, if non-null, is unioned with (in the local 103 * coordinate space) the overflow areas of the absolutely positioned 104 * children. 105 * @param aReflowStatus This function merges in the statuses of the absolutely 106 * positioned children's reflows. 107 * @param aContainingBlock Rect representing the area where absolute 108 * positioned children can be positioned. Generally, this is the padding rect 109 * of `aDelegatingFrame` (Which would not have a valid mRect set during 110 * reflow), offset against the `aDelegatingFrame`'s border rect. 111 * @param aFlags zero or more AbsPosReflowFlags 112 */ 113 void Reflow(nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext, 114 const ReflowInput& aReflowInput, nsReflowStatus& aReflowStatus, 115 const nsRect& aContainingBlock, AbsPosReflowFlags aFlags, 116 OverflowAreas* aOverflowAreas); 117 118 using DestroyContext = nsIFrame::DestroyContext; 119 void DestroyFrames(DestroyContext&); 120 121 /** 122 * Mark our size-dependent absolute frames with NS_FRAME_HAS_DIRTY_CHILDREN 123 * so that we'll make sure to reflow them. 124 */ 125 void MarkSizeDependentFramesDirty(); 126 127 /** 128 * Mark all our absolute frames with NS_FRAME_IS_DIRTY. 129 */ 130 void MarkAllFramesDirty(); 131 132 protected: 133 /** 134 * Returns true if the position of aFrame depends on the position of 135 * its placeholder or if the position or size of aFrame depends on a 136 * containing block dimension that changed. 137 */ 138 bool FrameDependsOnContainer( 139 nsIFrame* aFrame, bool aCBWidthChanged, bool aCBHeightChanged, 140 mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache = nullptr); 141 142 /** 143 * After an abspos child's size is known, this method can be used to 144 * resolve size-dependent values in the ComputedLogicalOffsets on its 145 * reflow input. 146 * 147 * aCBSize, aKidSize, aMargin, aOffsets, are all expected in the absolute 148 * containing block's writing-mode. 149 * 150 * aOffset is an outparam. 151 */ 152 void ResolveSizeDependentOffsets( 153 ReflowInput& aKidReflowInput, const LogicalSize& aCBSize, 154 const LogicalSize& aKidSize, const LogicalMargin& aMargin, 155 const StylePositionArea& aResolvedPositionArea, LogicalMargin& aOffsets); 156 157 /** 158 * For frames that have intrinsic block sizes, since we want to use the 159 * frame's actual instrinsic block-size, we don't compute margins in 160 * InitAbsoluteConstraints because the block-size isn't computed yet. This 161 * method computes the margins for them after layout. 162 * 163 * aCBSize, aKidSize, aMargin, aOffsets, are all expected in the absolute 164 * containing block's writing-mode. 165 * 166 * aMargin and aOffsets are both outparams (though we only touch aOffsets if 167 * the position is overconstrained) 168 */ 169 void ResolveAutoMarginsAfterLayout(ReflowInput& aKidReflowInput, 170 const LogicalSize& aCBSize, 171 const LogicalSize& aKidSize, 172 LogicalMargin& aMargin, 173 const LogicalMargin& aOffsets); 174 175 void ReflowAbsoluteFrame( 176 nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext, 177 const ReflowInput& aReflowInput, 178 const nsRect& aOriginalContainingBlockRect, 179 const nsRect& aOriginalScrollableContainingBlockRect, 180 AbsPosReflowFlags aFlags, nsIFrame* aKidFrame, nsReflowStatus& aStatus, 181 OverflowAreas* aOverflowAreas, 182 mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache = nullptr); 183 184 /** 185 * Mark our absolute frames dirty. 186 * @param aMarkAllDirty if true, all will be marked with NS_FRAME_IS_DIRTY. 187 * Otherwise, the size-dependant ones will be marked with 188 * NS_FRAME_HAS_DIRTY_CHILDREN. 189 */ 190 void DoMarkFramesDirty(bool aMarkAllDirty); 191 192 /** 193 * Remove aFrame from one of our frame lists without destroying it. 194 */ 195 void StealFrame(nsIFrame* aFrame); 196 197 /** 198 * Move any frame in our pushed absolute list into our absolute child list, if 199 * it is a first-in-flow, or if its prev-in-flow is not present in our 200 * absolute child list. 201 * 202 * @param aDelegatingFrame the frame that owns us. 203 */ 204 void DrainPushedChildList(const nsIFrame* aDelegatingFrame); 205 206 // Stores the abspos frames that have been placed in this containing block. 207 nsFrameList mAbsoluteFrames; 208 209 // A temporary frame list used during reflow, storing abspos frames that need 210 // to be reflowed by the delegating frame's next-in-flow after transferring 211 // them to its own AbsoluteContainingBlock. 212 nsFrameList mPushedAbsoluteFrames; 213 214 #ifdef DEBUG 215 // FrameChildListID::Fixed or FrameChildListID::Absolute 216 FrameChildListID const mChildListID; 217 #endif 218 }; 219 220 } // namespace mozilla 221 222 #endif /* LAYOUT_GENERIC_ABSOLUTE_CONTAINING_BLOCK_H_ */