Bug 770000 - Call WillPaint and DidPaint from the refresh driver instead of the widget events. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 13 Aug 2012 22:10:11 +1200
changeset 102191 0ad204385022dc9c34f91b5685e0d999c8101036
parent 102190 6723b36d8bfa33c25a5802fe6ab280e9f5b1d40f
child 102192 febfb5404b8202587119c079ee214af27e6015bf
push id13357
push usermwoodrow@mozilla.com
push dateMon, 13 Aug 2012 10:12:16 +0000
treeherdermozilla-inbound@6a0b53d78465 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs770000
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 770000 - Call WillPaint and DidPaint from the refresh driver instead of the widget events. r=roc
toolkit/content/tests/chrome/test_bug624329.xul
view/src/nsViewManager.cpp
--- a/toolkit/content/tests/chrome/test_bug624329.xul
+++ b/toolkit/content/tests/chrome/test_bug624329.xul
@@ -50,26 +50,25 @@ function childFocused() {
     // the right edge of the screen.
 
     listenOnce("resize", childResized);
     win.maximize();
 }
 
 function childResized() {
     const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
+
+    is(win.windowState, win.STATE_MAXIMIZED,
+       "window should be maximized");
+
     if (isOSXLion) {
-        todo_is(win.windowState, win.STATE_MAXIMIZED,
-                "A resize before being maximized breaks this test on 10.7");
         finish();
         return;
     }
 
-    is(win.windowState, win.STATE_MAXIMIZED,
-       "window should be maximized");
-
     isnot(win.innerWidth, 300,
          "window inner width should have changed");
 
     openContextMenu();
 }
 
 function openContextMenu() {
     var mouseX = win.innerWidth - 10;
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -333,17 +333,17 @@ void nsViewManager::Refresh(nsView *aVie
     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, nsIPresShell::PaintType_Composite,
-                        aWillSendDidPaint);
+                        false);
 #ifdef DEBUG_INVALIDATIONS
       printf("--ENDCOMPOSITE--\n");
 #endif
       mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT);
     }
 
     SetPainting(false);
   }
@@ -375,22 +375,39 @@ void nsViewManager::ProcessPendingUpdate
   }
 
   // Push out updates after we've processed the children; ensures that
   // damage is applied based on the final widget geometry
   if (aFlushDirtyRegion) {
     nsIWidget *widget = aView->GetWidget();
     if (widget && widget->NeedsPaint() && aView->HasNonEmptyDirtyRegion()) {
       FlushDirtyRegionToWidget(aView);
+      // 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;
-      mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, false);
+      NS_ASSERTION(aView->HasWidget(), "Must have a widget!");
+      mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, true);
 #ifdef DEBUG_INVALIDATIONS
       printf("---- PAINT END ----\n");
 #endif
       SetPainting(false);
     }
   }
 }
 
@@ -712,45 +729,16 @@ NS_IMETHODIMP nsViewManager::DispatchEve
       break;
 
     case NS_WILL_PAINT:
       {
         if (!aView || !mContext)
           break;
 
         *aStatus = nsEventStatus_eConsumeNoDefault;
-
-        nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
-
-        NS_ASSERTION(static_cast<nsView*>(aView) ==
-                       nsView::GetViewFor(event->widget),
-                     "view/widget mismatch");
-
-        // 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(event->willSendDidPaint);
-        }
-        // Flush view widget geometry updates and invalidations.
-        rootVM->ProcessPendingUpdates();
       }
       break;
 
     case NS_PAINT:
       {
         if (!aView || !mContext)
           break;
 
@@ -758,39 +746,26 @@ NS_IMETHODIMP nsViewManager::DispatchEve
         nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
         nsView* view = static_cast<nsView*>(aView);
         NS_ASSERTION(view == nsView::GetViewFor(event->widget),
                      "view/widget mismatch");
         NS_ASSERTION(IsPaintingAllowed(),
                      "shouldn't be receiving paint events while painting is "
                      "disallowed!");
 
-        if (!event->didSendWillPaint) {
-          // Send NS_WILL_PAINT event ourselves.
-          nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget);
-          willPaintEvent.willSendDidPaint = event->willSendDidPaint;
-          DispatchEvent(&willPaintEvent, view, aStatus);
-
-          // Get the view pointer again since NS_WILL_PAINT might have
-          // destroyed it during CallWillPaintOnObservers (bug 378273).
-          view = nsView::GetViewFor(event->widget);
-        }
-
         if (!view || event->region.IsEmpty())
           break;
 
         // Paint.
         Refresh(view, event->region, event->willSendDidPaint);
 
         break;
       }
 
     case NS_DID_PAINT: {
-      nsRefPtr<nsViewManager> rootVM = RootViewManager();
-      rootVM->CallDidPaintOnObserver();
       break;
     }
 
     case NS_CREATE:
     case NS_DESTROY:
     case NS_SETZLEVEL:
       /* Don't pass these events through. Passing them through
          causes performance problems on pages with lots of views/frames 
@@ -1306,32 +1281,39 @@ void
 nsViewManager::ProcessPendingUpdates()
 {
   if (!IsRootVM()) {
     RootViewManager()->ProcessPendingUpdates();
     return;
   }
 
   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);
-    mHasPendingUpdates = false;
+    CallDidPaintOnObserver();
   }
 }
 
 void
 nsViewManager::UpdateWidgetGeometry()
 {
   if (!IsRootVM()) {
     RootViewManager()->UpdateWidgetGeometry();
     return;
   }
 
   if (mHasPendingWidgetGeometryChanges) {
+    mHasPendingWidgetGeometryChanges = false;
     ProcessPendingUpdatesForView(mRootView, false);
-    mHasPendingWidgetGeometryChanges = false;
   }
 }
 
 void
 nsViewManager::CallWillPaintOnObservers(bool aWillSendDidPaint)
 {
   NS_PRECONDITION(IsRootVM(), "Must be root VM for this to be called!");