1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/view/src/nsViewManager.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1142 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1) 1.10 +#include "plarena.h" 1.11 + 1.12 +#include "nsAutoPtr.h" 1.13 +#include "nsViewManager.h" 1.14 +#include "nsGfxCIID.h" 1.15 +#include "nsView.h" 1.16 +#include "nsCOMPtr.h" 1.17 +#include "mozilla/MouseEvents.h" 1.18 +#include "nsRegion.h" 1.19 +#include "nsCOMArray.h" 1.20 +#include "nsIPluginWidget.h" 1.21 +#include "nsXULPopupManager.h" 1.22 +#include "nsIPresShell.h" 1.23 +#include "nsPresContext.h" 1.24 +#include "mozilla/StartupTimeline.h" 1.25 +#include "GeckoProfiler.h" 1.26 +#include "nsRefreshDriver.h" 1.27 +#include "mozilla/Preferences.h" 1.28 +#include "nsContentUtils.h" // for nsAutoScriptBlocker 1.29 +#include "nsLayoutUtils.h" 1.30 +#include "Layers.h" 1.31 +#include "gfxPlatform.h" 1.32 +#include "gfxPrefs.h" 1.33 +#include "nsIDocument.h" 1.34 + 1.35 +/** 1.36 + XXX TODO XXX 1.37 + 1.38 + DeCOMify newly private methods 1.39 + Optimize view storage 1.40 +*/ 1.41 + 1.42 +/** 1.43 + A note about platform assumptions: 1.44 + 1.45 + We assume that a widget is z-ordered on top of its parent. 1.46 + 1.47 + We do NOT assume anything about the relative z-ordering of sibling widgets. Even though 1.48 + we ask for a specific z-order, we don't assume that widget z-ordering actually works. 1.49 +*/ 1.50 + 1.51 +using namespace mozilla; 1.52 +using namespace mozilla::layers; 1.53 + 1.54 +#define NSCOORD_NONE INT32_MIN 1.55 + 1.56 +#undef DEBUG_MOUSE_LOCATION 1.57 + 1.58 +int32_t nsViewManager::mVMCount = 0; 1.59 + 1.60 +// Weakly held references to all of the view managers 1.61 +nsVoidArray* nsViewManager::gViewManagers = nullptr; 1.62 +uint32_t nsViewManager::gLastUserEventTime = 0; 1.63 + 1.64 +nsViewManager::nsViewManager() 1.65 + : mDelayedResize(NSCOORD_NONE, NSCOORD_NONE) 1.66 +{ 1.67 + mRootViewManager = this; 1.68 + if (gViewManagers == nullptr) { 1.69 + NS_ASSERTION(mVMCount == 0, "View Manager count is incorrect"); 1.70 + // Create an array to hold a list of view managers 1.71 + gViewManagers = new nsVoidArray; 1.72 + } 1.73 + 1.74 + gViewManagers->AppendElement(this); 1.75 + 1.76 + ++mVMCount; 1.77 + 1.78 + // NOTE: we use a zeroing operator new, so all data members are 1.79 + // assumed to be cleared here. 1.80 + mHasPendingWidgetGeometryChanges = false; 1.81 + mRecursiveRefreshPending = false; 1.82 +} 1.83 + 1.84 +nsViewManager::~nsViewManager() 1.85 +{ 1.86 + if (mRootView) { 1.87 + // Destroy any remaining views 1.88 + mRootView->Destroy(); 1.89 + mRootView = nullptr; 1.90 + } 1.91 + 1.92 + if (!IsRootVM()) { 1.93 + // We have a strong ref to mRootViewManager 1.94 + NS_RELEASE(mRootViewManager); 1.95 + } 1.96 + 1.97 + NS_ASSERTION((mVMCount > 0), "underflow of viewmanagers"); 1.98 + --mVMCount; 1.99 + 1.100 +#ifdef DEBUG 1.101 + bool removed = 1.102 +#endif 1.103 + gViewManagers->RemoveElement(this); 1.104 + NS_ASSERTION(removed, "Viewmanager instance not was not in the global list of viewmanagers"); 1.105 + 1.106 + if (0 == mVMCount) { 1.107 + // There aren't any more view managers so 1.108 + // release the global array of view managers 1.109 + 1.110 + NS_ASSERTION(gViewManagers != nullptr, "About to delete null gViewManagers"); 1.111 + delete gViewManagers; 1.112 + gViewManagers = nullptr; 1.113 + } 1.114 + 1.115 + mPresShell = nullptr; 1.116 +} 1.117 + 1.118 +// We don't hold a reference to the presentation context because it 1.119 +// holds a reference to us. 1.120 +nsresult 1.121 +nsViewManager::Init(nsDeviceContext* aContext) 1.122 +{ 1.123 + NS_PRECONDITION(nullptr != aContext, "null ptr"); 1.124 + 1.125 + if (nullptr == aContext) { 1.126 + return NS_ERROR_NULL_POINTER; 1.127 + } 1.128 + if (nullptr != mContext) { 1.129 + return NS_ERROR_ALREADY_INITIALIZED; 1.130 + } 1.131 + mContext = aContext; 1.132 + 1.133 + return NS_OK; 1.134 +} 1.135 + 1.136 +nsView* 1.137 +nsViewManager::CreateView(const nsRect& aBounds, 1.138 + nsView* aParent, 1.139 + nsViewVisibility aVisibilityFlag) 1.140 +{ 1.141 + nsView *v = new nsView(this, aVisibilityFlag); 1.142 + v->SetParent(aParent); 1.143 + v->SetPosition(aBounds.x, aBounds.y); 1.144 + nsRect dim(0, 0, aBounds.width, aBounds.height); 1.145 + v->SetDimensions(dim, false); 1.146 + return v; 1.147 +} 1.148 + 1.149 +void 1.150 +nsViewManager::SetRootView(nsView *aView) 1.151 +{ 1.152 + NS_PRECONDITION(!aView || aView->GetViewManager() == this, 1.153 + "Unexpected viewmanager on root view"); 1.154 + 1.155 + // Do NOT destroy the current root view. It's the caller's responsibility 1.156 + // to destroy it 1.157 + mRootView = aView; 1.158 + 1.159 + if (mRootView) { 1.160 + nsView* parent = mRootView->GetParent(); 1.161 + if (parent) { 1.162 + // Calling InsertChild on |parent| will InvalidateHierarchy() on us, so 1.163 + // no need to set mRootViewManager ourselves here. 1.164 + parent->InsertChild(mRootView, nullptr); 1.165 + } else { 1.166 + InvalidateHierarchy(); 1.167 + } 1.168 + 1.169 + mRootView->SetZIndex(false, 0); 1.170 + } 1.171 + // Else don't touch mRootViewManager 1.172 +} 1.173 + 1.174 +void 1.175 +nsViewManager::GetWindowDimensions(nscoord *aWidth, nscoord *aHeight) 1.176 +{ 1.177 + if (nullptr != mRootView) { 1.178 + if (mDelayedResize == nsSize(NSCOORD_NONE, NSCOORD_NONE)) { 1.179 + nsRect dim = mRootView->GetDimensions(); 1.180 + *aWidth = dim.width; 1.181 + *aHeight = dim.height; 1.182 + } else { 1.183 + *aWidth = mDelayedResize.width; 1.184 + *aHeight = mDelayedResize.height; 1.185 + } 1.186 + } 1.187 + else 1.188 + { 1.189 + *aWidth = 0; 1.190 + *aHeight = 0; 1.191 + } 1.192 +} 1.193 + 1.194 +void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight) 1.195 +{ 1.196 + nsRect oldDim = mRootView->GetDimensions(); 1.197 + nsRect newDim(0, 0, aWidth, aHeight); 1.198 + // We care about resizes even when one dimension is already zero. 1.199 + if (!oldDim.IsEqualEdges(newDim)) { 1.200 + // Don't resize the widget. It is already being set elsewhere. 1.201 + mRootView->SetDimensions(newDim, true, false); 1.202 + if (mPresShell) 1.203 + mPresShell->ResizeReflow(aWidth, aHeight); 1.204 + } 1.205 +} 1.206 + 1.207 +void 1.208 +nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight) 1.209 +{ 1.210 + if (mRootView) { 1.211 + if (mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) { 1.212 + if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && 1.213 + mDelayedResize != nsSize(aWidth, aHeight)) { 1.214 + // We have a delayed resize; that now obsolete size may already have 1.215 + // been flushed to the PresContext so we need to update the PresContext 1.216 + // with the new size because if the new size is exactly the same as the 1.217 + // root view's current size then DoSetWindowDimensions will not 1.218 + // request a resize reflow (which would correct it). See bug 617076. 1.219 + mDelayedResize = nsSize(aWidth, aHeight); 1.220 + FlushDelayedResize(false); 1.221 + } 1.222 + mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE); 1.223 + DoSetWindowDimensions(aWidth, aHeight); 1.224 + } else { 1.225 + mDelayedResize.SizeTo(aWidth, aHeight); 1.226 + if (mPresShell && mPresShell->GetDocument()) { 1.227 + mPresShell->GetDocument()->SetNeedStyleFlush(); 1.228 + } 1.229 + } 1.230 + } 1.231 +} 1.232 + 1.233 +void 1.234 +nsViewManager::FlushDelayedResize(bool aDoReflow) 1.235 +{ 1.236 + if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE)) { 1.237 + if (aDoReflow) { 1.238 + DoSetWindowDimensions(mDelayedResize.width, mDelayedResize.height); 1.239 + mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE); 1.240 + } else if (mPresShell) { 1.241 + nsPresContext* presContext = mPresShell->GetPresContext(); 1.242 + if (presContext) { 1.243 + presContext->SetVisibleArea(nsRect(nsPoint(0, 0), mDelayedResize)); 1.244 + } 1.245 + } 1.246 + } 1.247 +} 1.248 + 1.249 +// Convert aIn from being relative to and in appunits of aFromView, to being 1.250 +// relative to and in appunits of aToView. 1.251 +static nsRegion ConvertRegionBetweenViews(const nsRegion& aIn, 1.252 + nsView* aFromView, 1.253 + nsView* aToView) 1.254 +{ 1.255 + nsRegion out = aIn; 1.256 + out.MoveBy(aFromView->GetOffsetTo(aToView)); 1.257 + out = out.ConvertAppUnitsRoundOut( 1.258 + aFromView->GetViewManager()->AppUnitsPerDevPixel(), 1.259 + aToView->GetViewManager()->AppUnitsPerDevPixel()); 1.260 + return out; 1.261 +} 1.262 + 1.263 +nsView* nsViewManager::GetDisplayRootFor(nsView* aView) 1.264 +{ 1.265 + nsView *displayRoot = aView; 1.266 + for (;;) { 1.267 + nsView *displayParent = displayRoot->GetParent(); 1.268 + if (!displayParent) 1.269 + return displayRoot; 1.270 + 1.271 + if (displayRoot->GetFloating() && !displayParent->GetFloating()) 1.272 + return displayRoot; 1.273 + 1.274 + // If we have a combobox dropdown popup within a panel popup, both the view 1.275 + // for the dropdown popup and its parent will be floating, so we need to 1.276 + // distinguish this situation. We do this by looking for a widget. Any view 1.277 + // with a widget is a display root, except for plugins. 1.278 + nsIWidget* widget = displayRoot->GetWidget(); 1.279 + if (widget && widget->WindowType() == eWindowType_popup) { 1.280 + NS_ASSERTION(displayRoot->GetFloating() && displayParent->GetFloating(), 1.281 + "this should only happen with floating views that have floating parents"); 1.282 + return displayRoot; 1.283 + } 1.284 + 1.285 + displayRoot = displayParent; 1.286 + } 1.287 +} 1.288 + 1.289 +/** 1.290 + aRegion is given in device coordinates!! 1.291 + aContext may be null, in which case layers should be used for 1.292 + rendering. 1.293 +*/ 1.294 +void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion) 1.295 +{ 1.296 + NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); 1.297 + 1.298 + if (mPresShell && mPresShell->IsNeverPainting()) { 1.299 + return; 1.300 + } 1.301 + 1.302 + // damageRegion is the damaged area, in twips, relative to the view origin 1.303 + nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel()); 1.304 + // move region from widget coordinates into view coordinates 1.305 + damageRegion.MoveBy(-aView->ViewToWidgetOffset()); 1.306 + 1.307 + if (damageRegion.IsEmpty()) { 1.308 +#ifdef DEBUG_roc 1.309 + nsRect viewRect = aView->GetDimensions(); 1.310 + nsRect damageRect = damageRegion.GetBounds(); 1.311 + printf_stderr("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n", 1.312 + damageRect.x, damageRect.y, damageRect.width, damageRect.height, 1.313 + viewRect.x, viewRect.y, viewRect.width, viewRect.height); 1.314 +#endif 1.315 + return; 1.316 + } 1.317 + 1.318 + nsIWidget *widget = aView->GetWidget(); 1.319 + if (!widget) { 1.320 + return; 1.321 + } 1.322 + 1.323 + NS_ASSERTION(!IsPainting(), "recursive painting not permitted"); 1.324 + if (IsPainting()) { 1.325 + RootViewManager()->mRecursiveRefreshPending = true; 1.326 + return; 1.327 + } 1.328 + 1.329 + { 1.330 + nsAutoScriptBlocker scriptBlocker; 1.331 + SetPainting(true); 1.332 + 1.333 + NS_ASSERTION(GetDisplayRootFor(aView) == aView, 1.334 + "Widgets that we paint must all be display roots"); 1.335 + 1.336 + if (mPresShell) { 1.337 +#ifdef MOZ_DUMP_PAINTING 1.338 + if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { 1.339 + printf_stderr("--COMPOSITE-- %p\n", mPresShell); 1.340 + } 1.341 +#endif 1.342 + uint32_t paintFlags = nsIPresShell::PAINT_COMPOSITE; 1.343 + LayerManager *manager = widget->GetLayerManager(); 1.344 + if (!manager->NeedsWidgetInvalidation()) { 1.345 + manager->FlushRendering(); 1.346 + } else { 1.347 + mPresShell->Paint(aView, damageRegion, 1.348 + paintFlags); 1.349 + } 1.350 +#ifdef MOZ_DUMP_PAINTING 1.351 + if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { 1.352 + printf_stderr("--ENDCOMPOSITE--\n"); 1.353 + } 1.354 +#endif 1.355 + mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT); 1.356 + } 1.357 + 1.358 + SetPainting(false); 1.359 + } 1.360 + 1.361 + if (RootViewManager()->mRecursiveRefreshPending) { 1.362 + RootViewManager()->mRecursiveRefreshPending = false; 1.363 + InvalidateAllViews(); 1.364 + } 1.365 +} 1.366 + 1.367 +void 1.368 +nsViewManager::ProcessPendingUpdatesForView(nsView* aView, 1.369 + bool aFlushDirtyRegion) 1.370 +{ 1.371 + NS_ASSERTION(IsRootVM(), "Updates will be missed"); 1.372 + if (!aView) { 1.373 + return; 1.374 + } 1.375 + 1.376 + nsCOMPtr<nsIPresShell> rootShell(mPresShell); 1.377 + nsTArray<nsCOMPtr<nsIWidget> > widgets; 1.378 + aView->GetViewManager()->ProcessPendingUpdatesRecurse(aView, widgets); 1.379 + for (uint32_t i = 0; i < widgets.Length(); ++i) { 1.380 + nsView* view = nsView::GetViewFor(widgets[i]); 1.381 + if (view) { 1.382 + view->ResetWidgetBounds(false, true); 1.383 + } 1.384 + } 1.385 + if (rootShell->GetViewManager() != this) { 1.386 + return; // 'this' might have been destroyed 1.387 + } 1.388 + if (aFlushDirtyRegion) { 1.389 + nsAutoScriptBlocker scriptBlocker; 1.390 + SetPainting(true); 1.391 + for (uint32_t i = 0; i < widgets.Length(); ++i) { 1.392 + nsIWidget* widget = widgets[i]; 1.393 + nsView* view = nsView::GetViewFor(widget); 1.394 + if (view) { 1.395 + view->GetViewManager()->ProcessPendingUpdatesPaint(widget); 1.396 + } 1.397 + } 1.398 + SetPainting(false); 1.399 + } 1.400 +} 1.401 + 1.402 +void 1.403 +nsViewManager::ProcessPendingUpdatesRecurse(nsView* aView, 1.404 + nsTArray<nsCOMPtr<nsIWidget> >& aWidgets) 1.405 +{ 1.406 + if (mPresShell && mPresShell->IsNeverPainting()) { 1.407 + return; 1.408 + } 1.409 + 1.410 + for (nsView* childView = aView->GetFirstChild(); childView; 1.411 + childView = childView->GetNextSibling()) { 1.412 + childView->GetViewManager()-> 1.413 + ProcessPendingUpdatesRecurse(childView, aWidgets); 1.414 + } 1.415 + 1.416 + nsIWidget* widget = aView->GetWidget(); 1.417 + if (widget) { 1.418 + aWidgets.AppendElement(widget); 1.419 + } else { 1.420 + FlushDirtyRegionToWidget(aView); 1.421 + } 1.422 +} 1.423 + 1.424 +void 1.425 +nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget) 1.426 +{ 1.427 + if (aWidget->NeedsPaint()) { 1.428 + // If an ancestor widget was hidden and then shown, we could 1.429 + // have a delayed resize to handle. 1.430 + for (nsViewManager *vm = this; vm; 1.431 + vm = vm->mRootView->GetParent() 1.432 + ? vm->mRootView->GetParent()->GetViewManager() 1.433 + : nullptr) { 1.434 + if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && 1.435 + vm->mRootView->IsEffectivelyVisible() && 1.436 + vm->mPresShell && vm->mPresShell->IsVisible()) { 1.437 + vm->FlushDelayedResize(true); 1.438 + } 1.439 + } 1.440 + nsView* view = nsView::GetViewFor(aWidget); 1.441 + if (!view) { 1.442 + NS_ERROR("FlushDelayedResize destroyed the nsView?"); 1.443 + return; 1.444 + } 1.445 + 1.446 + if (mPresShell) { 1.447 +#ifdef MOZ_DUMP_PAINTING 1.448 + if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { 1.449 + printf_stderr("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", 1.450 + mPresShell, view, aWidget); 1.451 + } 1.452 +#endif 1.453 + 1.454 + mPresShell->Paint(view, nsRegion(), nsIPresShell::PAINT_LAYERS); 1.455 + view->SetForcedRepaint(false); 1.456 + 1.457 +#ifdef MOZ_DUMP_PAINTING 1.458 + if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { 1.459 + printf_stderr("---- PAINT END ----\n"); 1.460 + } 1.461 +#endif 1.462 + } 1.463 + } 1.464 + FlushDirtyRegionToWidget(nsView::GetViewFor(aWidget)); 1.465 +} 1.466 + 1.467 +void nsViewManager::FlushDirtyRegionToWidget(nsView* aView) 1.468 +{ 1.469 + NS_ASSERTION(aView->GetViewManager() == this, 1.470 + "FlushDirtyRegionToWidget called on view we don't own"); 1.471 + 1.472 + if (!aView->HasNonEmptyDirtyRegion()) 1.473 + return; 1.474 + 1.475 + nsRegion* dirtyRegion = aView->GetDirtyRegion(); 1.476 + nsView* nearestViewWithWidget = aView; 1.477 + while (!nearestViewWithWidget->HasWidget() && 1.478 + nearestViewWithWidget->GetParent()) { 1.479 + nearestViewWithWidget = nearestViewWithWidget->GetParent(); 1.480 + } 1.481 + nsRegion r = 1.482 + ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget); 1.483 + 1.484 + // If we draw the frame counter we need to make sure we invalidate the area 1.485 + // for it to make it on screen 1.486 + if (gfxPrefs::DrawFrameCounter()) { 1.487 + nsRect counterBounds = gfxPlatform::FrameCounterBounds().ToAppUnits(AppUnitsPerDevPixel()); 1.488 + r = r.Or(r, counterBounds); 1.489 + } 1.490 + 1.491 + nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager(); 1.492 + widgetVM->InvalidateWidgetArea(nearestViewWithWidget, r); 1.493 + dirtyRegion->SetEmpty(); 1.494 +} 1.495 + 1.496 +void 1.497 +nsViewManager::InvalidateView(nsView *aView) 1.498 +{ 1.499 + // Mark the entire view as damaged 1.500 + InvalidateView(aView, aView->GetDimensions()); 1.501 +} 1.502 + 1.503 +static void 1.504 +AddDirtyRegion(nsView *aView, const nsRegion &aDamagedRegion) 1.505 +{ 1.506 + nsRegion* dirtyRegion = aView->GetDirtyRegion(); 1.507 + if (!dirtyRegion) 1.508 + return; 1.509 + 1.510 + dirtyRegion->Or(*dirtyRegion, aDamagedRegion); 1.511 + dirtyRegion->SimplifyOutward(8); 1.512 +} 1.513 + 1.514 +void 1.515 +nsViewManager::PostPendingUpdate() 1.516 +{ 1.517 + nsViewManager* rootVM = RootViewManager(); 1.518 + rootVM->mHasPendingWidgetGeometryChanges = true; 1.519 + if (rootVM->mPresShell) { 1.520 + rootVM->mPresShell->ScheduleViewManagerFlush(); 1.521 + } 1.522 +} 1.523 + 1.524 +/** 1.525 + * @param aDamagedRegion this region, relative to aWidgetView, is invalidated in 1.526 + * every widget child of aWidgetView, plus aWidgetView's own widget 1.527 + */ 1.528 +void 1.529 +nsViewManager::InvalidateWidgetArea(nsView *aWidgetView, 1.530 + const nsRegion &aDamagedRegion) 1.531 +{ 1.532 + NS_ASSERTION(aWidgetView->GetViewManager() == this, 1.533 + "InvalidateWidgetArea called on view we don't own"); 1.534 + nsIWidget* widget = aWidgetView->GetWidget(); 1.535 + 1.536 +#if 0 1.537 + nsRect dbgBounds = aDamagedRegion.GetBounds(); 1.538 + printf("InvalidateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n", 1.539 + aWidgetView, aWidgetView->IsAttachedToTopLevel(), 1.540 + widget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height); 1.541 +#endif 1.542 + 1.543 + // If the widget is hidden, it don't cover nothing 1.544 + if (widget && !widget->IsVisible()) { 1.545 + return; 1.546 + } 1.547 + 1.548 + if (!widget) { 1.549 + // The root view or a scrolling view might not have a widget 1.550 + // (for example, during printing). We get here when we scroll 1.551 + // during printing to show selected options in a listbox, for example. 1.552 + return; 1.553 + } 1.554 + 1.555 + // Update all child widgets with the damage. In the process, 1.556 + // accumulate the union of all the child widget areas, or at least 1.557 + // some subset of that. 1.558 + nsRegion children; 1.559 + if (widget->GetTransparencyMode() != eTransparencyTransparent) { 1.560 + for (nsIWidget* childWidget = widget->GetFirstChild(); 1.561 + childWidget; 1.562 + childWidget = childWidget->GetNextSibling()) { 1.563 + nsView* view = nsView::GetViewFor(childWidget); 1.564 + NS_ASSERTION(view != aWidgetView, "will recur infinitely"); 1.565 + nsWindowType type = childWidget->WindowType(); 1.566 + if (view && childWidget->IsVisible() && type != eWindowType_popup) { 1.567 + NS_ASSERTION(type == eWindowType_plugin, 1.568 + "Only plugin or popup widgets can be children!"); 1.569 + 1.570 + // We do not need to invalidate in plugin widgets, but we should 1.571 + // exclude them from the invalidation region IF we're not on 1.572 + // Mac. On Mac we need to draw under plugin widgets, because 1.573 + // plugin widgets are basically invisible 1.574 +#ifndef XP_MACOSX 1.575 + // GetBounds should compensate for chrome on a toplevel widget 1.576 + nsIntRect bounds; 1.577 + childWidget->GetBounds(bounds); 1.578 + 1.579 + nsTArray<nsIntRect> clipRects; 1.580 + childWidget->GetWindowClipRegion(&clipRects); 1.581 + for (uint32_t i = 0; i < clipRects.Length(); ++i) { 1.582 + nsRect rr = (clipRects[i] + bounds.TopLeft()). 1.583 + ToAppUnits(AppUnitsPerDevPixel()); 1.584 + children.Or(children, rr - aWidgetView->ViewToWidgetOffset()); 1.585 + children.SimplifyInward(20); 1.586 + } 1.587 +#endif 1.588 + } 1.589 + } 1.590 + } 1.591 + 1.592 + nsRegion leftOver; 1.593 + leftOver.Sub(aDamagedRegion, children); 1.594 + 1.595 + if (!leftOver.IsEmpty()) { 1.596 + const nsRect* r; 1.597 + for (nsRegionRectIterator iter(leftOver); (r = iter.Next());) { 1.598 + nsIntRect bounds = ViewToWidget(aWidgetView, *r); 1.599 + widget->Invalidate(bounds); 1.600 + } 1.601 + } 1.602 +} 1.603 + 1.604 +static bool 1.605 +ShouldIgnoreInvalidation(nsViewManager* aVM) 1.606 +{ 1.607 + while (aVM) { 1.608 + nsIPresShell* shell = aVM->GetPresShell(); 1.609 + if (!shell || shell->ShouldIgnoreInvalidation()) { 1.610 + return true; 1.611 + } 1.612 + nsView* view = aVM->GetRootView()->GetParent(); 1.613 + aVM = view ? view->GetViewManager() : nullptr; 1.614 + } 1.615 + return false; 1.616 +} 1.617 + 1.618 +void 1.619 +nsViewManager::InvalidateView(nsView *aView, const nsRect &aRect) 1.620 +{ 1.621 + // If painting is suppressed in the presshell or an ancestor drop all 1.622 + // invalidates, it will invalidate everything when it unsuppresses. 1.623 + if (ShouldIgnoreInvalidation(this)) { 1.624 + return; 1.625 + } 1.626 + 1.627 + InvalidateViewNoSuppression(aView, aRect); 1.628 +} 1.629 + 1.630 +void 1.631 +nsViewManager::InvalidateViewNoSuppression(nsView *aView, 1.632 + const nsRect &aRect) 1.633 +{ 1.634 + NS_PRECONDITION(nullptr != aView, "null view"); 1.635 + 1.636 + NS_ASSERTION(aView->GetViewManager() == this, 1.637 + "InvalidateViewNoSuppression called on view we don't own"); 1.638 + 1.639 + nsRect damagedRect(aRect); 1.640 + if (damagedRect.IsEmpty()) { 1.641 + return; 1.642 + } 1.643 + 1.644 + nsView* displayRoot = GetDisplayRootFor(aView); 1.645 + nsViewManager* displayRootVM = displayRoot->GetViewManager(); 1.646 + // Propagate the update to the displayRoot, since iframes, for example, 1.647 + // can overlap each other and be translucent. So we have to possibly 1.648 + // invalidate our rect in each of the widgets we have lying about. 1.649 + damagedRect.MoveBy(aView->GetOffsetTo(displayRoot)); 1.650 + int32_t rootAPD = displayRootVM->AppUnitsPerDevPixel(); 1.651 + int32_t APD = AppUnitsPerDevPixel(); 1.652 + damagedRect = damagedRect.ConvertAppUnitsRoundOut(APD, rootAPD); 1.653 + 1.654 + // accumulate this rectangle in the view's dirty region, so we can 1.655 + // process it later. 1.656 + AddDirtyRegion(displayRoot, nsRegion(damagedRect)); 1.657 +} 1.658 + 1.659 +void 1.660 +nsViewManager::InvalidateAllViews() 1.661 +{ 1.662 + if (RootViewManager() != this) { 1.663 + return RootViewManager()->InvalidateAllViews(); 1.664 + } 1.665 + 1.666 + InvalidateViews(mRootView); 1.667 +} 1.668 + 1.669 +void nsViewManager::InvalidateViews(nsView *aView) 1.670 +{ 1.671 + // Invalidate this view. 1.672 + InvalidateView(aView); 1.673 + 1.674 + // Invalidate all children as well. 1.675 + nsView* childView = aView->GetFirstChild(); 1.676 + while (nullptr != childView) { 1.677 + childView->GetViewManager()->InvalidateViews(childView); 1.678 + childView = childView->GetNextSibling(); 1.679 + } 1.680 +} 1.681 + 1.682 +void nsViewManager::WillPaintWindow(nsIWidget* aWidget) 1.683 +{ 1.684 + if (aWidget) { 1.685 + nsView* view = nsView::GetViewFor(aWidget); 1.686 + LayerManager *manager = aWidget->GetLayerManager(); 1.687 + if (view && 1.688 + (view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) { 1.689 + ProcessPendingUpdates(); 1.690 + // Re-get the view pointer here since the ProcessPendingUpdates might have 1.691 + // destroyed it during CallWillPaintOnObservers. 1.692 + view = nsView::GetViewFor(aWidget); 1.693 + if (view) { 1.694 + view->SetForcedRepaint(false); 1.695 + } 1.696 + } 1.697 + } 1.698 + 1.699 + nsCOMPtr<nsIPresShell> shell = mPresShell; 1.700 + if (shell) { 1.701 + shell->WillPaintWindow(); 1.702 + } 1.703 +} 1.704 + 1.705 +bool nsViewManager::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion) 1.706 +{ 1.707 + if (!aWidget || !mContext) 1.708 + return false; 1.709 + 1.710 + NS_ASSERTION(IsPaintingAllowed(), 1.711 + "shouldn't be receiving paint events while painting is disallowed!"); 1.712 + 1.713 + // Get the view pointer here since NS_WILL_PAINT might have 1.714 + // destroyed it during CallWillPaintOnObservers (bug 378273). 1.715 + nsView* view = nsView::GetViewFor(aWidget); 1.716 + if (view && !aRegion.IsEmpty()) { 1.717 + Refresh(view, aRegion); 1.718 + } 1.719 + 1.720 + return true; 1.721 +} 1.722 + 1.723 +void nsViewManager::DidPaintWindow() 1.724 +{ 1.725 + nsCOMPtr<nsIPresShell> shell = mPresShell; 1.726 + if (shell) { 1.727 + shell->DidPaintWindow(); 1.728 + } 1.729 +} 1.730 + 1.731 +void 1.732 +nsViewManager::DispatchEvent(WidgetGUIEvent *aEvent, 1.733 + nsView* aView, 1.734 + nsEventStatus* aStatus) 1.735 +{ 1.736 + PROFILER_LABEL("event", "nsViewManager::DispatchEvent"); 1.737 + 1.738 + WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent(); 1.739 + if ((mouseEvent && 1.740 + // Ignore mouse events that we synthesize. 1.741 + mouseEvent->reason == WidgetMouseEvent::eReal && 1.742 + // Ignore mouse exit and enter (we'll get moves if the user 1.743 + // is really moving the mouse) since we get them when we 1.744 + // create and destroy widgets. 1.745 + mouseEvent->message != NS_MOUSE_EXIT && 1.746 + mouseEvent->message != NS_MOUSE_ENTER) || 1.747 + aEvent->HasKeyEventMessage() || 1.748 + aEvent->HasIMEEventMessage() || 1.749 + aEvent->message == NS_PLUGIN_INPUT_EVENT) { 1.750 + gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); 1.751 + } 1.752 + 1.753 + // Find the view whose coordinates system we're in. 1.754 + nsView* view = aView; 1.755 + bool dispatchUsingCoordinates = aEvent->IsUsingCoordinates(); 1.756 + if (dispatchUsingCoordinates) { 1.757 + // Will dispatch using coordinates. Pretty bogus but it's consistent 1.758 + // with what presshell does. 1.759 + view = GetDisplayRootFor(view); 1.760 + } 1.761 + 1.762 + // If the view has no frame, look for a view that does. 1.763 + nsIFrame* frame = view->GetFrame(); 1.764 + if (!frame && 1.765 + (dispatchUsingCoordinates || aEvent->HasKeyEventMessage() || 1.766 + aEvent->IsIMERelatedEvent() || 1.767 + aEvent->IsNonRetargetedNativeEventDelivererForPlugin() || 1.768 + aEvent->HasPluginActivationEventMessage() || 1.769 + aEvent->message == NS_PLUGIN_RESOLUTION_CHANGED)) { 1.770 + while (view && !view->GetFrame()) { 1.771 + view = view->GetParent(); 1.772 + } 1.773 + 1.774 + if (view) { 1.775 + frame = view->GetFrame(); 1.776 + } 1.777 + } 1.778 + 1.779 + if (nullptr != frame) { 1.780 + // Hold a refcount to the presshell. The continued existence of the 1.781 + // presshell will delay deletion of this view hierarchy should the event 1.782 + // want to cause its destruction in, say, some JavaScript event handler. 1.783 + nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell(); 1.784 + if (shell) { 1.785 + shell->HandleEvent(frame, aEvent, false, aStatus); 1.786 + return; 1.787 + } 1.788 + } 1.789 + 1.790 + *aStatus = nsEventStatus_eIgnore; 1.791 +} 1.792 + 1.793 +// Recursively reparent widgets if necessary 1.794 + 1.795 +void nsViewManager::ReparentChildWidgets(nsView* aView, nsIWidget *aNewWidget) 1.796 +{ 1.797 + NS_PRECONDITION(aNewWidget, ""); 1.798 + 1.799 + if (aView->HasWidget()) { 1.800 + // Check to see if the parent widget is the 1.801 + // same as the new parent. If not then reparent 1.802 + // the widget, otherwise there is nothing more 1.803 + // to do for the view and its descendants 1.804 + nsIWidget* widget = aView->GetWidget(); 1.805 + nsIWidget* parentWidget = widget->GetParent(); 1.806 + if (parentWidget) { 1.807 + // Child widget 1.808 + if (parentWidget != aNewWidget) { 1.809 +#ifdef DEBUG 1.810 + nsresult rv = 1.811 +#endif 1.812 + widget->SetParent(aNewWidget); 1.813 + NS_ASSERTION(NS_SUCCEEDED(rv), "SetParent failed!"); 1.814 + } 1.815 + } else { 1.816 + // Toplevel widget (popup, dialog, etc) 1.817 + widget->ReparentNativeWidget(aNewWidget); 1.818 + } 1.819 + return; 1.820 + } 1.821 + 1.822 + // Need to check each of the views children to see 1.823 + // if they have a widget and reparent it. 1.824 + 1.825 + for (nsView *kid = aView->GetFirstChild(); kid; kid = kid->GetNextSibling()) { 1.826 + ReparentChildWidgets(kid, aNewWidget); 1.827 + } 1.828 +} 1.829 + 1.830 +// Reparent a view and its descendant views widgets if necessary 1.831 + 1.832 +void nsViewManager::ReparentWidgets(nsView* aView, nsView *aParent) 1.833 +{ 1.834 + NS_PRECONDITION(aParent, "Must have a parent"); 1.835 + NS_PRECONDITION(aView, "Must have a view"); 1.836 + 1.837 + // Quickly determine whether the view has pre-existing children or a 1.838 + // widget. In most cases the view will not have any pre-existing 1.839 + // children when this is called. Only in the case 1.840 + // where a view has been reparented by removing it from 1.841 + // a reinserting it into a new location in the view hierarchy do we 1.842 + // have to consider reparenting the existing widgets for the view and 1.843 + // it's descendants. 1.844 + if (aView->HasWidget() || aView->GetFirstChild()) { 1.845 + nsIWidget* parentWidget = aParent->GetNearestWidget(nullptr); 1.846 + if (parentWidget) { 1.847 + ReparentChildWidgets(aView, parentWidget); 1.848 + return; 1.849 + } 1.850 + NS_WARNING("Can not find a widget for the parent view"); 1.851 + } 1.852 +} 1.853 + 1.854 +void 1.855 +nsViewManager::InsertChild(nsView *aParent, nsView *aChild, nsView *aSibling, 1.856 + bool aAfter) 1.857 +{ 1.858 + NS_PRECONDITION(nullptr != aParent, "null ptr"); 1.859 + NS_PRECONDITION(nullptr != aChild, "null ptr"); 1.860 + NS_ASSERTION(aSibling == nullptr || aSibling->GetParent() == aParent, 1.861 + "tried to insert view with invalid sibling"); 1.862 + NS_ASSERTION(!IsViewInserted(aChild), "tried to insert an already-inserted view"); 1.863 + 1.864 + if ((nullptr != aParent) && (nullptr != aChild)) 1.865 + { 1.866 + // if aAfter is set, we will insert the child after 'prev' (i.e. after 'kid' in document 1.867 + // order, otherwise after 'kid' (i.e. before 'kid' in document order). 1.868 + 1.869 + if (nullptr == aSibling) { 1.870 + if (aAfter) { 1.871 + // insert at end of document order, i.e., before first view 1.872 + // this is the common case, by far 1.873 + aParent->InsertChild(aChild, nullptr); 1.874 + ReparentWidgets(aChild, aParent); 1.875 + } else { 1.876 + // insert at beginning of document order, i.e., after last view 1.877 + nsView *kid = aParent->GetFirstChild(); 1.878 + nsView *prev = nullptr; 1.879 + while (kid) { 1.880 + prev = kid; 1.881 + kid = kid->GetNextSibling(); 1.882 + } 1.883 + // prev is last view or null if there are no children 1.884 + aParent->InsertChild(aChild, prev); 1.885 + ReparentWidgets(aChild, aParent); 1.886 + } 1.887 + } else { 1.888 + nsView *kid = aParent->GetFirstChild(); 1.889 + nsView *prev = nullptr; 1.890 + while (kid && aSibling != kid) { 1.891 + //get the next sibling view 1.892 + prev = kid; 1.893 + kid = kid->GetNextSibling(); 1.894 + } 1.895 + NS_ASSERTION(kid != nullptr, 1.896 + "couldn't find sibling in child list"); 1.897 + if (aAfter) { 1.898 + // insert after 'kid' in document order, i.e. before in view order 1.899 + aParent->InsertChild(aChild, prev); 1.900 + ReparentWidgets(aChild, aParent); 1.901 + } else { 1.902 + // insert before 'kid' in document order, i.e. after in view order 1.903 + aParent->InsertChild(aChild, kid); 1.904 + ReparentWidgets(aChild, aParent); 1.905 + } 1.906 + } 1.907 + 1.908 + // if the parent view is marked as "floating", make the newly added view float as well. 1.909 + if (aParent->GetFloating()) 1.910 + aChild->SetFloating(true); 1.911 + } 1.912 +} 1.913 + 1.914 +void 1.915 +nsViewManager::InsertChild(nsView *aParent, nsView *aChild, int32_t aZIndex) 1.916 +{ 1.917 + // no-one really calls this with anything other than aZIndex == 0 on a fresh view 1.918 + // XXX this method should simply be eliminated and its callers redirected to the real method 1.919 + SetViewZIndex(aChild, false, aZIndex); 1.920 + InsertChild(aParent, aChild, nullptr, true); 1.921 +} 1.922 + 1.923 +void 1.924 +nsViewManager::RemoveChild(nsView *aChild) 1.925 +{ 1.926 + NS_ASSERTION(aChild, "aChild must not be null"); 1.927 + 1.928 + nsView* parent = aChild->GetParent(); 1.929 + 1.930 + if (nullptr != parent) { 1.931 + NS_ASSERTION(aChild->GetViewManager() == this || 1.932 + parent->GetViewManager() == this, "wrong view manager"); 1.933 + parent->RemoveChild(aChild); 1.934 + } 1.935 +} 1.936 + 1.937 +void 1.938 +nsViewManager::MoveViewTo(nsView *aView, nscoord aX, nscoord aY) 1.939 +{ 1.940 + NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); 1.941 + aView->SetPosition(aX, aY); 1.942 +} 1.943 + 1.944 +void 1.945 +nsViewManager::ResizeView(nsView *aView, const nsRect &aRect, bool aRepaintExposedAreaOnly) 1.946 +{ 1.947 + NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); 1.948 + 1.949 + nsRect oldDimensions = aView->GetDimensions(); 1.950 + if (!oldDimensions.IsEqualEdges(aRect)) { 1.951 + aView->SetDimensions(aRect, true); 1.952 + } 1.953 + 1.954 + // Note that if layout resizes the view and the view has a custom clip 1.955 + // region set, then we expect layout to update the clip region too. Thus 1.956 + // in the case where mClipRect has been optimized away to just be a null 1.957 + // pointer, and this resize is implicitly changing the clip rect, it's OK 1.958 + // because layout will change it back again if necessary. 1.959 +} 1.960 + 1.961 +void 1.962 +nsViewManager::SetViewFloating(nsView *aView, bool aFloating) 1.963 +{ 1.964 + NS_ASSERTION(!(nullptr == aView), "no view"); 1.965 + 1.966 + aView->SetFloating(aFloating); 1.967 +} 1.968 + 1.969 +void 1.970 +nsViewManager::SetViewVisibility(nsView *aView, nsViewVisibility aVisible) 1.971 +{ 1.972 + NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); 1.973 + 1.974 + if (aVisible != aView->GetVisibility()) { 1.975 + aView->SetVisibility(aVisible); 1.976 + } 1.977 +} 1.978 + 1.979 +bool nsViewManager::IsViewInserted(nsView *aView) 1.980 +{ 1.981 + if (mRootView == aView) { 1.982 + return true; 1.983 + } else if (aView->GetParent() == nullptr) { 1.984 + return false; 1.985 + } else { 1.986 + nsView* view = aView->GetParent()->GetFirstChild(); 1.987 + while (view != nullptr) { 1.988 + if (view == aView) { 1.989 + return true; 1.990 + } 1.991 + view = view->GetNextSibling(); 1.992 + } 1.993 + return false; 1.994 + } 1.995 +} 1.996 + 1.997 +void 1.998 +nsViewManager::SetViewZIndex(nsView *aView, bool aAutoZIndex, int32_t aZIndex) 1.999 +{ 1.1000 + NS_ASSERTION((aView != nullptr), "no view"); 1.1001 + 1.1002 + // don't allow the root view's z-index to be changed. It should always be zero. 1.1003 + // This could be removed and replaced with a style rule, or just removed altogether, with interesting consequences 1.1004 + if (aView == mRootView) { 1.1005 + return; 1.1006 + } 1.1007 + 1.1008 + if (aAutoZIndex) { 1.1009 + aZIndex = 0; 1.1010 + } 1.1011 + 1.1012 + aView->SetZIndex(aAutoZIndex, aZIndex); 1.1013 +} 1.1014 + 1.1015 +nsViewManager* 1.1016 +nsViewManager::IncrementDisableRefreshCount() 1.1017 +{ 1.1018 + if (!IsRootVM()) { 1.1019 + return RootViewManager()->IncrementDisableRefreshCount(); 1.1020 + } 1.1021 + 1.1022 + ++mRefreshDisableCount; 1.1023 + 1.1024 + return this; 1.1025 +} 1.1026 + 1.1027 +void 1.1028 +nsViewManager::DecrementDisableRefreshCount() 1.1029 +{ 1.1030 + NS_ASSERTION(IsRootVM(), "Should only be called on root"); 1.1031 + --mRefreshDisableCount; 1.1032 + NS_ASSERTION(mRefreshDisableCount >= 0, "Invalid refresh disable count!"); 1.1033 +} 1.1034 + 1.1035 +void 1.1036 +nsViewManager::GetRootWidget(nsIWidget **aWidget) 1.1037 +{ 1.1038 + if (!mRootView) { 1.1039 + *aWidget = nullptr; 1.1040 + return; 1.1041 + } 1.1042 + if (mRootView->HasWidget()) { 1.1043 + *aWidget = mRootView->GetWidget(); 1.1044 + NS_ADDREF(*aWidget); 1.1045 + return; 1.1046 + } 1.1047 + if (mRootView->GetParent()) { 1.1048 + mRootView->GetParent()->GetViewManager()->GetRootWidget(aWidget); 1.1049 + return; 1.1050 + } 1.1051 + *aWidget = nullptr; 1.1052 +} 1.1053 + 1.1054 +nsIntRect nsViewManager::ViewToWidget(nsView *aView, const nsRect &aRect) const 1.1055 +{ 1.1056 + NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); 1.1057 + 1.1058 + // account for the view's origin not lining up with the widget's 1.1059 + nsRect rect = aRect + aView->ViewToWidgetOffset(); 1.1060 + 1.1061 + // finally, convert to device coordinates. 1.1062 + return rect.ToOutsidePixels(AppUnitsPerDevPixel()); 1.1063 +} 1.1064 + 1.1065 +void 1.1066 +nsViewManager::IsPainting(bool& aIsPainting) 1.1067 +{ 1.1068 + aIsPainting = IsPainting(); 1.1069 +} 1.1070 + 1.1071 +void 1.1072 +nsViewManager::ProcessPendingUpdates() 1.1073 +{ 1.1074 + if (!IsRootVM()) { 1.1075 + RootViewManager()->ProcessPendingUpdates(); 1.1076 + return; 1.1077 + } 1.1078 + 1.1079 + mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush(); 1.1080 + 1.1081 + // Flush things like reflows by calling WillPaint on observer presShells. 1.1082 + if (mPresShell) { 1.1083 + CallWillPaintOnObservers(); 1.1084 + } 1.1085 + ProcessPendingUpdatesForView(mRootView, true); 1.1086 +} 1.1087 + 1.1088 +void 1.1089 +nsViewManager::UpdateWidgetGeometry() 1.1090 +{ 1.1091 + if (!IsRootVM()) { 1.1092 + RootViewManager()->UpdateWidgetGeometry(); 1.1093 + return; 1.1094 + } 1.1095 + 1.1096 + if (mHasPendingWidgetGeometryChanges) { 1.1097 + mHasPendingWidgetGeometryChanges = false; 1.1098 + ProcessPendingUpdatesForView(mRootView, false); 1.1099 + } 1.1100 +} 1.1101 + 1.1102 +void 1.1103 +nsViewManager::CallWillPaintOnObservers() 1.1104 +{ 1.1105 + NS_PRECONDITION(IsRootVM(), "Must be root VM for this to be called!"); 1.1106 + 1.1107 + int32_t index; 1.1108 + for (index = 0; index < mVMCount; index++) { 1.1109 + nsViewManager* vm = (nsViewManager*)gViewManagers->ElementAt(index); 1.1110 + if (vm->RootViewManager() == this) { 1.1111 + // One of our kids. 1.1112 + if (vm->mRootView && vm->mRootView->IsEffectivelyVisible()) { 1.1113 + nsCOMPtr<nsIPresShell> shell = vm->GetPresShell(); 1.1114 + if (shell) { 1.1115 + shell->WillPaint(); 1.1116 + } 1.1117 + } 1.1118 + } 1.1119 + } 1.1120 +} 1.1121 + 1.1122 +void 1.1123 +nsViewManager::GetLastUserEventTime(uint32_t& aTime) 1.1124 +{ 1.1125 + aTime = gLastUserEventTime; 1.1126 +} 1.1127 + 1.1128 +void 1.1129 +nsViewManager::InvalidateHierarchy() 1.1130 +{ 1.1131 + if (mRootView) { 1.1132 + if (!IsRootVM()) { 1.1133 + NS_RELEASE(mRootViewManager); 1.1134 + } 1.1135 + nsView *parent = mRootView->GetParent(); 1.1136 + if (parent) { 1.1137 + mRootViewManager = parent->GetViewManager()->RootViewManager(); 1.1138 + NS_ADDREF(mRootViewManager); 1.1139 + NS_ASSERTION(mRootViewManager != this, 1.1140 + "Root view had a parent, but it has the same view manager"); 1.1141 + } else { 1.1142 + mRootViewManager = this; 1.1143 + } 1.1144 + } 1.1145 +}