LCOV - code coverage report
Current view: directory - view/src - nsViewManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 611 0 0.0 %
Date: 2012-06-02 Functions: 55 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                 :  *   Patrick C. Beard <beard@netscape.com>
      24                 :  *   Kevin McCluskey  <kmcclusk@netscape.com>
      25                 :  *   Robert O'Callahan <roc+@cs.cmu.edu>
      26                 :  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : #define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1)
      43                 : #include "plarena.h"
      44                 : 
      45                 : #include "nsAutoPtr.h"
      46                 : #include "nsViewManager.h"
      47                 : #include "nsGfxCIID.h"
      48                 : #include "nsView.h"
      49                 : #include "nsISupportsArray.h"
      50                 : #include "nsCOMPtr.h"
      51                 : #include "nsGUIEvent.h"
      52                 : #include "nsRegion.h"
      53                 : #include "nsHashtable.h"
      54                 : #include "nsCOMArray.h"
      55                 : #include "nsThreadUtils.h"
      56                 : #include "nsContentUtils.h"
      57                 : #include "nsIPluginWidget.h"
      58                 : #include "nsXULPopupManager.h"
      59                 : #include "nsIPresShell.h"
      60                 : #include "nsPresContext.h"
      61                 : #include "nsEventStateManager.h"
      62                 : #include "mozilla/StartupTimeline.h"
      63                 : #include "sampler.h"
      64                 : 
      65                 : /**
      66                 :    XXX TODO XXX
      67                 : 
      68                 :    DeCOMify newly private methods
      69                 :    Optimize view storage
      70                 : */
      71                 : 
      72                 : /**
      73                 :    A note about platform assumptions:
      74                 : 
      75                 :    We assume that a widget is z-ordered on top of its parent.
      76                 :    
      77                 :    We do NOT assume anything about the relative z-ordering of sibling widgets. Even though
      78                 :    we ask for a specific z-order, we don't assume that widget z-ordering actually works.
      79                 : */
      80                 : 
      81                 : #define NSCOORD_NONE      PR_INT32_MIN
      82                 : 
      83                 : #undef DEBUG_MOUSE_LOCATION
      84                 : 
      85                 : PRInt32 nsViewManager::mVMCount = 0;
      86                 : 
      87                 : // Weakly held references to all of the view managers
      88                 : nsVoidArray* nsViewManager::gViewManagers = nsnull;
      89                 : PRUint32 nsViewManager::gLastUserEventTime = 0;
      90                 : 
      91               0 : nsViewManager::nsViewManager()
      92                 :   : mDelayedResize(NSCOORD_NONE, NSCOORD_NONE)
      93               0 :   , mRootViewManager(this)
      94                 : {
      95               0 :   if (gViewManagers == nsnull) {
      96               0 :     NS_ASSERTION(mVMCount == 0, "View Manager count is incorrect");
      97                 :     // Create an array to hold a list of view managers
      98               0 :     gViewManagers = new nsVoidArray;
      99                 :   }
     100                 :  
     101               0 :   gViewManagers->AppendElement(this);
     102                 : 
     103               0 :   ++mVMCount;
     104                 : 
     105                 :   // NOTE:  we use a zeroing operator new, so all data members are
     106                 :   // assumed to be cleared here.
     107               0 :   mHasPendingUpdates = false;
     108               0 :   mHasPendingWidgetGeometryChanges = false;
     109               0 :   mRecursiveRefreshPending = false;
     110               0 : }
     111                 : 
     112               0 : nsViewManager::~nsViewManager()
     113                 : {
     114               0 :   if (mRootView) {
     115                 :     // Destroy any remaining views
     116               0 :     mRootView->Destroy();
     117               0 :     mRootView = nsnull;
     118                 :   }
     119                 : 
     120               0 :   if (!IsRootVM()) {
     121                 :     // We have a strong ref to mRootViewManager
     122               0 :     NS_RELEASE(mRootViewManager);
     123                 :   }
     124                 : 
     125               0 :   NS_ASSERTION((mVMCount > 0), "underflow of viewmanagers");
     126               0 :   --mVMCount;
     127                 : 
     128                 : #ifdef DEBUG
     129                 :   bool removed =
     130                 : #endif
     131               0 :     gViewManagers->RemoveElement(this);
     132               0 :   NS_ASSERTION(removed, "Viewmanager instance not was not in the global list of viewmanagers");
     133                 : 
     134               0 :   if (0 == mVMCount) {
     135                 :     // There aren't any more view managers so
     136                 :     // release the global array of view managers
     137                 :    
     138               0 :     NS_ASSERTION(gViewManagers != nsnull, "About to delete null gViewManagers");
     139               0 :     delete gViewManagers;
     140               0 :     gViewManagers = nsnull;
     141                 :   }
     142                 : 
     143               0 :   mPresShell = nsnull;
     144               0 : }
     145                 : 
     146               0 : NS_IMPL_ISUPPORTS1(nsViewManager, nsIViewManager)
     147                 : 
     148                 : // We don't hold a reference to the presentation context because it
     149                 : // holds a reference to us.
     150               0 : NS_IMETHODIMP nsViewManager::Init(nsDeviceContext* aContext)
     151                 : {
     152               0 :   NS_PRECONDITION(nsnull != aContext, "null ptr");
     153                 : 
     154               0 :   if (nsnull == aContext) {
     155               0 :     return NS_ERROR_NULL_POINTER;
     156                 :   }
     157               0 :   if (nsnull != mContext) {
     158               0 :     return NS_ERROR_ALREADY_INITIALIZED;
     159                 :   }
     160               0 :   mContext = aContext;
     161                 : 
     162               0 :   return NS_OK;
     163                 : }
     164                 : 
     165                 : NS_IMETHODIMP_(nsIView *)
     166               0 : nsViewManager::CreateView(const nsRect& aBounds,
     167                 :                           const nsIView* aParent,
     168                 :                           nsViewVisibility aVisibilityFlag)
     169                 : {
     170               0 :   nsView *v = new nsView(this, aVisibilityFlag);
     171               0 :   if (v) {
     172               0 :     v->SetParent(static_cast<nsView*>(const_cast<nsIView*>(aParent)));
     173               0 :     v->SetPosition(aBounds.x, aBounds.y);
     174               0 :     nsRect dim(0, 0, aBounds.width, aBounds.height);
     175               0 :     v->SetDimensions(dim, false);
     176                 :   }
     177               0 :   return v;
     178                 : }
     179                 : 
     180                 : NS_IMETHODIMP_(nsIView*)
     181               0 : nsViewManager::GetRootView()
     182                 : {
     183               0 :   return mRootView;
     184                 : }
     185                 : 
     186               0 : NS_IMETHODIMP nsViewManager::SetRootView(nsIView *aView)
     187                 : {
     188               0 :   nsView* view = static_cast<nsView*>(aView);
     189                 : 
     190               0 :   NS_PRECONDITION(!view || view->GetViewManager() == this,
     191                 :                   "Unexpected viewmanager on root view");
     192                 :   
     193                 :   // Do NOT destroy the current root view. It's the caller's responsibility
     194                 :   // to destroy it
     195               0 :   mRootView = view;
     196                 : 
     197               0 :   if (mRootView) {
     198               0 :     nsView* parent = mRootView->GetParent();
     199               0 :     if (parent) {
     200                 :       // Calling InsertChild on |parent| will InvalidateHierarchy() on us, so
     201                 :       // no need to set mRootViewManager ourselves here.
     202               0 :       parent->InsertChild(mRootView, nsnull);
     203                 :     } else {
     204               0 :       InvalidateHierarchy();
     205                 :     }
     206                 : 
     207               0 :     mRootView->SetZIndex(false, 0, false);
     208                 :   }
     209                 :   // Else don't touch mRootViewManager
     210                 : 
     211               0 :   return NS_OK;
     212                 : }
     213                 : 
     214               0 : NS_IMETHODIMP nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeight)
     215                 : {
     216               0 :   if (nsnull != mRootView) {
     217               0 :     if (mDelayedResize == nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
     218               0 :       nsRect dim = mRootView->GetDimensions();
     219               0 :       *aWidth = dim.width;
     220               0 :       *aHeight = dim.height;
     221                 :     } else {
     222               0 :       *aWidth = mDelayedResize.width;
     223               0 :       *aHeight = mDelayedResize.height;
     224                 :     }
     225                 :   }
     226                 :   else
     227                 :     {
     228               0 :       *aWidth = 0;
     229               0 :       *aHeight = 0;
     230                 :     }
     231               0 :   return NS_OK;
     232                 : }
     233                 : 
     234               0 : void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight)
     235                 : {
     236               0 :   nsRect oldDim = mRootView->GetDimensions();
     237               0 :   nsRect newDim(0, 0, aWidth, aHeight);
     238                 :   // We care about resizes even when one dimension is already zero.
     239               0 :   if (!oldDim.IsEqualEdges(newDim)) {
     240                 :     // Don't resize the widget. It is already being set elsewhere.
     241               0 :     mRootView->SetDimensions(newDim, true, false);
     242               0 :     if (mPresShell)
     243               0 :       mPresShell->ResizeReflow(aWidth, aHeight);
     244                 :   }
     245               0 : }
     246                 : 
     247               0 : NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight)
     248                 : {
     249               0 :   if (mRootView) {
     250               0 :     if (mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) {
     251               0 :       if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
     252               0 :           mDelayedResize != nsSize(aWidth, aHeight)) {
     253                 :         // We have a delayed resize; that now obsolete size may already have
     254                 :         // been flushed to the PresContext so we need to update the PresContext
     255                 :         // with the new size because if the new size is exactly the same as the
     256                 :         // root view's current size then DoSetWindowDimensions will not
     257                 :         // request a resize reflow (which would correct it). See bug 617076.
     258               0 :         mDelayedResize = nsSize(aWidth, aHeight);
     259               0 :         FlushDelayedResize(false);
     260                 :       }
     261               0 :       mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
     262               0 :       DoSetWindowDimensions(aWidth, aHeight);
     263                 :     } else {
     264               0 :       mDelayedResize.SizeTo(aWidth, aHeight);
     265               0 :       if (mPresShell && mPresShell->GetDocument()) {
     266               0 :         mPresShell->GetDocument()->SetNeedStyleFlush();
     267                 :       }
     268                 :     }
     269                 :   }
     270                 : 
     271               0 :   return NS_OK;
     272                 : }
     273                 : 
     274               0 : NS_IMETHODIMP nsViewManager::FlushDelayedResize(bool aDoReflow)
     275                 : {
     276               0 :   if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
     277               0 :     if (aDoReflow) {
     278               0 :       DoSetWindowDimensions(mDelayedResize.width, mDelayedResize.height);
     279               0 :       mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
     280               0 :     } else if (mPresShell) {
     281               0 :       nsPresContext* presContext = mPresShell->GetPresContext();
     282               0 :       if (presContext) {
     283               0 :         presContext->SetVisibleArea(nsRect(nsPoint(0, 0), mDelayedResize));
     284                 :       }
     285                 :     }
     286                 :   }
     287               0 :   return NS_OK;
     288                 : }
     289                 : 
     290                 : // Convert aIn from being relative to and in appunits of aFromView, to being
     291                 : // relative to and in appunits of aToView.
     292               0 : static nsRegion ConvertRegionBetweenViews(const nsRegion& aIn,
     293                 :                                           nsView* aFromView,
     294                 :                                           nsView* aToView)
     295                 : {
     296               0 :   nsRegion out = aIn;
     297               0 :   out.MoveBy(aFromView->GetOffsetTo(aToView));
     298                 :   out = out.ConvertAppUnitsRoundOut(
     299               0 :     aFromView->GetViewManager()->AppUnitsPerDevPixel(),
     300               0 :     aToView->GetViewManager()->AppUnitsPerDevPixel());
     301                 :   return out;
     302                 : }
     303                 : 
     304               0 : nsIView* nsIViewManager::GetDisplayRootFor(nsIView* aView)
     305                 : {
     306               0 :   nsIView *displayRoot = aView;
     307               0 :   for (;;) {
     308               0 :     nsIView *displayParent = displayRoot->GetParent();
     309               0 :     if (!displayParent)
     310               0 :       return displayRoot;
     311                 : 
     312               0 :     if (displayRoot->GetFloating() && !displayParent->GetFloating())
     313               0 :       return displayRoot;
     314                 : 
     315                 :     // If we have a combobox dropdown popup within a panel popup, both the view
     316                 :     // for the dropdown popup and its parent will be floating, so we need to
     317                 :     // distinguish this situation. We do this by looking for a widget. Any view
     318                 :     // with a widget is a display root, except for plugins.
     319               0 :     nsIWidget* widget = displayRoot->GetWidget();
     320               0 :     if (widget) {
     321                 :       nsWindowType type;
     322               0 :       widget->GetWindowType(type);
     323               0 :       if (type == eWindowType_popup) {
     324               0 :         NS_ASSERTION(displayRoot->GetFloating() && displayParent->GetFloating(),
     325                 :           "this should only happen with floating views that have floating parents");
     326               0 :         return displayRoot;
     327                 :       }
     328                 :     }
     329                 : 
     330               0 :     displayRoot = displayParent;
     331                 :   }
     332                 : }
     333                 : 
     334                 : /**
     335                 :    aRegion is given in device coordinates!!
     336                 :    aContext may be null, in which case layers should be used for
     337                 :    rendering.
     338                 : */
     339               0 : void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
     340                 :                             const nsIntRegion& aRegion,
     341                 :                             bool aWillSendDidPaint)
     342                 : {
     343               0 :   NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch");
     344               0 :   NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
     345                 : 
     346                 :   // damageRegion is the damaged area, in twips, relative to the view origin
     347               0 :   nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel());
     348                 :   // move region from widget coordinates into view coordinates
     349               0 :   damageRegion.MoveBy(-aView->ViewToWidgetOffset());
     350                 : 
     351               0 :   if (damageRegion.IsEmpty()) {
     352                 : #ifdef DEBUG_roc
     353                 :     nsRect viewRect = aView->GetDimensions();
     354                 :     nsRect damageRect = damageRegion.GetBounds();
     355                 :     printf("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n",
     356                 :            damageRect.x, damageRect.y, damageRect.width, damageRect.height,
     357                 :            viewRect.x, viewRect.y, viewRect.width, viewRect.height);
     358                 : #endif
     359                 :     return;
     360                 :   }
     361                 : 
     362               0 :   NS_ASSERTION(!IsPainting(), "recursive painting not permitted");
     363               0 :   if (IsPainting()) {
     364               0 :     RootViewManager()->mRecursiveRefreshPending = true;
     365                 :     return;
     366                 :   }  
     367                 : 
     368                 :   {
     369               0 :     nsAutoScriptBlocker scriptBlocker;
     370               0 :     SetPainting(true);
     371                 : 
     372               0 :     NS_ASSERTION(GetDisplayRootFor(aView) == aView,
     373                 :                  "Widgets that we paint must all be display roots");
     374                 : 
     375               0 :     if (mPresShell) {
     376                 :       mPresShell->Paint(aView, aWidget, damageRegion, aRegion,
     377               0 :                         aWillSendDidPaint);
     378               0 :       mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT);
     379                 :     }
     380                 : 
     381               0 :     SetPainting(false);
     382                 :   }
     383                 : 
     384               0 :   if (RootViewManager()->mRecursiveRefreshPending) {
     385               0 :     RootViewManager()->mRecursiveRefreshPending = false;
     386               0 :     InvalidateAllViews();
     387                 :   }
     388                 : }
     389                 : 
     390               0 : void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
     391                 :                                                  bool aFlushDirtyRegion)
     392                 : {
     393               0 :   NS_ASSERTION(IsRootVM(), "Updates will be missed");
     394                 : 
     395                 :   // Protect against a null-view.
     396               0 :   if (!aView) {
     397               0 :     return;
     398                 :   }
     399                 : 
     400               0 :   if (aView->HasWidget()) {
     401               0 :     aView->ResetWidgetBounds(false, true);
     402                 :   }
     403                 : 
     404                 :   // process pending updates in child view.
     405               0 :   for (nsView* childView = aView->GetFirstChild(); childView;
     406                 :        childView = childView->GetNextSibling()) {
     407               0 :     ProcessPendingUpdatesForView(childView, aFlushDirtyRegion);
     408                 :   }
     409                 : 
     410                 :   // Push out updates after we've processed the children; ensures that
     411                 :   // damage is applied based on the final widget geometry
     412               0 :   if (aFlushDirtyRegion) {
     413               0 :     FlushDirtyRegionToWidget(aView);
     414                 :   }
     415                 : }
     416                 : 
     417               0 : void nsViewManager::FlushDirtyRegionToWidget(nsView* aView)
     418                 : {
     419               0 :   if (!aView->HasNonEmptyDirtyRegion())
     420               0 :     return;
     421                 : 
     422               0 :   nsRegion* dirtyRegion = aView->GetDirtyRegion();
     423               0 :   nsView* nearestViewWithWidget = aView;
     424               0 :   while (!nearestViewWithWidget->HasWidget() &&
     425               0 :          nearestViewWithWidget->GetParent()) {
     426               0 :     nearestViewWithWidget = nearestViewWithWidget->GetParent();
     427                 :   }
     428                 :   nsRegion r =
     429               0 :     ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget);
     430               0 :   nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager();
     431               0 :   widgetVM->InvalidateWidgetArea(nearestViewWithWidget, r);
     432               0 :   dirtyRegion->SetEmpty();
     433                 : }
     434                 : 
     435               0 : NS_IMETHODIMP nsViewManager::InvalidateView(nsIView *aView)
     436                 : {
     437                 :   // Mark the entire view as damaged
     438               0 :   return InvalidateView(aView, aView->GetDimensions());
     439                 : }
     440                 : 
     441                 : static void
     442               0 : AddDirtyRegion(nsView *aView, const nsRegion &aDamagedRegion)
     443                 : {
     444               0 :   nsRegion* dirtyRegion = aView->GetDirtyRegion();
     445               0 :   if (!dirtyRegion)
     446               0 :     return;
     447                 : 
     448               0 :   dirtyRegion->Or(*dirtyRegion, aDamagedRegion);
     449               0 :   dirtyRegion->SimplifyOutward(8);
     450                 : }
     451                 : 
     452                 : void
     453               0 : nsViewManager::PostPendingUpdate()
     454                 : {
     455               0 :   nsViewManager* rootVM = RootViewManager();
     456               0 :   rootVM->mHasPendingUpdates = true;
     457               0 :   rootVM->mHasPendingWidgetGeometryChanges = true;
     458               0 :   if (rootVM->mPresShell) {
     459               0 :     rootVM->mPresShell->ScheduleViewManagerFlush();
     460                 :   }
     461               0 : }
     462                 : 
     463                 : /**
     464                 :  * @param aDamagedRegion this region, relative to aWidgetView, is invalidated in
     465                 :  * every widget child of aWidgetView, plus aWidgetView's own widget
     466                 :  */
     467                 : void
     468               0 : nsViewManager::InvalidateWidgetArea(nsView *aWidgetView,
     469                 :                                     const nsRegion &aDamagedRegion)
     470                 : {
     471               0 :   NS_ASSERTION(aWidgetView->GetViewManager() == this,
     472                 :                "InvalidateWidgetArea called on view we don't own");
     473               0 :   nsIWidget* widget = aWidgetView->GetWidget();
     474                 : 
     475                 : #if 0
     476                 :   nsRect dbgBounds = aDamagedRegion.GetBounds();
     477                 :   printf("InvalidateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n",
     478                 :     aWidgetView, aWidgetView->IsAttachedToTopLevel(),
     479                 :     widget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height);
     480                 : #endif
     481                 : 
     482                 :   // If the bounds don't overlap at all, there's nothing to do
     483               0 :   nsRegion intersection;
     484               0 :   intersection.And(aWidgetView->GetInvalidationDimensions(), aDamagedRegion);
     485               0 :   if (intersection.IsEmpty()) {
     486                 :     return;
     487                 :   }
     488                 : 
     489                 :   // If the widget is hidden, it don't cover nothing
     490               0 :   if (widget) {
     491                 :     bool visible;
     492               0 :     widget->IsVisible(visible);
     493               0 :     if (!visible)
     494                 :       return;
     495                 :   }
     496                 : 
     497               0 :   if (!widget) {
     498                 :     // The root view or a scrolling view might not have a widget
     499                 :     // (for example, during printing). We get here when we scroll
     500                 :     // during printing to show selected options in a listbox, for example.
     501                 :     return;
     502                 :   }
     503                 : 
     504                 :   // Update all child widgets with the damage. In the process,
     505                 :   // accumulate the union of all the child widget areas, or at least
     506                 :   // some subset of that.
     507               0 :   nsRegion children;
     508               0 :   if (widget->GetTransparencyMode() != eTransparencyTransparent) {
     509               0 :     for (nsIWidget* childWidget = widget->GetFirstChild();
     510                 :          childWidget;
     511                 :          childWidget = childWidget->GetNextSibling()) {
     512               0 :       nsView* view = nsView::GetViewFor(childWidget);
     513               0 :       NS_ASSERTION(view != aWidgetView, "will recur infinitely");
     514                 :       bool visible;
     515               0 :       childWidget->IsVisible(visible);
     516                 :       nsWindowType type;
     517               0 :       childWidget->GetWindowType(type);
     518               0 :       if (view && visible && type != eWindowType_popup) {
     519               0 :         NS_ASSERTION(type == eWindowType_plugin,
     520                 :                      "Only plugin or popup widgets can be children!");
     521                 : 
     522                 :         // We do not need to invalidate in plugin widgets, but we should
     523                 :         // exclude them from the invalidation region IF we're not on
     524                 :         // Mac. On Mac we need to draw under plugin widgets, because
     525                 :         // plugin widgets are basically invisible
     526                 : #ifndef XP_MACOSX
     527                 :         // GetBounds should compensate for chrome on a toplevel widget
     528               0 :         nsIntRect bounds;
     529               0 :         childWidget->GetBounds(bounds);
     530                 : 
     531               0 :         nsTArray<nsIntRect> clipRects;
     532               0 :         childWidget->GetWindowClipRegion(&clipRects);
     533               0 :         for (PRUint32 i = 0; i < clipRects.Length(); ++i) {
     534               0 :           nsRect rr = (clipRects[i] + bounds.TopLeft()).
     535               0 :             ToAppUnits(AppUnitsPerDevPixel());
     536               0 :           children.Or(children, rr - aWidgetView->ViewToWidgetOffset()); 
     537               0 :           children.SimplifyInward(20);
     538                 :         }
     539                 : #endif
     540                 :       }
     541                 :     }
     542                 :   }
     543                 : 
     544               0 :   nsRegion leftOver;
     545               0 :   leftOver.Sub(intersection, children);
     546                 : 
     547               0 :   if (!leftOver.IsEmpty()) {
     548                 :     const nsRect* r;
     549               0 :     for (nsRegionRectIterator iter(leftOver); (r = iter.Next());) {
     550               0 :       nsIntRect bounds = ViewToWidget(aWidgetView, *r);
     551               0 :       widget->Invalidate(bounds);
     552                 :     }
     553                 :   }
     554                 : }
     555                 : 
     556                 : static bool
     557               0 : ShouldIgnoreInvalidation(nsViewManager* aVM)
     558                 : {
     559               0 :   while (aVM) {
     560               0 :     nsIPresShell* shell = aVM->GetPresShell();
     561               0 :     if (!shell || shell->ShouldIgnoreInvalidation()) {
     562               0 :       return true;
     563                 :     }
     564               0 :     nsView* view = aVM->GetRootViewImpl()->GetParent();
     565               0 :     aVM = view ? view->GetViewManager() : nsnull;
     566                 :   }
     567               0 :   return false;
     568                 : }
     569                 : 
     570               0 : nsresult nsViewManager::InvalidateView(nsIView *aView, const nsRect &aRect)
     571                 : {
     572                 :   // If painting is suppressed in the presshell or an ancestor drop all
     573                 :   // invalidates, it will invalidate everything when it unsuppresses.
     574               0 :   if (ShouldIgnoreInvalidation(this)) {
     575               0 :     return NS_OK;
     576                 :   }
     577                 : 
     578               0 :   return InvalidateViewNoSuppression(aView, aRect);
     579                 : }
     580                 : 
     581               0 : NS_IMETHODIMP nsViewManager::InvalidateViewNoSuppression(nsIView *aView,
     582                 :                                                          const nsRect &aRect)
     583                 : {
     584               0 :   NS_PRECONDITION(nsnull != aView, "null view");
     585                 : 
     586               0 :   nsView* view = static_cast<nsView*>(aView);
     587                 : 
     588               0 :   NS_ASSERTION(view->GetViewManager() == this,
     589                 :                "InvalidateViewNoSuppression called on view we don't own");
     590                 : 
     591               0 :   nsRect damagedRect(aRect);
     592               0 :   if (damagedRect.IsEmpty()) {
     593               0 :     return NS_OK;
     594                 :   }
     595                 : 
     596               0 :   nsView* displayRoot = static_cast<nsView*>(GetDisplayRootFor(view));
     597               0 :   nsViewManager* displayRootVM = displayRoot->GetViewManager();
     598                 :   // Propagate the update to the displayRoot, since iframes, for example,
     599                 :   // can overlap each other and be translucent.  So we have to possibly
     600                 :   // invalidate our rect in each of the widgets we have lying about.
     601               0 :   damagedRect.MoveBy(view->GetOffsetTo(displayRoot));
     602               0 :   PRInt32 rootAPD = displayRootVM->AppUnitsPerDevPixel();
     603               0 :   PRInt32 APD = AppUnitsPerDevPixel();
     604               0 :   damagedRect = damagedRect.ConvertAppUnitsRoundOut(APD, rootAPD);
     605                 : 
     606                 :   // accumulate this rectangle in the view's dirty region, so we can
     607                 :   // process it later.
     608               0 :   AddDirtyRegion(displayRoot, nsRegion(damagedRect));
     609                 : 
     610                 :   // Schedule an invalidation flush with the refresh driver.
     611               0 :   PostPendingUpdate();
     612                 : 
     613               0 :   return NS_OK;
     614                 : }
     615                 : 
     616               0 : NS_IMETHODIMP nsViewManager::InvalidateAllViews()
     617                 : {
     618               0 :   if (RootViewManager() != this) {
     619               0 :     return RootViewManager()->InvalidateAllViews();
     620                 :   }
     621                 :   
     622               0 :   InvalidateViews(mRootView);
     623               0 :   return NS_OK;
     624                 : }
     625                 : 
     626               0 : void nsViewManager::InvalidateViews(nsView *aView)
     627                 : {
     628                 :   // Invalidate this view.
     629               0 :   InvalidateView(aView);
     630                 : 
     631                 :   // Invalidate all children as well.
     632               0 :   nsView* childView = aView->GetFirstChild();
     633               0 :   while (nsnull != childView)  {
     634               0 :     childView->GetViewManager()->InvalidateViews(childView);
     635               0 :     childView = childView->GetNextSibling();
     636                 :   }
     637               0 : }
     638                 : 
     639                 : static bool
     640               0 : IsViewForPopup(nsIView* aView)
     641                 : {
     642               0 :   nsIWidget* widget = aView->GetWidget();
     643               0 :   if (widget) {
     644                 :     nsWindowType type;
     645               0 :     widget->GetWindowType(type);
     646               0 :     return (type == eWindowType_popup);
     647                 :   }
     648                 : 
     649               0 :   return false;
     650                 : }
     651                 : 
     652               0 : NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
     653                 :                                            nsIView* aView, nsEventStatus *aStatus)
     654                 : {
     655               0 :   NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this,
     656                 :                "wrong view manager");
     657                 : 
     658               0 :   SAMPLE_LABEL("event", "nsViewManager::DispatchEvent");
     659                 : 
     660               0 :   *aStatus = nsEventStatus_eIgnore;
     661                 : 
     662               0 :   switch(aEvent->message)
     663                 :     {
     664                 :     case NS_SIZE:
     665                 :       {
     666               0 :         if (aView)
     667                 :           {
     668                 :             // client area dimensions are set on the view
     669               0 :             nscoord width = ((nsSizeEvent*)aEvent)->windowSize->width;
     670               0 :             nscoord height = ((nsSizeEvent*)aEvent)->windowSize->height;
     671                 : 
     672                 :             // The root view may not be set if this is the resize associated with
     673                 :             // window creation
     674                 : 
     675               0 :             if (aView == mRootView)
     676                 :               {
     677               0 :                 PRInt32 p2a = AppUnitsPerDevPixel();
     678                 :                 SetWindowDimensions(NSIntPixelsToAppUnits(width, p2a),
     679               0 :                                     NSIntPixelsToAppUnits(height, p2a));
     680               0 :                 *aStatus = nsEventStatus_eConsumeNoDefault;
     681                 :               }
     682               0 :             else if (IsViewForPopup(aView))
     683                 :               {
     684               0 :                 nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     685               0 :                 if (pm)
     686                 :                   {
     687               0 :                     pm->PopupResized(aView->GetFrame(), nsIntSize(width, height));
     688               0 :                     *aStatus = nsEventStatus_eConsumeNoDefault;
     689                 :                   }
     690                 :               }
     691                 :           }
     692                 :         }
     693                 : 
     694               0 :         break;
     695                 : 
     696                 :     case NS_MOVE:
     697                 :       {
     698                 :         // A popup's parent view is the root view for the parent window, so when
     699                 :         // a popup moves, the popup's frame and view position must be updated
     700                 :         // to match.
     701               0 :         if (aView && IsViewForPopup(aView))
     702                 :           {
     703               0 :             nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     704               0 :             if (pm)
     705                 :               {
     706               0 :                 pm->PopupMoved(aView->GetFrame(), aEvent->refPoint);
     707               0 :                 *aStatus = nsEventStatus_eConsumeNoDefault;
     708                 :               }
     709                 :           }
     710               0 :         break;
     711                 :       }
     712                 : 
     713                 :     case NS_DONESIZEMOVE:
     714                 :       {
     715               0 :         if (mPresShell) {
     716               0 :           nsPresContext* presContext = mPresShell->GetPresContext();
     717               0 :           if (presContext) {
     718               0 :             nsEventStateManager::ClearGlobalActiveContent(nsnull);
     719                 :           }
     720                 : 
     721                 :         }
     722                 : 
     723               0 :         nsIPresShell::ClearMouseCapture(nsnull);
     724                 :       }
     725               0 :       break;
     726                 :   
     727                 :     case NS_XUL_CLOSE:
     728                 :       {
     729                 :         // if this is a popup, make a request to hide it. Note that a popuphidden
     730                 :         // event listener may cancel the event and the popup will not be hidden.
     731               0 :         nsIWidget* widget = aView->GetWidget();
     732               0 :         if (widget) {
     733                 :           nsWindowType type;
     734               0 :           widget->GetWindowType(type);
     735               0 :           if (type == eWindowType_popup) {
     736               0 :             nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     737               0 :             if (pm) {
     738               0 :               pm->HidePopup(aView->GetFrame());
     739               0 :               *aStatus = nsEventStatus_eConsumeNoDefault;
     740                 :             }
     741                 :           }
     742                 :         }
     743                 :       }
     744               0 :       break;
     745                 : 
     746                 :     case NS_WILL_PAINT:
     747                 :       {
     748               0 :         if (!aView || !mContext)
     749               0 :           break;
     750                 : 
     751               0 :         *aStatus = nsEventStatus_eConsumeNoDefault;
     752                 : 
     753               0 :         nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
     754                 : 
     755               0 :         NS_ASSERTION(static_cast<nsView*>(aView) ==
     756                 :                        nsView::GetViewFor(event->widget),
     757                 :                      "view/widget mismatch");
     758                 : 
     759                 :         // If an ancestor widget was hidden and then shown, we could
     760                 :         // have a delayed resize to handle.
     761               0 :         for (nsViewManager *vm = this; vm;
     762               0 :              vm = vm->mRootView->GetParent()
     763               0 :                     ? vm->mRootView->GetParent()->GetViewManager()
     764                 :                     : nsnull) {
     765               0 :           if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
     766               0 :               vm->mRootView->IsEffectivelyVisible() &&
     767               0 :               mPresShell && mPresShell->IsVisible()) {
     768               0 :             vm->FlushDelayedResize(true);
     769               0 :             vm->InvalidateView(vm->mRootView);
     770                 :           }
     771                 :         }
     772                 : 
     773                 :         // Flush things like reflows and plugin widget geometry updates by
     774                 :         // calling WillPaint on observer presShells.
     775               0 :         nsRefPtr<nsViewManager> rootVM = RootViewManager();
     776               0 :         if (mPresShell) {
     777               0 :           rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
     778                 :         }
     779                 :         // Flush view widget geometry updates and invalidations.
     780               0 :         rootVM->ProcessPendingUpdates();
     781                 :       }
     782               0 :       break;
     783                 : 
     784                 :     case NS_PAINT:
     785                 :       {
     786               0 :         if (!aView || !mContext)
     787               0 :           break;
     788                 : 
     789               0 :         *aStatus = nsEventStatus_eConsumeNoDefault;
     790               0 :         nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
     791               0 :         nsView* view = static_cast<nsView*>(aView);
     792               0 :         NS_ASSERTION(view == nsView::GetViewFor(event->widget),
     793                 :                      "view/widget mismatch");
     794               0 :         NS_ASSERTION(IsPaintingAllowed(),
     795                 :                      "shouldn't be receiving paint events while painting is "
     796                 :                      "disallowed!");
     797                 : 
     798               0 :         if (!event->didSendWillPaint) {
     799                 :           // Send NS_WILL_PAINT event ourselves.
     800               0 :           nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget);
     801               0 :           willPaintEvent.willSendDidPaint = event->willSendDidPaint;
     802               0 :           DispatchEvent(&willPaintEvent, view, aStatus);
     803                 : 
     804                 :           // Get the view pointer again since NS_WILL_PAINT might have
     805                 :           // destroyed it during CallWillPaintOnObservers (bug 378273).
     806               0 :           view = nsView::GetViewFor(event->widget);
     807                 :         }
     808                 : 
     809               0 :         if (!view || event->region.IsEmpty())
     810               0 :           break;
     811                 : 
     812                 :         // Paint.
     813               0 :         Refresh(view, event->widget, event->region, event->willSendDidPaint);
     814                 : 
     815               0 :         break;
     816                 :       }
     817                 : 
     818                 :     case NS_DID_PAINT: {
     819               0 :       nsRefPtr<nsViewManager> rootVM = RootViewManager();
     820               0 :       rootVM->CallDidPaintOnObserver();
     821                 :       break;
     822                 :     }
     823                 : 
     824                 :     case NS_CREATE:
     825                 :     case NS_DESTROY:
     826                 :     case NS_SETZLEVEL:
     827                 :       /* Don't pass these events through. Passing them through
     828                 :          causes performance problems on pages with lots of views/frames 
     829                 :          @see bug 112861 */
     830               0 :       *aStatus = nsEventStatus_eConsumeNoDefault;
     831               0 :       break;
     832                 : 
     833                 :     case NS_DISPLAYCHANGED:
     834                 : 
     835                 :       //Destroy the cached backbuffer to force a new backbuffer
     836                 :       //be constructed with the appropriate display depth.
     837                 :       //@see bugzilla bug 6061
     838               0 :       *aStatus = nsEventStatus_eConsumeDoDefault;
     839               0 :       break;
     840                 : 
     841                 :     case NS_SYSCOLORCHANGED:
     842                 :       {
     843               0 :         if (mPresShell) {
     844                 :           // Hold a refcount to the presshell. The continued existence of the observer will
     845                 :           // delay deletion of this view hierarchy should the event want to cause its
     846                 :           // destruction in, say, some JavaScript event handler.
     847               0 :           nsCOMPtr<nsIPresShell> presShell = mPresShell;
     848               0 :           presShell->HandleEvent(aView->GetFrame(), aEvent, false, aStatus);
     849                 :         }
     850                 :       }
     851               0 :       break; 
     852                 : 
     853                 :     default:
     854                 :       {
     855               0 :         if ((NS_IS_MOUSE_EVENT(aEvent) &&
     856                 :              // Ignore mouse events that we synthesize.
     857                 :              static_cast<nsMouseEvent*>(aEvent)->reason ==
     858                 :                nsMouseEvent::eReal &&
     859                 :              // Ignore mouse exit and enter (we'll get moves if the user
     860                 :              // is really moving the mouse) since we get them when we
     861                 :              // create and destroy widgets.
     862                 :              aEvent->message != NS_MOUSE_EXIT &&
     863                 :              aEvent->message != NS_MOUSE_ENTER) ||
     864                 :             NS_IS_KEY_EVENT(aEvent) ||
     865                 :             NS_IS_IME_EVENT(aEvent) ||
     866                 :             aEvent->message == NS_PLUGIN_INPUT_EVENT) {
     867               0 :           gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
     868                 :         }
     869                 : 
     870               0 :         if (aEvent->message == NS_DEACTIVATE) {
     871                 :           // if a window is deactivated, clear the mouse capture regardless
     872                 :           // of what is capturing
     873               0 :           nsIPresShell::ClearMouseCapture(nsnull);
     874                 :         }
     875                 : 
     876                 :         // Find the view whose coordinates system we're in.
     877               0 :         nsIView* view = aView;
     878               0 :         bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
     879               0 :         if (dispatchUsingCoordinates) {
     880                 :           // Will dispatch using coordinates. Pretty bogus but it's consistent
     881                 :           // with what presshell does.
     882               0 :           view = GetDisplayRootFor(view);
     883                 :         }
     884                 :   
     885                 :         // If the view has no frame, look for a view that does.
     886               0 :         nsIFrame* frame = view->GetFrame();
     887               0 :         if (!frame &&
     888                 :             (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
     889                 :              NS_IS_IME_RELATED_EVENT(aEvent) ||
     890               0 :              NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
     891                 :              aEvent->message == NS_PLUGIN_ACTIVATE ||
     892                 :              aEvent->message == NS_PLUGIN_FOCUS)) {
     893               0 :           while (view && !view->GetFrame()) {
     894               0 :             view = view->GetParent();
     895                 :           }
     896                 : 
     897               0 :           if (view) {
     898               0 :             frame = view->GetFrame();
     899                 :           }
     900                 :         }
     901                 : 
     902               0 :         if (nsnull != frame) {
     903                 :           // Hold a refcount to the presshell. The continued existence of the
     904                 :           // presshell will delay deletion of this view hierarchy should the event
     905                 :           // want to cause its destruction in, say, some JavaScript event handler.
     906               0 :           nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
     907               0 :           if (shell) {
     908               0 :             shell->HandleEvent(frame, aEvent, false, aStatus);
     909                 :           }
     910                 :         }
     911                 :     
     912               0 :         break;
     913                 :       }
     914                 :     }
     915                 : 
     916               0 :   return NS_OK;
     917                 : }
     918                 : 
     919                 : // Recursively reparent widgets if necessary 
     920                 : 
     921               0 : void nsViewManager::ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget)
     922                 : {
     923               0 :   NS_PRECONDITION(aNewWidget, "");
     924                 : 
     925               0 :   if (aView->HasWidget()) {
     926                 :     // Check to see if the parent widget is the
     927                 :     // same as the new parent. If not then reparent
     928                 :     // the widget, otherwise there is nothing more
     929                 :     // to do for the view and its descendants
     930               0 :     nsIWidget* widget = aView->GetWidget();
     931               0 :     nsIWidget* parentWidget = widget->GetParent();
     932               0 :     if (parentWidget) {
     933                 :       // Child widget
     934               0 :       if (parentWidget != aNewWidget) {
     935                 : #ifdef DEBUG
     936                 :         nsresult rv =
     937                 : #endif
     938               0 :           widget->SetParent(aNewWidget);
     939               0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "SetParent failed!");
     940                 :       }
     941                 :     } else {
     942                 :       // Toplevel widget (popup, dialog, etc)
     943               0 :       widget->ReparentNativeWidget(aNewWidget);
     944                 :     }
     945               0 :     return;
     946                 :   }
     947                 : 
     948                 :   // Need to check each of the views children to see
     949                 :   // if they have a widget and reparent it.
     950                 : 
     951               0 :   nsView* view = static_cast<nsView*>(aView);
     952               0 :   for (nsView *kid = view->GetFirstChild(); kid; kid = kid->GetNextSibling()) {
     953               0 :     ReparentChildWidgets(kid, aNewWidget);
     954                 :   }
     955                 : }
     956                 : 
     957                 : // Reparent a view and its descendant views widgets if necessary
     958                 : 
     959               0 : void nsViewManager::ReparentWidgets(nsIView* aView, nsIView *aParent)
     960                 : {
     961               0 :   NS_PRECONDITION(aParent, "Must have a parent");
     962               0 :   NS_PRECONDITION(aView, "Must have a view");
     963                 :   
     964                 :   // Quickly determine whether the view has pre-existing children or a
     965                 :   // widget. In most cases the view will not have any pre-existing 
     966                 :   // children when this is called.  Only in the case
     967                 :   // where a view has been reparented by removing it from
     968                 :   // a reinserting it into a new location in the view hierarchy do we
     969                 :   // have to consider reparenting the existing widgets for the view and
     970                 :   // it's descendants.
     971               0 :   nsView* view = static_cast<nsView*>(aView);
     972               0 :   if (view->HasWidget() || view->GetFirstChild()) {
     973               0 :     nsIWidget* parentWidget = aParent->GetNearestWidget(nsnull);
     974               0 :     if (parentWidget) {
     975               0 :       ReparentChildWidgets(aView, parentWidget);
     976               0 :       return;
     977                 :     }
     978               0 :     NS_WARNING("Can not find a widget for the parent view");
     979                 :   }
     980                 : }
     981                 : 
     982               0 : NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIView *aSibling,
     983                 :                                          bool aAfter)
     984                 : {
     985               0 :   nsView* parent = static_cast<nsView*>(aParent);
     986               0 :   nsView* child = static_cast<nsView*>(aChild);
     987               0 :   nsView* sibling = static_cast<nsView*>(aSibling);
     988                 :   
     989               0 :   NS_PRECONDITION(nsnull != parent, "null ptr");
     990               0 :   NS_PRECONDITION(nsnull != child, "null ptr");
     991               0 :   NS_ASSERTION(sibling == nsnull || sibling->GetParent() == parent,
     992                 :                "tried to insert view with invalid sibling");
     993               0 :   NS_ASSERTION(!IsViewInserted(child), "tried to insert an already-inserted view");
     994                 : 
     995               0 :   if ((nsnull != parent) && (nsnull != child))
     996                 :     {
     997                 :       // if aAfter is set, we will insert the child after 'prev' (i.e. after 'kid' in document
     998                 :       // order, otherwise after 'kid' (i.e. before 'kid' in document order).
     999                 : 
    1000                 : #if 1
    1001               0 :       if (nsnull == aSibling) {
    1002               0 :         if (aAfter) {
    1003                 :           // insert at end of document order, i.e., before first view
    1004                 :           // this is the common case, by far
    1005               0 :           parent->InsertChild(child, nsnull);
    1006               0 :           ReparentWidgets(child, parent);
    1007                 :         } else {
    1008                 :           // insert at beginning of document order, i.e., after last view
    1009               0 :           nsView *kid = parent->GetFirstChild();
    1010               0 :           nsView *prev = nsnull;
    1011               0 :           while (kid) {
    1012               0 :             prev = kid;
    1013               0 :             kid = kid->GetNextSibling();
    1014                 :           }
    1015                 :           // prev is last view or null if there are no children
    1016               0 :           parent->InsertChild(child, prev);
    1017               0 :           ReparentWidgets(child, parent);
    1018                 :         }
    1019                 :       } else {
    1020               0 :         nsView *kid = parent->GetFirstChild();
    1021               0 :         nsView *prev = nsnull;
    1022               0 :         while (kid && sibling != kid) {
    1023                 :           //get the next sibling view
    1024               0 :           prev = kid;
    1025               0 :           kid = kid->GetNextSibling();
    1026                 :         }
    1027               0 :         NS_ASSERTION(kid != nsnull,
    1028                 :                      "couldn't find sibling in child list");
    1029               0 :         if (aAfter) {
    1030                 :           // insert after 'kid' in document order, i.e. before in view order
    1031               0 :           parent->InsertChild(child, prev);
    1032               0 :           ReparentWidgets(child, parent);
    1033                 :         } else {
    1034                 :           // insert before 'kid' in document order, i.e. after in view order
    1035               0 :           parent->InsertChild(child, kid);
    1036               0 :           ReparentWidgets(child, parent);
    1037                 :         }
    1038                 :       }
    1039                 : #else // don't keep consistent document order, but order things by z-index instead
    1040                 :       // essentially we're emulating the old InsertChild(parent, child, zindex)
    1041                 :       PRInt32 zIndex = child->GetZIndex();
    1042                 :       while (nsnull != kid)
    1043                 :         {
    1044                 :           PRInt32 idx = kid->GetZIndex();
    1045                 : 
    1046                 :           if (CompareZIndex(zIndex, child->IsTopMost(), child->GetZIndexIsAuto(),
    1047                 :                             idx, kid->IsTopMost(), kid->GetZIndexIsAuto()) >= 0)
    1048                 :             break;
    1049                 : 
    1050                 :           prev = kid;
    1051                 :           kid = kid->GetNextSibling();
    1052                 :         }
    1053                 : 
    1054                 :       parent->InsertChild(child, prev);
    1055                 :       ReparentWidgets(child, parent);
    1056                 : #endif
    1057                 : 
    1058                 :       // if the parent view is marked as "floating", make the newly added view float as well.
    1059               0 :       if (parent->GetFloating())
    1060               0 :         child->SetFloating(true);
    1061                 : 
    1062                 :       //and mark this area as dirty if the view is visible...
    1063                 : 
    1064               0 :       if (nsViewVisibility_kHide != child->GetVisibility())
    1065               0 :         child->GetViewManager()->InvalidateView(child);
    1066                 :     }
    1067               0 :   return NS_OK;
    1068                 : }
    1069                 : 
    1070               0 : NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, PRInt32 aZIndex)
    1071                 : {
    1072                 :   // no-one really calls this with anything other than aZIndex == 0 on a fresh view
    1073                 :   // XXX this method should simply be eliminated and its callers redirected to the real method
    1074               0 :   SetViewZIndex(aChild, false, aZIndex, false);
    1075               0 :   return InsertChild(aParent, aChild, nsnull, true);
    1076                 : }
    1077                 : 
    1078               0 : NS_IMETHODIMP nsViewManager::RemoveChild(nsIView *aChild)
    1079                 : {
    1080               0 :   nsView* child = static_cast<nsView*>(aChild);
    1081               0 :   NS_ENSURE_ARG_POINTER(child);
    1082                 : 
    1083               0 :   nsView* parent = child->GetParent();
    1084                 : 
    1085               0 :   if (nsnull != parent) {
    1086               0 :     NS_ASSERTION(child->GetViewManager() == this ||
    1087                 :                  parent->GetViewManager() == this, "wrong view manager");
    1088               0 :     child->GetViewManager()->InvalidateView(child);
    1089               0 :     parent->RemoveChild(child);
    1090                 :   }
    1091                 : 
    1092               0 :   return NS_OK;
    1093                 : }
    1094                 : 
    1095               0 : NS_IMETHODIMP nsViewManager::MoveViewTo(nsIView *aView, nscoord aX, nscoord aY)
    1096                 : {
    1097               0 :   nsView* view = static_cast<nsView*>(aView);
    1098               0 :   NS_ASSERTION(view->GetViewManager() == this, "wrong view manager");
    1099               0 :   nsPoint oldPt = view->GetPosition();
    1100               0 :   nsRect oldBounds = view->GetBoundsInParentUnits();
    1101               0 :   view->SetPosition(aX, aY);
    1102                 : 
    1103                 :   // only do damage control if the view is visible
    1104                 : 
    1105               0 :   if ((aX != oldPt.x) || (aY != oldPt.y)) {
    1106               0 :     if (view->GetVisibility() != nsViewVisibility_kHide) {
    1107               0 :       nsView* parentView = view->GetParent();
    1108               0 :       if (parentView) {
    1109               0 :         nsViewManager* parentVM = parentView->GetViewManager();
    1110               0 :         parentVM->InvalidateView(parentView, oldBounds);
    1111               0 :         parentVM->InvalidateView(parentView, view->GetBoundsInParentUnits());
    1112                 :       }
    1113                 :     }
    1114                 :   }
    1115               0 :   return NS_OK;
    1116                 : }
    1117                 : 
    1118               0 : void nsViewManager::InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
    1119                 :   nscoord aY1, nscoord aY2, bool aInCutOut) {
    1120               0 :   nscoord height = aY2 - aY1;
    1121               0 :   if (aRect.x < aCutOut.x) {
    1122               0 :     nsRect r(aRect.x, aY1, aCutOut.x - aRect.x, height);
    1123               0 :     InvalidateView(aView, r);
    1124                 :   }
    1125               0 :   if (!aInCutOut && aCutOut.x < aCutOut.XMost()) {
    1126               0 :     nsRect r(aCutOut.x, aY1, aCutOut.width, height);
    1127               0 :     InvalidateView(aView, r);
    1128                 :   }
    1129               0 :   if (aCutOut.XMost() < aRect.XMost()) {
    1130               0 :     nsRect r(aCutOut.XMost(), aY1, aRect.XMost() - aCutOut.XMost(), height);
    1131               0 :     InvalidateView(aView, r);
    1132                 :   }
    1133               0 : }
    1134                 : 
    1135               0 : void nsViewManager::InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut) {
    1136               0 :   NS_ASSERTION(aView->GetViewManager() == this,
    1137                 :                "InvalidateRectDifference called on view we don't own");
    1138               0 :   if (aRect.y < aCutOut.y) {
    1139               0 :     InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aRect.y, aCutOut.y, false);
    1140                 :   }
    1141               0 :   if (aCutOut.y < aCutOut.YMost()) {
    1142               0 :     InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aCutOut.y, aCutOut.YMost(), true);
    1143                 :   }
    1144               0 :   if (aCutOut.YMost() < aRect.YMost()) {
    1145               0 :     InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aCutOut.YMost(), aRect.YMost(), false);
    1146                 :   }
    1147               0 : }
    1148                 : 
    1149               0 : NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, bool aRepaintExposedAreaOnly)
    1150                 : {
    1151               0 :   nsView* view = static_cast<nsView*>(aView);
    1152               0 :   NS_ASSERTION(view->GetViewManager() == this, "wrong view manager");
    1153                 : 
    1154               0 :   nsRect oldDimensions = view->GetDimensions();
    1155               0 :   if (!oldDimensions.IsEqualEdges(aRect)) {
    1156                 :     // resize the view.
    1157                 :     // Prevent Invalidation of hidden views 
    1158               0 :     if (view->GetVisibility() == nsViewVisibility_kHide) {  
    1159               0 :       view->SetDimensions(aRect, false);
    1160                 :     } else {
    1161               0 :       nsView* parentView = view->GetParent();
    1162               0 :       if (!parentView) {
    1163               0 :         parentView = view;
    1164                 :       }
    1165               0 :       nsRect oldBounds = view->GetBoundsInParentUnits();
    1166               0 :       view->SetDimensions(aRect, true);
    1167               0 :       nsViewManager* parentVM = parentView->GetViewManager();
    1168               0 :       if (!aRepaintExposedAreaOnly) {
    1169                 :         // Invalidate the union of the old and new size
    1170               0 :         InvalidateView(view, aRect);
    1171               0 :         parentVM->InvalidateView(parentView, oldBounds);
    1172                 :       } else {
    1173               0 :         InvalidateRectDifference(view, aRect, oldDimensions);
    1174               0 :         nsRect newBounds = view->GetBoundsInParentUnits();
    1175               0 :         parentVM->InvalidateRectDifference(parentView, oldBounds, newBounds);
    1176                 :       } 
    1177                 :     }
    1178                 :   }
    1179                 : 
    1180                 :   // Note that if layout resizes the view and the view has a custom clip
    1181                 :   // region set, then we expect layout to update the clip region too. Thus
    1182                 :   // in the case where mClipRect has been optimized away to just be a null
    1183                 :   // pointer, and this resize is implicitly changing the clip rect, it's OK
    1184                 :   // because layout will change it back again if necessary.
    1185                 : 
    1186               0 :   return NS_OK;
    1187                 : }
    1188                 : 
    1189               0 : NS_IMETHODIMP nsViewManager::SetViewFloating(nsIView *aView, bool aFloating)
    1190                 : {
    1191               0 :   nsView* view = static_cast<nsView*>(aView);
    1192                 : 
    1193               0 :   NS_ASSERTION(!(nsnull == view), "no view");
    1194                 : 
    1195               0 :   view->SetFloating(aFloating);
    1196                 : 
    1197               0 :   return NS_OK;
    1198                 : }
    1199                 : 
    1200               0 : NS_IMETHODIMP nsViewManager::SetViewVisibility(nsIView *aView, nsViewVisibility aVisible)
    1201                 : {
    1202               0 :   nsView* view = static_cast<nsView*>(aView);
    1203               0 :   NS_ASSERTION(view->GetViewManager() == this, "wrong view manager");
    1204                 : 
    1205               0 :   if (aVisible != view->GetVisibility()) {
    1206               0 :     view->SetVisibility(aVisible);
    1207                 : 
    1208               0 :     if (IsViewInserted(view)) {
    1209               0 :       if (!view->HasWidget()) {
    1210               0 :         if (nsViewVisibility_kHide == aVisible) {
    1211               0 :           nsView* parentView = view->GetParent();
    1212               0 :           if (parentView) {
    1213                 :             parentView->GetViewManager()->
    1214               0 :               InvalidateView(parentView, view->GetBoundsInParentUnits());
    1215                 :           }
    1216                 :         }
    1217                 :         else {
    1218               0 :           InvalidateView(view);
    1219                 :         }
    1220                 :       }
    1221                 :     }
    1222                 :   }
    1223               0 :   return NS_OK;
    1224                 : }
    1225                 : 
    1226               0 : bool nsViewManager::IsViewInserted(nsView *aView)
    1227                 : {
    1228               0 :   if (mRootView == aView) {
    1229               0 :     return true;
    1230               0 :   } else if (aView->GetParent() == nsnull) {
    1231               0 :     return false;
    1232                 :   } else {
    1233               0 :     nsView* view = aView->GetParent()->GetFirstChild();
    1234               0 :     while (view != nsnull) {
    1235               0 :       if (view == aView) {
    1236               0 :         return true;
    1237                 :       }        
    1238               0 :       view = view->GetNextSibling();
    1239                 :     }
    1240               0 :     return false;
    1241                 :   }
    1242                 : }
    1243                 : 
    1244               0 : NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, bool aAutoZIndex, PRInt32 aZIndex, bool aTopMost)
    1245                 : {
    1246               0 :   nsView* view = static_cast<nsView*>(aView);
    1247               0 :   nsresult  rv = NS_OK;
    1248                 : 
    1249               0 :   NS_ASSERTION((view != nsnull), "no view");
    1250                 : 
    1251                 :   // don't allow the root view's z-index to be changed. It should always be zero.
    1252                 :   // This could be removed and replaced with a style rule, or just removed altogether, with interesting consequences
    1253               0 :   if (aView == mRootView) {
    1254               0 :     return rv;
    1255                 :   }
    1256                 : 
    1257               0 :   bool oldTopMost = view->IsTopMost();
    1258               0 :   bool oldIsAuto = view->GetZIndexIsAuto();
    1259                 : 
    1260               0 :   if (aAutoZIndex) {
    1261               0 :     aZIndex = 0;
    1262                 :   }
    1263                 : 
    1264               0 :   PRInt32 oldidx = view->GetZIndex();
    1265               0 :   view->SetZIndex(aAutoZIndex, aZIndex, aTopMost);
    1266                 : 
    1267               0 :   if (oldidx != aZIndex || oldTopMost != aTopMost ||
    1268                 :       oldIsAuto != aAutoZIndex) {
    1269               0 :     InvalidateView(view);
    1270                 :   }
    1271                 : 
    1272               0 :   return rv;
    1273                 : }
    1274                 : 
    1275               0 : NS_IMETHODIMP nsViewManager::GetDeviceContext(nsDeviceContext *&aContext)
    1276                 : {
    1277               0 :   aContext = mContext;
    1278               0 :   NS_IF_ADDREF(aContext);
    1279               0 :   return NS_OK;
    1280                 : }
    1281                 : 
    1282                 : nsIViewManager*
    1283               0 : nsViewManager::IncrementDisableRefreshCount()
    1284                 : {
    1285               0 :   if (!IsRootVM()) {
    1286               0 :     return RootViewManager()->IncrementDisableRefreshCount();
    1287                 :   }
    1288                 : 
    1289               0 :   ++mRefreshDisableCount;
    1290                 : 
    1291               0 :   return this;
    1292                 : }
    1293                 : 
    1294                 : void
    1295               0 : nsViewManager::DecrementDisableRefreshCount()
    1296                 : {
    1297               0 :   NS_ASSERTION(IsRootVM(), "Should only be called on root");
    1298               0 :   --mRefreshDisableCount;
    1299               0 :   NS_ASSERTION(mRefreshDisableCount >= 0, "Invalid refresh disable count!");
    1300               0 : }
    1301                 : 
    1302               0 : NS_IMETHODIMP nsViewManager::GetRootWidget(nsIWidget **aWidget)
    1303                 : {
    1304               0 :   if (!mRootView) {
    1305               0 :     *aWidget = nsnull;
    1306               0 :     return NS_OK;
    1307                 :   }
    1308               0 :   if (mRootView->HasWidget()) {
    1309               0 :     *aWidget = mRootView->GetWidget();
    1310               0 :     NS_ADDREF(*aWidget);
    1311               0 :     return NS_OK;
    1312                 :   }
    1313               0 :   if (mRootView->GetParent())
    1314               0 :     return mRootView->GetParent()->GetViewManager()->GetRootWidget(aWidget);
    1315               0 :   *aWidget = nsnull;
    1316               0 :   return NS_OK;
    1317                 : }
    1318                 : 
    1319               0 : nsIntRect nsViewManager::ViewToWidget(nsView *aView, const nsRect &aRect) const
    1320                 : {
    1321               0 :   NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
    1322                 : 
    1323                 :   // intersect aRect with bounds of aView, to prevent generating any illegal rectangles.
    1324               0 :   nsRect bounds = aView->GetInvalidationDimensions();
    1325               0 :   nsRect rect;
    1326               0 :   rect.IntersectRect(aRect, bounds);
    1327                 : 
    1328                 :   // account for the view's origin not lining up with the widget's
    1329               0 :   rect += aView->ViewToWidgetOffset();
    1330                 : 
    1331                 :   // finally, convert to device coordinates.
    1332               0 :   return rect.ToOutsidePixels(AppUnitsPerDevPixel());
    1333                 : }
    1334                 : 
    1335                 : NS_IMETHODIMP
    1336               0 : nsViewManager::IsPainting(bool& aIsPainting)
    1337                 : {
    1338               0 :   aIsPainting = IsPainting();
    1339               0 :   return NS_OK;
    1340                 : }
    1341                 : 
    1342                 : void
    1343               0 : nsViewManager::ProcessPendingUpdates()
    1344                 : {
    1345               0 :   if (!IsRootVM()) {
    1346               0 :     RootViewManager()->ProcessPendingUpdates();
    1347               0 :     return;
    1348                 :   }
    1349                 : 
    1350               0 :   if (mHasPendingUpdates) {
    1351               0 :     ProcessPendingUpdatesForView(mRootView, true);
    1352               0 :     mHasPendingUpdates = false;
    1353                 :   }
    1354                 : }
    1355                 : 
    1356                 : void
    1357               0 : nsViewManager::UpdateWidgetGeometry()
    1358                 : {
    1359               0 :   if (!IsRootVM()) {
    1360               0 :     RootViewManager()->UpdateWidgetGeometry();
    1361               0 :     return;
    1362                 :   }
    1363                 : 
    1364               0 :   if (mHasPendingWidgetGeometryChanges) {
    1365               0 :     ProcessPendingUpdatesForView(mRootView, false);
    1366               0 :     mHasPendingWidgetGeometryChanges = false;
    1367                 :   }
    1368                 : }
    1369                 : 
    1370                 : void
    1371               0 : nsViewManager::CallWillPaintOnObservers(bool aWillSendDidPaint)
    1372                 : {
    1373               0 :   NS_PRECONDITION(IsRootVM(), "Must be root VM for this to be called!");
    1374                 : 
    1375                 :   PRInt32 index;
    1376               0 :   for (index = 0; index < mVMCount; index++) {
    1377               0 :     nsViewManager* vm = (nsViewManager*)gViewManagers->ElementAt(index);
    1378               0 :     if (vm->RootViewManager() == this) {
    1379                 :       // One of our kids.
    1380               0 :       if (vm->mRootView && vm->mRootView->IsEffectivelyVisible()) {
    1381               0 :         nsCOMPtr<nsIPresShell> shell = vm->GetPresShell();
    1382               0 :         if (shell) {
    1383               0 :           shell->WillPaint(aWillSendDidPaint);
    1384                 :         }
    1385                 :       }
    1386                 :     }
    1387                 :   }
    1388               0 : }
    1389                 : 
    1390                 : void
    1391               0 : nsViewManager::CallDidPaintOnObserver()
    1392                 : {
    1393               0 :   NS_PRECONDITION(IsRootVM(), "Must be root VM for this to be called!");
    1394                 : 
    1395               0 :   if (mRootView && mRootView->IsEffectivelyVisible()) {
    1396               0 :     nsCOMPtr<nsIPresShell> shell = GetPresShell();
    1397               0 :     if (shell) {
    1398               0 :       shell->DidPaint();
    1399                 :     }
    1400                 :   }
    1401               0 : }
    1402                 : 
    1403                 : NS_IMETHODIMP
    1404               0 : nsViewManager::GetLastUserEventTime(PRUint32& aTime)
    1405                 : {
    1406               0 :   aTime = gLastUserEventTime;
    1407               0 :   return NS_OK;
    1408                 : }
    1409                 : 
    1410                 : void
    1411               0 : nsViewManager::InvalidateHierarchy()
    1412                 : {
    1413               0 :   if (mRootView) {
    1414               0 :     if (!IsRootVM()) {
    1415               0 :       NS_RELEASE(mRootViewManager);
    1416                 :     }
    1417               0 :     nsView *parent = mRootView->GetParent();
    1418               0 :     if (parent) {
    1419               0 :       mRootViewManager = parent->GetViewManager()->RootViewManager();
    1420               0 :       NS_ADDREF(mRootViewManager);
    1421               0 :       NS_ASSERTION(mRootViewManager != this,
    1422                 :                    "Root view had a parent, but it has the same view manager");
    1423                 :     } else {
    1424               0 :       mRootViewManager = this;
    1425                 :     }
    1426                 :   }
    1427               0 : }

Generated by: LCOV version 1.7