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 /* base class #1 for rendering objects that have child lists */
8 
9 #ifndef nsContainerFrame_h___
10 #define nsContainerFrame_h___
11 
12 #include "mozilla/Attributes.h"
13 #include "LayoutConstants.h"
14 #include "nsISelectionDisplay.h"
15 #include "nsSplittableFrame.h"
16 #include "nsFrameList.h"
17 #include "nsLineBox.h"
18 #include "nsTHashSet.h"
19 
20 class nsOverflowContinuationTracker;
21 
22 namespace mozilla {
23 class PresShell;
24 }  // namespace mozilla
25 
26 // Some macros for container classes to do sanity checking on
27 // width/height/x/y values computed during reflow.
28 // NOTE: AppUnitsPerCSSPixel value hardwired here to remove the
29 // dependency on nsDeviceContext.h.  It doesn't matter if it's a
30 // little off.
31 #ifdef DEBUG
32 // 10 million pixels, converted to app units. Note that this a bit larger
33 // than 1/4 of nscoord_MAX. So, if any content gets to be this large, we're
34 // definitely in danger of grazing up against nscoord_MAX; hence, it's ABSURD.
35 #  define ABSURD_COORD (10000000 * 60)
36 #  define ABSURD_SIZE(_x) (((_x) < -ABSURD_COORD) || ((_x) > ABSURD_COORD))
37 #endif
38 
39 /**
40  * Implementation of a container frame.
41  */
42 class nsContainerFrame : public nsSplittableFrame {
43  public:
44   NS_DECL_ABSTRACT_FRAME(nsContainerFrame)
45   NS_DECL_QUERYFRAME_TARGET(nsContainerFrame)
46   NS_DECL_QUERYFRAME
47 
48   // nsIFrame overrides
49   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
50                     nsIFrame* aPrevInFlow) override;
GetContentInsertionFrame()51   virtual nsContainerFrame* GetContentInsertionFrame() override { return this; }
52 
53   virtual const nsFrameList& GetChildList(ChildListID aList) const override;
54   virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
55   virtual void DestroyFrom(nsIFrame* aDestructRoot,
56                            PostDestroyData& aPostDestroyData) override;
57   virtual void ChildIsDirty(nsIFrame* aChild) override;
58 
59   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward,
60                                                int32_t* aOffset) override;
61   virtual FrameSearchResult PeekOffsetCharacter(
62       bool aForward, int32_t* aOffset,
63       PeekOffsetCharacterOptions aOptions =
64           PeekOffsetCharacterOptions()) override;
65 
66 #ifdef DEBUG_FRAME_DUMP
67   void List(FILE* out = stderr, const char* aPrefix = "",
68             ListFlags aFlags = ListFlags()) const override;
69   void ListWithMatchedRules(FILE* out = stderr,
70                             const char* aPrefix = "") const override;
71   void ListChildLists(FILE* aOut, const char* aPrefix, ListFlags aFlags,
72                       ChildListIDs aSkippedListIDs) const;
73   virtual void ExtraContainerFrameInfo(nsACString& aTo) const;
74 #endif
75 
76   // nsContainerFrame methods
77 
78   /**
79    * Called to set the initial list of frames. This happens after the frame
80    * has been initialized.
81    *
82    * This is only called once for a given child list, and won't be called
83    * at all for child lists with no initial list of frames.
84    *
85    * @param   aListID the child list identifier.
86    * @param   aChildList list of child frames. Each of the frames has its
87    *            NS_FRAME_IS_DIRTY bit set.  Must not be empty.
88    *            This method cannot handle the child list returned by
89    *            GetAbsoluteListID().
90    * @see     #Init()
91    */
92   virtual void SetInitialChildList(ChildListID aListID,
93                                    nsFrameList& aChildList);
94 
95   /**
96    * This method is responsible for appending frames to the frame
97    * list.  The implementation should append the frames to the specified
98    * child list and then generate a reflow command.
99    *
100    * @param   aListID the child list identifier.
101    * @param   aFrameList list of child frames to append. Each of the frames has
102    *            its NS_FRAME_IS_DIRTY bit set.  Must not be empty.
103    */
104   virtual void AppendFrames(ChildListID aListID, nsFrameList& aFrameList);
105 
106   /**
107    * This method is responsible for inserting frames into the frame
108    * list.  The implementation should insert the new frames into the specified
109    * child list and then generate a reflow command.
110    *
111    * @param   aListID the child list identifier.
112    * @param   aPrevFrame the frame to insert frames <b>after</b>
113    * @param   aPrevFrameLine (optional) if present (i.e., not null), the line
114    *            box that aPrevFrame is part of.
115    * @param   aFrameList list of child frames to insert <b>after</b> aPrevFrame.
116    *            Each of the frames has its NS_FRAME_IS_DIRTY bit set
117    */
118   virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
119                             const nsLineList::iterator* aPrevFrameLine,
120                             nsFrameList& aFrameList);
121 
122   /**
123    * This method is responsible for removing a frame in the frame
124    * list.  The implementation should do something with the removed frame
125    * and then generate a reflow command. The implementation is responsible
126    * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
127    *
128    * @param   aListID the child list identifier.
129    * @param   aOldFrame the frame to remove
130    */
131   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
132 
133   /**
134    * Helper method to create next-in-flows if necessary. If aFrame
135    * already has a next-in-flow then this method does
136    * nothing. Otherwise, a new continuation frame is created and
137    * linked into the flow. In addition, the new frame is inserted
138    * into the principal child list after aFrame.
139    * @note calling this method on a block frame is illegal. Use
140    * nsBlockFrame::CreateContinuationFor() instead.
141    * @return the next-in-flow <b>if and only if</b> one is created. If
142    *         a next-in-flow already exists, nullptr will be returned.
143    */
144   nsIFrame* CreateNextInFlow(nsIFrame* aFrame);
145 
146   /**
147    * Delete aNextInFlow and its next-in-flows.
148    * @param aDeletingEmptyFrames if set, then the reflow for aNextInFlow's
149    * content was complete before aNextInFlow, so aNextInFlow and its
150    * next-in-flows no longer map any real content.
151    */
152   virtual void DeleteNextInFlowChild(nsIFrame* aNextInFlow,
153                                      bool aDeletingEmptyFrames);
154 
155   // Positions the frame's view based on the frame's origin
156   static void PositionFrameView(nsIFrame* aKidFrame);
157 
158   static nsresult ReparentFrameView(nsIFrame* aChildFrame,
159                                     nsIFrame* aOldParentFrame,
160                                     nsIFrame* aNewParentFrame);
161 
162   static void ReparentFrameViewList(const nsFrameList& aChildFrameList,
163                                     nsIFrame* aOldParentFrame,
164                                     nsIFrame* aNewParentFrame);
165 
166   /**
167    * Reparent aFrame from aOldParent to aNewParent.
168    */
169   static void ReparentFrame(nsIFrame* aFrame, nsContainerFrame* aOldParent,
170                             nsContainerFrame* aNewParent);
171 
172   /**
173    * Reparent all the frames in aFrameList from aOldParent to aNewParent.
174    *
175    * Note: Reparenting a large frame list can be have huge performance impact.
176    * For example, instead of using this method, nsInlineFrame uses a "lazy
177    * reparenting" technique that it reparents a child frame just before
178    * reflowing the child. (See InlineReflowInput::mSetParentPointer.)
179    */
180   static void ReparentFrames(nsFrameList& aFrameList,
181                              nsContainerFrame* aOldParent,
182                              nsContainerFrame* aNewParent);
183 
184   // Set the view's size and position after its frame has been reflowed.
185   static void SyncFrameViewAfterReflow(
186       nsPresContext* aPresContext, nsIFrame* aFrame, nsView* aView,
187       const nsRect& aInkOverflowArea,
188       ReflowChildFlags aFlags = ReflowChildFlags::Default);
189 
190   // Syncs properties to the top level view and window, like transparency and
191   // shadow.
192   // The SET_ASYNC indicates that the actual nsIWidget calls to sync the window
193   // properties should be done async.
194   enum {
195     SET_ASYNC = 0x01,
196   };
197   static void SyncWindowProperties(nsPresContext* aPresContext,
198                                    nsIFrame* aFrame, nsView* aView,
199                                    gfxContext* aRC, uint32_t aFlags);
200 
201   /**
202    * Converts the minimum and maximum sizes given in inner window app units to
203    * outer window device pixel sizes and assigns these constraints to the
204    * widget.
205    *
206    * @param aPresContext pres context
207    * @param aWidget widget for this frame
208    * @param minimum size of the window in app units
209    * @param maxmimum size of the window in app units
210    */
211   static void SetSizeConstraints(nsPresContext* aPresContext,
212                                  nsIWidget* aWidget, const nsSize& aMinSize,
213                                  const nsSize& aMaxSize);
214 
215   /**
216    * Helper for calculating intrinsic inline size for inline containers.
217    *
218    * @param aData the intrinsic inline size data, either an InlineMinISizeData
219    *  or an InlinePrefISizeData
220    * @param aHandleChildren a callback function invoked for each in-flow
221    *  continuation, with the continuation frame and the intrinsic inline size
222    *  data passed into it.
223    */
224   template <typename ISizeData, typename F>
225   void DoInlineIntrinsicISize(ISizeData* aData, F& aHandleChildren);
226 
227   void DoInlineMinISize(gfxContext* aRenderingContext,
228                         InlineMinISizeData* aData);
229   void DoInlinePrefISize(gfxContext* aRenderingContext,
230                          InlinePrefISizeData* aData);
231 
232   /**
233    * This is the CSS block concept of computing 'auto' widths, which most
234    * classes derived from nsContainerFrame want.
235    */
236   virtual mozilla::LogicalSize ComputeAutoSize(
237       gfxContext* aRenderingContext, mozilla::WritingMode aWM,
238       const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
239       const mozilla::LogicalSize& aMargin,
240       const mozilla::LogicalSize& aBorderPadding,
241       const mozilla::StyleSizeOverrides& aSizeOverrides,
242       mozilla::ComputeSizeFlags aFlags) override;
243 
244   /**
245    * Positions aKidFrame and its view (if requested), and then calls Reflow().
246    * If the reflow status after reflowing the child is FullyComplete then any
247    * next-in-flows are deleted using DeleteNextInFlowChild().
248    *
249    * @param aReflowInput the reflow input for aKidFrame.
250    * @param aWM aPos's writing-mode (any writing mode will do).
251    * @param aPos Position of the aKidFrame to be moved, in terms of aWM.
252    * @param aContainerSize Size of the border-box of the containing frame.
253    *
254    * Note: If ReflowChildFlags::NoMoveFrame is requested, both aPos and
255    * aContainerSize are ignored.
256    */
257   void ReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext,
258                    ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
259                    const mozilla::WritingMode& aWM,
260                    const mozilla::LogicalPoint& aPos,
261                    const nsSize& aContainerSize, ReflowChildFlags aFlags,
262                    nsReflowStatus& aStatus,
263                    nsOverflowContinuationTracker* aTracker = nullptr);
264 
265   /**
266    * The second half of frame reflow. Does the following:
267    * - sets the frame's bounds
268    * - sizes and positions (if requested) the frame's view. If the frame's final
269    *   position differs from the current position and the frame itself does not
270    *   have a view, then any child frames with views are positioned so they stay
271    *   in sync
272    * - sets the view's visibility, opacity, content transparency, and clip
273    * - invoked the DidReflow() function
274    *
275    * @param aReflowInput the reflow input for aKidFrame.
276    * @param aWM aPos's writing-mode (any writing mode will do).
277    * @param aPos Position of the aKidFrame to be moved, in terms of aWM.
278    * @param aContainerSize Size of the border-box of the containing frame.
279    *
280    * Note: If ReflowChildFlags::NoMoveFrame is requested, both aPos and
281    * aContainerSize are ignored unless
282    * ReflowChildFlags::ApplyRelativePositioning is requested.
283    */
284   static void FinishReflowChild(
285       nsIFrame* aKidFrame, nsPresContext* aPresContext,
286       const ReflowOutput& aDesiredSize, const ReflowInput* aReflowInput,
287       const mozilla::WritingMode& aWM, const mozilla::LogicalPoint& aPos,
288       const nsSize& aContainerSize, ReflowChildFlags aFlags);
289 
290   // XXX temporary: hold on to a copy of the old physical versions of
291   //    ReflowChild and FinishReflowChild so that we can convert callers
292   //    incrementally.
293   void ReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext,
294                    ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
295                    nscoord aX, nscoord aY, ReflowChildFlags aFlags,
296                    nsReflowStatus& aStatus,
297                    nsOverflowContinuationTracker* aTracker = nullptr);
298 
299   static void FinishReflowChild(nsIFrame* aKidFrame,
300                                 nsPresContext* aPresContext,
301                                 const ReflowOutput& aDesiredSize,
302                                 const ReflowInput* aReflowInput, nscoord aX,
303                                 nscoord aY, ReflowChildFlags aFlags);
304 
305   static void PositionChildViews(nsIFrame* aFrame);
306 
307   // ==========================================================================
308   /* Overflow containers are continuation frames that hold overflow. They
309    * are created when the frame runs out of computed block-size, but still has
310    * too much content to fit in the AvailableBSize. The parent creates a
311    * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
312    * and adds it to its next-in-flow's overflow container list, either by
313    * adding it directly or by putting it in its own excess overflow containers
314    * list (to be drained by the next-in-flow when it calls
315    * ReflowOverflowContainerChildren). The parent continues reflow as if
316    * the frame was complete once it ran out of computed block-size, but returns
317    * a reflow status with either IsIncomplete() or IsOverflowIncomplete() equal
318    * to true to request a next-in-flow. The parent's next-in-flow is then
319    * responsible for calling ReflowOverflowContainerChildren to (drain and)
320    * reflow these overflow continuations. Overflow containers do not affect
321    * other frames' size or position during reflow (but do affect their
322    * parent's overflow area).
323    *
324    * Overflow container continuations are different from normal continuations
325    * in that
326    *   - more than one child of the frame can have its next-in-flow broken
327    *     off and pushed into the frame's next-in-flow
328    *   - new continuations may need to be spliced into the middle of the list
329    *     or deleted continuations slipped out
330    *     e.g. A, B, C are all fixed-size containers on one page, all have
331    *      overflow beyond AvailableBSize, and content is dynamically added
332    *      and removed from B
333    * As a result, it is not possible to simply prepend the new continuations
334    * to the old list as with the OverflowProperty mechanism. To avoid
335    * complicated list splicing, the code assumes only one overflow containers
336    * list exists for a given frame: either its own OverflowContainersProperty
337    * or its prev-in-flow's ExcessOverflowContainersProperty, not both.
338    *
339    * The nsOverflowContinuationTracker helper class should be used for tracking
340    * overflow containers and adding them to the appropriate list.
341    * See nsBlockFrame::Reflow for a sample implementation.
342    *
343    * For more information, see https://wiki.mozilla.org/Gecko:Continuation_Model
344    *
345    * Note that Flex/GridContainerFrame doesn't use nsOverflowContinuationTracker
346    * so the above doesn't apply.  Flex/Grid containers may have items that
347    * aren't in document order between fragments, due to the 'order' property,
348    * but they do maintain the invariant that children in the same nsFrameList
349    * are in document order.  This means that when pushing/pulling items or
350    * merging lists, the result needs to be sorted to restore the order.
351    * However, given that lists are individually sorted, it's a simple merge
352    * operation of the two lists to make the result sorted.
353    * DrainExcessOverflowContainersList takes a merging function to perform that
354    * operation.  (By "document order" here we mean normal frame tree order,
355    * which is approximately flattened DOM tree order.)
356    */
357 
358   friend class nsOverflowContinuationTracker;
359 
360   typedef void (*ChildFrameMerger)(nsFrameList& aDest, nsFrameList& aSrc,
361                                    nsContainerFrame* aParent);
DefaultChildFrameMerge(nsFrameList & aDest,nsFrameList & aSrc,nsContainerFrame * aParent)362   static inline void DefaultChildFrameMerge(nsFrameList& aDest,
363                                             nsFrameList& aSrc,
364                                             nsContainerFrame* aParent) {
365     aDest.AppendFrames(nullptr, aSrc);
366   }
367 
368   /**
369    * Reflow overflow container children. They are invisible to normal reflow
370    * (i.e. don't affect sizing or placement of other children) and inherit
371    * width and horizontal position from their prev-in-flow.
372    *
373    * This method
374    *   1. Pulls excess overflow containers from the prev-in-flow and adds
375    *      them to our overflow container list
376    *   2. Reflows all our overflow container kids
377    *   3. Expands aOverflowRect as necessary to accomodate these children.
378    *   4. Sets aStatus's mOverflowIncomplete flag (along with
379    *      mNextInFlowNeedsReflow as necessary) if any overflow children
380    *      are incomplete and
381    *   5. Prepends a list of their continuations to our excess overflow
382    *      container list, to be drained into our next-in-flow when it is
383    *      reflowed.
384    *
385    * The caller is responsible for tracking any new overflow container
386    * continuations it makes, removing them from its child list, and
387    * making sure they are stored properly in the overflow container lists.
388    * The nsOverflowContinuationTracker helper class should be used for this.
389    *
390    * @param aFlags is passed through to ReflowChild
391    * @param aMergeFunc is passed to DrainExcessOverflowContainersList
392    * @param aContainerSize is used only for converting logical coordinate to
393    *        physical coordinate. If a tentative container size is used, caller
394    *        may need to adjust the position of our overflow container children
395    *        once the real size is known if our writing mode is vertical-rl.
396    */
397   void ReflowOverflowContainerChildren(
398       nsPresContext* aPresContext, const ReflowInput& aReflowInput,
399       mozilla::OverflowAreas& aOverflowRects, ReflowChildFlags aFlags,
400       nsReflowStatus& aStatus,
401       ChildFrameMerger aMergeFunc = DefaultChildFrameMerge,
402       Maybe<nsSize> aContainerSize = Nothing());
403 
404   /**
405    * Move any frames on our overflow list to the end of our principal list.
406    * @return true if there were any overflow frames
407    */
408   virtual bool DrainSelfOverflowList() override;
409 
410   /**
411    * Move all frames on our prev-in-flow's and our own ExcessOverflowContainers
412    * lists to our OverflowContainers list.  If there are frames on multiple
413    * lists they are merged using aMergeFunc.
414    * @return a pointer to our OverflowContainers list, if any
415    */
416   nsFrameList* DrainExcessOverflowContainersList(
417       ChildFrameMerger aMergeFunc = DefaultChildFrameMerge);
418 
419   /**
420    * Removes aChild without destroying it and without requesting reflow.
421    * Continuations are not affected.  Checks the principal and overflow lists,
422    * and also the [excess] overflow containers lists if the frame bit
423    * NS_FRAME_IS_OVERFLOW_CONTAINER is set.  It does not check any other lists.
424    * aChild must be in one of the above mentioned lists, or an assertion is
425    * triggered.
426    *
427    * Note: This method can destroy either overflow list or [excess] overflow
428    * containers list if aChild is the only child in the list. Any pointer to the
429    * list obtained prior to calling this method shouldn't be used.
430    */
431   virtual void StealFrame(nsIFrame* aChild);
432 
433   /**
434    * Removes the next-siblings of aChild without destroying them and without
435    * requesting reflow. Checks the principal and overflow lists (not
436    * overflow containers / excess overflow containers). Does not check any
437    * other auxiliary lists.
438    * @param aChild a child frame or nullptr
439    * @return If aChild is non-null, the next-siblings of aChild, if any.
440    *         If aChild is null, all child frames on the principal list, if any.
441    */
442   nsFrameList StealFramesAfter(nsIFrame* aChild);
443 
444   /**
445    * Add overflow containers to the display list
446    */
447   void DisplayOverflowContainers(nsDisplayListBuilder* aBuilder,
448                                  const nsDisplayListSet& aLists);
449 
450   /**
451    * Builds display lists for the children. The background
452    * of each child is placed in the Content() list (suitable for inline
453    * children and other elements that behave like inlines,
454    * but not for in-flow block children of blocks).  DOES NOT
455    * paint the background/borders/outline of this frame. This should
456    * probably be avoided and eventually removed. It's currently here
457    * to emulate what nsContainerFrame::Paint did.
458    */
459   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
460                                 const nsDisplayListSet& aLists) override;
461 
PlaceFrameView(nsIFrame * aFrame)462   static void PlaceFrameView(nsIFrame* aFrame) {
463     if (aFrame->HasView())
464       nsContainerFrame::PositionFrameView(aFrame);
465     else
466       nsContainerFrame::PositionChildViews(aFrame);
467   }
468 
469   /**
470    * Returns a CSS Box Alignment constant which the caller can use to align
471    * the absolutely-positioned child (whose ReflowInput is aChildRI) within
472    * a CSS Box Alignment area associated with this container.
473    *
474    * The lower 8 bits of the returned value are guaranteed to form a valid
475    * argument for CSSAlignUtils::AlignJustifySelf(). (The upper 8 bits may
476    * encode an <overflow-position>.)
477    *
478    * NOTE: This default nsContainerFrame implementation is a stub, and isn't
479    * meant to be called.  Subclasses must provide their own implementations, if
480    * they use CSS Box Alignment to determine the static position of their
481    * absolutely-positioned children. (Though: if subclasses share enough code,
482    * maybe this nsContainerFrame impl should include some shared code.)
483    *
484    * @param aChildRI A ReflowInput for the positioned child frame that's being
485    *                 aligned.
486    * @param aLogicalAxis The axis (of this container frame) in which the caller
487    *                     would like to align the child frame.
488    */
489   virtual mozilla::StyleAlignFlags CSSAlignmentForAbsPosChild(
490       const ReflowInput& aChildRI, mozilla::LogicalAxis aLogicalAxis) const;
491 
492 #define NS_DECLARE_FRAME_PROPERTY_FRAMELIST(prop) \
493   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, nsFrameList)
494 
495   using FrameListPropertyDescriptor =
496       mozilla::FrameProperties::Descriptor<nsFrameList>;
497 
498   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowProperty)
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)499   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)
500   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(ExcessOverflowContainersProperty)
501   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(BackdropProperty)
502 
503   // Only really used on nsBlockFrame instances, but the caller thinks it could
504   // have arbitrary nsContainerFrames.
505   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(FirstLetterProperty, nsIFrame)
506 
507   void SetHasFirstLetterChild() { mHasFirstLetterChild = true; }
508 
ClearHasFirstLetterChild()509   void ClearHasFirstLetterChild() { mHasFirstLetterChild = false; }
510 
511 #ifdef DEBUG
512   // Use this to suppress the ABSURD_SIZE assertions.
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize,bool)513   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize, bool)
514   bool IsAbsurdSizeAssertSuppressed() const {
515     return GetProperty(DebugReflowingWithInfiniteISize());
516   }
517 #endif
518 
519   // Incorporate the child overflow areas into aOverflowAreas.
520   // If the child does not have a overflow, use the child area.
521   void ConsiderChildOverflow(mozilla::OverflowAreas& aOverflowAreas,
522                              nsIFrame* aChildFrame);
523 
524  protected:
nsContainerFrame(ComputedStyle * aStyle,nsPresContext * aPresContext,ClassID aID)525   nsContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
526                    ClassID aID)
527       : nsSplittableFrame(aStyle, aPresContext, aID) {}
528 
529   ~nsContainerFrame();
530 
531   /**
532    * Helper for DestroyFrom. DestroyAbsoluteFrames is called before
533    * destroying frames on lists that can contain placeholders.
534    * Derived classes must do that too, if they destroy such frame lists.
535    * See nsBlockFrame::DestroyFrom for an example.
536    */
537   void DestroyAbsoluteFrames(nsIFrame* aDestructRoot,
538                              PostDestroyData& aPostDestroyData);
539 
540   /**
541    * Helper for StealFrame.  Returns true if aChild was removed from its list.
542    */
543   bool MaybeStealOverflowContainerFrame(nsIFrame* aChild);
544 
545   /**
546    * Builds a display list for non-block children that behave like
547    * inlines. This puts the background of each child into the
548    * Content() list (suitable for inline children but not for
549    * in-flow block children of blocks).
550    * @param aForcePseudoStack forces each child into a pseudo-stacking-context
551    * so its background and all other display items (except for positioned
552    * display items) go into the Content() list.
553    */
554   void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
555                                            const nsDisplayListSet& aLists,
556                                            DisplayChildFlags aFlags = {});
557 
558   /**
559    * A version of BuildDisplayList that use DisplayChildFlag::Inline.
560    * Intended as a convenience for derived classes.
561    */
BuildDisplayListForInline(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)562   void BuildDisplayListForInline(nsDisplayListBuilder* aBuilder,
563                                  const nsDisplayListSet& aLists) {
564     DisplayBorderBackgroundOutline(aBuilder, aLists);
565     BuildDisplayListForNonBlockChildren(aBuilder, aLists,
566                                         DisplayChildFlag::Inline);
567   }
568 
569   // ==========================================================================
570   /* Overflow Frames are frames that did not fit and must be pulled by
571    * our next-in-flow during its reflow. (The same concept for overflow
572    * containers is called "excess frames". We should probably make the
573    * names match.)
574    */
575 
576   /**
577    * Get the frames on the overflow list, overflow containers list, or excess
578    * overflow containers list. Can return null if there are no frames in the
579    * list.
580    *
581    * The caller does NOT take ownership of the list; it's still owned by this
582    * frame. A non-null return value indicates that the list is non-empty.
583    */
GetOverflowFrames()584   [[nodiscard]] nsFrameList* GetOverflowFrames() const {
585     nsFrameList* list = GetProperty(OverflowProperty());
586     NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
587     return list;
588   }
GetOverflowContainers()589   [[nodiscard]] nsFrameList* GetOverflowContainers() const {
590     nsFrameList* list = GetProperty(OverflowContainersProperty());
591     NS_ASSERTION(!list || !list->IsEmpty(),
592                  "Unexpected empty overflow containers list");
593     return list;
594   }
GetExcessOverflowContainers()595   [[nodiscard]] nsFrameList* GetExcessOverflowContainers() const {
596     nsFrameList* list = GetProperty(ExcessOverflowContainersProperty());
597     NS_ASSERTION(!list || !list->IsEmpty(),
598                  "Unexpected empty overflow containers list");
599     return list;
600   }
601 
602   /**
603    * Same as the Get methods above, but also remove and the property from this
604    * frame.
605    *
606    * The caller is responsible for deleting nsFrameList and either passing
607    * ownership of the frames to someone else or destroying the frames. A
608    * non-null return value indicates that the list is non-empty. The recommended
609    * way to use this function it to assign its return value into an
610    * AutoFrameListPtr.
611    */
StealOverflowFrames()612   [[nodiscard]] nsFrameList* StealOverflowFrames() {
613     nsFrameList* list = TakeProperty(OverflowProperty());
614     NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
615     return list;
616   }
StealOverflowContainers()617   [[nodiscard]] nsFrameList* StealOverflowContainers() {
618     nsFrameList* list = TakeProperty(OverflowContainersProperty());
619     NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
620     return list;
621   }
StealExcessOverflowContainers()622   [[nodiscard]] nsFrameList* StealExcessOverflowContainers() {
623     nsFrameList* list = TakeProperty(ExcessOverflowContainersProperty());
624     NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
625     return list;
626   }
627 
628   /**
629    * Set the overflow list, overflow containers list, or excess overflow
630    * containers list. The argument must be a *non-empty* list.
631    *
632    * After this operation, the argument becomes an empty list.
633    *
634    * @return the frame list associated with the property.
635    */
SetOverflowFrames(nsFrameList && aOverflowFrames)636   nsFrameList* SetOverflowFrames(nsFrameList&& aOverflowFrames) {
637     MOZ_ASSERT(aOverflowFrames.NotEmpty(), "Shouldn't be called");
638     auto* list = new (PresShell()) nsFrameList(std::move(aOverflowFrames));
639     SetProperty(OverflowProperty(), list);
640     return list;
641   }
SetOverflowContainers(nsFrameList && aOverflowContainers)642   nsFrameList* SetOverflowContainers(nsFrameList&& aOverflowContainers) {
643     MOZ_ASSERT(aOverflowContainers.NotEmpty(), "Shouldn't set an empty list!");
644     MOZ_ASSERT(!GetProperty(OverflowContainersProperty()),
645                "Shouldn't override existing list!");
646     MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
647                "This type of frame can't have overflow containers!");
648     auto* list = new (PresShell()) nsFrameList(std::move(aOverflowContainers));
649     SetProperty(OverflowContainersProperty(), list);
650     return list;
651   }
SetExcessOverflowContainers(nsFrameList && aExcessOverflowContainers)652   nsFrameList* SetExcessOverflowContainers(
653       nsFrameList&& aExcessOverflowContainers) {
654     MOZ_ASSERT(aExcessOverflowContainers.NotEmpty(),
655                "Shouldn't set an empty list!");
656     MOZ_ASSERT(!GetProperty(ExcessOverflowContainersProperty()),
657                "Shouldn't override existing list!");
658     MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
659                "This type of frame can't have overflow containers!");
660     auto* list =
661         new (PresShell()) nsFrameList(std::move(aExcessOverflowContainers));
662     SetProperty(ExcessOverflowContainersProperty(), list);
663     return list;
664   }
665 
666   /**
667    * Destroy the overflow list, overflow containers list, or excess overflow
668    * containers list.
669    *
670    * The list to be destroyed must be empty. That is, the caller is responsible
671    * for either passing ownership of the frames to someone else or destroying
672    * the frames before calling these methods.
673    */
DestroyOverflowList()674   void DestroyOverflowList() {
675     nsFrameList* list = TakeProperty(OverflowProperty());
676     MOZ_ASSERT(list && list->IsEmpty());
677     list->Delete(PresShell());
678   }
DestroyOverflowContainers()679   void DestroyOverflowContainers() {
680     nsFrameList* list = TakeProperty(OverflowContainersProperty());
681     MOZ_ASSERT(list && list->IsEmpty());
682     list->Delete(PresShell());
683   }
DestroyExcessOverflowContainers()684   void DestroyExcessOverflowContainers() {
685     nsFrameList* list = TakeProperty(ExcessOverflowContainersProperty());
686     MOZ_ASSERT(list && list->IsEmpty());
687     list->Delete(PresShell());
688   }
689 
690   /**
691    * Moves any frames on both the prev-in-flow's overflow list and the
692    * receiver's overflow to the receiver's child list.
693    *
694    * Resets the overlist pointers to nullptr, and updates the receiver's child
695    * count and content mapping.
696    *
697    * @return true if any frames were moved and false otherwise
698    */
699   bool MoveOverflowToChildList();
700 
701   /**
702    * Merge a sorted frame list into our overflow list. aList becomes empty after
703    * this call.
704    */
705   void MergeSortedOverflow(nsFrameList& aList);
706 
707   /**
708    * Merge a sorted frame list into our excess overflow containers list. aList
709    * becomes empty after this call.
710    */
711   void MergeSortedExcessOverflowContainers(nsFrameList& aList);
712 
713   /**
714    * Moves all frames from aSrc into aDest such that the resulting aDest
715    * is still sorted in document content order and continuation order. aSrc
716    * becomes empty after this call.
717    *
718    * Precondition: both |aSrc| and |aDest| must be sorted to begin with.
719    * @param aCommonAncestor a hint for nsLayoutUtils::CompareTreePosition
720    */
721   static void MergeSortedFrameLists(nsFrameList& aDest, nsFrameList& aSrc,
722                                     nsIContent* aCommonAncestor);
723 
724   /**
725    * This is intended to be used as a ChildFrameMerger argument for
726    * ReflowOverflowContainerChildren() and DrainExcessOverflowContainersList().
727    */
MergeSortedFrameListsFor(nsFrameList & aDest,nsFrameList & aSrc,nsContainerFrame * aParent)728   static inline void MergeSortedFrameListsFor(nsFrameList& aDest,
729                                               nsFrameList& aSrc,
730                                               nsContainerFrame* aParent) {
731     MergeSortedFrameLists(aDest, aSrc, aParent->GetContent());
732   }
733 
734   /**
735    * Basically same as MoveOverflowToChildList, except that this is for
736    * handling inline children where children of prev-in-flow can be
737    * pushed to overflow list even if a next-in-flow exists.
738    *
739    * @param aLineContainer the line container of the current frame.
740    *
741    * @return true if any frames were moved and false otherwise
742    */
743   bool MoveInlineOverflowToChildList(nsIFrame* aLineContainer);
744 
745   /**
746    * Push aFromChild and its next siblings to the overflow list.
747    *
748    * @param aFromChild the first child frame to push. It is disconnected
749    *          from aPrevSibling
750    * @param aPrevSibling aFrameChild's previous sibling. Must not be null.
751    *          It's an error to push a parent's first child frame.
752    */
753   void PushChildrenToOverflow(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
754 
755   /**
756    * Same as above, except that this pushes frames to the next-in-flow
757    * frame and changes the geometric parent of the pushed frames when
758    * there is a next-in-flow frame.
759    *
760    * Updates the next-in-flow's child count. Does <b>not</b> update the
761    * pusher's child count.
762    */
763   void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
764 
765   /**
766    * Iterate our children in our principal child list in the normal document
767    * order, and append them (or their next-in-flows) to either our overflow list
768    * or excess overflow container list according to their presence in
769    * aPushedItems, aIncompleteItems, or aOverflowIncompleteItems.
770    *
771    * Note: This method is only intended for Grid / Flex containers.
772    * aPushedItems, aIncompleteItems, and aOverflowIncompleteItems are expected
773    * to contain only Grid / Flex items. That is, they should contain only
774    * in-flow children.
775    *
776    * @return true if any items are moved; false otherwise.
777    */
778   using FrameHashtable = nsTHashSet<nsIFrame*>;
779   bool PushIncompleteChildren(const FrameHashtable& aPushedItems,
780                               const FrameHashtable& aIncompleteItems,
781                               const FrameHashtable& aOverflowIncompleteItems);
782 
783   /**
784    * Prepare our child lists so that they are ready to reflow by the following
785    * operations:
786    *
787    * - Merge overflow list from our prev-in-flow into our principal child list.
788    * - Merge our own overflow list into our principal child list,
789    * - Push any child's next-in-flows in our principal child list to our
790    *   overflow list.
791    * - Pull up any first-in-flow child we might have pushed from our
792    *   next-in-flows.
793    */
794   void NormalizeChildLists();
795 
796   /**
797    * Helper to implement AppendFrames / InsertFrames for flex / grid
798    * containers.
799    */
800   void NoteNewChildren(ChildListID aListID, const nsFrameList& aFrameList);
801 
802   /**
803    * Helper to implement DrainSelfOverflowList() for flex / grid containers.
804    */
805   bool DrainAndMergeSelfOverflowList();
806 
807   /**
808    * Helper to find the first non-anonymous-box frame in the subtree rooted at
809    * aFrame.
810    */
811   static nsIFrame* GetFirstNonAnonBoxInSubtree(nsIFrame* aFrame);
812 
813   /**
814    * Reparent floats whose placeholders are inline descendants of aFrame from
815    * whatever block they're currently parented by to aOurBlock.
816    * @param aReparentSiblings if this is true, we follow aFrame's
817    * GetNextSibling chain reparenting them all
818    */
819   static void ReparentFloatsForInlineChild(nsIFrame* aOurBlock,
820                                            nsIFrame* aFrame,
821                                            bool aReparentSiblings);
822 
823   /**
824    * Try to remove aChildToRemove from the frame list stored in aProp.
825    * If aChildToRemove was removed from the aProp list and that list became
826    * empty, then aProp is removed from this frame and deleted.
827    * @note if aChildToRemove isn't on the aProp frame list, it might still be
828    * removed from whatever list it happens to be on, so use this method
829    * carefully.  This method is primarily meant for removing frames from the
830    * [Excess]OverflowContainers lists.
831    * @return true if aChildToRemove was removed from some list
832    */
833   bool TryRemoveFrame(FrameListPropertyDescriptor aProp,
834                       nsIFrame* aChildToRemove);
835 
836   // ==========================================================================
837   /*
838    * Convenience methods for traversing continuations
839    */
840 
841   struct ContinuationTraversingState {
842     nsContainerFrame* mNextInFlow;
ContinuationTraversingStateContinuationTraversingState843     explicit ContinuationTraversingState(nsContainerFrame* aFrame)
844         : mNextInFlow(static_cast<nsContainerFrame*>(aFrame->GetNextInFlow())) {
845     }
846   };
847 
848   /**
849    * Find the first frame that is a child of this frame's next-in-flows,
850    * considering both their principal child lists and overflow lists.
851    */
852   nsIFrame* GetNextInFlowChild(ContinuationTraversingState& aState,
853                                bool* aIsInOverflow = nullptr);
854 
855   /**
856    * Remove the result of GetNextInFlowChild from its current parent and
857    * append it to this frame's principal child list.
858    */
859   nsIFrame* PullNextInFlowChild(ContinuationTraversingState& aState);
860 
861   /**
862    * Safely destroy the frames on the nsFrameList stored on aProp for this
863    * frame then remove the property and delete the frame list.
864    * Nothing happens if the property doesn't exist.
865    */
866   void SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
867                                   PostDestroyData& aPostDestroyData,
868                                   mozilla::PresShell* aPresShell,
869                                   FrameListPropertyDescriptor aProp);
870 
871   // ==========================================================================
872 
873   // Helper used by Progress and Meter frames. Returns true if the bar should
874   // be rendered vertically, based on writing-mode and -moz-orient properties.
875   bool ResolvedOrientationIsVertical();
876 
877   /**
878    * Calculate the used values for 'width' and 'height' for a replaced element.
879    *   http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
880    *
881    * @param aAspectRatio the aspect ratio calculated by GetAspectRatio().
882    */
883   mozilla::LogicalSize ComputeSizeWithIntrinsicDimensions(
884       gfxContext* aRenderingContext, mozilla::WritingMode aWM,
885       const mozilla::IntrinsicSize& aIntrinsicSize,
886       const mozilla::AspectRatio& aAspectRatio,
887       const mozilla::LogicalSize& aCBSize, const mozilla::LogicalSize& aMargin,
888       const mozilla::LogicalSize& aBorderPadding,
889       const mozilla::StyleSizeOverrides& aSizeOverrides,
890       mozilla::ComputeSizeFlags aFlags);
891 
892   // Compute tight bounds assuming this frame honours its border, background
893   // and outline, its children's tight bounds, and nothing else.
894   nsRect ComputeSimpleTightBounds(mozilla::gfx::DrawTarget* aDrawTarget) const;
895 
896   /*
897    * If this frame is dirty, marks all absolutely-positioned children of this
898    * frame dirty. If this frame isn't dirty, or if there are no
899    * absolutely-positioned children, does nothing.
900    *
901    * It's necessary to use PushDirtyBitToAbsoluteFrames() when you plan to
902    * reflow this frame's absolutely-positioned children after the dirty bit on
903    * this frame has already been cleared, which prevents ReflowInput from
904    * propagating the dirty bit normally. This situation generally only arises
905    * when a multipass layout algorithm is used.
906    */
907   void PushDirtyBitToAbsoluteFrames();
908 
909   // Helper function that tests if the frame tree is too deep; if it is
910   // it marks the frame as "unflowable", zeroes out the metrics, sets
911   // the reflow status, and returns true. Otherwise, the frame is
912   // unmarked "unflowable" and the metrics and reflow status are not
913   // touched and false is returned.
914   bool IsFrameTreeTooDeep(const ReflowInput& aReflowInput,
915                           ReflowOutput& aMetrics, nsReflowStatus& aStatus);
916 
917   /**
918    * @return true if we should avoid a page/column break in this frame.
919    */
920   bool ShouldAvoidBreakInside(const ReflowInput& aReflowInput) const;
921 
922   /**
923    * To be called by |BuildDisplayLists| of this class or derived classes to add
924    * a translucent overlay if this frame's content is selected.
925    * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
926    * which kind of content this is for
927    */
928   void DisplaySelectionOverlay(
929       nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
930       uint16_t aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
931 
932   // ==========================================================================
933 
934 #ifdef DEBUG
935   // A helper for flex / grid container to sanity check child lists before
936   // reflow. Intended to be called after calling NormalizeChildLists().
937   void SanityCheckChildListsBeforeReflow() const;
938 
939   // A helper to set mDidPushItemsBitMayLie if needed. Intended to be called
940   // only in flex / grid container's RemoveFrame.
941   void SetDidPushItemsBitIfNeeded(ChildListID aListID, nsIFrame* aOldFrame);
942 
943   // A flag for flex / grid containers. If true, NS_STATE_GRID_DID_PUSH_ITEMS or
944   // NS_STATE_FLEX_DID_PUSH_ITEMS may be set even though all pushed frames may
945   // have been removed. This is used to suppress an assertion in case
946   // RemoveFrame removed all associated child frames.
947   bool mDidPushItemsBitMayLie{false};
948 #endif
949 
950   nsFrameList mFrames;
951 };
952 
953 // ==========================================================================
954 /* The out-of-flow-related code below is for a hacky way of splitting
955  * absolutely-positioned frames. Basically what we do is split the frame
956  * in nsAbsoluteContainingBlock and pretend the continuation is an overflow
957  * container. This isn't an ideal solution, but it lets us print the content
958  * at least. See bug 154892.
959  */
960 
961 /**
962  * Helper class for tracking overflow container continuations during reflow.
963  *
964  * A frame is related to two sets of overflow containers: those that /are/
965  * its own children, and those that are /continuations/ of its children.
966  * This tracker walks through those continuations (the frame's NIF's children)
967  * and their prev-in-flows (a subset of the frame's normal and overflow
968  * container children) in parallel. It allows the reflower to synchronously
969  * walk its overflow continuations while it loops through and reflows its
970  * children. This makes it possible to insert new continuations at the correct
971  * place in the overflow containers list.
972  *
973  * The reflower is expected to loop through its children in the same order it
974  * looped through them the last time (if there was a last time).
975  * For each child, the reflower should either
976  *   - call Skip for the child if was not reflowed in this pass
977  *   - call Insert for the overflow continuation if the child was reflowed
978  *     but has incomplete overflow
979  *   - call Finished for the child if it was reflowed in this pass but
980  *     is either complete or has a normal next-in-flow. This call can
981  *     be skipped if the child did not previously have an overflow
982  *     continuation.
983  */
984 class nsOverflowContinuationTracker {
985  public:
986   /**
987    * Initializes an nsOverflowContinuationTracker to help track overflow
988    * continuations of aFrame's children. Typically invoked on 'this'.
989    *
990    * aWalkOOFFrames determines whether the walker skips out-of-flow frames
991    * or skips non-out-of-flow frames.
992    *
993    * Don't set aSkipOverflowContainerChildren to false unless you plan
994    * to walk your own overflow container children. (Usually they are handled
995    * by calling ReflowOverflowContainerChildren.) aWalkOOFFrames is ignored
996    * if aSkipOverflowContainerChildren is false.
997    */
998   nsOverflowContinuationTracker(nsContainerFrame* aFrame, bool aWalkOOFFrames,
999                                 bool aSkipOverflowContainerChildren = true);
1000   /**
1001    * This function adds an overflow continuation to our running list and
1002    * sets its NS_FRAME_IS_OVERFLOW_CONTAINER flag.
1003    *
1004    * aReflowStatus should preferably be specific to the recently-reflowed
1005    * child and not influenced by any of its siblings' statuses. This
1006    * function sets the NS_FRAME_IS_DIRTY bit on aOverflowCont if it needs
1007    * to be reflowed. (Its need for reflow depends on changes to its
1008    * prev-in-flow, not to its parent--for whom it is invisible, reflow-wise.)
1009    *
1010    * The caller MUST disconnect the frame from its parent's child list
1011    * if it was not previously an NS_FRAME_IS_OVERFLOW_CONTAINER (because
1012    * StealFrame is much more inefficient than disconnecting in place
1013    * during Reflow, which the caller is able to do but we are not).
1014    *
1015    * The caller MUST NOT disconnect the frame from its parent's
1016    * child list if it is already an NS_FRAME_IS_OVERFLOW_CONTAINER.
1017    * (In this case we will disconnect and reconnect it ourselves.)
1018    */
1019   nsresult Insert(nsIFrame* aOverflowCont, nsReflowStatus& aReflowStatus);
1020   /**
1021    * Begin/EndFinish() must be called for each child that is reflowed
1022    * but no longer has an overflow continuation. (It may be called for
1023    * other children, but in that case has no effect.) It increments our
1024    * walker and makes sure we drop any dangling pointers to its
1025    * next-in-flow. This function MUST be called before stealing or
1026    * deleting aChild's next-in-flow.
1027    * The AutoFinish helper object does that for you. Use it like so:
1028    * if (kidNextInFlow) {
1029    *   nsOverflowContinuationTracker::AutoFinish fini(tracker, kid);
1030    *   ... DeleteNextInFlowChild/StealFrame(kidNextInFlow) here ...
1031    * }
1032    */
1033   class MOZ_RAII AutoFinish {
1034    public:
AutoFinish(nsOverflowContinuationTracker * aTracker,nsIFrame * aChild)1035     AutoFinish(nsOverflowContinuationTracker* aTracker, nsIFrame* aChild)
1036         : mTracker(aTracker), mChild(aChild) {
1037       if (mTracker) mTracker->BeginFinish(mChild);
1038     }
~AutoFinish()1039     ~AutoFinish() {
1040       if (mTracker) mTracker->EndFinish(mChild);
1041     }
1042 
1043    private:
1044     nsOverflowContinuationTracker* mTracker;
1045     nsIFrame* mChild;
1046   };
1047 
1048   /**
1049    * This function should be called for each child that isn't reflowed.
1050    * It increments our walker and sets the mOverflowIncomplete
1051    * reflow flag if it encounters an overflow continuation so that our
1052    * next-in-flow doesn't get prematurely deleted. It MUST be called on
1053    * each unreflowed child that has an overflow container continuation;
1054    * it MAY be called on other children, but it isn't necessary (doesn't
1055    * do anything).
1056    */
Skip(nsIFrame * aChild,nsReflowStatus & aReflowStatus)1057   void Skip(nsIFrame* aChild, nsReflowStatus& aReflowStatus) {
1058     MOZ_ASSERT(aChild, "null ptr");
1059     if (aChild == mSentry) {
1060       StepForward();
1061       if (aReflowStatus.IsComplete()) {
1062         aReflowStatus.SetOverflowIncomplete();
1063       }
1064     }
1065   }
1066 
1067  private:
1068   /**
1069    * @see class AutoFinish
1070    */
1071   void BeginFinish(nsIFrame* aChild);
1072   void EndFinish(nsIFrame* aChild);
1073 
1074   void SetupOverflowContList();
1075   void SetUpListWalker();
1076   void StepForward();
1077 
1078   /* We hold a pointer to either the next-in-flow's overflow containers list
1079      or, if that doesn't exist, our frame's excess overflow containers list.
1080      We need to make sure that we drop that pointer if the list becomes
1081      empty and is deleted elsewhere. */
1082   nsFrameList* mOverflowContList;
1083   /* We hold a pointer to the most recently-reflowed child that has an
1084      overflow container next-in-flow. We do this because it's a known
1085      good point; this pointer won't be deleted on us. We can use it to
1086      recover our place in the list. */
1087   nsIFrame* mPrevOverflowCont;
1088   /* This is a pointer to the next overflow container's prev-in-flow, which
1089      is (or should be) a child of our frame. When we hit this, we will need
1090      to increment this walker to the next overflow container. */
1091   nsIFrame* mSentry;
1092   /* Parent of all frames in mOverflowContList. If our mOverflowContList
1093      is an excessOverflowContainersProperty, or null, then this is our frame
1094      (the frame that was passed in to our constructor). Otherwise this is
1095      that frame's next-in-flow, and our mOverflowContList is mParent's
1096      overflowContainersProperty */
1097   nsContainerFrame* mParent;
1098   /* Tells SetUpListWalker whether or not to walk us past any continuations
1099      of overflow containers. aWalkOOFFrames is ignored when this is false. */
1100   bool mSkipOverflowContainerChildren;
1101   /* Tells us whether to pay attention to OOF frames or non-OOF frames */
1102   bool mWalkOOFFrames;
1103 };
1104 
1105 // Start Display Reflow Debugging
1106 #ifdef DEBUG
1107 
1108 struct DR_cookie {
1109   DR_cookie(nsPresContext* aPresContext, nsIFrame* aFrame,
1110             const mozilla::ReflowInput& aReflowInput,
1111             mozilla::ReflowOutput& aMetrics, nsReflowStatus& aStatus);
1112   ~DR_cookie();
1113   void Change() const;
1114 
1115   nsPresContext* mPresContext;
1116   nsIFrame* mFrame;
1117   const mozilla::ReflowInput& mReflowInput;
1118   mozilla::ReflowOutput& mMetrics;
1119   nsReflowStatus& mStatus;
1120   void* mValue;
1121 };
1122 
1123 struct DR_layout_cookie {
1124   explicit DR_layout_cookie(nsIFrame* aFrame);
1125   ~DR_layout_cookie();
1126 
1127   nsIFrame* mFrame;
1128   void* mValue;
1129 };
1130 
1131 struct DR_intrinsic_inline_size_cookie {
1132   DR_intrinsic_inline_size_cookie(nsIFrame* aFrame, const char* aType,
1133                                   nscoord& aResult);
1134   ~DR_intrinsic_inline_size_cookie();
1135 
1136   nsIFrame* mFrame;
1137   const char* mType;
1138   nscoord& mResult;
1139   void* mValue;
1140 };
1141 
1142 struct DR_intrinsic_size_cookie {
1143   DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
1144                            nsSize& aResult);
1145   ~DR_intrinsic_size_cookie();
1146 
1147   nsIFrame* mFrame;
1148   const char* mType;
1149   nsSize& mResult;
1150   void* mValue;
1151 };
1152 
1153 struct DR_init_constraints_cookie {
1154   DR_init_constraints_cookie(
1155       nsIFrame* aFrame, mozilla::ReflowInput* aState, nscoord aCBWidth,
1156       nscoord aCBHeight, const mozilla::Maybe<mozilla::LogicalMargin> aBorder,
1157       const mozilla::Maybe<mozilla::LogicalMargin> aPadding);
1158   ~DR_init_constraints_cookie();
1159 
1160   nsIFrame* mFrame;
1161   mozilla::ReflowInput* mState;
1162   void* mValue;
1163 };
1164 
1165 struct DR_init_offsets_cookie {
1166   DR_init_offsets_cookie(nsIFrame* aFrame,
1167                          mozilla::SizeComputationInput* aState,
1168                          nscoord aPercentBasis,
1169                          mozilla::WritingMode aCBWritingMode,
1170                          const mozilla::Maybe<mozilla::LogicalMargin> aBorder,
1171                          const mozilla::Maybe<mozilla::LogicalMargin> aPadding);
1172   ~DR_init_offsets_cookie();
1173 
1174   nsIFrame* mFrame;
1175   mozilla::SizeComputationInput* mState;
1176   void* mValue;
1177 };
1178 
1179 #  define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state,               \
1180                          dr_rf_metrics, dr_rf_status)                          \
1181     DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, \
1182                         dr_rf_status);
1183 #  define DISPLAY_REFLOW_CHANGE() dr_cookie.Change();
1184 #  define DISPLAY_LAYOUT(dr_frame) DR_layout_cookie dr_cookie(dr_frame);
1185 #  define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
1186     DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Min", dr_result)
1187 #  define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
1188     DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
1189 #  define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
1190     DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
1191 #  define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
1192     DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
1193 #  define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
1194     DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
1195 #  define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \
1196                                    dr_pad)                                     \
1197     DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh,   \
1198                                          dr_bdr, dr_pad)
1199 #  define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
1200                                dr_pad)                                     \
1201     DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_cbwm,   \
1202                                      dr_bdr, dr_pad)
1203 
1204 #else
1205 
1206 #  define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, \
1207                          dr_rf_metrics, dr_rf_status)
1208 #  define DISPLAY_REFLOW_CHANGE()
1209 #  define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
1210 #  define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
1211     PR_BEGIN_MACRO PR_END_MACRO
1212 #  define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
1213     PR_BEGIN_MACRO PR_END_MACRO
1214 #  define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1215 #  define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1216 #  define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1217 #  define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \
1218                                    dr_pad)                                     \
1219     PR_BEGIN_MACRO PR_END_MACRO
1220 #  define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
1221                                dr_pad)                                     \
1222     PR_BEGIN_MACRO PR_END_MACRO
1223 
1224 #endif
1225 // End Display Reflow Debugging
1226 
1227 #endif /* nsContainerFrame_h___ */
1228