Bug 770000 - Call WillPaint and DidPaint from the refresh driver instead of the widget events. r=roc
☠☠ backed out by 902e4fd79c9e ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 03 Jul 2012 21:06:04 +1200
changeset 98157 674cde7d007a5adb887578529255998fb6812c98
parent 98156 d8a4ef92f06e08cebf9e40ecfd4e112803df0419
child 98158 3175d72d8a40878ee9e030f31672a421649ad597
push id11389
push usermwoodrow@mozilla.com
push dateTue, 03 Jul 2012 09:18:28 +0000
treeherdermozilla-inbound@3175d72d8a40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs770000
milestone16.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
@@ -336,17 +336,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);
   }
@@ -382,29 +382,52 @@ bool nsViewManager::ProcessPendingUpdate
   // damage is applied based on the final widget geometry
   if (aFlushDirtyRegion) {
     nsIWidget *widget = aView->GetWidget();
     if (widget && widget->NeedsPaint()) {
       if (aView->PendingRefresh() && aView->SkippedPaints() < 5) {
         aView->SkippedPaint();
         skipped = true;
       } else {
+        // 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()
+                    : nsnull) {
+          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(true);
+        }
+
         aView->ClearSkippedPaints();
         aView->SetPendingRefresh(false);
         widget->SetNeedsPaint(false);
         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);
+        mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, true);
 #ifdef DEBUG_INVALIDATIONS
         printf("---- PAINT END ----\n");
 #endif
         SetPainting(false);
+      
+        rootVM->CallDidPaintOnObserver();
       }
     }
     FlushDirtyRegionToWidget(aView);
   }
   return skipped;
 }
 
 void nsViewManager::FlushDirtyRegionToWidget(nsView* aView)
@@ -727,45 +750,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()
-                    : nsnull) {
-          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;
 
@@ -773,39 +767,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