LCOV - app.info - view/src/nsViewManager.cpp

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