Bug 1421088 - Move menu background drawing into a separate method. r?spohl draft
authorMarkus Stange <mstange@themasta.com>
Sat, 14 Apr 2018 21:56:23 -0400
changeset 782223 5656421d647e14f52730195444cae3d1bb1d4adc
parent 782222 20a17ad3efbaa5241ff1bf59e37712199f186a00
child 782224 89b9dcf889ea3922e48afbea8b27a3be9c6d146f
push id106503
push userbmo:mstange@themasta.com
push dateSun, 15 Apr 2018 02:35:01 +0000
reviewersspohl
bugs1421088
milestone61.0a1
Bug 1421088 - Move menu background drawing into a separate method. r?spohl MozReview-Commit-ID: CSa4zlI8juN
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -72,16 +72,22 @@ public:
 
     bool disabled : 1;
     bool insideActiveWindow : 1;
     bool pressed : 1;
     bool focused : 1;
     bool rtl : 1;
   };
 
+  struct MenuBackgroundParams {
+    mozilla::Maybe<mozilla::gfx::Color> vibrancyColor;
+    bool disabled = false;
+    bool submenuRightOfParent = false;
+  };
+
   struct ButtonParams {
     ControlParams controlParams;
     ButtonType button = ButtonType::eRegularPushButton;
   };
 
   struct TreeHeaderCellParams {
     ControlParams controlParams;
     TreeSortDirection sortDirection = eTreeSortDirection_Natural;
@@ -148,16 +154,18 @@ protected:
 
   nsIntMargin DirectionAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame);
   nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter);
   CGRect SeparatorAdjustedRect(CGRect aRect, nsIFrame* aLeft,
                                nsIFrame* aCurrent, nsIFrame* aRight);
   bool IsWindowSheet(nsIFrame* aFrame);
   ControlParams ComputeControlParams(nsIFrame* aFrame,
                                      mozilla::EventStates aEventState);
+  MenuBackgroundParams ComputeMenuBackgroundParams(nsIFrame* aFrame,
+                                                   mozilla::EventStates aEventState);
   TreeHeaderCellParams ComputeTreeHeaderCellParams(nsIFrame* aFrame,
                                                    mozilla::EventStates aEventState);
 
   // HITheme drawing routines
   void DrawFrame(CGContextRef context, HIThemeFrameKind inKind,
                  const HIRect& inBoxRect, bool inReadOnly,
                  mozilla::EventStates inState);
   void DrawMeter(CGContextRef context, const HIRect& inBoxRect,
@@ -180,16 +188,18 @@ protected:
                                   ControlParams aControlParams);
   void DrawSquareBezelPushButton(CGContextRef cgContext,
                                  const HIRect& inBoxRect,
                                  ControlParams aControlParams);
   void DrawHelpButton(CGContextRef cgContext, const HIRect& inBoxRect,
                       ControlParams aControlParams);
   void DrawDisclosureButton(CGContextRef cgContext, const HIRect& inBoxRect,
                             ControlParams aControlParams, NSCellStateValue aState);
