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 idunknown
push userunknown
push dateunknown
reviewersroc
bugs797431
milestone19.0a1
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() { }