layout/generic/nsContainerFrame.h

changeset 0
6474c204b198
     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___ */

mercurial