LCOV - app.info - layout/generic/nsContainerFrame.cpp

LCOV - code coverage report
| Current view: | directory - layout/generic - nsContainerFrame.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 714 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 56 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
          24                 :  *   Elika J. Etemad ("fantasai") <fantasai@inkedblade.net>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : /* base class #1 for rendering objects that have child lists */
          41                 :
          42                 : #include "nsContainerFrame.h"
          43                 :
          44                 : #include "nsIContent.h"
          45                 : #include "nsIDocument.h"
          46                 : #include "nsPresContext.h"
          47                 : #include "nsStyleContext.h"
          48                 : #include "nsRect.h"
          49                 : #include "nsPoint.h"
          50                 : #include "nsGUIEvent.h"
          51                 : #include "nsStyleConsts.h"
          52                 : #include "nsIView.h"
          53                 : #include "nsFrameManager.h"
          54                 : #include "nsIPresShell.h"
          55                 : #include "nsCOMPtr.h"
          56                 : #include "nsGkAtoms.h"
          57                 : #include "nsCSSAnonBoxes.h"
          58                 : #include "nsIViewManager.h"
          59                 : #include "nsIWidget.h"
          60                 : #include "nsGfxCIID.h"
          61                 : #include "nsIServiceManager.h"
          62                 : #include "nsCSSRendering.h"
          63                 : #include "nsTransform2D.h"
          64                 : #include "nsRegion.h"
          65                 : #include "nsLayoutErrors.h"
          66                 : #include "nsDisplayList.h"
          67                 : #include "nsContentErrors.h"
          68                 : #include "nsListControlFrame.h"
          69                 : #include "nsIBaseWindow.h"
          70                 : #include "nsThemeConstants.h"
          71                 : #include "nsCSSFrameConstructor.h"
          72                 : #include "mozilla/dom/Element.h"
          73                 :
          74                 : #ifdef NS_DEBUG
          75                 : #undef NOISY
          76                 : #else
          77                 : #undef NOISY
          78                 : #endif
          79                 :
          80                 : using namespace mozilla;
          81                 : using namespace mozilla::dom;
          82                 :
          83               0 : NS_IMPL_FRAMEARENA_HELPERS(nsContainerFrame)
          84                 :
          85               0 : nsContainerFrame::~nsContainerFrame()
          86                 : {
          87               0 : }
          88                 :
          89               0 : NS_QUERYFRAME_HEAD(nsContainerFrame)
          90               0 :   NS_QUERYFRAME_ENTRY(nsContainerFrame)
          91               0 : NS_QUERYFRAME_TAIL_INHERITING(nsSplittableFrame)
          92                 :
          93                 : NS_IMETHODIMP
          94               0 : nsContainerFrame::Init(nsIContent* aContent,
          95                 :                        nsIFrame*   aParent,
          96                 :                        nsIFrame*   aPrevInFlow)
          97                 : {
          98               0 :   nsresult rv = nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
          99               0 :   if (aPrevInFlow) {
         100                 :     // Make sure we copy bits from our prev-in-flow that will affect
         101                 :     // us. A continuation for a container frame needs to know if it
         102                 :     // has a child with a view so that we'll properly reposition it.
         103               0 :     if (aPrevInFlow->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)
         104               0 :       AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
         105                 :   }
         106               0 :   return rv;
         107                 : }
         108                 :
         109                 : NS_IMETHODIMP
         110               0 : nsContainerFrame::SetInitialChildList(ChildListID  aListID,
         111                 :                                       nsFrameList& aChildList)
         112                 : {
         113                 :   nsresult  result;
         114               0 :   if (mFrames.NotEmpty()) {
         115                 :     // We already have child frames which means we've already been
         116                 :     // initialized
         117               0 :     NS_NOTREACHED("unexpected second call to SetInitialChildList");
         118               0 :     result = NS_ERROR_UNEXPECTED;
         119               0 :   } else if (aListID != kPrincipalList) {
         120                 :     // All we know about is the principal child list.
         121               0 :     NS_NOTREACHED("unknown frame list");
         122               0 :     result = NS_ERROR_INVALID_ARG;
         123                 :   } else {
         124                 : #ifdef NS_DEBUG
         125               0 :     nsFrame::VerifyDirtyBitSet(aChildList);
         126                 : #endif
         127               0 :     mFrames.SetFrames(aChildList);
         128               0 :     result = NS_OK;
         129                 :   }
         130               0 :   return result;
         131                 : }
         132                 :
         133                 : NS_IMETHODIMP
         134               0 : nsContainerFrame::AppendFrames(ChildListID  aListID,
         135                 :                                nsFrameList& aFrameList)
         136                 : {
         137               0 :   if (aListID != kPrincipalList) {
         138                 : #ifdef IBMBIDI
         139               0 :     if (aListID != kNoReflowPrincipalList)
         140                 : #endif
         141                 :     {
         142               0 :       NS_ERROR("unexpected child list");
         143               0 :       return NS_ERROR_INVALID_ARG;
         144                 :     }
         145                 :   }
         146               0 :   if (aFrameList.NotEmpty()) {
         147               0 :     mFrames.AppendFrames(this, aFrameList);
         148                 :
         149                 :     // Ask the parent frame to reflow me.
         150                 : #ifdef IBMBIDI
         151               0 :     if (aListID == kPrincipalList)
         152                 : #endif
         153                 :     {
         154               0 :       PresContext()->PresShell()->
         155                 :         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
         156               0 :                          NS_FRAME_HAS_DIRTY_CHILDREN);
         157                 :     }
         158                 :   }
         159               0 :   return NS_OK;
         160                 : }
         161                 :
         162                 : NS_IMETHODIMP
         163               0 : nsContainerFrame::InsertFrames(ChildListID aListID,
         164                 :                                nsIFrame* aPrevFrame,
         165                 :                                nsFrameList& aFrameList)
         166                 : {
         167               0 :   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
         168                 :                "inserting after sibling frame with different parent");
         169                 :
         170               0 :   if (aListID != kPrincipalList) {
         171                 : #ifdef IBMBIDI
         172               0 :     if (aListID != kNoReflowPrincipalList)
         173                 : #endif
         174                 :     {
         175               0 :       NS_ERROR("unexpected child list");
         176               0 :       return NS_ERROR_INVALID_ARG;
         177                 :     }
         178                 :   }
         179               0 :   if (aFrameList.NotEmpty()) {
         180                 :     // Insert frames after aPrevFrame
         181               0 :     mFrames.InsertFrames(this, aPrevFrame, aFrameList);
         182                 :
         183                 : #ifdef IBMBIDI
         184               0 :     if (aListID == kPrincipalList)
         185                 : #endif
         186                 :     {
         187               0 :       PresContext()->PresShell()->
         188                 :         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
         189               0 :                          NS_FRAME_HAS_DIRTY_CHILDREN);
         190                 :     }
         191                 :   }
         192               0 :   return NS_OK;
         193                 : }
         194                 :
         195                 : NS_IMETHODIMP
         196               0 : nsContainerFrame::RemoveFrame(ChildListID aListID,
         197                 :                               nsIFrame* aOldFrame)
         198                 : {
         199               0 :   if (aListID != kPrincipalList) {
         200                 : #ifdef IBMBIDI
         201               0 :     if (kNoReflowPrincipalList != aListID)
         202                 : #endif
         203                 :     {
         204               0 :       NS_ERROR("unexpected child list");
         205               0 :       return NS_ERROR_INVALID_ARG;
         206                 :     }
         207                 :   }
         208                 :
         209                 :   // Loop and destroy aOldFrame and all of its continuations.
         210                 :   // Request a reflow on the parent frames involved unless we were explicitly
         211                 :   // told not to (kNoReflowPrincipalList).
         212               0 :   bool generateReflowCommand = true;
         213                 : #ifdef IBMBIDI
         214               0 :   if (kNoReflowPrincipalList == aListID) {
         215               0 :     generateReflowCommand = false;
         216                 :   }
         217                 : #endif
         218               0 :   nsPresContext* pc = PresContext();
         219               0 :   nsContainerFrame* lastParent = nsnull;
         220               0 :   while (aOldFrame) {
         221                 :     //XXXfr probably should use StealFrame here. I'm not sure if we need to
         222                 :     //      check the overflow lists atm, but we'll need a prescontext lookup
         223                 :     //      for overflow containers once we can split abspos elements with
         224                 :     //      inline containing blocks.
         225               0 :     nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation();
         226                 :     nsContainerFrame* parent =
         227               0 :       static_cast<nsContainerFrame*>(aOldFrame->GetParent());
         228               0 :     parent->StealFrame(pc, aOldFrame, true);
         229               0 :     aOldFrame->Destroy();
         230               0 :     aOldFrame = oldFrameNextContinuation;
         231               0 :     if (parent != lastParent && generateReflowCommand) {
         232               0 :       pc->PresShell()->
         233                 :         FrameNeedsReflow(parent, nsIPresShell::eTreeChange,
         234               0 :                          NS_FRAME_HAS_DIRTY_CHILDREN);
         235               0 :       lastParent = parent;
         236                 :     }
         237                 :   }
         238               0 :   return NS_OK;
         239                 : }
         240                 :
         241                 : void
         242               0 : nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
         243                 : {
         244                 :   // Prevent event dispatch during destruction
         245               0 :   if (HasView()) {
         246               0 :     GetView()->SetFrame(nsnull);
         247                 :   }
         248                 :
         249                 :   // Delete the primary child list
         250               0 :   mFrames.DestroyFramesFrom(aDestructRoot);
         251                 :
         252                 :   // Destroy auxiliary frame lists
         253               0 :   nsPresContext* prescontext = PresContext();
         254                 :
         255               0 :   DestroyOverflowList(prescontext, aDestructRoot);
         256                 :
         257               0 :   if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
         258                 :     nsFrameList* frameList =
         259               0 :       RemovePropTableFrames(prescontext, OverflowContainersProperty());
         260               0 :     if (frameList)
         261               0 :       frameList->DestroyFrom(aDestructRoot);
         262                 :
         263                 :     frameList = RemovePropTableFrames(prescontext,
         264               0 :                                       ExcessOverflowContainersProperty());
         265               0 :     if (frameList)
         266               0 :       frameList->DestroyFrom(aDestructRoot);
         267                 :   }
         268                 :
         269                 :   // Destroy the frame and remove the flow pointers
         270               0 :   nsSplittableFrame::DestroyFrom(aDestructRoot);
         271               0 : }
         272                 :
         273                 : /////////////////////////////////////////////////////////////////////////////
         274                 : // Child frame enumeration
         275                 :
         276                 : const nsFrameList&
         277               0 : nsContainerFrame::GetChildList(ChildListID aListID) const
         278                 : {
         279                 :   // We only know about the principal child list and the overflow lists.
         280               0 :   switch (aListID) {
         281                 :     case kPrincipalList:
         282               0 :       return mFrames;
         283                 :     case kOverflowList: {
         284               0 :       nsFrameList* list = GetOverflowFrames();
         285               0 :       return list ? *list : nsFrameList::EmptyList();
         286                 :     }
         287                 :     case kOverflowContainersList: {
         288                 :       nsFrameList* list =
         289               0 :         GetPropTableFrames(PresContext(), OverflowContainersProperty());
         290               0 :       return list ? *list : nsFrameList::EmptyList();
         291                 :     }
         292                 :     case kExcessOverflowContainersList: {
         293                 :       nsFrameList* list =
         294               0 :         GetPropTableFrames(PresContext(), ExcessOverflowContainersProperty());
         295               0 :       return list ? *list : nsFrameList::EmptyList();
         296                 :     }
         297                 :     default:
         298               0 :       return nsSplittableFrame::GetChildList(aListID);
         299                 :   }
         300                 : }
         301                 :
         302               0 : static void AppendIfNonempty(const nsIFrame* aFrame,
         303                 :                             FramePropertyTable* aPropTable,
         304                 :                             const FramePropertyDescriptor* aProperty,
         305                 :                             nsTArray<nsIFrame::ChildList>* aLists,
         306                 :                             nsIFrame::ChildListID aListID)
         307                 : {
         308                 :   nsFrameList* list = static_cast<nsFrameList*>(
         309               0 :     aPropTable->Get(aFrame, aProperty));
         310               0 :   if (list) {
         311               0 :     list->AppendIfNonempty(aLists, aListID);
         312                 :   }
         313               0 : }
         314                 :
         315                 : void
         316               0 : nsContainerFrame::GetChildLists(nsTArray<ChildList>* aLists) const
         317                 : {
         318               0 :   mFrames.AppendIfNonempty(aLists, kPrincipalList);
         319               0 :   FramePropertyTable* propTable = PresContext()->PropertyTable();
         320                 :   ::AppendIfNonempty(this, propTable, OverflowProperty(),
         321               0 :                      aLists, kOverflowList);
         322               0 :   if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
         323                 :     ::AppendIfNonempty(this, propTable, OverflowContainersProperty(),
         324               0 :                        aLists, kOverflowContainersList);
         325                 :     ::AppendIfNonempty(this, propTable, ExcessOverflowContainersProperty(),
         326               0 :                        aLists, kExcessOverflowContainersList);
         327                 :   }
         328               0 :   nsSplittableFrame::GetChildLists(aLists);
         329               0 : }
         330                 :
         331                 : /////////////////////////////////////////////////////////////////////////////
         332                 : // Painting/Events
         333                 :
         334                 : NS_IMETHODIMP
         335               0 : nsContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
         336                 :                                    const nsRect&           aDirtyRect,
         337                 :                                    const nsDisplayListSet& aLists)
         338                 : {
         339               0 :   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
         340               0 :   NS_ENSURE_SUCCESS(rv, rv);
         341                 :
         342               0 :   return BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists);
         343                 : }
         344                 :
         345                 : nsresult
         346               0 : nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder*   aBuilder,
         347                 :                                                       const nsRect&           aDirtyRect,
         348                 :                                                       const nsDisplayListSet& aLists,
         349                 :                                                       PRUint32                aFlags)
         350                 : {
         351               0 :   nsIFrame* kid = mFrames.FirstChild();
         352                 :   // Put each child's background directly onto the content list
         353               0 :   nsDisplayListSet set(aLists, aLists.Content());
         354                 :   // The children should be in content order
         355               0 :   while (kid) {
         356               0 :     nsresult rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set, aFlags);
         357               0 :     NS_ENSURE_SUCCESS(rv, rv);
         358               0 :     kid = kid->GetNextSibling();
         359                 :   }
         360               0 :   return NS_OK;
         361                 : }
         362                 :
         363                 : /* virtual */ void
         364               0 : nsContainerFrame::ChildIsDirty(nsIFrame* aChild)
         365                 : {
         366               0 :   AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
         367               0 : }
         368                 :
         369                 : bool
         370               0 : nsContainerFrame::IsLeaf() const
         371                 : {
         372               0 :   return false;
         373                 : }
         374                 :
         375                 : bool
         376               0 : nsContainerFrame::PeekOffsetNoAmount(bool aForward, PRInt32* aOffset)
         377                 : {
         378               0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
         379                 :   // Don't allow the caret to stay in an empty (leaf) container frame.
         380               0 :   return false;
         381                 : }
         382                 :
         383                 : bool
         384               0 : nsContainerFrame::PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
         385                 :                                       bool aRespectClusters)
         386                 : {
         387               0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
         388                 :   // Don't allow the caret to stay in an empty (leaf) container frame.
         389               0 :   return false;
         390                 : }
         391                 :
         392                 : /////////////////////////////////////////////////////////////////////////////
         393                 : // Helper member functions
         394                 :
         395                 : static nsresult
         396               0 : ReparentFrameViewTo(nsIFrame*       aFrame,
         397                 :                     nsIViewManager* aViewManager,
         398                 :                     nsIView*        aNewParentView,
         399                 :                     nsIView*        aOldParentView)
         400                 : {
         401                 :
         402                 :   // XXX What to do about placeholder views for "position: fixed" elements?
         403                 :   // They should be reparented too.
         404                 :
         405                 :   // Does aFrame have a view?
         406               0 :   if (aFrame->HasView()) {
         407                 : #ifdef MOZ_XUL
         408               0 :     if (aFrame->GetType() == nsGkAtoms::menuPopupFrame) {
         409                 :       // This view must be parented by the root view, don't reparent it.
         410               0 :       return NS_OK;
         411                 :     }
         412                 : #endif
         413               0 :     nsIView* view = aFrame->GetView();
         414                 :     // Verify that the current parent view is what we think it is
         415                 :     //nsIView*  parentView;
         416                 :     //NS_ASSERTION(parentView == aOldParentView, "unexpected parent view");
         417                 :
         418               0 :     aViewManager->RemoveChild(view);
         419                 :
         420                 :     // The view will remember the Z-order and other attributes that have been set on it.
         421               0 :     nsIView* insertBefore = nsLayoutUtils::FindSiblingViewFor(aNewParentView, aFrame);
         422               0 :     aViewManager->InsertChild(aNewParentView, view, insertBefore, insertBefore != nsnull);
         423                 :   } else {
         424               0 :     nsIFrame::ChildListIterator lists(aFrame);
         425               0 :     for (; !lists.IsDone(); lists.Next()) {
         426                 :       // Iterate the child frames, and check each child frame to see if it has
         427                 :       // a view
         428               0 :       nsFrameList::Enumerator childFrames(lists.CurrentList());
         429               0 :       for (; !childFrames.AtEnd(); childFrames.Next()) {
         430                 :         ReparentFrameViewTo(childFrames.get(), aViewManager,
         431               0 :                             aNewParentView, aOldParentView);
         432                 :       }
         433                 :     }
         434                 :   }
         435                 :
         436               0 :   return NS_OK;
         437                 : }
         438                 :
         439                 : nsresult
         440               0 : nsContainerFrame::CreateViewForFrame(nsIFrame* aFrame,
         441                 :                                      bool aForce)
         442                 : {
         443               0 :   if (aFrame->HasView()) {
         444               0 :     return NS_OK;
         445                 :   }
         446                 :
         447                 :   // If we don't yet have a view, see if we need a view
         448               0 :   if (!aForce && !aFrame->NeedsView()) {
         449                 :     // don't need a view
         450               0 :     return NS_OK;
         451                 :   }
         452                 :
         453               0 :   nsIView* parentView = aFrame->GetParent()->GetClosestView();
         454               0 :   NS_ASSERTION(parentView, "no parent with view");
         455                 :
         456               0 :   nsIViewManager* viewManager = parentView->GetViewManager();
         457               0 :   NS_ASSERTION(viewManager, "null view manager");
         458                 :
         459                 :   // Create a view
         460               0 :   nsIView* view = viewManager->CreateView(aFrame->GetRect(), parentView);
         461               0 :   if (!view)
         462               0 :     return NS_ERROR_OUT_OF_MEMORY;
         463                 :
         464               0 :   SyncFrameViewProperties(aFrame->PresContext(), aFrame, nsnull, view);
         465                 :
         466               0 :   nsIView* insertBefore = nsLayoutUtils::FindSiblingViewFor(parentView, aFrame);
         467                 :   // we insert this view 'above' the insertBefore view, unless insertBefore is null,
         468                 :   // in which case we want to call with aAbove == false to insert at the beginning
         469                 :   // in document order
         470               0 :   viewManager->InsertChild(parentView, view, insertBefore, insertBefore != nsnull);
         471                 :
         472                 :   // REVIEW: Don't create a widget for fixed-pos elements anymore.
         473                 :   // ComputeRepaintRegionForCopy will calculate the right area to repaint
         474                 :   // when we scroll.
         475                 :   // Reparent views on any child frames (or their descendants) to this
         476                 :   // view. We can just call ReparentFrameViewTo on this frame because
         477                 :   // we know this frame has no view, so it will crawl the children. Also,
         478                 :   // we know that any descendants with views must have 'parentView' as their
         479                 :   // parent view.
         480               0 :   ReparentFrameViewTo(aFrame, viewManager, view, parentView);
         481                 :
         482                 :   // Remember our view
         483               0 :   aFrame->SetView(view);
         484                 :
         485               0 :   NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
         486                 :                ("nsContainerFrame::CreateViewForFrame: frame=%p view=%p",
         487                 :                 aFrame));
         488               0 :   return NS_OK;
         489                 : }
         490                 :
         491                 : /**
         492                 :  * Position the view associated with |aKidFrame|, if there is one. A
         493                 :  * container frame should call this method after positioning a frame,
         494                 :  * but before |Reflow|.
         495                 :  */
         496                 : void
         497               0 : nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame)
         498                 : {
         499               0 :   nsIFrame* parentFrame = aKidFrame->GetParent();
         500               0 :   if (!aKidFrame->HasView() || !parentFrame)
         501               0 :     return;
         502                 :
         503               0 :   nsIView* view = aKidFrame->GetView();
         504               0 :   nsIViewManager* vm = view->GetViewManager();
         505               0 :   nsPoint pt;
         506               0 :   nsIView* ancestorView = parentFrame->GetClosestView(&pt);
         507                 :
         508               0 :   if (ancestorView != view->GetParent()) {
         509               0 :     NS_ASSERTION(ancestorView == view->GetParent()->GetParent(),
         510                 :                  "Allowed only one anonymous view between frames");
         511                 :     // parentFrame is responsible for positioning aKidFrame's view
         512                 :     // explicitly
         513               0 :     return;
         514                 :   }
         515                 :
         516               0 :   pt += aKidFrame->GetPosition();
         517               0 :   vm->MoveViewTo(view, pt.x, pt.y);
         518                 : }
         519                 :
         520                 : nsresult
         521               0 : nsContainerFrame::ReparentFrameView(nsPresContext* aPresContext,
         522                 :                                     nsIFrame*       aChildFrame,
         523                 :                                     nsIFrame*       aOldParentFrame,
         524                 :                                     nsIFrame*       aNewParentFrame)
         525                 : {
         526               0 :   NS_PRECONDITION(aChildFrame, "null child frame pointer");
         527               0 :   NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer");
         528               0 :   NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer");
         529               0 :   NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame");
         530                 :
         531                 :   // See if either the old parent frame or the new parent frame have a view
         532               0 :   while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) {
         533                 :     // Walk up both the old parent frame and the new parent frame nodes
         534                 :     // stopping when we either find a common parent or views for one
         535                 :     // or both of the frames.
         536                 :     //
         537                 :     // This works well in the common case where we push/pull and the old parent
         538                 :     // frame and the new parent frame are part of the same flow. They will
         539                 :     // typically be the same distance (height wise) from the
         540               0 :     aOldParentFrame = aOldParentFrame->GetParent();
         541               0 :     aNewParentFrame = aNewParentFrame->GetParent();
         542                 :
         543                 :     // We should never walk all the way to the root frame without finding
         544                 :     // a view
         545               0 :     NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view");
         546                 :
         547                 :     // See if we reached a common ancestor
         548               0 :     if (aOldParentFrame == aNewParentFrame) {
         549               0 :       break;
         550                 :     }
         551                 :   }
         552                 :
         553                 :   // See if we found a common parent frame
         554               0 :   if (aOldParentFrame == aNewParentFrame) {
         555                 :     // We found a common parent and there are no views between the old parent
         556                 :     // and the common parent or the new parent frame and the common parent.
         557                 :     // Because neither the old parent frame nor the new parent frame have views,
         558                 :     // then any child views don't need reparenting
         559               0 :     return NS_OK;
         560                 :   }
         561                 :
         562                 :   // We found views for one or both of the ancestor frames before we
         563                 :   // found a common ancestor.
         564               0 :   nsIView* oldParentView = aOldParentFrame->GetClosestView();
         565               0 :   nsIView* newParentView = aNewParentFrame->GetClosestView();
         566                 :
         567                 :   // See if the old parent frame and the new parent frame are in the
         568                 :   // same view sub-hierarchy. If they are then we don't have to do
         569                 :   // anything
         570               0 :   if (oldParentView != newParentView) {
         571                 :     // They're not so we need to reparent any child views
         572                 :     return ReparentFrameViewTo(aChildFrame, oldParentView->GetViewManager(), newParentView,
         573               0 :                                oldParentView);
         574                 :   }
         575                 :
         576               0 :   return NS_OK;
         577                 : }
         578                 :
         579                 : nsresult
         580               0 : nsContainerFrame::ReparentFrameViewList(nsPresContext*     aPresContext,
         581                 :                                         const nsFrameList& aChildFrameList,
         582                 :                                         nsIFrame*          aOldParentFrame,
         583                 :                                         nsIFrame*          aNewParentFrame)
         584                 : {
         585               0 :   NS_PRECONDITION(aChildFrameList.NotEmpty(), "empty child frame list");
         586               0 :   NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer");
         587               0 :   NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer");
         588               0 :   NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame");
         589                 :
         590                 :   // See if either the old parent frame or the new parent frame have a view
         591               0 :   while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) {
         592                 :     // Walk up both the old parent frame and the new parent frame nodes
         593                 :     // stopping when we either find a common parent or views for one
         594                 :     // or both of the frames.
         595                 :     //
         596                 :     // This works well in the common case where we push/pull and the old parent
         597                 :     // frame and the new parent frame are part of the same flow. They will
         598                 :     // typically be the same distance (height wise) from the
         599               0 :     aOldParentFrame = aOldParentFrame->GetParent();
         600               0 :     aNewParentFrame = aNewParentFrame->GetParent();
         601                 :
         602                 :     // We should never walk all the way to the root frame without finding
         603                 :     // a view
         604               0 :     NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view");
         605                 :
         606                 :     // See if we reached a common ancestor
         607               0 :     if (aOldParentFrame == aNewParentFrame) {
         608               0 :       break;
         609                 :     }
         610                 :   }
         611                 :
         612                 :
         613                 :   // See if we found a common parent frame
         614               0 :   if (aOldParentFrame == aNewParentFrame) {
         615                 :     // We found a common parent and there are no views between the old parent
         616                 :     // and the common parent or the new parent frame and the common parent.
         617                 :     // Because neither the old parent frame nor the new parent frame have views,
         618                 :     // then any child views don't need reparenting
         619               0 :     return NS_OK;
         620                 :   }
         621                 :
         622                 :   // We found views for one or both of the ancestor frames before we
         623                 :   // found a common ancestor.
         624               0 :   nsIView* oldParentView = aOldParentFrame->GetClosestView();
         625               0 :   nsIView* newParentView = aNewParentFrame->GetClosestView();
         626                 :
         627                 :   // See if the old parent frame and the new parent frame are in the
         628                 :   // same view sub-hierarchy. If they are then we don't have to do
         629                 :   // anything
         630               0 :   if (oldParentView != newParentView) {
         631               0 :     nsIViewManager* viewManager = oldParentView->GetViewManager();
         632                 :
         633                 :     // They're not so we need to reparent any child views
         634               0 :     for (nsFrameList::Enumerator e(aChildFrameList); !e.AtEnd(); e.Next()) {
         635               0 :       ReparentFrameViewTo(e.get(), viewManager, newParentView, oldParentView);
         636                 :     }
         637                 :   }
         638                 :
         639               0 :   return NS_OK;
         640                 : }
         641                 :
         642                 : static nsIWidget*
         643               0 : GetPresContextContainerWidget(nsPresContext* aPresContext)
         644                 : {
         645               0 :   nsCOMPtr<nsISupports> container = aPresContext->Document()->GetContainer();
         646               0 :   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
         647               0 :   if (!baseWindow)
         648               0 :     return nsnull;
         649                 :
         650               0 :   nsCOMPtr<nsIWidget> mainWidget;
         651               0 :   baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
         652               0 :   return mainWidget;
         653                 : }
         654                 :
         655                 : static bool
         656               0 : IsTopLevelWidget(nsIWidget* aWidget)
         657                 : {
         658                 :   nsWindowType windowType;
         659               0 :   aWidget->GetWindowType(windowType);
         660                 :   return windowType == eWindowType_toplevel ||
         661                 :          windowType == eWindowType_dialog ||
         662               0 :          windowType == eWindowType_sheet;
         663                 :   // popups aren't toplevel so they're not handled here
         664                 : }
         665                 :
         666                 : void
         667               0 : nsContainerFrame::SyncWindowProperties(nsPresContext*       aPresContext,
         668                 :                                        nsIFrame*            aFrame,
         669                 :                                        nsIView*             aView)
         670                 : {
         671                 : #ifdef MOZ_XUL
         672               0 :   if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget())
         673               0 :     return;
         674                 :
         675               0 :   nsIWidget* windowWidget = GetPresContextContainerWidget(aPresContext);
         676               0 :   if (!windowWidget || !IsTopLevelWidget(windowWidget))
         677               0 :     return;
         678                 :
         679               0 :   nsIViewManager* vm = aView->GetViewManager();
         680               0 :   nsIView* rootView = vm->GetRootView();
         681                 :
         682               0 :   if (aView != rootView)
         683               0 :     return;
         684                 :
         685               0 :   Element* rootElement = aPresContext->Document()->GetRootElement();
         686               0 :   if (!rootElement || !rootElement->IsXUL()) {
         687                 :     // Scrollframes use native widgets which don't work well with
         688                 :     // translucent windows, at least in Windows XP. So if the document
         689                 :     // has a root scrollrame it's useless to try to make it transparent,
         690                 :     // we'll just get something broken.
         691                 :     // nsCSSFrameConstructor::ConstructRootFrame constructs root
         692                 :     // scrollframes whenever the root element is not a XUL element, so
         693                 :     // we test for that here. We can't just call
         694                 :     // presShell->GetRootScrollFrame() since that might not have
         695                 :     // been constructed yet.
         696                 :     // We can change this to allow translucent toplevel HTML documents
         697                 :     // (e.g. to do something like Dashboard widgets), once we
         698                 :     // have broad support for translucent scrolled documents, but be
         699                 :     // careful because apparently some Firefox extensions expect
         700                 :     // openDialog("something.html") to produce an opaque window
         701                 :     // even if the HTML doesn't have a background-color set.
         702               0 :     return;
         703                 :   }
         704                 :
         705               0 :   nsIFrame *rootFrame = aPresContext->PresShell()->FrameConstructor()->GetRootElementStyleFrame();
         706               0 :   if (!rootFrame)
         707               0 :     return;
         708                 :
         709               0 :   nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(aFrame, rootFrame);
         710               0 :   nsIWidget* viewWidget = aView->GetWidget();
         711               0 :   viewWidget->SetTransparencyMode(mode);
         712               0 :   windowWidget->SetWindowShadowStyle(rootFrame->GetStyleUIReset()->mWindowShadow);
         713                 : #endif
         714                 : }
         715                 :
         716                 : void
         717               0 : nsContainerFrame::SyncFrameViewAfterReflow(nsPresContext* aPresContext,
         718                 :                                            nsIFrame*       aFrame,
         719                 :                                            nsIView*        aView,
         720                 :                                            const nsRect&   aVisualOverflowArea,
         721                 :                                            PRUint32        aFlags)
         722                 : {
         723               0 :   if (!aView) {
         724               0 :     return;
         725                 :   }
         726                 :
         727                 :   // Make sure the view is sized and positioned correctly
         728               0 :   if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
         729               0 :     PositionFrameView(aFrame);
         730                 :   }
         731                 :
         732               0 :   if (0 == (aFlags & NS_FRAME_NO_SIZE_VIEW)) {
         733               0 :     nsIViewManager* vm = aView->GetViewManager();
         734                 :
         735               0 :     vm->ResizeView(aView, aVisualOverflowArea, true);
         736                 :   }
         737                 : }
         738                 :
         739                 : void
         740               0 : nsContainerFrame::SyncFrameViewProperties(nsPresContext*  aPresContext,
         741                 :                                           nsIFrame*        aFrame,
         742                 :                                           nsStyleContext*  aStyleContext,
         743                 :                                           nsIView*         aView,
         744                 :                                           PRUint32         aFlags)
         745                 : {
         746               0 :   NS_ASSERTION(!aStyleContext || aFrame->GetStyleContext() == aStyleContext,
         747                 :                "Wrong style context for frame?");
         748                 :
         749               0 :   if (!aView) {
         750               0 :     return;
         751                 :   }
         752                 :
         753               0 :   nsIViewManager* vm = aView->GetViewManager();
         754                 :
         755               0 :   if (nsnull == aStyleContext) {
         756               0 :     aStyleContext = aFrame->GetStyleContext();
         757                 :   }
         758                 :
         759                 :   // Make sure visibility is correct. This only affects nsSubdocumentFrame.
         760               0 :   if (0 == (aFlags & NS_FRAME_NO_VISIBILITY) &&
         761               0 :       !aFrame->SupportsVisibilityHidden()) {
         762                 :     // See if the view should be hidden or visible
         763                 :     vm->SetViewVisibility(aView,
         764               0 :         aStyleContext->GetStyleVisibility()->IsVisible()
         765               0 :             ? nsViewVisibility_kShow : nsViewVisibility_kHide);
         766                 :   }
         767                 :
         768                 :   // See if the frame is being relatively positioned or absolutely
         769                 :   // positioned
         770               0 :   bool isPositioned = aStyleContext->GetStyleDisplay()->IsPositioned();
         771                 :
         772               0 :   PRInt32 zIndex = 0;
         773               0 :   bool    autoZIndex = false;
         774                 :
         775               0 :   if (!isPositioned) {
         776               0 :     autoZIndex = true;
         777                 :   } else {
         778                 :     // Make sure z-index is correct
         779               0 :     const nsStylePosition* position = aStyleContext->GetStylePosition();
         780                 :
         781               0 :     if (position->mZIndex.GetUnit() == eStyleUnit_Integer) {
         782               0 :       zIndex = position->mZIndex.GetIntValue();
         783               0 :     } else if (position->mZIndex.GetUnit() == eStyleUnit_Auto) {
         784               0 :       autoZIndex = true;
         785                 :     }
         786                 :   }
         787                 :
         788               0 :   vm->SetViewZIndex(aView, autoZIndex, zIndex, isPositioned);
         789                 : }
         790                 :
         791               0 : static nscoord GetCoord(const nsStyleCoord& aCoord, nscoord aIfNotCoord)
         792                 : {
         793               0 :   if (aCoord.ConvertsToLength()) {
         794               0 :     return nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
         795                 :   }
         796               0 :   return aIfNotCoord;
         797                 : }
         798                 :
         799                 : void
         800               0 : nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
         801                 :                                          InlineIntrinsicWidthData *aData,
         802                 :                                          nsLayoutUtils::IntrinsicWidthType aType)
         803                 : {
         804               0 :   if (GetPrevInFlow())
         805               0 :     return; // Already added.
         806                 :
         807               0 :   NS_PRECONDITION(aType == nsLayoutUtils::MIN_WIDTH ||
         808                 :                   aType == nsLayoutUtils::PREF_WIDTH, "bad type");
         809                 :
         810                 :   mozilla::css::Side startSide, endSide;
         811               0 :   if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR) {
         812               0 :     startSide = NS_SIDE_LEFT;
         813               0 :     endSide = NS_SIDE_RIGHT;
         814                 :   } else {
         815               0 :     startSide = NS_SIDE_RIGHT;
         816               0 :     endSide = NS_SIDE_LEFT;
         817                 :   }
         818                 :
         819               0 :   const nsStylePadding *stylePadding = GetStylePadding();
         820               0 :   const nsStyleBorder *styleBorder = GetStyleBorder();
         821               0 :   const nsStyleMargin *styleMargin = GetStyleMargin();
         822                 :
         823                 :   // This goes at the beginning no matter how things are broken and how
         824                 :   // messy the bidi situations are, since per CSS2.1 section 8.6
         825                 :   // (implemented in bug 328168), the startSide border is always on the
         826                 :   // first line.
         827                 :   // This frame is a first-in-flow, but it might have a previous bidi
         828                 :   // continuation, in which case that continuation should handle the startSide
         829                 :   // border.
         830               0 :   if (!GetPrevContinuation()) {
         831                 :     aData->currentLine +=
         832                 :       // clamp negative calc() to 0
         833               0 :       NS_MAX(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
         834               0 :       styleBorder->GetActualBorderWidth(startSide) +
         835               0 :       GetCoord(styleMargin->mMargin.Get(startSide), 0);
         836                 :   }
         837                 :
         838               0 :   const nsLineList_iterator* savedLine = aData->line;
         839               0 :   nsIFrame* const savedLineContainer = aData->lineContainer;
         840                 :
         841                 :   nsContainerFrame *lastInFlow;
         842               0 :   for (nsContainerFrame *nif = this; nif;
         843               0 :        nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
         844               0 :     for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
         845                 :          kid = kid->GetNextSibling()) {
         846               0 :       if (aType == nsLayoutUtils::MIN_WIDTH)
         847                 :         kid->AddInlineMinWidth(aRenderingContext,
         848               0 :                                static_cast<InlineMinWidthData*>(aData));
         849                 :       else
         850                 :         kid->AddInlinePrefWidth(aRenderingContext,
         851               0 :                                 static_cast<InlinePrefWidthData*>(aData));
         852                 :     }
         853                 :
         854                 :     // After we advance to our next-in-flow, the stored line and line container
         855                 :     // may no longer be correct. Just forget them.
         856               0 :     aData->line = nsnull;
         857               0 :     aData->lineContainer = nsnull;
         858                 :
         859               0 :     lastInFlow = nif;
         860                 :   }
         861                 :
         862               0 :   aData->line = savedLine;
         863               0 :   aData->lineContainer = savedLineContainer;
         864                 :
         865                 :   // This goes at the end no matter how things are broken and how
         866                 :   // messy the bidi situations are, since per CSS2.1 section 8.6
         867                 :   // (implemented in bug 328168), the endSide border is always on the
         868                 :   // last line.
         869                 :   // We reached the last-in-flow, but it might have a next bidi
         870                 :   // continuation, in which case that continuation should handle
         871                 :   // the endSide border.
         872               0 :   if (!lastInFlow->GetNextContinuation()) {
         873                 :     aData->currentLine +=
         874                 :       // clamp negative calc() to 0
         875               0 :       NS_MAX(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
         876               0 :       styleBorder->GetActualBorderWidth(endSide) +
         877               0 :       GetCoord(styleMargin->mMargin.Get(endSide), 0);
         878                 :   }
         879                 : }
         880                 :
         881                 : /* virtual */ nsSize
         882               0 : nsContainerFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
         883                 :                                   nsSize aCBSize, nscoord aAvailableWidth,
         884                 :                                   nsSize aMargin, nsSize aBorder,
         885                 :                                   nsSize aPadding, bool aShrinkWrap)
         886                 : {
         887               0 :   nsSize result(0xdeadbeef, NS_UNCONSTRAINEDSIZE);
         888                 :   nscoord availBased = aAvailableWidth - aMargin.width - aBorder.width -
         889               0 :                        aPadding.width;
         890                 :   // replaced elements always shrink-wrap
         891               0 :   if (aShrinkWrap || IsFrameOfType(eReplaced)) {
         892                 :     // don't bother setting it if the result won't be used
         893               0 :     if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
         894               0 :       result.width = ShrinkWidthToFit(aRenderingContext, availBased);
         895                 :     }
         896                 :   } else {
         897               0 :     result.width = availBased;
         898                 :   }
         899                 :   return result;
         900                 : }
         901                 :
         902                 : /**
         903                 :  * Invokes the WillReflow() function, positions the frame and its view (if
         904                 :  * requested), and then calls Reflow(). If the reflow succeeds and the child
         905                 :  * frame is complete, deletes any next-in-flows using DeleteNextInFlowChild()
         906                 :  */
         907                 : nsresult
         908               0 : nsContainerFrame::ReflowChild(nsIFrame*                aKidFrame,
         909                 :                               nsPresContext*           aPresContext,
         910                 :                               nsHTMLReflowMetrics&     aDesiredSize,
         911                 :                               const nsHTMLReflowState& aReflowState,
         912                 :                               nscoord                  aX,
         913                 :                               nscoord                  aY,
         914                 :                               PRUint32                 aFlags,
         915                 :                               nsReflowStatus&          aStatus,
         916                 :                               nsOverflowContinuationTracker* aTracker)
         917                 : {
         918               0 :   NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
         919                 :
         920                 :   nsresult  result;
         921                 :
         922                 :   // Send the WillReflow() notification, and position the child frame
         923                 :   // and its view if requested
         924               0 :   aKidFrame->WillReflow(aPresContext);
         925                 :
         926               0 :   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
         927               0 :     if ((aFlags & NS_FRAME_INVALIDATE_ON_MOVE) &&
         928               0 :         !(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
         929               0 :         aKidFrame->GetPosition() != nsPoint(aX, aY)) {
         930               0 :       aKidFrame->InvalidateFrameSubtree();
         931                 :     }
         932               0 :     aKidFrame->SetPosition(nsPoint(aX, aY));
         933                 :   }
         934                 :
         935               0 :   if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
         936               0 :     PositionFrameView(aKidFrame);
         937                 :   }
         938                 :
         939                 :   // Reflow the child frame
         940                 :   result = aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState,
         941               0 :                              aStatus);
         942                 :
         943                 :   // If the reflow was successful and the child frame is complete, delete any
         944                 :   // next-in-flows
         945               0 :   if (NS_SUCCEEDED(result) && NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
         946               0 :     nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
         947               0 :     if (nsnull != kidNextInFlow) {
         948                 :       // Remove all of the childs next-in-flows. Make sure that we ask
         949                 :       // the right parent to do the removal (it's possible that the
         950                 :       // parent is not this because we are executing pullup code)
         951               0 :       if (aTracker) aTracker->Finish(aKidFrame);
         952               0 :       static_cast<nsContainerFrame*>(kidNextInFlow->GetParent())
         953               0 :         ->DeleteNextInFlowChild(aPresContext, kidNextInFlow, true);
         954                 :     }
         955                 :   }
         956               0 :   return result;
         957                 : }
         958                 :
         959                 :
         960                 : /**
         961                 :  * Position the views of |aFrame|'s descendants. A container frame
         962                 :  * should call this method if it moves a frame after |Reflow|.
         963                 :  */
         964                 : void
         965               0 : nsContainerFrame::PositionChildViews(nsIFrame* aFrame)
         966                 : {
         967               0 :   if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)) {
         968               0 :     return;
         969                 :   }
         970                 :
         971                 :   // Recursively walk aFrame's child frames.
         972                 :   // Process the additional child lists, but skip the popup list as the
         973                 :   // view for popups is managed by the parent. Currently only nsMenuFrame
         974                 :   // has a popupList and during layout will call nsMenuPopupFrame::AdjustView.
         975               0 :   ChildListIterator lists(aFrame);
         976               0 :   for (; !lists.IsDone(); lists.Next()) {
         977               0 :     if (lists.CurrentID() == kPopupList) {
         978               0 :       continue;
         979                 :     }
         980               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
         981               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
         982                 :       // Position the frame's view (if it has one) otherwise recursively
         983                 :       // process its children
         984               0 :       nsIFrame* childFrame = childFrames.get();
         985               0 :       if (childFrame->HasView()) {
         986               0 :         PositionFrameView(childFrame);
         987                 :       } else {
         988               0 :         PositionChildViews(childFrame);
         989                 :       }
         990                 :     }
         991                 :   }
         992                 : }
         993                 :
         994                 : /**
         995                 :  * The second half of frame reflow. Does the following:
         996                 :  * - sets the frame's bounds
         997                 :  * - sizes and positions (if requested) the frame's view. If the frame's final
         998                 :  *   position differs from the current position and the frame itself does not
         999                 :  *   have a view, then any child frames with views are positioned so they stay
        1000                 :  *   in sync
        1001                 :  * - sets the view's visibility, opacity, content transparency, and clip
        1002                 :  * - invoked the DidReflow() function
        1003                 :  *
        1004                 :  * Flags:
        1005                 :  * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this
        1006                 :  *    case. Also implies NS_FRAME_NO_MOVE_VIEW
        1007                 :  * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
        1008                 :  *    don't want to automatically sync the frame and view
        1009                 :  * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
        1010                 :  */
        1011                 : nsresult
        1012               0 : nsContainerFrame::FinishReflowChild(nsIFrame*                  aKidFrame,
        1013                 :                                     nsPresContext*             aPresContext,
        1014                 :                                     const nsHTMLReflowState*   aReflowState,
        1015                 :                                     const nsHTMLReflowMetrics& aDesiredSize,
        1016                 :                                     nscoord                    aX,
        1017                 :                                     nscoord                    aY,
        1018                 :                                     PRUint32                   aFlags)
        1019                 : {
        1020               0 :   nsPoint curOrigin = aKidFrame->GetPosition();
        1021               0 :   nsRect  bounds(aX, aY, aDesiredSize.width, aDesiredSize.height);
        1022                 :
        1023               0 :   aKidFrame->SetRect(bounds);
        1024                 :
        1025               0 :   if (aKidFrame->HasView()) {
        1026               0 :     nsIView* view = aKidFrame->GetView();
        1027                 :     // Make sure the frame's view is properly sized and positioned and has
        1028                 :     // things like opacity correct
        1029                 :     SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
        1030               0 :                              aDesiredSize.VisualOverflow(), aFlags);
        1031                 :   }
        1032                 :
        1033               0 :   if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) &&
        1034                 :       (curOrigin.x != aX || curOrigin.y != aY)) {
        1035               0 :     if (!aKidFrame->HasView()) {
        1036                 :       // If the frame has moved, then we need to make sure any child views are
        1037                 :       // correctly positioned
        1038               0 :       PositionChildViews(aKidFrame);
        1039                 :     }
        1040                 :
        1041                 :     // We also need to redraw everything associated with the frame
        1042                 :     // because if the frame's Reflow issued any invalidates, then they
        1043                 :     // will be at the wrong offset ... note that this includes
        1044                 :     // invalidates issued against the frame's children, so we need to
        1045                 :     // invalidate the overflow area too.
        1046               0 :     aKidFrame->Invalidate(aDesiredSize.VisualOverflow());
        1047                 :   }
        1048                 :
        1049               0 :   return aKidFrame->DidReflow(aPresContext, aReflowState, NS_FRAME_REFLOW_FINISHED);
        1050                 : }
        1051                 :
        1052                 : nsresult
        1053               0 : nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext*           aPresContext,
        1054                 :                                                   const nsHTMLReflowState& aReflowState,
        1055                 :                                                   nsOverflowAreas&         aOverflowRects,
        1056                 :                                                   PRUint32                 aFlags,
        1057                 :                                                   nsReflowStatus&          aStatus)
        1058                 : {
        1059               0 :   NS_PRECONDITION(aPresContext, "null pointer");
        1060               0 :   nsresult rv = NS_OK;
        1061                 :
        1062                 :   nsFrameList* overflowContainers =
        1063                 :                GetPropTableFrames(aPresContext,
        1064               0 :                                   OverflowContainersProperty());
        1065                 :
        1066               0 :   NS_ASSERTION(!(overflowContainers && GetPrevInFlow()
        1067                 :                  && static_cast<nsContainerFrame*>(GetPrevInFlow())
        1068                 :                       ->GetPropTableFrames(aPresContext,
        1069                 :                           ExcessOverflowContainersProperty())),
        1070                 :                "conflicting overflow containers lists");
        1071                 :
        1072               0 :   if (!overflowContainers) {
        1073                 :     // Drain excess from previnflow
        1074               0 :     nsContainerFrame* prev = (nsContainerFrame*) GetPrevInFlow();
        1075               0 :     if (prev) {
        1076                 :       nsFrameList* excessFrames =
        1077                 :         prev->RemovePropTableFrames(aPresContext,
        1078               0 :                                     ExcessOverflowContainersProperty());
        1079               0 :       if (excessFrames) {
        1080               0 :         excessFrames->ApplySetParent(this);
        1081                 :         nsContainerFrame::ReparentFrameViewList(aPresContext, *excessFrames,
        1082               0 :                                                 prev, this);
        1083               0 :         overflowContainers = excessFrames;
        1084                 :         rv = SetPropTableFrames(aPresContext, overflowContainers,
        1085               0 :                                 OverflowContainersProperty());
        1086               0 :         if (NS_FAILED(rv)) {
        1087               0 :           excessFrames->DestroyFrames();
        1088               0 :           delete excessFrames;
        1089               0 :           return rv;
        1090                 :         }
        1091                 :       }
        1092                 :     }
        1093                 :   }
        1094                 :
        1095               0 :   if (!overflowContainers)
        1096               0 :     return NS_OK; // nothing to reflow
        1097                 :
        1098               0 :   nsOverflowContinuationTracker tracker(aPresContext, this, false, false);
        1099               0 :   bool shouldReflowAllKids = aReflowState.ShouldReflowAllKids();
        1100                 :
        1101               0 :   for (nsIFrame* frame = overflowContainers->FirstChild(); frame;
        1102                 :        frame = frame->GetNextSibling()) {
        1103               0 :     if (frame->GetPrevInFlow()->GetParent() != GetPrevInFlow()) {
        1104                 :       // frame's prevInFlow has moved, skip reflowing this frame;
        1105                 :       // it will get reflowed once it's been placed
        1106               0 :       continue;
        1107                 :     }
        1108                 :     // If the available vertical height has changed, we need to reflow
        1109                 :     // even if the frame isn't dirty.
        1110               0 :     if (shouldReflowAllKids || NS_SUBTREE_DIRTY(frame)) {
        1111                 :       // Get prev-in-flow
        1112               0 :       nsIFrame* prevInFlow = frame->GetPrevInFlow();
        1113               0 :       NS_ASSERTION(prevInFlow,
        1114                 :                    "overflow container frame must have a prev-in-flow");
        1115               0 :       NS_ASSERTION(frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
        1116                 :                    "overflow container frame must have overflow container bit set");
        1117               0 :       nsRect prevRect = prevInFlow->GetRect();
        1118                 :
        1119                 :       // Initialize reflow params
        1120               0 :       nsSize availSpace(prevRect.width, aReflowState.availableHeight);
        1121               0 :       nsHTMLReflowMetrics desiredSize;
        1122                 :       nsHTMLReflowState frameState(aPresContext, aReflowState,
        1123               0 :                                    frame, availSpace);
        1124               0 :       nsReflowStatus frameStatus = NS_FRAME_COMPLETE;
        1125                 :
        1126                 :       // Cache old bounds
        1127               0 :       nsRect oldRect = frame->GetRect();
        1128               0 :       nsRect oldOverflow = frame->GetVisualOverflowRect();
        1129                 :
        1130                 :       // Reflow
        1131                 :       rv = ReflowChild(frame, aPresContext, desiredSize, frameState,
        1132               0 :                        prevRect.x, 0, aFlags, frameStatus, &tracker);
        1133               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1134                 :       //XXXfr Do we need to override any shrinkwrap effects here?
        1135                 :       // e.g. desiredSize.width = prevRect.width;
        1136                 :       rv = FinishReflowChild(frame, aPresContext, &frameState, desiredSize,
        1137               0 :                              prevRect.x, 0, aFlags);
        1138               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1139                 :
        1140                 :       // Invalidate if there was a position or size change
        1141               0 :       nsRect rect = frame->GetRect();
        1142               0 :       if (!rect.IsEqualInterior(oldRect)) {
        1143               0 :         nsRect dirtyRect = oldOverflow;
        1144               0 :         dirtyRect.MoveBy(oldRect.x, oldRect.y);
        1145               0 :         Invalidate(dirtyRect);
        1146                 :
        1147               0 :         dirtyRect = frame->GetVisualOverflowRect();
        1148               0 :         dirtyRect.MoveBy(rect.x, rect.y);
        1149               0 :         Invalidate(dirtyRect);
        1150                 :       }
        1151                 :
        1152                 :       // Handle continuations
        1153               0 :       if (!NS_FRAME_IS_FULLY_COMPLETE(frameStatus)) {
        1154               0 :         if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
        1155                 :           // Abspos frames can't cause their parent to be incomplete,
        1156                 :           // only overflow incomplete.
        1157               0 :           NS_FRAME_SET_OVERFLOW_INCOMPLETE(frameStatus);
        1158                 :         }
        1159                 :         else {
        1160               0 :           NS_ASSERTION(NS_FRAME_IS_COMPLETE(frameStatus),
        1161                 :                        "overflow container frames can't be incomplete, only overflow-incomplete");
        1162                 :         }
        1163                 :
        1164                 :         // Acquire a next-in-flow, creating it if necessary
        1165               0 :         nsIFrame* nif = frame->GetNextInFlow();
        1166               0 :         if (!nif) {
        1167               0 :           NS_ASSERTION(frameStatus & NS_FRAME_REFLOW_NEXTINFLOW,
        1168                 :                        "Someone forgot a REFLOW_NEXTINFLOW flag");
        1169                 :           rv = aPresContext->PresShell()->FrameConstructor()->
        1170               0 :                  CreateContinuingFrame(aPresContext, frame, this, &nif);
        1171               0 :           NS_ENSURE_SUCCESS(rv, rv);
        1172                 :         }
        1173               0 :         else if (!(nif->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
        1174                 :           // used to be a normal next-in-flow; steal it from the child list
        1175               0 :           rv = static_cast<nsContainerFrame*>(nif->GetParent())
        1176               0 :                  ->StealFrame(aPresContext, nif);
        1177               0 :           NS_ENSURE_SUCCESS(rv, rv);
        1178                 :         }
        1179                 :
        1180               0 :         tracker.Insert(nif, frameStatus);
        1181                 :       }
        1182               0 :       NS_MergeReflowStatusInto(&aStatus, frameStatus);
        1183                 :       // At this point it would be nice to assert !frame->GetOverflowRect().IsEmpty(),
        1184                 :       // but we have some unsplittable frames that, when taller than
        1185                 :       // availableHeight will push zero-height content into a next-in-flow.
        1186                 :     }
        1187                 :     else {
        1188               0 :       tracker.Skip(frame, aStatus);
        1189               0 :       if (aReflowState.mFloatManager)
        1190               0 :         nsBlockFrame::RecoverFloatsFor(frame, *aReflowState.mFloatManager);
        1191                 :     }
        1192               0 :     ConsiderChildOverflow(aOverflowRects, frame);
        1193                 :   }
        1194                 :
        1195               0 :   return NS_OK;
        1196                 : }
        1197                 :
        1198                 : void
        1199               0 : nsContainerFrame::DisplayOverflowContainers(nsDisplayListBuilder*   aBuilder,
        1200                 :                                             const nsRect&           aDirtyRect,
        1201                 :                                             const nsDisplayListSet& aLists)
        1202                 : {
        1203                 :   nsFrameList* overflowconts =
        1204               0 :     GetPropTableFrames(PresContext(), OverflowContainersProperty());
        1205               0 :   if (overflowconts) {
        1206               0 :     for (nsIFrame* frame = overflowconts->FirstChild(); frame;
        1207                 :          frame = frame->GetNextSibling()) {
        1208               0 :       BuildDisplayListForChild(aBuilder, frame, aDirtyRect, aLists);
        1209                 :     }
        1210                 :   }
        1211               0 : }
        1212                 :
        1213                 : nsresult
        1214               0 : nsContainerFrame::StealFrame(nsPresContext* aPresContext,
        1215                 :                              nsIFrame*      aChild,
        1216                 :                              bool           aForceNormal)
        1217                 : {
        1218               0 :   bool removed = true;
        1219               0 :   if ((aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)
        1220               0 :       && !aForceNormal) {
        1221                 :     // Try removing from the overflow container list
        1222               0 :     if (!RemovePropTableFrame(aPresContext, aChild,
        1223               0 :                               OverflowContainersProperty())) {
        1224                 :       // It must be in the excess overflow container list
        1225                 :       removed = RemovePropTableFrame(aPresContext, aChild,
        1226               0 :                                      ExcessOverflowContainersProperty());
        1227                 :     }
        1228                 :   }
        1229                 :   else {
        1230               0 :     if (!mFrames.RemoveFrameIfPresent(aChild)) {
        1231               0 :       removed = false;
        1232                 :       // We didn't find the child in the parent's principal child list.
        1233                 :       // Maybe it's on the overflow list?
        1234               0 :       nsFrameList* frameList = GetOverflowFrames();
        1235               0 :       if (frameList) {
        1236               0 :         removed = frameList->RemoveFrameIfPresent(aChild);
        1237               0 :         if (frameList->IsEmpty()) {
        1238               0 :           DestroyOverflowList(aPresContext, nsnull);
        1239                 :         }
        1240                 :       }
        1241                 :     }
        1242                 :   }
        1243                 :
        1244               0 :   NS_POSTCONDITION(removed, "StealFrame: can't find aChild");
        1245               0 :   return removed ? NS_OK : NS_ERROR_UNEXPECTED;
        1246                 : }
        1247                 :
        1248                 : nsFrameList
        1249               0 : nsContainerFrame::StealFramesAfter(nsIFrame* aChild)
        1250                 : {
        1251               0 :   NS_ASSERTION(!aChild ||
        1252                 :                !(aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER),
        1253                 :                "StealFramesAfter doesn't handle overflow containers");
        1254               0 :   NS_ASSERTION(GetType() != nsGkAtoms::blockFrame, "unexpected call");
        1255                 :
        1256               0 :   if (!aChild) {
        1257               0 :     nsFrameList copy(mFrames);
        1258               0 :     mFrames.Clear();
        1259               0 :     return copy;
        1260                 :   }
        1261                 :
        1262               0 :   for (nsFrameList::FrameLinkEnumerator iter(mFrames); !iter.AtEnd();
        1263               0 :        iter.Next()) {
        1264               0 :     if (iter.PrevFrame() == aChild) {
        1265               0 :       return mFrames.ExtractTail(iter);
        1266                 :     }
        1267                 :   }
        1268                 :
        1269                 :   // We didn't find the child in the principal child list.
        1270                 :   // Maybe it's on the overflow list?
        1271               0 :   nsFrameList* overflowFrames = GetOverflowFrames();
        1272               0 :   if (overflowFrames) {
        1273               0 :     for (nsFrameList::FrameLinkEnumerator iter(*overflowFrames); !iter.AtEnd();
        1274               0 :          iter.Next()) {
        1275               0 :       if (iter.PrevFrame() == aChild) {
        1276               0 :         return overflowFrames->ExtractTail(iter);
        1277                 :       }
        1278                 :     }
        1279                 :   }
        1280                 :
        1281               0 :   NS_ERROR("StealFramesAfter: can't find aChild");
        1282               0 :   return nsFrameList::EmptyList();
        1283                 : }
        1284                 :
        1285                 : void
        1286               0 : nsContainerFrame::DestroyOverflowList(nsPresContext* aPresContext,
        1287                 :                                       nsIFrame*      aDestructRoot)
        1288                 : {
        1289                 :   nsFrameList* list =
        1290               0 :     RemovePropTableFrames(aPresContext, OverflowProperty());
        1291               0 :   if (list) {
        1292               0 :     if (aDestructRoot)
        1293               0 :       list->DestroyFrom(aDestructRoot);
        1294                 :     else
        1295               0 :       list->Destroy();
        1296                 :   }
        1297               0 : }
        1298                 :
        1299                 : /*
        1300                 :  * Create a next-in-flow for aFrame. Will return the newly created
        1301                 :  * frame in aNextInFlowResult <b>if and only if</b> a new frame is
        1302                 :  * created; otherwise nsnull is returned in aNextInFlowResult.
        1303                 :  */
        1304                 : nsresult
        1305               0 : nsContainerFrame::CreateNextInFlow(nsPresContext* aPresContext,
        1306                 :                                    nsIFrame*      aFrame,
        1307                 :                                    nsIFrame*&     aNextInFlowResult)
        1308                 : {
        1309               0 :   NS_PRECONDITION(GetType() != nsGkAtoms::blockFrame,
        1310                 :                   "you should have called nsBlockFrame::CreateContinuationFor instead");
        1311               0 :   NS_PRECONDITION(mFrames.ContainsFrame(aFrame), "expected an in-flow child frame");
        1312                 :
        1313               0 :   aNextInFlowResult = nsnull;
        1314                 :
        1315               0 :   nsIFrame* nextInFlow = aFrame->GetNextInFlow();
        1316               0 :   if (nsnull == nextInFlow) {
        1317                 :     // Create a continuation frame for the child frame and insert it
        1318                 :     // into our child list.
        1319                 :     nsresult rv = aPresContext->PresShell()->FrameConstructor()->
        1320               0 :       CreateContinuingFrame(aPresContext, aFrame, this, &nextInFlow);
        1321               0 :     if (NS_FAILED(rv)) {
        1322               0 :       return rv;
        1323                 :     }
        1324               0 :     mFrames.InsertFrame(nsnull, aFrame, nextInFlow);
        1325                 :
        1326               0 :     NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES,
        1327                 :        ("nsContainerFrame::CreateNextInFlow: frame=%p nextInFlow=%p",
        1328                 :         aFrame, nextInFlow));
        1329                 :
        1330               0 :     aNextInFlowResult = nextInFlow;
        1331                 :   }
        1332               0 :   return NS_OK;
        1333                 : }
        1334                 :
        1335                 : /**
        1336                 :  * Remove and delete aNextInFlow and its next-in-flows. Updates the sibling and flow
        1337                 :  * pointers
        1338                 :  */
        1339                 : void
        1340               0 : nsContainerFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
        1341                 :                                         nsIFrame*      aNextInFlow,
        1342                 :                                         bool           aDeletingEmptyFrames)
        1343                 : {
        1344                 : #ifdef DEBUG
        1345               0 :   nsIFrame* prevInFlow = aNextInFlow->GetPrevInFlow();
        1346                 : #endif
        1347               0 :   NS_PRECONDITION(prevInFlow, "bad prev-in-flow");
        1348                 :
        1349                 :   // If the next-in-flow has a next-in-flow then delete it, too (and
        1350                 :   // delete it first).
        1351                 :   // Do this in a loop so we don't overflow the stack for frames
        1352                 :   // with very many next-in-flows
        1353               0 :   nsIFrame* nextNextInFlow = aNextInFlow->GetNextInFlow();
        1354               0 :   if (nextNextInFlow) {
        1355               0 :     nsAutoTArray<nsIFrame*, 8> frames;
        1356               0 :     for (nsIFrame* f = nextNextInFlow; f; f = f->GetNextInFlow()) {
        1357               0 :       frames.AppendElement(f);
        1358                 :     }
        1359               0 :     for (PRInt32 i = frames.Length() - 1; i >= 0; --i) {
        1360               0 :       nsIFrame* delFrame = frames.ElementAt(i);
        1361               0 :       static_cast<nsContainerFrame*>(delFrame->GetParent())
        1362               0 :         ->DeleteNextInFlowChild(aPresContext, delFrame, aDeletingEmptyFrames);
        1363                 :     }
        1364                 :   }
        1365                 :
        1366               0 :   aNextInFlow->InvalidateFrameSubtree();
        1367                 :
        1368                 :   // Take the next-in-flow out of the parent's child list
        1369                 : #ifdef DEBUG
        1370                 :   nsresult rv =
        1371                 : #endif
        1372               0 :     StealFrame(aPresContext, aNextInFlow);
        1373               0 :   NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame failure");
        1374                 :
        1375                 : #ifdef DEBUG
        1376               0 :   if (aDeletingEmptyFrames) {
        1377               0 :     nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(aNextInFlow);
        1378                 :   }
        1379                 : #endif
        1380                 :
        1381                 :   // Delete the next-in-flow frame and its descendants. This will also
        1382                 :   // remove it from its next-in-flow/prev-in-flow chain.
        1383               0 :   aNextInFlow->Destroy();
        1384                 :
        1385               0 :   NS_POSTCONDITION(!prevInFlow->GetNextInFlow(), "non null next-in-flow");
        1386               0 : }
        1387                 :
        1388                 : /**
        1389                 :  * Set the frames on the overflow list
        1390                 :  */
        1391                 : void
        1392               0 : nsContainerFrame::SetOverflowFrames(nsPresContext* aPresContext,
        1393                 :                                     const nsFrameList& aOverflowFrames)
        1394                 : {
        1395               0 :   NS_PRECONDITION(aOverflowFrames.NotEmpty(), "Shouldn't be called");
        1396               0 :   nsFrameList* newList = new nsFrameList(aOverflowFrames);
        1397                 :
        1398               0 :   aPresContext->PropertyTable()->Set(this, OverflowProperty(), newList);
        1399               0 : }
        1400                 :
        1401                 : nsFrameList*
        1402               0 : nsContainerFrame::GetPropTableFrames(nsPresContext*                 aPresContext,
        1403                 :                                      const FramePropertyDescriptor* aProperty) const
        1404                 : {
        1405               0 :   FramePropertyTable* propTable = aPresContext->PropertyTable();
        1406               0 :   return static_cast<nsFrameList*>(propTable->Get(this, aProperty));
        1407                 : }
        1408                 :
        1409                 : nsFrameList*
        1410               0 : nsContainerFrame::RemovePropTableFrames(nsPresContext*                 aPresContext,
        1411                 :                                         const FramePropertyDescriptor* aProperty)
        1412                 : {
        1413               0 :   FramePropertyTable* propTable = aPresContext->PropertyTable();
        1414               0 :   return static_cast<nsFrameList*>(propTable->Remove(this, aProperty));
        1415                 : }
        1416                 :
        1417                 : bool
        1418               0 : nsContainerFrame::RemovePropTableFrame(nsPresContext*                 aPresContext,
        1419                 :                                        nsIFrame*                      aFrame,
        1420                 :                                        const FramePropertyDescriptor* aProperty)
        1421                 : {
        1422               0 :   nsFrameList* frameList = RemovePropTableFrames(aPresContext, aProperty);
        1423               0 :   if (!frameList) {
        1424                 :     // No such list
        1425               0 :     return false;
        1426                 :   }
        1427               0 :   if (!frameList->RemoveFrameIfPresent(aFrame)) {
        1428                 :     // Found list, but it doesn't have the frame. Put list back.
        1429               0 :     SetPropTableFrames(aPresContext, frameList, aProperty);
        1430               0 :     return false;
        1431                 :   }
        1432                 :
        1433               0 :   if (frameList->IsEmpty()) {
        1434                 :     // Removed frame and now list is empty. Delete it.
        1435               0 :     delete frameList;
        1436                 :   }
        1437                 :   else {
        1438                 :     // Removed frame, but list not empty. Put it back.
        1439               0 :     SetPropTableFrames(aPresContext, frameList, aProperty);
        1440                 :   }
        1441               0 :   return true;
        1442                 : }
        1443                 :
        1444                 : nsresult
        1445               0 : nsContainerFrame::SetPropTableFrames(nsPresContext*                 aPresContext,
        1446                 :                                      nsFrameList*                   aFrameList,
        1447                 :                                      const FramePropertyDescriptor* aProperty)
        1448                 : {
        1449               0 :   NS_PRECONDITION(aPresContext && aProperty && aFrameList, "null ptr");
        1450               0 :   NS_PRECONDITION(
        1451                 :     (aProperty != nsContainerFrame::OverflowContainersProperty() &&
        1452                 :      aProperty != nsContainerFrame::ExcessOverflowContainersProperty()) ||
        1453                 :     IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
        1454                 :     "this type of frame can't have overflow containers");
        1455               0 :   aPresContext->PropertyTable()->Set(this, aProperty, aFrameList);
        1456               0 :   return NS_OK;
        1457                 : }
        1458                 :
        1459                 : /**
        1460                 :  * Push aFromChild and its next siblings to the next-in-flow. Change the
        1461                 :  * geometric parent of each frame that's pushed. If there is no next-in-flow
        1462                 :  * the frames are placed on the overflow list (and the geometric parent is
        1463                 :  * left unchanged).
        1464                 :  *
        1465                 :  * Updates the next-in-flow's child count. Does <b>not</b> update the
        1466                 :  * pusher's child count.
        1467                 :  *
        1468                 :  * @param   aFromChild the first child frame to push. It is disconnected from
        1469                 :  *            aPrevSibling
        1470                 :  * @param   aPrevSibling aFromChild's previous sibling. Must not be null. It's
        1471                 :  *            an error to push a parent's first child frame
        1472                 :  */
        1473                 : void
        1474               0 : nsContainerFrame::PushChildren(nsPresContext* aPresContext,
        1475                 :                                nsIFrame*       aFromChild,
        1476                 :                                nsIFrame*       aPrevSibling)
        1477                 : {
        1478               0 :   NS_PRECONDITION(aFromChild, "null pointer");
        1479               0 :   NS_PRECONDITION(aPrevSibling, "pushing first child");
        1480               0 :   NS_PRECONDITION(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
        1481                 :
        1482                 :   // Disconnect aFromChild from its previous sibling
        1483               0 :   nsFrameList tail = mFrames.RemoveFramesAfter(aPrevSibling);
        1484                 :
        1485                 :   nsContainerFrame* nextInFlow =
        1486               0 :     static_cast<nsContainerFrame*>(GetNextInFlow());
        1487               0 :   if (nextInFlow) {
        1488                 :     // XXX This is not a very good thing to do. If it gets removed
        1489                 :     // then remove the copy of this routine that doesn't do this from
        1490                 :     // nsInlineFrame.
        1491                 :     // When pushing and pulling frames we need to check for whether any
        1492                 :     // views need to be reparented.
        1493               0 :     for (nsIFrame* f = aFromChild; f; f = f->GetNextSibling()) {
        1494               0 :       nsContainerFrame::ReparentFrameView(aPresContext, f, this, nextInFlow);
        1495                 :     }
        1496               0 :     nextInFlow->mFrames.InsertFrames(nextInFlow, nsnull, tail);
        1497                 :   }
        1498                 :   else {
        1499                 :     // Add the frames to our overflow list
        1500               0 :     SetOverflowFrames(aPresContext, tail);
        1501                 :   }
        1502               0 : }
        1503                 :
        1504                 : /**
        1505                 :  * Moves any frames on the overflow lists (the prev-in-flow's overflow list and
        1506                 :  * the receiver's overflow list) to the child list.
        1507                 :  *
        1508                 :  * Updates this frame's child count and content mapping.
        1509                 :  *
        1510                 :  * @return  true if any frames were moved and false otherwise
        1511                 :  */
        1512                 : bool
        1513               0 : nsContainerFrame::MoveOverflowToChildList(nsPresContext* aPresContext)
        1514                 : {
        1515               0 :   bool result = false;
        1516                 :
        1517                 :   // Check for an overflow list with our prev-in-flow
        1518               0 :   nsContainerFrame* prevInFlow = (nsContainerFrame*)GetPrevInFlow();
        1519               0 :   if (nsnull != prevInFlow) {
        1520               0 :     nsAutoPtr<nsFrameList> prevOverflowFrames(prevInFlow->StealOverflowFrames());
        1521               0 :     if (prevOverflowFrames) {
        1522                 :       // Tables are special; they can have repeated header/footer
        1523                 :       // frames on mFrames at this point.
        1524               0 :       NS_ASSERTION(mFrames.IsEmpty() || GetType() == nsGkAtoms::tableFrame,
        1525                 :                    "bad overflow list");
        1526                 :       // When pushing and pulling frames we need to check for whether any
        1527                 :       // views need to be reparented.
        1528                 :       nsContainerFrame::ReparentFrameViewList(aPresContext,
        1529               0 :                                               *prevOverflowFrames,
        1530               0 :                                               prevInFlow, this);
        1531               0 :       mFrames.AppendFrames(this, *prevOverflowFrames);
        1532               0 :       result = true;
        1533                 :     }
        1534                 :   }
        1535                 :
        1536                 :   // It's also possible that we have an overflow list for ourselves
        1537               0 :   nsAutoPtr<nsFrameList> overflowFrames(StealOverflowFrames());
        1538               0 :   if (overflowFrames) {
        1539               0 :     NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
        1540               0 :     mFrames.AppendFrames(nsnull, *overflowFrames);
        1541               0 :     result = true;
        1542                 :   }
        1543               0 :   return result;
        1544                 : }
        1545                 :
        1546               0 : nsOverflowContinuationTracker::nsOverflowContinuationTracker(nsPresContext*    aPresContext,
        1547                 :                                                              nsContainerFrame* aFrame,
        1548                 :                                                              bool              aWalkOOFFrames,
        1549                 :                                                              bool              aSkipOverflowContainerChildren)
        1550                 :   : mOverflowContList(nsnull),
        1551                 :     mPrevOverflowCont(nsnull),
        1552                 :     mSentry(nsnull),
        1553                 :     mParent(aFrame),
        1554                 :     mSkipOverflowContainerChildren(aSkipOverflowContainerChildren),
        1555               0 :     mWalkOOFFrames(aWalkOOFFrames)
        1556                 : {
        1557               0 :   NS_PRECONDITION(aFrame, "null frame pointer");
        1558                 :   nsContainerFrame* next = static_cast<nsContainerFrame*>
        1559               0 :                              (aFrame->GetNextInFlow());
        1560               0 :   if (next) {
        1561                 :     mOverflowContList = next->GetPropTableFrames(aPresContext,
        1562               0 :       nsContainerFrame::OverflowContainersProperty());
        1563               0 :     if (mOverflowContList) {
        1564               0 :       mParent = next;
        1565               0 :       SetUpListWalker();
        1566                 :     }
        1567                 :   }
        1568               0 :   if (!mOverflowContList) {
        1569                 :     mOverflowContList = mParent->GetPropTableFrames(aPresContext,
        1570               0 :       nsContainerFrame::ExcessOverflowContainersProperty());
        1571               0 :     if (mOverflowContList) {
        1572               0 :       SetUpListWalker();
        1573                 :     }
        1574                 :   }
        1575               0 : }
        1576                 :
        1577                 : /**
        1578                 :  * Helper function to walk past overflow continuations whose prev-in-flow
        1579                 :  * isn't a normal child and to set mSentry and mPrevOverflowCont correctly.
        1580                 :  */
        1581                 : void
        1582               0 : nsOverflowContinuationTracker::SetUpListWalker()
        1583                 : {
        1584               0 :   NS_ASSERTION(!mSentry && !mPrevOverflowCont,
        1585                 :                "forgot to reset mSentry or mPrevOverflowCont");
        1586               0 :   if (mOverflowContList) {
        1587               0 :     nsIFrame* cur = mOverflowContList->FirstChild();
        1588               0 :     if (mSkipOverflowContainerChildren) {
        1589               0 :       while (cur && (cur->GetPrevInFlow()->GetStateBits()
        1590                 :                      & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
        1591               0 :         mPrevOverflowCont = cur;
        1592               0 :         cur = cur->GetNextSibling();
        1593                 :       }
        1594               0 :       while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
        1595                 :                      == mWalkOOFFrames)) {
        1596               0 :         mPrevOverflowCont = cur;
        1597               0 :         cur = cur->GetNextSibling();
        1598                 :       }
        1599                 :     }
        1600               0 :     if (cur) {
        1601               0 :       mSentry = cur->GetPrevInFlow();
        1602                 :     }
        1603                 :   }
        1604               0 : }
        1605                 :
        1606                 : /**
        1607                 :  * Helper function to step forward through the overflow continuations list.
        1608                 :  * Sets mSentry and mPrevOverflowCont, skipping over OOF or non-OOF frames
        1609                 :  * as appropriate. May only be called when we have already set up an
        1610                 :  * mOverflowContList; mOverflowContList cannot be null.
        1611                 :  */
        1612                 : void
        1613               0 : nsOverflowContinuationTracker::StepForward()
        1614                 : {
        1615               0 :   NS_PRECONDITION(mOverflowContList, "null list");
        1616                 :
        1617                 :   // Step forward
        1618               0 :   if (mPrevOverflowCont) {
        1619               0 :     mPrevOverflowCont = mPrevOverflowCont->GetNextSibling();
        1620                 :   }
        1621                 :   else {
        1622               0 :     mPrevOverflowCont = mOverflowContList->FirstChild();
        1623                 :   }
        1624                 :
        1625                 :   // Skip over oof or non-oof frames as appropriate
        1626               0 :   if (mSkipOverflowContainerChildren) {
        1627               0 :     nsIFrame* cur = mPrevOverflowCont->GetNextSibling();
        1628               0 :     while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
        1629                 :                    == mWalkOOFFrames)) {
        1630               0 :       mPrevOverflowCont = cur;
        1631               0 :       cur = cur->GetNextSibling();
        1632                 :     }
        1633                 :   }
        1634                 :
        1635                 :   // Set up the sentry
        1636               0 :   mSentry = (mPrevOverflowCont->GetNextSibling())
        1637               0 :             ? mPrevOverflowCont->GetNextSibling()->GetPrevInFlow()
        1638               0 :             : nsnull;
        1639               0 : }
        1640                 :
        1641                 : nsresult
        1642               0 : nsOverflowContinuationTracker::Insert(nsIFrame*       aOverflowCont,
        1643                 :                                       nsReflowStatus& aReflowStatus)
        1644                 : {
        1645               0 :   NS_PRECONDITION(aOverflowCont, "null frame pointer");
        1646               0 :   NS_PRECONDITION(!mSkipOverflowContainerChildren || mWalkOOFFrames ==
        1647                 :                   !!(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
        1648                 :                   "shouldn't insert frame that doesn't match walker type");
        1649               0 :   NS_PRECONDITION(aOverflowCont->GetPrevInFlow(),
        1650                 :                   "overflow containers must have a prev-in-flow");
        1651               0 :   nsresult rv = NS_OK;
        1652               0 :   bool convertedToOverflowContainer = false;
        1653               0 :   nsPresContext* presContext = aOverflowCont->PresContext();
        1654               0 :   if (!mSentry || aOverflowCont != mSentry->GetNextInFlow()) {
        1655                 :     // Not in our list, so we need to add it
        1656               0 :     if (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
        1657                 :       // aOverflowCont is in some other overflow container list,
        1658                 :       // steal it first
        1659               0 :       NS_ASSERTION(!(mOverflowContList &&
        1660                 :                      mOverflowContList->ContainsFrame(aOverflowCont)),
        1661                 :                    "overflow containers out of order");
        1662               0 :       rv = static_cast<nsContainerFrame*>(aOverflowCont->GetParent())
        1663               0 :              ->StealFrame(presContext, aOverflowCont);
        1664               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1665                 :     }
        1666                 :     else {
        1667               0 :       aOverflowCont->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
        1668               0 :       convertedToOverflowContainer = true;
        1669                 :     }
        1670               0 :     if (!mOverflowContList) {
        1671               0 :       mOverflowContList = new nsFrameList();
        1672                 :       rv = mParent->SetPropTableFrames(presContext, mOverflowContList,
        1673               0 :         nsContainerFrame::ExcessOverflowContainersProperty());
        1674               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1675               0 :       SetUpListWalker();
        1676                 :     }
        1677               0 :     if (aOverflowCont->GetParent() != mParent) {
        1678                 :       nsContainerFrame::ReparentFrameView(presContext, aOverflowCont,
        1679                 :                                           aOverflowCont->GetParent(),
        1680               0 :                                           mParent);
        1681                 :     }
        1682               0 :     mOverflowContList->InsertFrame(mParent, mPrevOverflowCont, aOverflowCont);
        1683               0 :     aReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
        1684                 :   }
        1685                 :
        1686                 :   // If we need to reflow it, mark it dirty
        1687               0 :   if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW)
        1688               0 :     aOverflowCont->AddStateBits(NS_FRAME_IS_DIRTY);
        1689                 :
        1690                 :   // It's in our list, just step forward
        1691               0 :   StepForward();
        1692               0 :   NS_ASSERTION(mPrevOverflowCont == aOverflowCont ||
        1693                 :                (mSkipOverflowContainerChildren &&
        1694                 :                 (mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
        1695                 :                 (aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
        1696                 :               "OverflowContTracker in unexpected state");
        1697                 :
        1698               0 :   if (convertedToOverflowContainer) {
        1699                 :     // Convert all non-overflow-container continuations of aOverflowCont
        1700                 :     // into overflow containers and move them to our overflow
        1701                 :     // tracker. This preserves the invariant that the next-continuations
        1702                 :     // of an overflow container are also overflow containers.
        1703               0 :     nsIFrame* f = aOverflowCont->GetNextContinuation();
        1704               0 :     if (f && !(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
        1705               0 :       nsContainerFrame* parent = static_cast<nsContainerFrame*>(f->GetParent());
        1706               0 :       rv = parent->StealFrame(presContext, f);
        1707               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1708               0 :       Insert(f, aReflowStatus);
        1709                 :     }
        1710                 :   }
        1711               0 :   return rv;
        1712                 : }
        1713                 :
        1714                 : void
        1715               0 : nsOverflowContinuationTracker::Finish(nsIFrame* aChild)
        1716                 : {
        1717               0 :   NS_PRECONDITION(aChild, "null ptr");
        1718               0 :   NS_PRECONDITION(aChild->GetNextInFlow(),
        1719                 :                 "supposed to call Finish *before* deleting next-in-flow!");
        1720                 :
        1721               0 :   for (nsIFrame* f = aChild; f; f = f->GetNextInFlow()) {
        1722                 :     // Make sure we drop all references if the only frame
        1723                 :     // in the overflow containers list is about to be destroyed
        1724               0 :     if (mOverflowContList &&
        1725               0 :         mOverflowContList->FirstChild() == f->GetNextInFlow() &&
        1726               0 :         !f->GetNextInFlow()->GetNextSibling()) {
        1727               0 :       mOverflowContList = nsnull;
        1728               0 :       mPrevOverflowCont = nsnull;
        1729               0 :       mSentry = nsnull;
        1730               0 :       mParent = static_cast<nsContainerFrame*>(f->GetParent());
        1731               0 :       break;
        1732                 :     }
        1733               0 :     if (f == mSentry) {
        1734                 :       // Step past aChild
        1735               0 :       nsIFrame* prevOverflowCont = mPrevOverflowCont;
        1736               0 :       StepForward();
        1737               0 :       if (mPrevOverflowCont == f->GetNextInFlow()) {
        1738                 :         // Pull mPrevOverflowChild back to aChild's prevSibling:
        1739                 :         // aChild will be removed from our list by our caller
        1740               0 :         mPrevOverflowCont = prevOverflowCont;
        1741                 :       }
        1742                 :     }
        1743                 :   }
        1744               0 : }
        1745                 :
        1746                 : /////////////////////////////////////////////////////////////////////////////
        1747                 : // Debugging
        1748                 :
        1749                 : #ifdef NS_DEBUG
        1750                 : NS_IMETHODIMP
        1751               0 : nsContainerFrame::List(FILE* out, PRInt32 aIndent) const
        1752                 : {
        1753               0 :   IndentBy(out, aIndent);
        1754               0 :   ListTag(out);
        1755                 : #ifdef DEBUG_waterson
        1756                 :   fprintf(out, " [parent=%p]", static_cast<void*>(mParent));
        1757                 : #endif
        1758               0 :   if (HasView()) {
        1759               0 :     fprintf(out, " [view=%p]", static_cast<void*>(GetView()));
        1760                 :   }
        1761               0 :   if (GetNextSibling()) {
        1762               0 :     fprintf(out, " next=%p", static_cast<void*>(GetNextSibling()));
        1763                 :   }
        1764               0 :   if (nsnull != GetPrevContinuation()) {
        1765               0 :     fprintf(out, " prev-continuation=%p", static_cast<void*>(GetPrevContinuation()));
        1766                 :   }
        1767               0 :   if (nsnull != GetNextContinuation()) {
        1768               0 :     fprintf(out, " next-continuation=%p", static_cast<void*>(GetNextContinuation()));
        1769                 :   }
        1770               0 :   void* IBsibling = Properties().Get(IBSplitSpecialSibling());
        1771               0 :   if (IBsibling) {
        1772               0 :     fprintf(out, " IBSplitSpecialSibling=%p", IBsibling);
        1773                 :   }
        1774               0 :   void* IBprevsibling = Properties().Get(IBSplitSpecialPrevSibling());
        1775               0 :   if (IBprevsibling) {
        1776               0 :     fprintf(out, " IBSplitSpecialPrevSibling=%p", IBprevsibling);
        1777                 :   }
        1778               0 :   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
        1779               0 :   if (0 != mState) {
        1780               0 :     fprintf(out, " [state=%016llx]", (unsigned long long)mState);
        1781                 :   }
        1782               0 :   fprintf(out, " [content=%p]", static_cast<void*>(mContent));
        1783               0 :   nsContainerFrame* f = const_cast<nsContainerFrame*>(this);
        1784               0 :   if (f->HasOverflowAreas()) {
        1785               0 :     nsRect overflowArea = f->GetVisualOverflowRect();
        1786                 :     fprintf(out, " [vis-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
        1787               0 :             overflowArea.width, overflowArea.height);
        1788               0 :     overflowArea = f->GetScrollableOverflowRect();
        1789                 :     fprintf(out, " [scr-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
        1790               0 :             overflowArea.width, overflowArea.height);
        1791                 :   }
        1792               0 :   fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext));
        1793               0 :   nsIAtom* pseudoTag = mStyleContext->GetPseudo();
        1794               0 :   if (pseudoTag) {
        1795               0 :     nsAutoString atomString;
        1796               0 :     pseudoTag->ToString(atomString);
        1797                 :     fprintf(out, " pst=%s",
        1798               0 :             NS_LossyConvertUTF16toASCII(atomString).get());
        1799                 :   }
        1800                 :
        1801                 :   // Output the children
        1802               0 :   bool outputOneList = false;
        1803               0 :   ChildListIterator lists(this);
        1804               0 :   for (; !lists.IsDone(); lists.Next()) {
        1805               0 :     if (outputOneList) {
        1806               0 :       IndentBy(out, aIndent);
        1807                 :     }
        1808               0 :     outputOneList = true;
        1809               0 :     fputs(mozilla::layout::ChildListName(lists.CurrentID()), out);
        1810               0 :     fputs("<\n", out);
        1811               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
        1812               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
        1813               0 :       nsIFrame* kid = childFrames.get();
        1814                 :       // Verify the child frame's parent frame pointer is correct
        1815               0 :       NS_ASSERTION(kid->GetParent() == this, "bad parent frame pointer");
        1816                 :
        1817                 :       // Have the child frame list
        1818               0 :       kid->List(out, aIndent + 1);
        1819                 :     }
        1820               0 :     IndentBy(out, aIndent);
        1821               0 :     fputs(">\n", out);
        1822                 :   }
        1823                 :
        1824               0 :   if (!outputOneList) {
        1825               0 :     fputs("<>\n", out);
        1826                 :   }
        1827                 :
        1828               0 :   return NS_OK;
        1829                 : }
        1830                 : #endif

Generated by: LCOV version 1.7