tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_ */