Bug 826817. Part 1: Send WillPaintWindow/DidPaintWindow from all widget implementations. r=tnikkel
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 28 Jan 2013 13:34:03 -0600
changeset 129970 954ef23857baab1c472c6ecc2fb9fda4daffda67
parent 129969 72f40d55cde7fa72ca6f503318c4f5317da8416d
child 129971 dbd2536c95b386af1e2de26a26a9e0f786521455
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs826817
milestone21.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 826817. Part 1: Send WillPaintWindow/DidPaintWindow from all widget implementations. r=tnikkel
widget/android/nsWindow.cpp
widget/cocoa/nsChildView.mm
widget/gonk/nsWindow.cpp
widget/nsIWidgetListener.h
widget/xpwidgets/PuppetWidget.cpp
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1009,27 +1009,30 @@ nsWindow::DrawTo(gfxASurface *targetSurf
         }
     }
 
     // If we have no covering child, then we need to render this.
     if (coveringChildIndex == -1) {
         bool painted = false;
         nsIntRegion region = invalidRect;
 
+        mWidgetListener->WillPaintWindow(this, true);
+
         switch (GetLayerManager(nullptr)->GetBackendType()) {
             case mozilla::layers::LAYERS_BASIC: {
 
                 nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
 
                 {
                     mozilla::layers::RenderTraceScope trace2("Basic DrawTo", "727272");
                     AutoLayerManagerSetup
                       setupLayerManager(this, ctx, mozilla::layers::BUFFER_NONE);
 
-                    painted = mWidgetListener->PaintWindow(this, region, 0);
+                    painted = mWidgetListener->PaintWindow(this, region,
+                        nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
                 }
 
                 // XXX uhh.. we can't just ignore this because we no longer have
                 // what we needed before, but let's keep drawing the children anyway?
 #if 0
                 if (!painted)
                     return false;
 #endif
@@ -1039,24 +1042,27 @@ nsWindow::DrawTo(gfxASurface *targetSurf
                 break;
             }
 
             case mozilla::layers::LAYERS_OPENGL: {
 
                 static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager(nullptr))->
                     SetClippingRegion(nsIntRegion(boundsRect));
 
-                painted = mWidgetListener->PaintWindow(this, region, 0);
+                painted = mWidgetListener->PaintWindow(this, region,
+                    nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
                 break;
             }
 
             default:
                 NS_ERROR("Invalid layer manager");
         }
 
+        mWidgetListener->DidPaintWindow();
+
         // We had no covering child, so make sure we draw all the children,
         // starting from index 0.
         coveringChildIndex = 0;
     }
 
     gfxPoint offset;
 
     if (targetSurface)
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1484,40 +1484,46 @@ bool nsChildView::DispatchWindowEvent(ns
 {
   nsEventStatus status;
   DispatchEvent(&event, status);
   return ConvertStatus(status);
 }
 
 bool nsChildView::PaintWindow(nsIntRegion aRegion, bool aIsAlternate)
 {
-  nsIWidget* widget = this;
-  nsIWidgetListener* listener = mWidgetListener;
+  nsCOMPtr<nsIWidget> widget = this;
 
   // If there is no listener, use the parent popup's listener if that exists.
-  if (!listener && mParentWidget) {
+  if (!mWidgetListener && mParentWidget) {
     nsWindowType type;
     mParentWidget->GetWindowType(type);
     if (type == eWindowType_popup) {
       widget = mParentWidget;
-      listener = mParentWidget->GetWidgetListener();
     }
   }
 
+  nsIWidgetListener* listener = widget->GetWidgetListener();
   if (!listener)
     return false;
 
   bool returnValue = false;
   bool oldDispatchPaint = mIsDispatchPaint;
   mIsDispatchPaint = true;
-  uint32_t flags = nsIWidgetListener::SENT_WILL_PAINT;
+  uint32_t flags =
+    nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT;
   if (aIsAlternate) {
     flags |= nsIWidgetListener::PAINT_IS_ALTERNATE; 
   }
   returnValue = listener->PaintWindow(widget, aRegion, flags);
+
+  listener = widget->GetWidgetListener();
+  if (listener) {
+    listener->DidPaintWindow();
+  }
+
   mIsDispatchPaint = oldDispatchPaint;
   return returnValue;
 }
 
 #pragma mark -
 
 void nsChildView::ReportMoveEvent()
 {
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -217,24 +217,32 @@ nsWindow::DoDraw(void)
         return;
     }
 
     StopBootAnimation();
 
     nsIntRegion region = gWindowToRedraw->mDirtyRegion;
     gWindowToRedraw->mDirtyRegion.SetEmpty();
 
+    nsIWidgetListener* listener = gWindowToRedraw->GetWidgetListener();
+    if (listener) {
+        listener->WillPaintWindow(gWindowToRedraw, true);
+    }
+
     LayerManager* lm = gWindowToRedraw->GetLayerManager();
     if (mozilla::layers::LAYERS_OPENGL == lm->GetBackendType()) {
         LayerManagerOGL* oglm = static_cast<LayerManagerOGL*>(lm);
         oglm->SetClippingRegion(region);
         oglm->SetWorldTransform(sRotationMatrix);
 
-        if (nsIWidgetListener* listener = gWindowToRedraw->GetWidgetListener())
-          listener->PaintWindow(gWindowToRedraw, region, 0);
+        listener = gWindowToRedraw->GetWidgetListener();
+        if (listener) {
+            listener->PaintWindow(gWindowToRedraw, region,
+                nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
+        }
     } else if (mozilla::layers::LAYERS_BASIC == lm->GetBackendType()) {
         MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
         nsRefPtr<gfxASurface> targetSurface;
 
         if(sUsingOMTC)
             targetSurface = sOMTCSurface;
         else
             targetSurface = Framebuffer::BackBuffer();
@@ -244,27 +252,35 @@ nsWindow::DoDraw(void)
             gfxUtils::PathFromRegion(ctx, region);
             ctx->Clip();
 
             // No double-buffering needed.
             AutoLayerManagerSetup setupLayerManager(
                 gWindowToRedraw, ctx, mozilla::layers::BUFFER_NONE,
                 ScreenRotation(EffectiveScreenRotation()));
 
-            if (nsIWidgetListener* listener = gWindowToRedraw->GetWidgetListener())
-              listener->PaintWindow(gWindowToRedraw, region, 0);
+            listener = gWindowToRedraw->GetWidgetListener();
+            if (listener) {
+                listener->PaintWindow(gWindowToRedraw, region,
+                    nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
+            }
         }
 
         if (!sUsingOMTC) {
             targetSurface->Flush();
             Framebuffer::Present(region);
         }
     } else {
         NS_RUNTIMEABORT("Unexpected layer manager type");
     }
+
+    listener = gWindowToRedraw->GetWidgetListener();
+    if (listener) {
+        listener->DidPaintWindow();
+    }
 }
 
 nsEventStatus
 nsWindow::DispatchInputEvent(nsGUIEvent &aEvent, bool* aWasCaptured)
 {
     if (aWasCaptured) {
         *aWasCaptured = false;
     }
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -108,33 +108,39 @@ public:
 
   /**
    * Called when a request is made to close the window. Returns true if the
    * notification was handled. Returns true if the notification was handled.
    */
   virtual bool RequestWindowClose(nsIWidget* aWidget) { return false; }
 
   /*
-   * Indicate that a paint is about to occur on this window.
+   * Indicate that a paint is about to occur on this window. This is called
+   * at a time when it's OK to change the geometry of this widget or of
+   * other widgets.
    */
   virtual void WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint) { }
 
   /**
    * Paint the specified region of the window. Returns true if the
    * notification was handled.
+   * This is called at a time when it is not OK to change the geometry of
+   * this widget or of other widgets.
    */
   enum {
     SENT_WILL_PAINT = 1 << 0, /* WillPaintWindow has already been called */
     WILL_SEND_DID_PAINT = 1 << 1, /* A call to DidPaintWindow will be made afterwards. */
     PAINT_IS_ALTERNATE = 1 << 2 /* We are painting something other than the normal widget */
   };
   virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion, uint32_t aFlags) { return false; }
 
   /**
-   * On some platforms, indicates that a paint occurred.
+   * Indicates that a paint occurred.
+   * This is called at a time when it is OK to change the geometry of
+   * this widget or of other widgets.
    */
   virtual void DidPaintWindow() { }
 
   /**
    * Request that layout schedules a repaint on the next refresh driver tick.
    */
   virtual void RequestRepaint() { }
 
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -516,31 +516,35 @@ PuppetWidget::Paint()
     return NS_OK;
 
   nsIntRegion region = mDirtyRegion;
 
   // reset repaint tracking
   mDirtyRegion.SetEmpty();
   mPaintTask.Revoke();
 
-  {
+  mAttachedWidgetListener->WillPaintWindow(this, true);
+
+  if (mAttachedWidgetListener) {
 #ifdef DEBUG
     debug_DumpPaintEvent(stderr, this, region,
                          nsAutoCString("PuppetWidget"), 0);
 #endif
 
     if (mozilla::layers::LAYERS_D3D10 == mLayerManager->GetBackendType()) {
-      mAttachedWidgetListener->PaintWindow(this, region, nsIWidgetListener::WILL_SEND_DID_PAINT);
+      mAttachedWidgetListener->PaintWindow(this, region,
+        nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
     } else {
       nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
       ctx->Rectangle(gfxRect(0,0,0,0));
       ctx->Clip();
       AutoLayerManagerSetup setupLayerManager(this, ctx,
                                               BUFFER_NONE);
-      mAttachedWidgetListener->PaintWindow(this, region, nsIWidgetListener::WILL_SEND_DID_PAINT);
+      mAttachedWidgetListener->PaintWindow(this, region,
+        nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
       mTabChild->NotifyPainted();
     }
   }
 
   if (mAttachedWidgetListener) {
     mAttachedWidgetListener->DidPaintWindow();
   }