LCOV - code coverage report
Current view: directory - layout/generic - nsContainerFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 717 0 0.0 %
Date: 2012-06-02 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; ) {
    1722                 :     // Make sure we drop all references if all the frames in the
    1723                 :     // overflow containers list are about to be destroyed.
    1724               0 :     nsIFrame* nif = f->GetNextInFlow();
    1725               0 :     if (mOverflowContList &&
    1726               0 :         mOverflowContList->FirstChild() == nif &&
    1727               0 :         (!nif->GetNextSibling() ||
    1728               0 :          nif->GetNextSibling() == nif->GetNextInFlow())) {
    1729               0 :       mOverflowContList = nsnull;
    1730               0 :       mPrevOverflowCont = nsnull;
    1731               0 :       mSentry = nsnull;
    1732               0 :       mParent = static_cast<nsContainerFrame*>(f->GetParent());
    1733               0 :       break;
    1734                 :     }
    1735               0 :     if (f == mSentry) {
    1736                 :       // Step past aChild
    1737               0 :       nsIFrame* prevOverflowCont = mPrevOverflowCont;
    1738               0 :       StepForward();
    1739               0 :       if (mPrevOverflowCont == nif) {
    1740                 :         // Pull mPrevOverflowChild back to aChild's prevSibling:
    1741                 :         // aChild will be removed from our list by our caller
    1742               0 :         mPrevOverflowCont = prevOverflowCont;
    1743                 :       }
    1744                 :     }
    1745               0 :     f = nif;
    1746                 :   }
    1747               0 : }
    1748                 : 
    1749                 : /////////////////////////////////////////////////////////////////////////////
    1750                 : // Debugging
    1751                 : 
    1752                 : #ifdef NS_DEBUG
    1753                 : NS_IMETHODIMP
    1754               0 : nsContainerFrame::List(FILE* out, PRInt32 aIndent) const
    1755                 : {
    1756               0 :   IndentBy(out, aIndent);
    1757               0 :   ListTag(out);
    1758                 : #ifdef DEBUG_waterson
    1759                 :   fprintf(out, " [parent=%p]", static_cast<void*>(mParent));
    1760                 : #endif
    1761               0 :   if (HasView()) {
    1762               0 :     fprintf(out, " [view=%p]", static_cast<void*>(GetView()));
    1763                 :   }
    1764               0 :   if (GetNextSibling()) {
    1765               0 :     fprintf(out, " next=%p", static_cast<void*>(GetNextSibling()));
    1766                 :   }
    1767               0 :   if (nsnull != GetPrevContinuation()) {
    1768               0 :     fprintf(out, " prev-continuation=%p", static_cast<void*>(GetPrevContinuation()));
    1769                 :   }
    1770               0 :   if (nsnull != GetNextContinuation()) {
    1771               0 :     fprintf(out, " next-continuation=%p", static_cast<void*>(GetNextContinuation()));
    1772                 :   }
    1773               0 :   void* IBsibling = Properties().Get(IBSplitSpecialSibling());
    1774               0 :   if (IBsibling) {
    1775               0 :     fprintf(out, " IBSplitSpecialSibling=%p", IBsibling);
    1776                 :   }
    1777               0 :   void* IBprevsibling = Properties().Get(IBSplitSpecialPrevSibling());
    1778               0 :   if (IBprevsibling) {
    1779               0 :     fprintf(out, " IBSplitSpecialPrevSibling=%p", IBprevsibling);
    1780                 :   }
    1781               0 :   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
    1782               0 :   if (0 != mState) {
    1783               0 :     fprintf(out, " [state=%016llx]", (unsigned long long)mState);
    1784                 :   }
    1785               0 :   fprintf(out, " [content=%p]", static_cast<void*>(mContent));
    1786               0 :   nsContainerFrame* f = const_cast<nsContainerFrame*>(this);
    1787               0 :   if (f->HasOverflowAreas()) {
    1788               0 :     nsRect overflowArea = f->GetVisualOverflowRect();
    1789                 :     fprintf(out, " [vis-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
    1790               0 :             overflowArea.width, overflowArea.height);
    1791               0 :     overflowArea = f->GetScrollableOverflowRect();
    1792                 :     fprintf(out, " [scr-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
    1793               0 :             overflowArea.width, overflowArea.height);
    1794                 :   }
    1795               0 :   fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext));
    1796               0 :   nsIAtom* pseudoTag = mStyleContext->GetPseudo();
    1797               0 :   if (pseudoTag) {
    1798               0 :     nsAutoString atomString;
    1799               0 :     pseudoTag->ToString(atomString);
    1800                 :     fprintf(out, " pst=%s",
    1801               0 :             NS_LossyConvertUTF16toASCII(atomString).get());
    1802                 :   }
    1803                 : 
    1804                 :   // Output the children
    1805               0 :   bool outputOneList = false;
    1806               0 :   ChildListIterator lists(this);
    1807               0 :   for (; !lists.IsDone(); lists.Next()) {
    1808               0 :     if (outputOneList) {
    1809               0 :       IndentBy(out, aIndent);
    1810                 :     }
    1811               0 :     outputOneList = true;
    1812               0 :     fputs(mozilla::layout::ChildListName(lists.CurrentID()), out);
    1813               0 :     fputs("<\n", out);
    1814               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    1815               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    1816               0 :       nsIFrame* kid = childFrames.get();
    1817                 :       // Verify the child frame's parent frame pointer is correct
    1818               0 :       NS_ASSERTION(kid->GetParent() == this, "bad parent frame pointer");
    1819                 : 
    1820                 :       // Have the child frame list
    1821               0 :       kid->List(out, aIndent + 1);
    1822                 :     }
    1823               0 :     IndentBy(out, aIndent);
    1824               0 :     fputs(">\n", out);
    1825                 :   }
    1826                 : 
    1827               0 :   if (!outputOneList) {
    1828               0 :     fputs("<>\n", out);
    1829                 :   }
    1830                 : 
    1831               0 :   return NS_OK;
    1832                 : }
    1833                 : #endif

Generated by: LCOV version 1.7