Bug 797431 - Add 'alternate paint' flag to PaintWindow, and don't clear ForcedRepaint on the view when it is set. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 15 Oct 2012 17:53:37 +1300
changeset 118184 1bca31fd0e58c29bfdfb713321f55a4078ae489b
parent 118183 ab00790e8fedd734508a739b982af34c08a1a238
child 118185 65652fcb58dcb1417f6cefc7191ce54a6676639d
push id1997
push userakeybl@mozilla.com
push dateMon, 07 Jan 2013 21:25:26 +0000
treeherdermozilla-beta@4baf45cdcf21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs797431
milestone19.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 797431 - Add 'alternate paint' flag to PaintWindow, and don't clear ForcedRepaint on the view when it is set. r=roc
view/public/nsIView.h
view/src/nsView.cpp
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/nsIWidgetListener.h
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -302,17 +302,21 @@ public:
    */
   nsIWidget* GetWidget() const { return mWindow; }
 
   /**
    * Returns true if the view has a widget associated with it.
    */
   bool HasWidget() const { return mWindow != nullptr; }
   
-  void SetForcedRepaint(bool aForceRepaint) { mForcedRepaint = aForceRepaint; }
+  void SetForcedRepaint(bool aForceRepaint) { 
+    if (!mInAlternatePaint) { 
+      mForcedRepaint = aForceRepaint; 
+    }
+  }
   bool ForcedRepaint() { return mForcedRepaint; }
 
   /**
    * Make aWidget direct its events to this view.
    * The caller must call DetachWidgetEventHandler before this view
    * is destroyed.
    */
   void AttachWidgetEventHandler(nsIWidget* aWidget);
@@ -362,16 +366,17 @@ protected:
   // relative to parent, but in our appunits
   nsRect            mDimBounds;
   // in our appunits
   nsPoint           mViewToWidgetOffset;
   float             mOpacity;
   uint32_t          mVFlags;
   bool              mWidgetIsTopLevel;
   bool              mForcedRepaint;
+  bool              mInAlternatePaint;
 
   virtual ~nsIView() {}
 
 private:
   nsView* Impl();
   const nsView* Impl() const;
 };
 
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -24,16 +24,17 @@ nsView::nsView(nsViewManager* aViewManag
   // Views should be transparent by default. Not being transparent is
   // a promise that the view will paint all its pixels opaquely. Views
   // should make this promise explicitly by calling
   // SetViewContentTransparency.
   mVFlags = 0;
   mViewManager = aViewManager;
   mDirtyRegion = nullptr;
   mWidgetIsTopLevel = false;
+  mInAlternatePaint = false;
 }
 
 void nsView::DropMouseGrabbing()
 {
   nsIPresShell* presShell = mViewManager->GetPresShell();
   if (presShell)
     presShell->ClearMouseCaptureOnView(this);
 }
@@ -1027,18 +1028,21 @@ void
 nsView::WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint)
 {
   mViewManager->WillPaintWindow(aWidget, aWillSendDidPaint);
 }
 
 bool
 nsView::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion, uint32_t aFlags)
 {
+  mInAlternatePaint = aFlags & PAINT_IS_ALTERNATE;
   nsCOMPtr<nsViewManager> vm = mViewManager;
-  return vm->PaintWindow(aWidget, aRegion, aFlags);
+  bool result = vm->PaintWindow(aWidget, aRegion, aFlags);
+  mInAlternatePaint = false;
+  return result;
 }
 
 void
 nsView::DidPaintWindow()
 {
   mViewManager->DidPaintWindow();
 }
 
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -484,17 +484,17 @@ public:
 
   virtual nsresult SynthesizeNativeMouseMove(nsIntPoint aPoint)
   { return SynthesizeNativeMouseEvent(aPoint, NSMouseMoved, 0); }
 
   // Mac specific methods
   
   virtual bool      DispatchWindowEvent(nsGUIEvent& event);
 
-  bool PaintWindow(nsIntRegion aRegion);
+  bool PaintWindow(nsIntRegion aRegion, bool aIsAlternate);
 
 #ifdef ACCESSIBILITY
   already_AddRefed<Accessible> GetDocumentAccessible();
 #endif
 
   virtual void CreateCompositor();
   virtual gfxASurface* GetThebesSurface();
   virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect);
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -131,17 +131,17 @@ uint32_t nsChildView::sLastInputEventCou
 - (void)setPluginEventModel:(NPEventModel)eventModel;
 - (void)setPluginDrawingModel:(NPDrawingModel)drawingModel;
 - (NPDrawingModel)pluginDrawingModel;
 
 - (BOOL)isRectObscuredBySubview:(NSRect)inRect;
 
 - (void)processPendingRedraws;
 
-- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext;
+- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext alternate:(BOOL)aIsAlternate;
 
 // Called using performSelector:withObject:afterDelay:0 to release
 // aWidgetArray (and its contents) the next time through the run loop.
 - (void)releaseWidgets:(NSArray*)aWidgetArray;
 
 #if USE_CLICK_HOLD_CONTEXTMENU
  // called on a timer two seconds after a mouse down to see if we should display
  // a context menu (click-hold)
@@ -1413,17 +1413,17 @@ NS_IMETHODIMP nsChildView::DispatchEvent
 
 bool nsChildView::DispatchWindowEvent(nsGUIEvent &event)
 {
   nsEventStatus status;
   DispatchEvent(&event, status);
   return ConvertStatus(status);
 }
 
-bool nsChildView::PaintWindow(nsIntRegion aRegion)
+bool nsChildView::PaintWindow(nsIntRegion aRegion, bool aIsAlternate)
 {
   nsIWidget* widget = this;
   nsIWidgetListener* listener = mWidgetListener;
 
   // If there is no listener, use the parent popup's listener if that exists.
   if (!listener && mParentWidget) {
     nsWindowType type;
     mParentWidget->GetWindowType(type);
@@ -1434,17 +1434,21 @@ bool nsChildView::PaintWindow(nsIntRegio
   }
 
   if (!listener)
     return false;
 
   bool returnValue = false;
   bool oldDispatchPaint = mIsDispatchPaint;
   mIsDispatchPaint = true;
-  returnValue = listener->PaintWindow(widget, aRegion, SENT_WILL_PAINT);
+  uint32_t flags = nsIWidgetListener::SENT_WILL_PAINT;
+  if (aIsAlternate) {
+    flags |= nsIWidgetListener::PAINT_IS_ALTERNATE; 
+  }
+  returnValue = listener->PaintWindow(widget, aRegion, flags);
   mIsDispatchPaint = oldDispatchPaint;
   return returnValue;
 }
 
 #pragma mark -
 
 void nsChildView::ReportMoveEvent()
 {
@@ -2369,37 +2373,37 @@ NSEvent* gLastDragMouseDownEvent = nil;
   return nsCocoaUtils::HiDPIEnabled() ? YES : NO;
 }
 
 // The display system has told us that a portion of our view is dirty. Tell
 // gecko to paint it
 - (void)drawRect:(NSRect)aRect
 {
   CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-  [self drawRect:aRect inContext:cgContext];
+  [self drawRect:aRect inContext:cgContext alternate:false];
 
   // If we're a transparent window and our contents have changed, we need
   // to make sure the shadow is updated to the new contents.
   if ([[self window] isKindOfClass:[BaseWindow class]]) {
     [(BaseWindow*)[self window] deferredInvalidateShadow];
   }
 }
 
 - (void)drawRect:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext
 {
   if (!mGeckoChild)
     return;
 
   // Title bar drawing only works if we really draw into aContext, which only
   // the basic layer manager will do.
   nsBaseWidget::AutoUseBasicLayerManager setupLayerManager(mGeckoChild);
-  [self drawRect:aRect inContext:aContext];
-}
-
-- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext
+  [self drawRect:aRect inContext:aContext alternate:true];
+}
+
+- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext alternate:(BOOL)aIsAlternate
 {
   SAMPLE_LABEL("widget", "ChildView::drawRect");
   if (!mGeckoChild || !mGeckoChild->IsVisible())
     return;
 
   // Don't ever draw plugin views explicitly; they'll be drawn as part of their parent widget.
   if (mIsPluginView)
     return;
@@ -2443,17 +2447,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
     if (!mGLContext) {
       [self setGLContext:glContext];
     }
 
     [glContext setView:self];
     [glContext update];
 
-    mGeckoChild->PaintWindow(region);
+    mGeckoChild->PaintWindow(region, aIsAlternate);
 
     // Force OpenGL to refresh the very first time we draw. This works around a
     // Mac OS X bug that stops windows updating on OS X when we use OpenGL.
     if (!mDidForceRefreshOpenGL) {
       [self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
       mDidForceRefreshOpenGL = YES;
     }
 
@@ -2487,17 +2491,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
   }
   targetContext->Clip();
 
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
   bool painted;
   {
     nsBaseWidget::AutoLayerManagerSetup
       setupLayerManager(mGeckoChild, targetContext, BUFFER_NONE);
-    painted = mGeckoChild->PaintWindow(region);
+    painted = mGeckoChild->PaintWindow(region, aIsAlternate);
   }
 
   // Force OpenGL to refresh the very first time we draw. This works around a
   // Mac OS X bug that stops windows updating on OS X when we use OpenGL.
   if (painted && !mDidForceRefreshOpenGL &&
       layerManager->AsShadowManager() && mUsingOMTCompositor) {
     if (!mDidForceRefreshOpenGL) {
       [self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -119,16 +119,17 @@ public:
 
   /**
    * Paint the specified region of the window. Returns true if the
    * notification was handled.
    */
   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.
    */
   virtual void DidPaintWindow() { }