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 nsAbsoluteContainingBlock_h___ 13 #define nsAbsoluteContainingBlock_h___ 14 15 #include "nsFrameList.h" 16 #include "nsIFrame.h" 17 #include "mozilla/TypedEnumBits.h" 18 19 class nsContainerFrame; 20 class nsPresContext; 21 22 /** 23 * This class contains the logic for being an absolute containing block. This 24 * class is used within viewport frames (for frames representing content with 25 * fixed position) and blocks (for frames representing absolutely positioned 26 * content), since each set of frames is absolutely positioned with respect to 27 * its parent. 28 * 29 * There is no principal child list, just a named child list which contains 30 * the absolutely positioned frames (kAbsoluteList or kFixedList). 31 * 32 * All functions include as the first argument the frame that is delegating 33 * the request. 34 */ 35 class nsAbsoluteContainingBlock { 36 using ReflowInput = mozilla::ReflowInput; 37 38 public: 39 typedef nsIFrame::ChildListID ChildListID; 40 nsAbsoluteContainingBlock(ChildListID aChildListID)41 explicit nsAbsoluteContainingBlock(ChildListID aChildListID) 42 #ifdef DEBUG 43 : mChildListID(aChildListID) 44 #endif 45 { 46 MOZ_ASSERT(mChildListID == nsIFrame::kAbsoluteList || 47 mChildListID == nsIFrame::kFixedList, 48 "should either represent position:fixed or absolute content"); 49 } 50 GetChildList()51 const nsFrameList& GetChildList() const { return mAbsoluteFrames; } AppendChildList(nsTArray<nsIFrame::ChildList> * aLists,ChildListID aListID)52 void AppendChildList(nsTArray<nsIFrame::ChildList>* aLists, 53 ChildListID aListID) const { 54 NS_ASSERTION(aListID == mChildListID, "wrong list ID"); 55 GetChildList().AppendIfNonempty(aLists, aListID); 56 } 57 58 void SetInitialChildList(nsIFrame* aDelegatingFrame, ChildListID aListID, 59 nsFrameList& aChildList); 60 void AppendFrames(nsIFrame* aDelegatingFrame, ChildListID aListID, 61 nsFrameList& aFrameList); 62 void InsertFrames(nsIFrame* aDelegatingFrame, ChildListID aListID, 63 nsIFrame* aPrevFrame, nsFrameList& aFrameList); 64 void RemoveFrame(nsIFrame* aDelegatingFrame, ChildListID aListID, 65 nsIFrame* aOldFrame); 66 67 enum class AbsPosReflowFlags { 68 ConstrainHeight = 0x1, 69 CBWidthChanged = 0x2, 70 CBHeightChanged = 0x4, 71 CBWidthAndHeightChanged = CBWidthChanged | CBHeightChanged, 72 IsGridContainerCB = 0x8, 73 }; 74 75 /** 76 * Called by the delegating frame after it has done its reflow first. This 77 * function will reflow any absolutely positioned child frames that need to 78 * be reflowed, e.g., because the absolutely positioned child frame has 79 * 'auto' for an offset, or a percentage based width or height. 80 * 81 * @param aOverflowAreas, if non-null, is unioned with (in the local 82 * coordinate space) the overflow areas of the absolutely positioned 83 * children. 84 * 85 * @param aReflowStatus is assumed to be already-initialized, e.g. with the 86 * status of the delegating frame's main reflow. This function merges in the 87 * statuses of the absolutely positioned children's reflows. 88 * 89 * @param aFlags zero or more AbsPosReflowFlags 90 */ 91 void Reflow(nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext, 92 const ReflowInput& aReflowInput, nsReflowStatus& aReflowStatus, 93 const nsRect& aContainingBlock, AbsPosReflowFlags aFlags, 94 mozilla::OverflowAreas* aOverflowAreas); 95 96 using PostDestroyData = nsIFrame::PostDestroyData; 97 void DestroyFrames(nsIFrame* aDelegatingFrame, nsIFrame* aDestructRoot, 98 PostDestroyData& aPostDestroyData); 99 HasAbsoluteFrames()100 bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); } 101 102 /** 103 * Mark our size-dependent absolute frames with NS_FRAME_HAS_DIRTY_CHILDREN 104 * so that we'll make sure to reflow them. 105 */ 106 void MarkSizeDependentFramesDirty(); 107 108 /** 109 * Mark all our absolute frames with NS_FRAME_IS_DIRTY. 110 */ 111 void MarkAllFramesDirty(); 112 113 protected: 114 /** 115 * Returns true if the position of aFrame depends on the position of 116 * its placeholder or if the position or size of aFrame depends on a 117 * containing block dimension that changed. 118 */ 119 bool FrameDependsOnContainer(nsIFrame* aFrame, bool aCBWidthChanged, 120 bool aCBHeightChanged); 121 122 /** 123 * After an abspos child's size is known, this method can be used to 124 * resolve size-dependent values in the ComputedLogicalOffsets on its 125 * reflow input. (This may involve resolving the inline dimension of 126 * aLogicalCBSize, too; hence, that variable is an in/outparam.) 127 * 128 * aKidSize, aMargin, aOffsets, and aLogicalCBSize are all expected to be 129 * represented in terms of the absolute containing block's writing-mode. 130 */ 131 void ResolveSizeDependentOffsets(nsPresContext* aPresContext, 132 ReflowInput& aKidReflowInput, 133 const mozilla::LogicalSize& aKidSize, 134 const mozilla::LogicalMargin& aMargin, 135 mozilla::LogicalMargin* aOffsets, 136 mozilla::LogicalSize* aLogicalCBSize); 137 138 /** 139 * For frames that have intrinsic block sizes, since we want to use the 140 * frame's actual instrinsic block-size, we don't compute margins in 141 * InitAbsoluteConstraints because the block-size isn't computed yet. This 142 * method computes the margins for them after layout. 143 * aMargin and aOffsets are both outparams (though we only touch aOffsets if 144 * the position is overconstrained) 145 */ 146 void ResolveAutoMarginsAfterLayout(ReflowInput& aKidReflowInput, 147 const mozilla::LogicalSize* aLogicalCBSize, 148 const mozilla::LogicalSize& aKidSize, 149 mozilla::LogicalMargin& aMargin, 150 mozilla::LogicalMargin& aOffsets); 151 152 void ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, 153 nsPresContext* aPresContext, 154 const ReflowInput& aReflowInput, 155 const nsRect& aContainingBlockRect, 156 AbsPosReflowFlags aFlags, nsIFrame* aKidFrame, 157 nsReflowStatus& aStatus, 158 mozilla::OverflowAreas* aOverflowAreas); 159 160 /** 161 * Mark our absolute frames dirty. 162 * @param aMarkAllDirty if true, all will be marked with NS_FRAME_IS_DIRTY. 163 * Otherwise, the size-dependant ones will be marked with 164 * NS_FRAME_HAS_DIRTY_CHILDREN. 165 */ 166 void DoMarkFramesDirty(bool aMarkAllDirty); 167 168 protected: 169 nsFrameList mAbsoluteFrames; // additional named child list 170 171 #ifdef DEBUG 172 ChildListID const mChildListID; // kFixedList or kAbsoluteList 173 #endif 174 }; 175 176 namespace mozilla { 177 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS( 178 nsAbsoluteContainingBlock::AbsPosReflowFlags) 179 } 180 #endif /* nsnsAbsoluteContainingBlock_h___ */ 181