void nsViewManager::WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint) { if (IsRefreshDriverPaintingEnabled()) return; if (!aWidget || !mContext) return; // If an ancestor widget was hidden and then shown, we could // have a delayed resize to handle. for (nsViewManager *vm = this; vm; vm = vm->mRootView->GetParent() ? vm->mRootView->GetParent()->GetViewManager() : nullptr) { if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && vm->mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) { vm->FlushDelayedResize(true); vm->InvalidateView(vm->mRootView); } } // Flush things like reflows and plugin widget geometry updates by // calling WillPaint on observer presShells. nsRefPtr<nsViewManager> rootVM = RootViewManager(); if (mPresShell) { rootVM->CallWillPaintOnObservers(aWillSendDidPaint); } // Flush view widget geometry updates and invalidations. rootVM->ProcessPendingUpdates(); }
void nsViewManager::ProcessPendingUpdates() { if (!IsRootVM()) { RootViewManager()->ProcessPendingUpdates(); return; } if (IsRefreshDriverPaintingEnabled()) { mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush(); if (mHasPendingUpdates) { mHasPendingUpdates = false; // Flush things like reflows and plugin widget geometry updates by // calling WillPaint on observer presShells. if (mPresShell) { CallWillPaintOnObservers(true); } ProcessPendingUpdatesForView(mRootView, true); CallDidPaintOnObserver(); } } else if (mHasPendingUpdates) { ProcessPendingUpdatesForView(mRootView, true); mHasPendingUpdates = false; } }
void nsViewManager::ProcessPendingUpdatesForView(nsView* aView, bool aFlushDirtyRegion) { NS_ASSERTION(IsRootVM(), "Updates will be missed"); // Protect against a null-view. if (!aView) { return; } if (aView->HasWidget()) { aView->ResetWidgetBounds(false, true); } // process pending updates in child view. for (nsView* childView = aView->GetFirstChild(); childView; childView = childView->GetNextSibling()) { ProcessPendingUpdatesForView(childView, aFlushDirtyRegion); } // Push out updates after we've processed the children; ensures that // damage is applied based on the final widget geometry if (aFlushDirtyRegion && aView->HasNonEmptyDirtyRegion()) { FlushDirtyRegionToWidget(aView); if (IsRefreshDriverPaintingEnabled()) { nsIWidget *widget = aView->GetWidget(); if (widget && widget->NeedsPaint()) { // If an ancestor widget was hidden and then shown, we could // have a delayed resize to handle. for (nsViewManager *vm = this; vm; vm = vm->mRootView->GetParent() ? vm->mRootView->GetParent()->GetViewManager() : nullptr) { if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && vm->mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) { vm->FlushDelayedResize(true); vm->InvalidateView(vm->mRootView); } } NS_ASSERTION(aView->HasWidget(), "Must have a widget!"); SetPainting(true); #ifdef DEBUG_INVALIDATIONS printf("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", mPresShell, aView, widget); #endif nsAutoScriptBlocker scriptBlocker; NS_ASSERTION(aView->HasWidget(), "Must have a widget!"); mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, true); #ifdef DEBUG_INVALIDATIONS printf("---- PAINT END ----\n"); #endif aView->SetForcedRepaint(false); SetPainting(false); } } } }
void nsViewManager::UpdateWidgetGeometry() { if (!IsRootVM()) { RootViewManager()->UpdateWidgetGeometry(); return; } if (mHasPendingWidgetGeometryChanges) { if (IsRefreshDriverPaintingEnabled()) { mHasPendingWidgetGeometryChanges = false; } ProcessPendingUpdatesForView(mRootView, false); if (!IsRefreshDriverPaintingEnabled()) { mHasPendingWidgetGeometryChanges = false; } } }
void nsViewManager::WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint) { if (!IsRefreshDriverPaintingEnabled() && aWidget && mContext) { // If an ancestor widget was hidden and then shown, we could // have a delayed resize to handle. for (nsViewManager *vm = this; vm; vm = vm->mRootView->GetParent() ? vm->mRootView->GetParent()->GetViewManager() : nullptr) { if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && vm->mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) { vm->FlushDelayedResize(true); vm->InvalidateView(vm->mRootView); } } // Flush things like reflows by calling WillPaint on observer presShells. nsRefPtr<nsViewManager> rootVM = RootViewManager(); rootVM->CallWillPaintOnObservers(aWillSendDidPaint); // Flush view widget geometry updates and invalidations. rootVM->ProcessPendingUpdates(); } if (aWidget && IsRefreshDriverPaintingEnabled()) { nsView* view = nsView::GetViewFor(aWidget); if (view && view->ForcedRepaint()) { ProcessPendingUpdates(); // Re-get the view pointer here since the ProcessPendingUpdates might have // destroyed it during CallWillPaintOnObservers. view = nsView::GetViewFor(aWidget); if (view) { view->SetForcedRepaint(false); } } } nsCOMPtr<nsIPresShell> shell = mPresShell; if (shell) { shell->WillPaintWindow(aWillSendDidPaint); } }
void nsViewManager::ProcessPendingUpdates() { if (!IsRootVM()) { RootViewManager()->ProcessPendingUpdates(); return; } if (IsRefreshDriverPaintingEnabled()) { mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush(); // Flush things like reflows by calling WillPaint on observer presShells. if (mPresShell) { CallWillPaintOnObservers(true); } ProcessPendingUpdatesForView(mRootView, true); } else { ProcessPendingUpdatesForView(mRootView, true); } }
bool nsViewManager::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion, uint32_t aFlags) { if (!aWidget || !mContext) return false; NS_ASSERTION(IsPaintingAllowed(), "shouldn't be receiving paint events while painting is disallowed!"); if (!(aFlags & nsIWidgetListener::SENT_WILL_PAINT) && !IsRefreshDriverPaintingEnabled()) { WillPaintWindow(aWidget, (aFlags & nsIWidgetListener::WILL_SEND_DID_PAINT)); } // Get the view pointer here since NS_WILL_PAINT might have // destroyed it during CallWillPaintOnObservers (bug 378273). nsView* view = nsView::GetViewFor(aWidget); if (view && !aRegion.IsEmpty()) { Refresh(view, aRegion, (aFlags & nsIWidgetListener::WILL_SEND_DID_PAINT)); } return true; }
/** aRegion is given in device coordinates!! aContext may be null, in which case layers should be used for rendering. */ void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion, bool aWillSendDidPaint) { NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); // damageRegion is the damaged area, in twips, relative to the view origin nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel()); // move region from widget coordinates into view coordinates damageRegion.MoveBy(-aView->ViewToWidgetOffset()); if (damageRegion.IsEmpty()) { #ifdef DEBUG_roc nsRect viewRect = aView->GetDimensions(); nsRect damageRect = damageRegion.GetBounds(); printf("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n", damageRect.x, damageRect.y, damageRect.width, damageRect.height, viewRect.x, viewRect.y, viewRect.width, viewRect.height); #endif return; } nsIWidget *widget = aView->GetWidget(); if (!widget) { return; } NS_ASSERTION(!IsPainting(), "recursive painting not permitted"); if (IsPainting()) { RootViewManager()->mRecursiveRefreshPending = true; return; } { nsAutoScriptBlocker scriptBlocker; SetPainting(true); NS_ASSERTION(GetDisplayRootFor(aView) == aView, "Widgets that we paint must all be display roots"); if (mPresShell) { #ifdef DEBUG_INVALIDATIONS printf("--COMPOSITE-- %p\n", mPresShell); #endif mPresShell->Paint(aView, damageRegion, (IsRefreshDriverPaintingEnabled() ? 0 : nsIPresShell::PAINT_LAYERS) | nsIPresShell::PAINT_COMPOSITE | (aWillSendDidPaint ? nsIPresShell::PAINT_WILL_SEND_DID_PAINT : 0)); #ifdef DEBUG_INVALIDATIONS printf("--ENDCOMPOSITE--\n"); #endif mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT); } SetPainting(false); } if (RootViewManager()->mRecursiveRefreshPending) { RootViewManager()->mRecursiveRefreshPending = false; InvalidateAllViews(); } }
void nsViewManager::DidPaintWindow() { if (!IsRefreshDriverPaintingEnabled()) { mRootViewManager->CallDidPaintOnObserver(); } }