replaced by .editorconfig Differential Revision: https://phabricator.services.mozilla.com/D287852
247 lines
9.4 KiB
C++
247 lines
9.4 KiB
C++
/* 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 LAYOUT_GENERIC_ABSOLUTE_CONTAINING_BLOCK_H_
|
|
#define LAYOUT_GENERIC_ABSOLUTE_CONTAINING_BLOCK_H_
|
|
|
|
#include "nsFrameList.h"
|
|
#include "nsIFrame.h"
|
|
|
|
class nsContainerFrame;
|
|
class nsPresContext;
|
|
|
|
namespace mozilla {
|
|
enum class AbsPosReflowFlag : uint8_t {
|
|
// Allow the children in the absolute containing block to fragment. Without
|
|
// this flag, the children will be monolithic.
|
|
AllowFragmentation,
|
|
CBWidthChanged,
|
|
CBHeightChanged,
|
|
IsGridContainerCB,
|
|
};
|
|
using AbsPosReflowFlags = EnumSet<AbsPosReflowFlag>;
|
|
struct StylePositionArea;
|
|
|
|
/**
|
|
* 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).
|
|
*
|
|
* All functions include as the first argument the frame that is delegating
|
|
* the request.
|
|
*/
|
|
class AbsoluteContainingBlock {
|
|
public:
|
|
struct AnchorOffsetInfo {
|
|
nsPoint mScrollOffset;
|
|
StylePositionArea mResolvedPositionArea;
|
|
};
|
|
|
|
AbsoluteContainingBlock() = default;
|
|
|
|
const nsFrameList& GetChildList() const { return mAbsoluteFrames; }
|
|
const nsFrameList& GetPushedChildList() const {
|
|
return mPushedAbsoluteFrames;
|
|
}
|
|
|
|
void SetInitialChildList(nsIFrame* aDelegatingFrame, FrameChildListID aListID,
|
|
nsFrameList&& aChildList);
|
|
void AppendFrames(nsIFrame* aDelegatingFrame, FrameChildListID aListID,
|
|
nsFrameList&& aFrameList);
|
|
void InsertFrames(nsIFrame* aDelegatingFrame, FrameChildListID aListID,
|
|
nsIFrame* aPrevFrame, nsFrameList&& aFrameList);
|
|
void RemoveFrame(FrameDestroyContext&, FrameChildListID, nsIFrame*);
|
|
|
|
/**
|
|
* Return the pushed absolute frames. The caller is responsible for passing
|
|
* the ownership of the frames to someone else, or destroying them.
|
|
*/
|
|
[[nodiscard]] nsFrameList StealPushedChildList();
|
|
|
|
/**
|
|
* Prepare our absolute child list so that it is ready to reflow by moving all
|
|
* the pushed absolute frames in aDelegatingFrame's prev-in-flow's absCB, and
|
|
* some in our own pushed absolute child list, to our absolute child list.
|
|
*
|
|
* @return true if we have absolute frames after we return.
|
|
*/
|
|
bool PrepareAbsoluteFrames(nsContainerFrame* aDelegatingFrame);
|
|
|
|
/**
|
|
* Return true if we have absolute frames.
|
|
*
|
|
* Note: During reflow, consider calling PrepareAbsoluteFrames() rather than
|
|
* this method; it moves absolute frames from other lists to mAbsoluteFrames,
|
|
* which may be needed to get the correct result.
|
|
*/
|
|
bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); }
|
|
|
|
/**
|
|
* 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 This function merges in the statuses of the absolutely
|
|
* positioned children's reflows.
|
|
* @param aContainingBlock Rect representing the area where absolute
|
|
* positioned children can be positioned. Generally, this is the padding rect
|
|
* of `aDelegatingFrame` (Which would not have a valid mRect set during
|
|
* reflow), offset against the `aDelegatingFrame`'s border rect.
|
|
* @param aFlags zero or more AbsPosReflowFlags
|
|
*/
|
|
void Reflow(nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext,
|
|
const ReflowInput& aReflowInput, nsReflowStatus& aReflowStatus,
|
|
const nsRect& aContainingBlock, AbsPosReflowFlags aFlags,
|
|
OverflowAreas* aOverflowAreas);
|
|
|
|
using DestroyContext = nsIFrame::DestroyContext;
|
|
void DestroyFrames(DestroyContext&);
|
|
|
|
/**
|
|
* 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();
|
|
|
|
/**
|
|
* Rects for abspos frames to position against. Differences are relevant
|
|
* for containing blocks that scroll.
|
|
*
|
|
* See https://drafts.csswg.org/css-position-4/#scrollable-cb
|
|
*/
|
|
struct ContainingBlockRects {
|
|
nsRect mLocal;
|
|
nsRect mScrollable;
|
|
};
|
|
|
|
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,
|
|
mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache = nullptr);
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* aCBSize, aKidSize, aMargin, aOffsets, are all expected in the absolute
|
|
* containing block's writing-mode.
|
|
*
|
|
* aOffset is an outparam.
|
|
*/
|
|
void ResolveSizeDependentOffsets(ReflowInput& aKidReflowInput,
|
|
const LogicalSize& aCBSize,
|
|
const LogicalSize& aKidSize,
|
|
const LogicalMargin& aMargin,
|
|
const AnchorOffsetInfo& aAnchorOffsetInfo,
|
|
LogicalMargin& aOffsets);
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* aCBSize, aKidSize, aMargin, aOffsets, are all expected in the absolute
|
|
* containing block's writing-mode.
|
|
*
|
|
* aMargin and aOffsets are both outparams (though we only touch aOffsets if
|
|
* the position is overconstrained)
|
|
*/
|
|
void ResolveAutoMarginsAfterLayout(ReflowInput& aKidReflowInput,
|
|
const LogicalSize& aCBSize,
|
|
const LogicalSize& aKidSize,
|
|
LogicalMargin& aMargin,
|
|
const LogicalMargin& aOffsets);
|
|
|
|
void ReflowAbsoluteFrame(
|
|
nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext,
|
|
const ReflowInput& aReflowInput,
|
|
const ContainingBlockRects& aContainingBlockRects,
|
|
AbsPosReflowFlags aFlags, nsIFrame* aKidFrame, nsReflowStatus& aStatus,
|
|
OverflowAreas* aOverflowAreas,
|
|
const ContainingBlockRects* aFragmentedContainingBlockRects,
|
|
AnchorPosResolutionCache* aAnchorPosResolutionCache,
|
|
bool aReuseUnfragmentedAnchorPosReferences);
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* Remove aFrame from one of our frame lists without destroying it.
|
|
*/
|
|
void StealFrame(nsIFrame* aFrame);
|
|
|
|
/**
|
|
* Move any frame in our pushed absolute list into our absolute child list, if
|
|
* it is a first-in-flow, or if its prev-in-flow is not present in our
|
|
* absolute child list.
|
|
*
|
|
* @param aDelegatingFrame the frame that owns us.
|
|
*/
|
|
void DrainPushedChildList(const nsIFrame* aDelegatingFrame);
|
|
|
|
// Stores the abspos frames that have been placed in this containing block.
|
|
nsFrameList mAbsoluteFrames;
|
|
|
|
// A temporary frame list used during reflow, storing abspos frames that need
|
|
// to be reflowed by the delegating frame's next-in-flow after transferring
|
|
// them to its own AbsoluteContainingBlock.
|
|
nsFrameList mPushedAbsoluteFrames;
|
|
|
|
// Suppose D is the distance from an absolute containing block fragment's
|
|
// border-box block-start edge to whichever is larger of either (a) its
|
|
// border-box block-end edge, or (b) the available space's block-end
|
|
// edge.
|
|
//
|
|
// TODO (TYLin, Bug 2009647): We currently assume (a) cannot be bigger than
|
|
// (b), but it can if there is an unfragmentable in-flow element.
|
|
//
|
|
// This variable stores the sum of the D values for the current absolute
|
|
// containing block fragment and for all its previous fragments. It represents
|
|
// the offset from the start of the theoretical unfragmented abspos containing
|
|
// block to the start of the current fragment. During reflow, we subtract this
|
|
// value from abspos frames' unfragmented positions to get their local
|
|
// coordinate space position in the current fragment.
|
|
nscoord mCumulativeContainingBlockBSize = 0;
|
|
|
|
#ifdef DEBUG
|
|
void SanityCheckChildListsBeforeReflow(
|
|
const nsIFrame* aDelegatingFrame) const;
|
|
#endif
|
|
};
|
|
|
|
} // namespace mozilla
|
|
|
|
#endif /* LAYOUT_GENERIC_ABSOLUTE_CONTAINING_BLOCK_H_ */
|