From 1ada24c3010b8c0f32638876ee2f2992de41f099 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 28 Jan 2013 13:34:03 -0600 Subject: [PATCH] Bug 826817. Part 1: Send WillPaintWindow/DidPaintWindow from all widget implementations. r=tnikkel --- widget/android/nsWindow.cpp | 10 ++++++++-- widget/cocoa/nsChildView.mm | 16 +++++++++++----- widget/gonk/nsWindow.cpp | 24 ++++++++++++++++++++---- widget/nsIWidgetListener.h | 10 ++++++++-- widget/xpwidgets/PuppetWidget.cpp | 10 +++++++--- 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index c989dcbbf27..8453b496d4c 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1014,6 +1014,8 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) bool painted = false; nsIntRegion region = invalidRect; + mWidgetListener->WillPaintWindow(this, true); + switch (GetLayerManager(nullptr)->GetBackendType()) { case mozilla::layers::LAYERS_BASIC: { @@ -1024,7 +1026,8 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) 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 @@ -1044,7 +1047,8 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) static_cast(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; } @@ -1052,6 +1056,8 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect) 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; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index b11e26de49e..aad74dacb91 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1489,30 +1489,36 @@ bool nsChildView::DispatchWindowEvent(nsGUIEvent &event) bool nsChildView::PaintWindow(nsIntRegion aRegion, bool aIsAlternate) { - nsIWidget* widget = this; - nsIWidgetListener* listener = mWidgetListener; + nsCOMPtr 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; } diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 57d9820c297..7c656729528 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -222,14 +222,22 @@ nsWindow::DoDraw(void) 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(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 targetSurface; @@ -249,8 +257,11 @@ nsWindow::DoDraw(void) 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) { @@ -260,6 +271,11 @@ nsWindow::DoDraw(void) } else { NS_RUNTIMEABORT("Unexpected layer manager type"); } + + listener = gWindowToRedraw->GetWidgetListener(); + if (listener) { + listener->DidPaintWindow(); + } } nsEventStatus diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h index b7ae8523a93..0bd47900621 100644 --- a/widget/nsIWidgetListener.h +++ b/widget/nsIWidgetListener.h @@ -113,13 +113,17 @@ public: 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 */ @@ -129,7 +133,9 @@ public: 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() { } diff --git a/widget/xpwidgets/PuppetWidget.cpp b/widget/xpwidgets/PuppetWidget.cpp index 2dd9660e413..6cd8e3327c6 100644 --- a/widget/xpwidgets/PuppetWidget.cpp +++ b/widget/xpwidgets/PuppetWidget.cpp @@ -521,21 +521,25 @@ PuppetWidget::Paint() 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 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(); } }