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