+  void DrawMenuBackground(CGContextRef cgContext, const CGRect& inBoxRect,
+                          const MenuBackgroundParams& aParams);
   void DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect,
                     mozilla::EventStates inState, nsIFrame* aFrame,
                     const NSSize& aIconSize, NSString* aImageName,
                     bool aCenterHorizontally);
   void DrawHIThemeButton(CGContextRef cgContext, const HIRect& aRect,
                          ThemeButtonKind aKind, ThemeButtonValue aValue,
                          ThemeDrawState aState, ThemeButtonAdornment aAdornment,
                          const ControlParams& aParams);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -1107,16 +1107,119 @@ nsNativeThemeCocoa::DrawSearchField(CGCo
 
   DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings,
                        VerticalAlignFactor(aFrame), mCellDrawView,
                        IsFrameRTL(aFrame));
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
+static Color
+NSColorToColor(NSColor* aColor)
+{
+  NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+  return Color([deviceColor redComponent],
+               [deviceColor greenComponent],
+               [deviceColor blueComponent],
+               [deviceColor alphaComponent]);
+}
+
+static Color
+VibrancyFillColor(nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType)
+{
+  ChildView* childView = ChildViewForFrame(aFrame);
+  if (childView) {
+    return NSColorToColor(
+      [childView vibrancyFillColorForThemeGeometryType:aThemeGeometryType]);
+  }
+  return Color();
+}
+
+static void
+DrawVibrancyBackground(CGContextRef cgContext, CGRect inBoxRect,
+                       const Color& aColor, int aCornerRadiusIfOpaque = 0)
+{
+  NSRect rect = NSRectFromCGRect(inBoxRect);
+  NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
+  NSGraphicsContext* context =
+    [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES];
+  [NSGraphicsContext setCurrentContext:context];
+  [NSGraphicsContext saveGraphicsState];
+
+  NSColor* fillColor = [NSColor colorWithDeviceRed:aColor.r
+                                             green:aColor.g
+                                              blue:aColor.b
+                                             alpha:aColor.a];
+
+  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];
+}
+
+nsNativeThemeCocoa::MenuBackgroundParams
+nsNativeThemeCocoa::ComputeMenuBackgroundParams(nsIFrame* aFrame,
+                                                EventStates aEventState)
+{
+  MenuBackgroundParams params;
+  if (VibrancyManager::SystemSupportsVibrancy()) {
+    params.vibrancyColor = Some(VibrancyFillColor(aFrame, eThemeGeometryTypeMenu));
+  } else {
+    params.disabled = IsDisabled(aFrame, aEventState);
+    bool isLeftOfParent = false;
+    params.submenuRightOfParent =
+      IsSubmenu(aFrame, &isLeftOfParent) && !isLeftOfParent;
+  }
+  return params;
+}
+
+void
+nsNativeThemeCocoa::DrawMenuBackground(CGContextRef cgContext,
+                                       const CGRect& inBoxRect,
+                                       const MenuBackgroundParams& aParams)
+{
+  if (aParams.vibrancyColor) {
+    DrawVibrancyBackground(cgContext, inBoxRect, *aParams.vibrancyColor, 4);
+  } else {
+    HIThemeMenuDrawInfo mdi;
+    memset(&mdi, 0, sizeof(mdi));
+    mdi.version = 0;
+    mdi.menuType = aParams.disabled ?
+                      static_cast<ThemeMenuType>(kThemeMenuTypeInactive) :
+                      static_cast<ThemeMenuType>(kThemeMenuTypePopUp);
+
+    if (aParams.submenuRightOfParent) {
+      mdi.menuType = kThemeMenuTypeHierarchical;
+    }
+
+    // The rounded corners draw outside the frame.
+    CGRect deflatedRect =
+      CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y + 4,
+                 inBoxRect.size.width, inBoxRect.size.height - 8);
+    HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext,
+                              HITHEME_ORIENTATION);
+  }
+}
+
 static const NSSize kCheckmarkSize = NSMakeSize(11, 11);
 static const NSSize kMenuarrowSize = NSMakeSize(9, 10);
 static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8);
 static NSString* kCheckmarkImage = @"MenuOnState";
 static NSString* kMenuarrowRightImage = @"MenuSubmenu";
 static NSString* kMenuarrowLeftImage = @"MenuSubmenuLeft";
 static NSString* kMenuDownScrollArrowImage = @"MenuScrollDown";
 static NSString* kMenuUpScrollArrowImage = @"MenuScrollUp";
@@ -2324,70 +2427,22 @@ nsNativeThemeCocoa::DrawResizer(CGContex
   drawInfo.size = kHIThemeGrowBoxSizeNormal;
 
   RenderTransformedHIThemeControl(cgContext, aRect, RenderResizer, &drawInfo,
                                   IsFrameRTL(aFrame));
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-static Color
-NSColorToColor(NSColor* aColor)
-{
-  NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
-  return Color([deviceColor redComponent],
-               [deviceColor greenComponent],
-               [deviceColor blueComponent],
-               [deviceColor alphaComponent]);
-}
-
-static Color
-VibrancyFillColor(nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType)
-{
-  ChildView* childView = ChildViewForFrame(aFrame);
-  if (childView) {
-    return NSColorToColor([childView vibrancyFillColorForThemeGeometryType:aThemeGeometryType]);
-  }
-  return Color();
-}
-
 static void
 DrawVibrancyBackground(CGContextRef cgContext, CGRect inBoxRect,
-                       nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType,
-                       int aCornerRadiusIfOpaque = 0)
+                       nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType)
 {
-  ChildView* childView = ChildViewForFrame(aFrame);
-  if (childView) {
-    NSRect rect = NSRectFromCGRect(inBoxRect);
-    NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
-    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
-    [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];
-  }
+  DrawVibrancyBackground(cgContext, inBoxRect,
+                         VibrancyFillColor(aFrame, aThemeGeometryType), 0);
 }
 
 bool
 nsNativeThemeCocoa::IsParentScrollbarRolledOver(nsIFrame* aFrame)
 {
   nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
   return nsLookAndFeel::UseOverlayScrollbars()
     ? CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover)
@@ -2506,36 +2561,18 @@ nsNativeThemeCocoa::DrawWidgetBackground
         HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION);
         CGContextFillRect(cgContext, macRect);
       }
 
     }
       break;
 
     case NS_THEME_MENUPOPUP:
-      if (VibrancyManager::SystemSupportsVibrancy()) {
-        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);
-
-        bool isLeftOfParent = false;
-        if (IsSubmenu(aFrame, &isLeftOfParent) && !isLeftOfParent) {
-          mdi.menuType = kThemeMenuTypeHierarchical;
-        }
-
-        // The rounded corners draw outside the frame.
-        CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4,
-                                         macRect.size.width, macRect.size.height - 8);
-        HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION);
-      }
+      DrawMenuBackground(cgContext, macRect,
+                         ComputeMenuBackgroundParams(aFrame, eventState));
       break;
 
     case NS_THEME_MENUARROW: {
       bool isRTL = IsFrameRTL(aFrame);
       DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuarrowSize,
                    isRTL ? kMenuarrowLeftImage : kMenuarrowRightImage, true);
     }
       break;