Bug 1142393 - Make menus look correct when 'Reduce transparency' is set. r=smichaud
authorMarkus Stange <mstange@themasta.com>
Mon, 16 Mar 2015 16:20:46 -0400
changeset 234056 58b677bbf8b878e79ea1df19899d4608d5679291
parent 234055 b83f949ac00d7cf6eeb640bca55cf5373a2a76e3
child 234057 2b78320baffb3a3b1b6afb301d916d0bec03dd2b
push id57027
push usermstange@themasta.com
push dateTue, 17 Mar 2015 15:46:55 +0000
treeherdermozilla-inbound@58b677bbf8b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud
bugs1142393
milestone39.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 1142393 - Make menus look correct when 'Reduce transparency' is set. r=smichaud
widget/cocoa/VibrancyManager.mm
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/VibrancyManager.mm
+++ b/widget/cocoa/VibrancyManager.mm
@@ -82,28 +82,41 @@ VibrancyManager::ClearVibrantRegion(cons
     NSRectFill(mCoordinateConverter.DevPixelsToCocoaPoints(*rect));
   }
 }
 
 @interface NSView(CurrentFillColor)
 - (NSColor*)_currentFillColor;
 @end
 
+static NSColor*
+AdjustedColor(NSColor* aFillColor, VibrancyType aType)
+{
+  if (aType == VibrancyType::MENU && [aFillColor alphaComponent] == 1.0) {
+    // The opaque fill color that's used for the menu background when "Reduce
+    // vibrancy" is checked in the system accessibility prefs is too dark.
+    // This is probably because we're not using the right material for menus,
+    // see VibrancyManager::CreateEffectView.
+    return [NSColor colorWithDeviceWhite:0.96 alpha:1.0];
+  }
+  return aFillColor;
+}
+
 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 AdjustedColor([views[0] _currentFillColor], aType);
   }
   return [NSColor whiteColor];
 }
 
 @interface NSView(FontSmoothingBackgroundColor)
 - (NSColor*)fontSmoothingBackgroundColor;
 @end
 
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2251,27 +2251,46 @@ nsNativeThemeCocoa::DrawResizer(CGContex
   RenderTransformedHIThemeControl(cgContext, aRect, RenderResizer, &drawInfo,
                                   IsFrameRTL(aFrame));
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static void
 DrawVibrancyBackground(CGContextRef cgContext, CGRect inBoxRect,
-                       nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType)
+                       nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType,
+                       int aCornerRadiusIfOpaque = 0)
 {
   ChildView* childView = ChildViewForFrame(aFrame);
   if (childView) {
     NSRect rect = NSRectFromCGRect(inBoxRect);
     NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
-
-    [[childView vibrancyFillColorForThemeGeometryType:aThemeGeometryType] set];
+    [NSGraphicsContext saveGraphicsState];
+
+    NSColor* fillColor = [childView vibrancyFillColorForThemeGeometryType:aThemeGeometryType];
+    if ([fillColor alphaComponent] == 1.0 && aCornerRadiusIfOpaque > 0) {
+      // The fillColor being opaque means that the system-wide pref "reduce
+      // transparency" is set. In that scenario, we still go through all the
+      // vibrancy rendering paths (VibrancyManager::SystemSupportsVibrancy()
+      // will still return true), but the result just won't look "vibrant".
+      // However, there's one unfortunate change of behavior that this pref
+      // has: It stops the window server from applying window masks. We use
+      // a window mask to get rounded corners on menus. So since the mask
+      // doesn't work in "reduce vibrancy" mode, we need to do our own rounded
+      // corner clipping here.
+      [[NSBezierPath bezierPathWithRoundedRect:rect
+                                       xRadius:aCornerRadiusIfOpaque
+                                       yRadius:aCornerRadiusIfOpaque] addClip];
+    }
+
+    [fillColor set];
     NSRectFill(rect);
 
+    [NSGraphicsContext restoreGraphicsState];
     [NSGraphicsContext setCurrentContext:savedContext];
   }
 }
 
 static bool
 ScrollbarTrackAndThumbDrawSeparately()
 {
   return nsLookAndFeel::UseOverlayScrollbars() || nsCocoaFeatures::OnLionOrLater();
@@ -2379,17 +2398,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
     case NS_THEME_DIALOG: {
       HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION);
       CGContextFillRect(cgContext, macRect);
     }
       break;
 
     case NS_THEME_MENUPOPUP:
       if (VibrancyManager::SystemSupportsVibrancy()) {
-        DrawVibrancyBackground(cgContext, macRect, aFrame, eThemeGeometryTypeMenu);
+        DrawVibrancyBackground(cgContext, macRect, aFrame, eThemeGeometryTypeMenu, 4);
       } else {
         HIThemeMenuDrawInfo mdi;
         memset(&mdi, 0, sizeof(mdi));
         mdi.version = 0;
         mdi.menuType = IsDisabled(aFrame, eventState) ?
                          static_cast<ThemeMenuType>(kThemeMenuTypeInactive) :
                          static_cast<ThemeMenuType>(kThemeMenuTypePopUp);