Bug 1062801 - Fill vibrant window regions with the correct vibrancy fill color. r=smichaud, a=lmandel
authorMarkus Stange <mstange@themasta.com>
Tue, 07 Oct 2014 16:18:01 +0200
changeset 225626 61d8f01fdd45f9c489847700f5ddb6da67dc8da9
parent 225625 5e6a9d665beb39b4688d584940d6c24d7728b824
child 225627 9bedbe95e531a9a93c52a437a5aa5caff1df83f3
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud, lmandel
bugs1062801
milestone34.0a2
Bug 1062801 - Fill vibrant window regions with the correct vibrancy fill color. r=smichaud, a=lmandel
widget/cocoa/VibrancyManager.h
widget/cocoa/VibrancyManager.mm
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/VibrancyManager.h
+++ b/widget/cocoa/VibrancyManager.h
@@ -10,16 +10,17 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/TypedEnum.h"
 #include "nsClassHashtable.h"
 #include "nsRegion.h"
 #include "nsTArray.h"
 
 #import <Foundation/NSGeometry.h>
 
+@class NSColor;
 @class NSView;
 class nsChildView;
 class nsIntRegion;
 
 namespace mozilla {
 
 MOZ_BEGIN_ENUM_CLASS(VibrancyType)
   LIGHT,
@@ -71,16 +72,24 @@ public:
    * Clear the vibrant areas that we know about.
    * The clearing happens in the current NSGraphicsContext. If you call this
    * from within an -[NSView drawRect:] implementation, the currrent
    * NSGraphicsContext is already correctly set to the window drawing context.
    */
   void ClearVibrantAreas() const;
 
   /**
+   * Return the fill color that should be drawn on top of the cleared window
+   * parts. Usually this would be drawn by -[NSVisualEffectView drawRect:].
+   * The returned color is opaque if the system-wide "Reduce transparency"
+   * preference is set.
+   */
+  NSColor* VibrancyFillColorForType(VibrancyType aType);
+
+  /**
    * Check whether the operating system supports vibrancy at all.
    * You may only create a VibrancyManager instance if this returns true.
    * @return Whether VibrancyManager can be used on this OS.
    */
   static bool SystemSupportsVibrancy();
 
   // The following are only public because otherwise ClearVibrantRegionFunc
   // can't see them.
--- a/widget/cocoa/VibrancyManager.mm
+++ b/widget/cocoa/VibrancyManager.mm
@@ -78,16 +78,36 @@ VibrancyManager::ClearVibrantRegion(cons
   [[NSColor clearColor] set];
 
   nsIntRegionRectIterator iter(aVibrantRegion.region);
   while (const nsIntRect* rect = iter.Next()) {
     NSRectFill(mCoordinateConverter.DevPixelsToCocoaPoints(*rect));
   }
 }
 
+@interface NSView(CurrentFillColor)
+- (NSColor*)_currentFillColor;
+@end
+
+NSColor*
+VibrancyManager::VibrancyFillColorForType(VibrancyType aType)
+{
+  const nsTArray<NSView*>& views =
+    mVibrantRegions.LookupOrAdd(uint32_t(aType))->effectViews;
+
+  if (!views.IsEmpty() &&
+      [views[0] respondsToSelector:@selector(_currentFillColor)]) {
+    // -[NSVisualEffectView _currentFillColor] is the color that our view
+    // would draw during its drawRect implementation, if we hadn't
+    // disabled that.
+    return [views[0] _currentFillColor];
+  }
+  return [NSColor whiteColor];
+}
+
 static void
 DrawRectNothing(id self, SEL _cmd, NSRect aRect)
 {
   // The super implementation would clear the background.
   // That's fine for views that are placed below their content, but our
   // setup is different: Our drawn content is drawn to mContainerView, which
   // sits below this EffectView. So we must not clear the background here,
   // because we'd erase that drawn content.
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -326,16 +326,18 @@ typedef NSInteger NSEventGestureAxis;
 - (BOOL)isInFailingLeftClickThrough;
 
 - (void)setGLContext:(NSOpenGLContext *)aGLContext;
 - (bool)preRender:(NSOpenGLContext *)aGLContext;
 - (void)postRender:(NSOpenGLContext *)aGLContext;
 
 - (BOOL)isCoveringTitlebar;
 
+- (NSColor*)vibrancyFillColorForWidgetType:(uint8_t)aWidgetType;
+
 // Simple gestures support
 //
 // XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
 // rotateWithEvent, and endGestureWithEvent methods are part of a
 // PRIVATE interface exported by nsResponder and reverse-engineering
 // was necessary to obtain the methods' prototypes. Thus, Apple may
 // change the interface in the future without notice.
 //
@@ -567,16 +569,17 @@ public:
 
   mozilla::widget::TextInputHandler* GetTextInputHandler()
   {
     return mTextInputHandler;
   }
 
   void              NotifyDirtyRegion(const nsIntRegion& aDirtyRegion);
   void              ClearVibrantAreas();
+  NSColor*          VibrancyFillColorForWidgetType(uint8_t aWidgetType);
 
   // unit conversion convenience functions
   int32_t           CocoaPointsToDevPixels(CGFloat aPts) const {
     return nsCocoaUtils::CocoaPointsToDevPixels(aPts, BackingScaleFactor());
   }
   nsIntPoint        CocoaPointsToDevPixels(const NSPoint& aPt) const {
     return nsCocoaUtils::CocoaPointsToDevPixels(aPt, BackingScaleFactor());
   }
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2644,16 +2644,27 @@ nsChildView::UpdateVibrancy(const nsTArr
 void
 nsChildView::ClearVibrantAreas()
 {
   if (VibrancyManager::SystemSupportsVibrancy()) {
     EnsureVibrancyManager().ClearVibrantAreas();
   }
 }
 
+NSColor*
+nsChildView::VibrancyFillColorForWidgetType(uint8_t aWidgetType)
+{
+  if (VibrancyManager::SystemSupportsVibrancy()) {
+    return EnsureVibrancyManager().VibrancyFillColorForType(
+      aWidgetType == NS_THEME_MAC_VIBRANCY_LIGHT
+        ? VibrancyType::LIGHT : VibrancyType::DARK);
+  }
+  return [NSColor whiteColor];
+}
+
 mozilla::VibrancyManager&
 nsChildView::EnsureVibrancyManager()
 {
   MOZ_ASSERT(mView, "Only call this once we have a view!");
   if (!mVibrancyManager) {
     mVibrancyManager = MakeUnique<VibrancyManager>(*this, mView);
   }
   return *mVibrancyManager;
@@ -3616,16 +3627,24 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 - (BOOL)isCoveringTitlebar
 {
   return [[self window] isKindOfClass:[BaseWindow class]] &&
          [(BaseWindow*)[self window] mainChildView] == self &&
          [(BaseWindow*)[self window] drawsContentsIntoWindowFrame];
 }
 
+- (NSColor*)vibrancyFillColorForWidgetType:(uint8_t)aWidgetType
+{
+  if (!mGeckoChild) {
+    return [NSColor whiteColor];
+  }
+  return mGeckoChild->VibrancyFillColorForWidgetType(aWidgetType);
+}
+
 - (nsIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect
 {
   nsIntRect boundingRect = mGeckoChild->CocoaPointsToDevPixels(aRect);
   const NSRect *rects;
   NSInteger count;
   [self getRectsBeingDrawn:&rects count:&count];
 
   if (count > MAX_RECTS_IN_REGION) {
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2817,16 +2817,33 @@ nsNativeThemeCocoa::DrawWidgetBackground
 
     case NS_THEME_TAB_PANELS:
       DrawTabPanel(cgContext, macRect, aFrame);
       break;
 
     case NS_THEME_RESIZER:
       DrawResizer(cgContext, macRect, aFrame);
       break;
+
+    case NS_THEME_MAC_VIBRANCY_LIGHT:
+    case NS_THEME_MAC_VIBRANCY_DARK:
+    {
+      NSWindow* win = NativeWindowForFrame(aFrame);
+      if ([win isKindOfClass:[ToolbarWindow class]]) {
+        NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
+
+        ChildView* childView = [(ToolbarWindow*)win mainChildView];
+        [[childView vibrancyFillColorForWidgetType:aWidgetType] set];
+        NSRectFill(NSRectFromCGRect(macRect));
+
+        [NSGraphicsContext setCurrentContext:savedContext];
+      }
+      break;
+    }
   }
 
   nativeDrawing.EndNativeDrawing();
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }