Bug 1464722 part 5 - Paint scrollcorner for custom scrollbars on cocoa. r=spohl
authorXidorn Quan <me@upsuper.org>
Mon, 25 Jun 2018 09:56:38 +1000
changeset 423986 a8b609fb90ade459a1a79fc495045401230e8169
parent 423985 664fc5136a49ef5f0178073ffd1f00bc95663472
child 423987 479c0a3c61fd2e8b86c958541d362560c97ae078
push id34197
push usercsabou@mozilla.com
push dateThu, 28 Jun 2018 09:44:02 +0000
treeherdermozilla-central@db455160668d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1464722
milestone63.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 1464722 part 5 - Paint scrollcorner for custom scrollbars on cocoa. r=spohl MozReview-Commit-ID: EMj8urC6AWX
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -274,16 +274,17 @@ public:
     eTextBox,                      // TextBoxParams
     eSearchField,                  // SearchFieldParams
     eProgressBar,                  // ProgressParams
     eMeter,                        // MeterParams
     eTreeHeaderCell,               // TreeHeaderCellParams
     eScale,                        // ScaleParams
     eScrollbarThumb,               // ScrollbarParams
     eScrollbarTrack,               // ScrollbarParams
+    eScrollCorner,                 // ScrollbarParams
     eMultilineTextField,           // bool
     eListBox,
     eSourceList,                   // bool
     eActiveSourceListSelection,    // bool
     eInactiveSourceListSelection,  // bool
     eTabPanel,
     eResizer
   };
@@ -315,16 +316,17 @@ public:
     static WidgetInfo TextBox(const TextBoxParams& aParams) { return WidgetInfo(Widget::eTextBox, aParams); }
     static WidgetInfo SearchField(const SearchFieldParams& aParams) { return WidgetInfo(Widget::eSearchField, aParams); }
     static WidgetInfo ProgressBar(const ProgressParams& aParams) { return WidgetInfo(Widget::eProgressBar, aParams); }
     static WidgetInfo Meter(const MeterParams& aParams) { return WidgetInfo(Widget::eMeter, aParams); }
     static WidgetInfo TreeHeaderCell(const TreeHeaderCellParams& aParams) { return WidgetInfo(Widget::eTreeHeaderCell, aParams); }
     static WidgetInfo Scale(const ScaleParams& aParams) { return WidgetInfo(Widget::eScale, aParams); }
     static WidgetInfo ScrollbarThumb(const ScrollbarParams& aParams) { return WidgetInfo(Widget::eScrollbarThumb, aParams); }
     static WidgetInfo ScrollbarTrack(const ScrollbarParams& aParams) { return WidgetInfo(Widget::eScrollbarTrack, aParams); }
+    static WidgetInfo ScrollCorner(const ScrollbarParams& aParams) { return WidgetInfo(Widget::eScrollCorner, aParams); }
     static WidgetInfo MultilineTextField(bool aParams) { return WidgetInfo(Widget::eMultilineTextField, aParams); }
     static WidgetInfo ListBox() { return WidgetInfo(Widget::eListBox, false); }
     static WidgetInfo SourceList(bool aParams) { return WidgetInfo(Widget::eSourceList, aParams); }
     static WidgetInfo ActiveSourceListSelection(bool aParams) { return WidgetInfo(Widget::eActiveSourceListSelection, aParams); }
     static WidgetInfo InactiveSourceListSelection(bool aParams) { return WidgetInfo(Widget::eInactiveSourceListSelection, aParams); }
     static WidgetInfo TabPanel(bool aParams) { return WidgetInfo(Widget::eTabPanel, aParams); }
     static WidgetInfo Resizer(bool aParams) { return WidgetInfo(Widget::eResizer, aParams); }
 
@@ -520,16 +522,18 @@ protected:
                           const UnifiedToolbarParams& aParams);
   void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
                      bool aIsMain);
   void DrawResizer(CGContextRef cgContext, const HIRect& aRect, bool aIsRTL);
   void DrawScrollbarThumb(CGContextRef cgContext, const CGRect& inBoxRect,
                           ScrollbarParams aParams);
   void DrawScrollbarTrack(CGContextRef cgContext, const CGRect& inBoxRect,
                           ScrollbarParams aParams);
+  void DrawScrollCorner(CGContextRef cgContext, const CGRect& inBoxRect,
+                        ScrollbarParams aParams);
   void DrawMultilineTextField(CGContextRef cgContext, const CGRect& inBoxRect,
                               bool aIsFocused);
   void DrawSourceList(CGContextRef cgContext, const CGRect& inBoxRect,
                       bool aIsActive);
 
   // Scrollbars
   nsIFrame* GetParentScrollbarFrame(nsIFrame *aFrame);
   bool IsParentScrollbarRolledOver(nsIFrame* aFrame);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2819,16 +2819,46 @@ nsNativeThemeCocoa::DrawScrollbarThumb(C
   if (aParams.rolledOver) {
     NSMutableDictionary* mutableOptions = [options mutableCopy];
     [mutableOptions setObject:@"rollover" forKey:@"state"];
     options = mutableOptions;
   }
   RenderWithCoreUI(drawRect, cgContext, options, true);
 }
 
+struct ScrollbarTrackDecorationColors
+{
+  nscolor mInnerColor;
+  nscolor mShadowColor;
+  nscolor mOuterColor;
+};
+
+static ScrollbarTrackDecorationColors
+ComputeScrollbarTrackDecorationColors(nscolor aTrackColor)
+{
+  ScrollbarTrackDecorationColors result;
+  float luminance = RelativeLuminanceUtils::Compute(aTrackColor);
+  if (luminance >= 0.5) {
+    result.mInnerColor =
+      RelativeLuminanceUtils::Adjust(aTrackColor, luminance * 0.836);
+    result.mShadowColor =
+      RelativeLuminanceUtils::Adjust(aTrackColor, luminance * 0.982);
+    result.mOuterColor =
+      RelativeLuminanceUtils::Adjust(aTrackColor, luminance * 0.886);
+  } else {
+    result.mInnerColor =
+      RelativeLuminanceUtils::Adjust(aTrackColor, luminance * 1.196);
+    result.mShadowColor =
+      RelativeLuminanceUtils::Adjust(aTrackColor, luminance * 1.018);
+    result.mOuterColor =
+      RelativeLuminanceUtils::Adjust(aTrackColor, luminance * 1.129);
+  }
+  return result;
+}
+
 void
 nsNativeThemeCocoa::DrawScrollbarTrack(CGContextRef cgContext,
                                        const CGRect& inBoxRect,
                                        ScrollbarParams aParams)
 {
   if (aParams.overlay && !aParams.rolledOver) {
     // Non-hovered overlay scrollbars don't have a track. Draw nothing.
     return;
@@ -2844,32 +2874,22 @@ nsNativeThemeCocoa::DrawScrollbarTrack(C
         [NSNumber numberWithBool:YES], @"noindicator",
         [NSNumber numberWithBool:YES], @"kCUIThumbProportionKey",
         [NSNumber numberWithBool:YES], @"is.flipped",
         nil],
       true);
     return;
   }
 
-  nscolor color = aParams.trackColor;
   // Paint the background color
-  SetCGContextFillColor(cgContext, color);
+  SetCGContextFillColor(cgContext, aParams.trackColor);
   CGContextFillRect(cgContext, inBoxRect);
   // Paint decorations
-  float luminance = RelativeLuminanceUtils::Compute(color);
-  nscolor innerColor, shadowColor, outerColor;
-  if (luminance >= 0.5) {
-    innerColor = RelativeLuminanceUtils::Adjust(color, luminance * 0.836);
-    shadowColor = RelativeLuminanceUtils::Adjust(color, luminance * 0.982);
-    outerColor = RelativeLuminanceUtils::Adjust(color, luminance * 0.886);
-  } else {
-    innerColor = RelativeLuminanceUtils::Adjust(color, luminance * 1.196);
-    shadowColor = RelativeLuminanceUtils::Adjust(color, luminance * 1.018);
-    outerColor = RelativeLuminanceUtils::Adjust(color, luminance * 1.129);
-  }
+  ScrollbarTrackDecorationColors colors =
+    ComputeScrollbarTrackDecorationColors(aParams.trackColor);
   CGPoint innerPoints[2];
   CGPoint shadowPoints[2];
   CGPoint outerPoints[2];
   if (aParams.horizontal) {
     innerPoints[0].x = inBoxRect.origin.x;
     innerPoints[0].y = inBoxRect.origin.y + 0.5f;
     innerPoints[1].x = innerPoints[0].x + inBoxRect.size.width;
     innerPoints[1].y = innerPoints[0].y;
@@ -2896,24 +2916,81 @@ nsNativeThemeCocoa::DrawScrollbarTrack(C
     innerPoints[1].y = innerPoints[0].y + inBoxRect.size.height;
     shadowPoints[0].y = innerPoints[0].y;
     shadowPoints[1].x = shadowPoints[0].x;
     shadowPoints[1].y = innerPoints[1].y;
     outerPoints[0].y = innerPoints[0].y;
     outerPoints[1].x = outerPoints[0].x;
     outerPoints[1].y = innerPoints[1].y;
   }
-  SetCGContextStrokeColor(cgContext, innerColor);
+  SetCGContextStrokeColor(cgContext, colors.mInnerColor);
   CGContextStrokeLineSegments(cgContext, innerPoints, 2);
-  SetCGContextStrokeColor(cgContext, shadowColor);
+  SetCGContextStrokeColor(cgContext, colors.mShadowColor);
   CGContextStrokeLineSegments(cgContext, shadowPoints, 2);
-  SetCGContextStrokeColor(cgContext, outerColor);
+  SetCGContextStrokeColor(cgContext, colors.mOuterColor);
   CGContextStrokeLineSegments(cgContext, outerPoints, 2);
 }
 
