1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsContainerFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,708 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* base class #1 for rendering objects that have child lists */ 1.10 + 1.11 +#ifndef nsContainerFrame_h___ 1.12 +#define nsContainerFrame_h___ 1.13 + 1.14 +#include "mozilla/Attributes.h" 1.15 +#include "nsSplittableFrame.h" 1.16 +#include "nsFrameList.h" 1.17 +#include "nsLayoutUtils.h" 1.18 + 1.19 +// Option flags for ReflowChild() and FinishReflowChild() 1.20 +// member functions 1.21 +#define NS_FRAME_NO_MOVE_VIEW 0x0001 1.22 +#define NS_FRAME_NO_MOVE_FRAME (0x0002 | NS_FRAME_NO_MOVE_VIEW) 1.23 +#define NS_FRAME_NO_SIZE_VIEW 0x0004 1.24 +#define NS_FRAME_NO_VISIBILITY 0x0008 1.25 +// Only applies to ReflowChild; if true, don't delete the next-in-flow, even 1.26 +// if the reflow is fully complete. 1.27 +#define NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD 0x0010 1.28 + 1.29 +class nsOverflowContinuationTracker; 1.30 +namespace mozilla { 1.31 +class FramePropertyTable; 1.32 +} 1.33 + 1.34 +// Some macros for container classes to do sanity checking on 1.35 +// width/height/x/y values computed during reflow. 1.36 +// NOTE: AppUnitsPerCSSPixel value hardwired here to remove the 1.37 +// dependency on nsDeviceContext.h. It doesn't matter if it's a 1.38 +// little off. 1.39 +#ifdef DEBUG 1.40 +#define CRAZY_COORD (1000000*60) 1.41 +#define CRAZY_SIZE(_x) (((_x) < -CRAZY_COORD) || ((_x) > CRAZY_COORD)) 1.42 +#endif 1.43 + 1.44 +/** 1.45 + * Implementation of a container frame. 1.46 + */ 1.47 +class nsContainerFrame : public nsSplittableFrame 1.48 +{ 1.49 +public: 1.50 + NS_DECL_FRAMEARENA_HELPERS 1.51 + NS_DECL_QUERYFRAME_TARGET(nsContainerFrame) 1.52 + NS_DECL_QUERYFRAME 1.53 + 1.54 + // nsIFrame overrides 1.55 + virtual void Init(nsIContent* aContent, 1.56 + nsIFrame* aParent, 1.57 + nsIFrame* aPrevInFlow) MOZ_OVERRIDE; 1.58 + virtual nsresult SetInitialChildList(ChildListID aListID, 1.59 + nsFrameList& aChildList) MOZ_OVERRIDE; 1.60 + virtual nsresult AppendFrames(ChildListID aListID, 1.61 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.62 + virtual nsresult InsertFrames(ChildListID aListID, 1.63 + nsIFrame* aPrevFrame, 1.64 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.65 + virtual nsresult RemoveFrame(ChildListID aListID, 1.66 + nsIFrame* aOldFrame) MOZ_OVERRIDE; 1.67 + 1.68 + virtual const nsFrameList& GetChildList(ChildListID aList) const MOZ_OVERRIDE; 1.69 + virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE; 1.70 + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; 1.71 + virtual void ChildIsDirty(nsIFrame* aChild) MOZ_OVERRIDE; 1.72 + 1.73 + virtual bool IsLeaf() const MOZ_OVERRIDE; 1.74 + virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE; 1.75 + virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset, 1.76 + bool aRespectClusters = true) MOZ_OVERRIDE; 1.77 + 1.78 +#ifdef DEBUG_FRAME_DUMP 1.79 + void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const MOZ_OVERRIDE; 1.80 +#endif 1.81 + 1.82 + // nsContainerFrame methods 1.83 + 1.84 + /** 1.85 + * Helper method to create next-in-flows if necessary. If aFrame 1.86 + * already has a next-in-flow then this method does 1.87 + * nothing. Otherwise, a new continuation frame is created and 1.88 + * linked into the flow. In addition, the new frame is inserted 1.89 + * into the principal child list after aFrame. 1.90 + * @note calling this method on a block frame is illegal. Use 1.91 + * nsBlockFrame::CreateContinuationFor() instead. 1.92 + * @param aNextInFlowResult will contain the next-in-flow 1.93 + * <b>if and only if</b> one is created. If a next-in-flow already 1.94 + * exists aNextInFlowResult is set to nullptr. 1.95 + * @return NS_OK if a next-in-flow already exists or is successfully created. 1.96 + */ 1.97 + nsresult CreateNextInFlow(nsIFrame* aFrame, nsIFrame*& aNextInFlowResult); 1.98 + 1.99 + /** 1.100 + * Delete aNextInFlow and its next-in-flows. 1.101 + * @param aDeletingEmptyFrames if set, then the reflow for aNextInFlow's 1.102 + * content was complete before aNextInFlow, so aNextInFlow and its 1.103 + * next-in-flows no longer map any real content. 1.104 + */ 1.105 + virtual void DeleteNextInFlowChild(nsIFrame* aNextInFlow, 1.106 + bool aDeletingEmptyFrames); 1.107 + 1.108 + /** 1.109 + * Helper method to wrap views around frames. Used by containers 1.110 + * under special circumstances (can be used by leaf frames as well) 1.111 + */ 1.112 + static void CreateViewForFrame(nsIFrame* aFrame, 1.113 + bool aForce); 1.114 + 1.115 + // Positions the frame's view based on the frame's origin 1.116 + static void PositionFrameView(nsIFrame* aKidFrame); 1.117 + 1.118 + static nsresult ReparentFrameView(nsIFrame* aChildFrame, 1.119 + nsIFrame* aOldParentFrame, 1.120 + nsIFrame* aNewParentFrame); 1.121 + 1.122 + static nsresult ReparentFrameViewList(const nsFrameList& aChildFrameList, 1.123 + nsIFrame* aOldParentFrame, 1.124 + nsIFrame* aNewParentFrame); 1.125 + 1.126 + // Set the view's size and position after its frame has been reflowed. 1.127 + // 1.128 + // Flags: 1.129 + // NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you 1.130 + // don't want to automatically sync the frame and view 1.131 + // NS_FRAME_NO_SIZE_VIEW - don't size the view 1.132 + static void SyncFrameViewAfterReflow(nsPresContext* aPresContext, 1.133 + nsIFrame* aFrame, 1.134 + nsView* aView, 1.135 + const nsRect& aVisualOverflowArea, 1.136 + uint32_t aFlags = 0); 1.137 + 1.138 + // Syncs properties to the top level view and window, like transparency and 1.139 + // shadow. 1.140 + static void SyncWindowProperties(nsPresContext* aPresContext, 1.141 + nsIFrame* aFrame, 1.142 + nsView* aView, 1.143 + nsRenderingContext* aRC = nullptr); 1.144 + 1.145 + // Sets the view's attributes from the frame style. 1.146 + // - visibility 1.147 + // - clip 1.148 + // Call this when one of these styles changes or when the view has just 1.149 + // been created. 1.150 + // @param aStyleContext can be null, in which case the frame's style context is used 1.151 + static void SyncFrameViewProperties(nsPresContext* aPresContext, 1.152 + nsIFrame* aFrame, 1.153 + nsStyleContext* aStyleContext, 1.154 + nsView* aView, 1.155 + uint32_t aFlags = 0); 1.156 + 1.157 + /** 1.158 + * Converts the minimum and maximum sizes given in inner window app units to 1.159 + * outer window device pixel sizes and assigns these constraints to the widget. 1.160 + * 1.161 + * @param aPresContext pres context 1.162 + * @param aWidget widget for this frame 1.163 + * @param minimum size of the window in app units 1.164 + * @param maxmimum size of the window in app units 1.165 + */ 1.166 + static void SetSizeConstraints(nsPresContext* aPresContext, 1.167 + nsIWidget* aWidget, 1.168 + const nsSize& aMinSize, 1.169 + const nsSize& aMaxSize); 1.170 + 1.171 + // Used by both nsInlineFrame and nsFirstLetterFrame. 1.172 + void DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext, 1.173 + InlineIntrinsicWidthData *aData, 1.174 + nsLayoutUtils::IntrinsicWidthType aType); 1.175 + 1.176 + /** 1.177 + * This is the CSS block concept of computing 'auto' widths, which most 1.178 + * classes derived from nsContainerFrame want. 1.179 + */ 1.180 + virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext, 1.181 + nsSize aCBSize, nscoord aAvailableWidth, 1.182 + nsSize aMargin, nsSize aBorder, 1.183 + nsSize aPadding, bool aShrinkWrap) MOZ_OVERRIDE; 1.184 + 1.185 + /** 1.186 + * Invokes the WillReflow() function, positions the frame and its view (if 1.187 + * requested), and then calls Reflow(). If the reflow succeeds and the child 1.188 + * frame is complete, deletes any next-in-flows using DeleteNextInFlowChild() 1.189 + * 1.190 + * Flags: 1.191 + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you 1.192 + * don't want to automatically sync the frame and view 1.193 + * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this 1.194 + * case. Also implies NS_FRAME_NO_MOVE_VIEW 1.195 + */ 1.196 + nsresult ReflowChild(nsIFrame* aKidFrame, 1.197 + nsPresContext* aPresContext, 1.198 + nsHTMLReflowMetrics& aDesiredSize, 1.199 + const nsHTMLReflowState& aReflowState, 1.200 + nscoord aX, 1.201 + nscoord aY, 1.202 + uint32_t aFlags, 1.203 + nsReflowStatus& aStatus, 1.204 + nsOverflowContinuationTracker* aTracker = nullptr); 1.205 + 1.206 + /** 1.207 + * The second half of frame reflow. Does the following: 1.208 + * - sets the frame's bounds 1.209 + * - sizes and positions (if requested) the frame's view. If the frame's final 1.210 + * position differs from the current position and the frame itself does not 1.211 + * have a view, then any child frames with views are positioned so they stay 1.212 + * in sync 1.213 + * - sets the view's visibility, opacity, content transparency, and clip 1.214 + * - invoked the DidReflow() function 1.215 + * 1.216 + * Flags: 1.217 + * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this 1.218 + * case. Also implies NS_FRAME_NO_MOVE_VIEW 1.219 + * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you 1.220 + * don't want to automatically sync the frame and view 1.221 + * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view 1.222 + */ 1.223 + static nsresult FinishReflowChild(nsIFrame* aKidFrame, 1.224 + nsPresContext* aPresContext, 1.225 + const nsHTMLReflowMetrics& aDesiredSize, 1.226 + const nsHTMLReflowState* aReflowState, 1.227 + nscoord aX, 1.228 + nscoord aY, 1.229 + uint32_t aFlags); 1.230 + 1.231 + 1.232 + static void PositionChildViews(nsIFrame* aFrame); 1.233 + 1.234 + // ========================================================================== 1.235 + /* Overflow containers are continuation frames that hold overflow. They 1.236 + * are created when the frame runs out of computed height, but still has 1.237 + * too much content to fit in the availableHeight. The parent creates a 1.238 + * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER 1.239 + * and adds it to its next-in-flow's overflow container list, either by 1.240 + * adding it directly or by putting it in its own excess overflow containers 1.241 + * list (to be drained by the next-in-flow when it calls 1.242 + * ReflowOverflowContainerChildren). The parent continues reflow as if 1.243 + * the frame was complete once it ran out of computed height, but returns 1.244 + * either an NS_FRAME_NOT_COMPLETE or NS_FRAME_OVERFLOW_INCOMPLETE reflow 1.245 + * status to request a next-in-flow. The parent's next-in-flow is then 1.246 + * responsible for calling ReflowOverflowContainerChildren to (drain and) 1.247 + * reflow these overflow continuations. Overflow containers do not affect 1.248 + * other frames' size or position during reflow (but do affect their 1.249 + * parent's overflow area). 1.250 + * 1.251 + * Overflow container continuations are different from normal continuations 1.252 + * in that 1.253 + * - more than one child of the frame can have its next-in-flow broken 1.254 + * off and pushed into the frame's next-in-flow 1.255 + * - new continuations may need to be spliced into the middle of the list 1.256 + * or deleted continuations slipped out 1.257 + * e.g. A, B, C are all fixed-size containers on one page, all have 1.258 + * overflow beyond availableHeight, and content is dynamically added 1.259 + * and removed from B 1.260 + * As a result, it is not possible to simply prepend the new continuations 1.261 + * to the old list as with the overflowProperty mechanism. To avoid 1.262 + * complicated list splicing, the code assumes only one overflow containers 1.263 + * list exists for a given frame: either its own overflowContainersProperty 1.264 + * or its prev-in-flow's excessOverflowContainersProperty, not both. 1.265 + * 1.266 + * The nsOverflowContinuationTracker helper class should be used for tracking 1.267 + * overflow containers and adding them to the appropriate list. 1.268 + * See nsBlockFrame::Reflow for a sample implementation. 1.269 + */ 1.270 + 1.271 + friend class nsOverflowContinuationTracker; 1.272 + 1.273 + /** 1.274 + * Reflow overflow container children. They are invisible to normal reflow 1.275 + * (i.e. don't affect sizing or placement of other children) and inherit 1.276 + * width and horizontal position from their prev-in-flow. 1.277 + * 1.278 + * This method 1.279 + * 1. Pulls excess overflow containers from the prev-in-flow and adds 1.280 + * them to our overflow container list 1.281 + * 2. Reflows all our overflow container kids 1.282 + * 3. Expands aOverflowRect as necessary to accomodate these children. 1.283 + * 4. Sets aStatus's NS_FRAME_OVERFLOW_IS_INCOMPLETE flag (along with 1.284 + * NS_FRAME_REFLOW_NEXTINFLOW as necessary) if any overflow children 1.285 + * are incomplete and 1.286 + * 5. Prepends a list of their continuations to our excess overflow 1.287 + * container list, to be drained into our next-in-flow when it is 1.288 + * reflowed. 1.289 + * 1.290 + * The caller is responsible for tracking any new overflow container 1.291 + * continuations it makes, removing them from its child list, and 1.292 + * making sure they are stored properly in the overflow container lists. 1.293 + * The nsOverflowContinuationTracker helper class should be used for this. 1.294 + * 1.295 + * (aFlags just gets passed through to ReflowChild) 1.296 + */ 1.297 + nsresult ReflowOverflowContainerChildren(nsPresContext* aPresContext, 1.298 + const nsHTMLReflowState& aReflowState, 1.299 + nsOverflowAreas& aOverflowRects, 1.300 + uint32_t aFlags, 1.301 + nsReflowStatus& aStatus); 1.302 + 1.303 + /** 1.304 + * Move any frames on our overflow list to the end of our principal list. 1.305 + * @return true if there were any overflow frames 1.306 + */ 1.307 + virtual bool DrainSelfOverflowList() MOZ_OVERRIDE; 1.308 + 1.309 + /** 1.310 + * Removes aChild without destroying it and without requesting reflow. 1.311 + * Continuations are not affected. Checks the primary and overflow 1.312 + * or overflow containers and excess overflow containers lists, depending 1.313 + * on whether the NS_FRAME_IS_OVERFLOW_CONTAINER flag is set. Does not 1.314 + * check any other auxiliary lists. 1.315 + * Returns NS_ERROR_UNEXPECTED if we failed to remove aChild. 1.316 + * Returns other error codes if we failed to put back a proptable list. 1.317 + * If aForceNormal is true, only checks the primary and overflow lists 1.318 + * even when the NS_FRAME_IS_OVERFLOW_CONTAINER flag is set. 1.319 + */ 1.320 + virtual nsresult StealFrame(nsIFrame* aChild, 1.321 + bool aForceNormal = false); 1.322 + 1.323 + /** 1.324 + * Removes the next-siblings of aChild without destroying them and without 1.325 + * requesting reflow. Checks the principal and overflow lists (not 1.326 + * overflow containers / excess overflow containers). Does not check any 1.327 + * other auxiliary lists. 1.328 + * @param aChild a child frame or nullptr 1.329 + * @return If aChild is non-null, the next-siblings of aChild, if any. 1.330 + * If aChild is null, all child frames on the principal list, if any. 1.331 + */ 1.332 + nsFrameList StealFramesAfter(nsIFrame* aChild); 1.333 + 1.334 + /** 1.335 + * Add overflow containers to the display list 1.336 + */ 1.337 + void DisplayOverflowContainers(nsDisplayListBuilder* aBuilder, 1.338 + const nsRect& aDirtyRect, 1.339 + const nsDisplayListSet& aLists); 1.340 + 1.341 + /** 1.342 + * Builds display lists for the children. The background 1.343 + * of each child is placed in the Content() list (suitable for inline 1.344 + * children and other elements that behave like inlines, 1.345 + * but not for in-flow block children of blocks). DOES NOT 1.346 + * paint the background/borders/outline of this frame. This should 1.347 + * probably be avoided and eventually removed. It's currently here 1.348 + * to emulate what nsContainerFrame::Paint did. 1.349 + */ 1.350 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.351 + const nsRect& aDirtyRect, 1.352 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.353 + 1.354 + /** 1.355 + * Destructor function for the proptable-stored framelists -- 1.356 + * it should never be called. 1.357 + */ 1.358 + static void DestroyFrameList(void* aPropertyValue) 1.359 + { 1.360 + MOZ_ASSERT(false, "The owning frame should destroy its nsFrameList props"); 1.361 + } 1.362 + 1.363 + static void PlaceFrameView(nsIFrame* aFrame) 1.364 + { 1.365 + if (aFrame->HasView()) 1.366 + nsContainerFrame::PositionFrameView(aFrame); 1.367 + else 1.368 + nsContainerFrame::PositionChildViews(aFrame); 1.369 + } 1.370 + 1.371 +#define NS_DECLARE_FRAME_PROPERTY_FRAMELIST(prop) \ 1.372 + NS_DECLARE_FRAME_PROPERTY(prop, nsContainerFrame::DestroyFrameList) 1.373 + 1.374 + NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowProperty) 1.375 + NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty) 1.376 + NS_DECLARE_FRAME_PROPERTY_FRAMELIST(ExcessOverflowContainersProperty) 1.377 + 1.378 +protected: 1.379 + nsContainerFrame(nsStyleContext* aContext) : nsSplittableFrame(aContext) {} 1.380 + ~nsContainerFrame(); 1.381 + 1.382 + /** 1.383 + * Helper for DestroyFrom. DestroyAbsoluteFrames is called before 1.384 + * destroying frames on lists that can contain placeholders. 1.385 + * Derived classes must do that too, if they destroy such frame lists. 1.386 + * See nsBlockFrame::DestroyFrom for an example. 1.387 + */ 1.388 + void DestroyAbsoluteFrames(nsIFrame* aDestructRoot); 1.389 + 1.390 + /** 1.391 + * Builds a display list for non-block children that behave like 1.392 + * inlines. This puts the background of each child into the 1.393 + * Content() list (suitable for inline children but not for 1.394 + * in-flow block children of blocks). 1.395 + * @param aForcePseudoStack forces each child into a pseudo-stacking-context 1.396 + * so its background and all other display items (except for positioned 1.397 + * display items) go into the Content() list. 1.398 + */ 1.399 + void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder, 1.400 + const nsRect& aDirtyRect, 1.401 + const nsDisplayListSet& aLists, 1.402 + uint32_t aFlags = 0); 1.403 + 1.404 + /** 1.405 + * A version of BuildDisplayList that use DISPLAY_CHILD_INLINE. 1.406 + * Intended as a convenience for derived classes. 1.407 + */ 1.408 + void BuildDisplayListForInline(nsDisplayListBuilder* aBuilder, 1.409 + const nsRect& aDirtyRect, 1.410 + const nsDisplayListSet& aLists) { 1.411 + DisplayBorderBackgroundOutline(aBuilder, aLists); 1.412 + BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists, 1.413 + DISPLAY_CHILD_INLINE); 1.414 + } 1.415 + 1.416 + 1.417 + // ========================================================================== 1.418 + /* Overflow Frames are frames that did not fit and must be pulled by 1.419 + * our next-in-flow during its reflow. (The same concept for overflow 1.420 + * containers is called "excess frames". We should probably make the 1.421 + * names match.) 1.422 + */ 1.423 + 1.424 + /** 1.425 + * Get the frames on the overflow list. Can return null if there are no 1.426 + * overflow frames. The caller does NOT take ownership of the list; it's 1.427 + * still owned by this frame. A non-null return value indicates that the 1.428 + * list is nonempty. 1.429 + */ 1.430 + inline nsFrameList* GetOverflowFrames() const; 1.431 + 1.432 + /** 1.433 + * As GetOverflowFrames, but removes the overflow frames property. The 1.434 + * caller is responsible for deleting nsFrameList and either passing 1.435 + * ownership of the frames to someone else or destroying the frames. 1.436 + * A non-null return value indicates that the list is nonempty. The 1.437 + * recommended way to use this function it to assign its return value 1.438 + * into an AutoFrameListPtr. 1.439 + */ 1.440 + inline nsFrameList* StealOverflowFrames(); 1.441 + 1.442 + /** 1.443 + * Set the overflow list. aOverflowFrames must not be an empty list. 1.444 + */ 1.445 + void SetOverflowFrames(const nsFrameList& aOverflowFrames); 1.446 + 1.447 + /** 1.448 + * Destroy the overflow list, which must be empty. 1.449 + */ 1.450 + inline void DestroyOverflowList(); 1.451 + 1.452 + /** 1.453 + * Moves any frames on both the prev-in-flow's overflow list and the 1.454 + * receiver's overflow to the receiver's child list. 1.455 + * 1.456 + * Resets the overlist pointers to nullptr, and updates the receiver's child 1.457 + * count and content mapping. 1.458 + * 1.459 + * @return true if any frames were moved and false otherwise 1.460 + */ 1.461 + bool MoveOverflowToChildList(); 1.462 + 1.463 + /** 1.464 + * Push aFromChild and its next siblings to the next-in-flow. Change 1.465 + * the geometric parent of each frame that's pushed. If there is no 1.466 + * next-in-flow the frames are placed on the overflow list (and the 1.467 + * geometric parent is left unchanged). 1.468 + * 1.469 + * Updates the next-in-flow's child count. Does <b>not</b> update the 1.470 + * pusher's child count. 1.471 + * 1.472 + * @param aFromChild the first child frame to push. It is disconnected from 1.473 + * aPrevSibling 1.474 + * @param aPrevSibling aFromChild's previous sibling. Must not be null. 1.475 + * It's an error to push a parent's first child frame 1.476 + */ 1.477 + void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling); 1.478 + 1.479 + // ========================================================================== 1.480 + /* 1.481 + * Convenience methods for nsFrameLists stored in the 1.482 + * PresContext's proptable 1.483 + */ 1.484 + 1.485 + /** 1.486 + * Get the PresContext-stored nsFrameList named aPropID for this frame. 1.487 + * May return null. 1.488 + */ 1.489 + nsFrameList* GetPropTableFrames(const FramePropertyDescriptor* aProperty) const; 1.490 + 1.491 + /** 1.492 + * Remove and return the PresContext-stored nsFrameList named aPropID for 1.493 + * this frame. May return null. 1.494 + */ 1.495 + nsFrameList* RemovePropTableFrames(const FramePropertyDescriptor* aProperty); 1.496 + 1.497 + /** 1.498 + * Set the PresContext-stored nsFrameList named aPropID for this frame 1.499 + * to the given aFrameList, which must not be null. 1.500 + */ 1.501 + void SetPropTableFrames(nsFrameList* aFrameList, 1.502 + const FramePropertyDescriptor* aProperty); 1.503 + 1.504 + /** 1.505 + * Safely destroy the frames on the nsFrameList stored on aProp for this 1.506 + * frame then remove the property and delete the frame list. 1.507 + * Nothing happens if the property doesn't exist. 1.508 + */ 1.509 + void SafelyDestroyFrameListProp(nsIFrame* aDestructRoot, 1.510 + nsIPresShell* aPresShell, 1.511 + mozilla::FramePropertyTable* aPropTable, 1.512 + const FramePropertyDescriptor* aProp); 1.513 + 1.514 + // ========================================================================== 1.515 + 1.516 + nsFrameList mFrames; 1.517 +}; 1.518 + 1.519 +// ========================================================================== 1.520 +/* The out-of-flow-related code below is for a hacky way of splitting 1.521 + * absolutely-positioned frames. Basically what we do is split the frame 1.522 + * in nsAbsoluteContainingBlock and pretend the continuation is an overflow 1.523 + * container. This isn't an ideal solution, but it lets us print the content 1.524 + * at least. See bug 154892. 1.525 + */ 1.526 + 1.527 +#define IS_TRUE_OVERFLOW_CONTAINER(frame) \ 1.528 + ( (frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) \ 1.529 + && !( (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) && \ 1.530 + frame->IsAbsolutelyPositioned() ) ) 1.531 +//XXXfr This check isn't quite correct, because it doesn't handle cases 1.532 +// where the out-of-flow has overflow.. but that's rare. 1.533 +// We'll need to revisit the way abspos continuations are handled later 1.534 +// for various reasons, this detail is one of them. See bug 154892 1.535 + 1.536 +/** 1.537 + * Helper class for tracking overflow container continuations during reflow. 1.538 + * 1.539 + * A frame is related to two sets of overflow containers: those that /are/ 1.540 + * its own children, and those that are /continuations/ of its children. 1.541 + * This tracker walks through those continuations (the frame's NIF's children) 1.542 + * and their prev-in-flows (a subset of the frame's normal and overflow 1.543 + * container children) in parallel. It allows the reflower to synchronously 1.544 + * walk its overflow continuations while it loops through and reflows its 1.545 + * children. This makes it possible to insert new continuations at the correct 1.546 + * place in the overflow containers list. 1.547 + * 1.548 + * The reflower is expected to loop through its children in the same order it 1.549 + * looped through them the last time (if there was a last time). 1.550 + * For each child, the reflower should either 1.551 + * - call Skip for the child if was not reflowed in this pass 1.552 + * - call Insert for the overflow continuation if the child was reflowed 1.553 + * but has incomplete overflow 1.554 + * - call Finished for the child if it was reflowed in this pass but 1.555 + * is either complete or has a normal next-in-flow. This call can 1.556 + * be skipped if the child did not previously have an overflow 1.557 + * continuation. 1.558 + */ 1.559 +class nsOverflowContinuationTracker { 1.560 +public: 1.561 + /** 1.562 + * Initializes an nsOverflowContinuationTracker to help track overflow 1.563 + * continuations of aFrame's children. Typically invoked on 'this'. 1.564 + * 1.565 + * aWalkOOFFrames determines whether the walker skips out-of-flow frames 1.566 + * or skips non-out-of-flow frames. 1.567 + * 1.568 + * Don't set aSkipOverflowContainerChildren to false unless you plan 1.569 + * to walk your own overflow container children. (Usually they are handled 1.570 + * by calling ReflowOverflowContainerChildren.) aWalkOOFFrames is ignored 1.571 + * if aSkipOverflowContainerChildren is false. 1.572 + */ 1.573 + nsOverflowContinuationTracker(nsContainerFrame* aFrame, 1.574 + bool aWalkOOFFrames, 1.575 + bool aSkipOverflowContainerChildren = true); 1.576 + /** 1.577 + * This function adds an overflow continuation to our running list and 1.578 + * sets its NS_FRAME_IS_OVERFLOW_CONTAINER flag. 1.579 + * 1.580 + * aReflowStatus should preferably be specific to the recently-reflowed 1.581 + * child and not influenced by any of its siblings' statuses. This 1.582 + * function sets the NS_FRAME_IS_DIRTY bit on aOverflowCont if it needs 1.583 + * to be reflowed. (Its need for reflow depends on changes to its 1.584 + * prev-in-flow, not to its parent--for whom it is invisible, reflow-wise.) 1.585 + * 1.586 + * The caller MUST disconnect the frame from its parent's child list 1.587 + * if it was not previously an NS_FRAME_IS_OVERFLOW_CONTAINER (because 1.588 + * StealFrame is much more inefficient than disconnecting in place 1.589 + * during Reflow, which the caller is able to do but we are not). 1.590 + * 1.591 + * The caller MUST NOT disconnect the frame from its parent's 1.592 + * child list if it is already an NS_FRAME_IS_OVERFLOW_CONTAINER. 1.593 + * (In this case we will disconnect and reconnect it ourselves.) 1.594 + */ 1.595 + nsresult Insert(nsIFrame* aOverflowCont, 1.596 + nsReflowStatus& aReflowStatus); 1.597 + /** 1.598 + * Begin/EndFinish() must be called for each child that is reflowed 1.599 + * but no longer has an overflow continuation. (It may be called for 1.600 + * other children, but in that case has no effect.) It increments our 1.601 + * walker and makes sure we drop any dangling pointers to its 1.602 + * next-in-flow. This function MUST be called before stealing or 1.603 + * deleting aChild's next-in-flow. 1.604 + * The AutoFinish helper object does that for you. Use it like so: 1.605 + * if (kidNextInFlow) { 1.606 + * nsOverflowContinuationTracker::AutoFinish fini(tracker, kid); 1.607 + * ... DeleteNextInFlowChild/StealFrame(kidNextInFlow) here ... 1.608 + * } 1.609 + */ 1.610 + class MOZ_STACK_CLASS AutoFinish { 1.611 + public: 1.612 + AutoFinish(nsOverflowContinuationTracker* aTracker, nsIFrame* aChild) 1.613 + : mTracker(aTracker), mChild(aChild) 1.614 + { 1.615 + if (mTracker) mTracker->BeginFinish(mChild); 1.616 + } 1.617 + ~AutoFinish() 1.618 + { 1.619 + if (mTracker) mTracker->EndFinish(mChild); 1.620 + } 1.621 + private: 1.622 + nsOverflowContinuationTracker* mTracker; 1.623 + nsIFrame* mChild; 1.624 + }; 1.625 + 1.626 + /** 1.627 + * This function should be called for each child that isn't reflowed. 1.628 + * It increments our walker and sets the NS_FRAME_OVERFLOW_INCOMPLETE 1.629 + * reflow flag if it encounters an overflow continuation so that our 1.630 + * next-in-flow doesn't get prematurely deleted. It MUST be called on 1.631 + * each unreflowed child that has an overflow container continuation; 1.632 + * it MAY be called on other children, but it isn't necessary (doesn't 1.633 + * do anything). 1.634 + */ 1.635 + void Skip(nsIFrame* aChild, nsReflowStatus& aReflowStatus) 1.636 + { 1.637 + NS_PRECONDITION(aChild, "null ptr"); 1.638 + if (aChild == mSentry) { 1.639 + StepForward(); 1.640 + NS_MergeReflowStatusInto(&aReflowStatus, NS_FRAME_OVERFLOW_INCOMPLETE); 1.641 + } 1.642 + } 1.643 + 1.644 +private: 1.645 + 1.646 + /** 1.647 + * @see class AutoFinish 1.648 + */ 1.649 + void BeginFinish(nsIFrame* aChild); 1.650 + void EndFinish(nsIFrame* aChild); 1.651 + 1.652 + void SetupOverflowContList(); 1.653 + void SetUpListWalker(); 1.654 + void StepForward(); 1.655 + 1.656 + /* We hold a pointer to either the next-in-flow's overflow containers list 1.657 + or, if that doesn't exist, our frame's excess overflow containers list. 1.658 + We need to make sure that we drop that pointer if the list becomes 1.659 + empty and is deleted elsewhere. */ 1.660 + nsFrameList* mOverflowContList; 1.661 + /* We hold a pointer to the most recently-reflowed child that has an 1.662 + overflow container next-in-flow. We do this because it's a known 1.663 + good point; this pointer won't be deleted on us. We can use it to 1.664 + recover our place in the list. */ 1.665 + nsIFrame* mPrevOverflowCont; 1.666 + /* This is a pointer to the next overflow container's prev-in-flow, which 1.667 + is (or should be) a child of our frame. When we hit this, we will need 1.668 + to increment this walker to the next overflow container. */ 1.669 + nsIFrame* mSentry; 1.670 + /* Parent of all frames in mOverflowContList. If our mOverflowContList 1.671 + is an excessOverflowContainersProperty, or null, then this is our frame 1.672 + (the frame that was passed in to our constructor). Otherwise this is 1.673 + that frame's next-in-flow, and our mOverflowContList is mParent's 1.674 + overflowContainersProperty */ 1.675 + nsContainerFrame* mParent; 1.676 + /* Tells SetUpListWalker whether or not to walk us past any continuations 1.677 + of overflow containers. aWalkOOFFrames is ignored when this is false. */ 1.678 + bool mSkipOverflowContainerChildren; 1.679 + /* Tells us whether to pay attention to OOF frames or non-OOF frames */ 1.680 + bool mWalkOOFFrames; 1.681 +}; 1.682 + 1.683 +inline 1.684 +nsFrameList* 1.685 +nsContainerFrame::GetOverflowFrames() const 1.686 +{ 1.687 + nsFrameList* list = 1.688 + static_cast<nsFrameList*>(Properties().Get(OverflowProperty())); 1.689 + NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list"); 1.690 + return list; 1.691 +} 1.692 + 1.693 +inline 1.694 +nsFrameList* 1.695 +nsContainerFrame::StealOverflowFrames() 1.696 +{ 1.697 + nsFrameList* list = 1.698 + static_cast<nsFrameList*>(Properties().Remove(OverflowProperty())); 1.699 + NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list"); 1.700 + return list; 1.701 +} 1.702 + 1.703 +inline void 1.704 +nsContainerFrame::DestroyOverflowList() 1.705 +{ 1.706 + nsFrameList* list = RemovePropTableFrames(OverflowProperty()); 1.707 + MOZ_ASSERT(list && list->IsEmpty()); 1.708 + list->Delete(PresContext()->PresShell()); 1.709 +} 1.710 + 1.711 +#endif /* nsContainerFrame_h___ */