+void
+nsNativeThemeCocoa::DrawScrollCorner(CGContextRef cgContext,
+                                     const CGRect& inBoxRect,
+                                     ScrollbarParams aParams)
+{
+  if (aParams.overlay && !aParams.rolledOver) {
+    // Non-hovered overlay scrollbars don't have a corner. Draw nothing.
+    return;
+  }
+
+  if (!aParams.custom) {
+    // For non-custom scrollbar, just draw a white rect. It is what
+    // Safari does. We don't want to try painting the decorations like
+    // the custom case below because we don't have control over what
+    // the system would draw for the scrollbar.
+    SetCGContextFillColor(cgContext, NS_RGB(255, 255, 255));
+    CGContextFillRect(cgContext, inBoxRect);
+    return;
+  }
+
+  // Paint the background
+  SetCGContextFillColor(cgContext, aParams.trackColor);
+  CGContextFillRect(cgContext, inBoxRect);
+  // Paint the decorations
+  ScrollbarTrackDecorationColors colors =
+    ComputeScrollbarTrackDecorationColors(aParams.trackColor);
+  CGRect shadowRect, innerRect;
+  if (aParams.rtl) {
+    shadowRect.origin.x = inBoxRect.origin.x + inBoxRect.size.width - 2;
+    innerRect.origin.x = shadowRect.origin.x + 1;
+  } else {
+    shadowRect.origin.x = inBoxRect.origin.x;
+    innerRect.origin.x = shadowRect.origin.x;
+  }
+  shadowRect.origin.y = inBoxRect.origin.y;
+  shadowRect.size.width = shadowRect.size.height = 2;
+  innerRect.origin.y = inBoxRect.origin.y;
+  innerRect.size.width = innerRect.size.height = 1;
+  SetCGContextFillColor(cgContext, colors.mShadowColor);
+  CGContextFillRect(cgContext, shadowRect);
+  SetCGContextFillColor(cgContext, colors.mInnerColor);
+  CGContextFillRect(cgContext, innerRect);
+  CGPoint outerPoints[4];
+  outerPoints[0].x = aParams.rtl
+    ? inBoxRect.origin.x + 0.5
+    : inBoxRect.origin.x + inBoxRect.size.width - 0.5;
+  outerPoints[0].y = inBoxRect.origin.y;
+  outerPoints[1].x = outerPoints[0].x;
+  outerPoints[1].y = outerPoints[0].y + inBoxRect.size.height;
+  outerPoints[2].x = inBoxRect.origin.x;
+  outerPoints[2].y = inBoxRect.origin.y + inBoxRect.size.height - 0.5;
+  outerPoints[3].x = outerPoints[2].x + inBoxRect.size.width - 1;
+  outerPoints[3].y = outerPoints[2].y;
+  SetCGContextStrokeColor(cgContext, colors.mOuterColor);
+  CGContextStrokeLineSegments(cgContext, outerPoints, 4);
+}
+
 static const Color kTooltipBackgroundColor(0.996, 1.000, 0.792, 0.950);
 static const Color kMultilineTextFieldTopBorderColor(0.4510, 0.4510, 0.4510, 1.0);
 static const Color kMultilineTextFieldSidesAndBottomBorderColor(0.6, 0.6, 0.6, 1.0);
 static const Color kListboxTopBorderColor(0.557, 0.557, 0.557, 1.0);
 static const Color kListBoxSidesAndBottomBorderColor(0.745, 0.745, 0.745, 1.0);
 
 void
 nsNativeThemeCocoa::DrawMultilineTextField(CGContextRef cgContext,
@@ -3361,16 +3438,20 @@ nsNativeThemeCocoa::ComputeWidgetInfo(ns
       break;
 
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
       return Some(WidgetInfo::ScrollbarTrack(
         ComputeScrollbarParams(
           aFrame, aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL)));
 
+    case NS_THEME_SCROLLCORNER:
+      return Some(WidgetInfo::ScrollCorner(
+        ComputeScrollbarParams(aFrame, false)));
+
     case NS_THEME_TEXTFIELD_MULTILINE:
       return Some(WidgetInfo::MultilineTextField(
         eventState.HasState(NS_EVENT_STATE_FOCUS)));
 
     case NS_THEME_LISTBOX:
       return Some(WidgetInfo::ListBox());
 
     case NS_THEME_MAC_SOURCE_LIST: {
@@ -3640,16 +3721,21 @@ nsNativeThemeCocoa::RenderWidget(const W
       DrawScrollbarThumb(cgContext, macRect, params);
       break;
     }
     case Widget::eScrollbarTrack: {
       ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
       DrawScrollbarTrack(cgContext, macRect, params);
       break;
     }
+    case Widget::eScrollCorner: {
+      ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
+      DrawScrollCorner(cgContext, macRect, params);
+      break;
+    }
     case Widget::eMultilineTextField: {
       bool isFocused = aWidgetInfo.Params<bool>();
       DrawMultilineTextField(cgContext, macRect, isFocused);
       break;
     }
     case Widget::eListBox: {
       // We have to draw this by hand because kHIThemeFrameListBox drawing
       // is buggy on 10.5, see bug 579259.
@@ -4606,16 +4692,19 @@ nsNativeThemeCocoa::ThemeSupportsWidget(
     case NS_THEME_SCROLLBARBUTTON_RIGHT:
     case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
     case NS_THEME_SCROLLBARTHUMB_VERTICAL:
     case NS_THEME_SCROLLBARTRACK_VERTICAL:
     case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
     case NS_THEME_SCROLLBAR_NON_DISAPPEARING:
       return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
 
+    case NS_THEME_SCROLLCORNER:
+      return true;
+
     case NS_THEME_RESIZER:
     {
       nsIFrame* parentFrame = aFrame->GetParent();
       if (!parentFrame || !parentFrame->IsScrollFrame())
         return true;
 
       // Note that IsWidgetStyled is not called for resizers on Mac. This is
       // because for scrollable containers, the native resizer looks better
@@ -4812,16 +4901,17 @@ nsNativeThemeCocoa::GetWidgetTransparenc
   case NS_THEME_TOOLTIP:
     return eTransparent;
 
   case NS_THEME_DIALOG:
     return IsWindowSheet(aFrame) ? eTransparent : eOpaque;
 
   case NS_THEME_SCROLLBAR_SMALL:
   case NS_THEME_SCROLLBAR:
+  case NS_THEME_SCROLLCORNER:
     return nsLookAndFeel::UseOverlayScrollbars() ? eTransparent : eOpaque;
 
   case NS_THEME_STATUSBAR:
     // Knowing that scrollbars and statusbars are opaque improves
     // performance, because we create layers for them.
     return eOpaque;
 
   case NS_THEME_TOOLBAR: