Bug 1464722 part 5 - Paint scrollcorner for custom scrollbars on cocoa. r?spohl draft
authorXidorn Quan <me@upsuper.org>
Mon, 25 Jun 2018 09:56:38 +1000
changeset 810030 7f14abc673f5e1144b1ad2e7e1bb63d3f6e2ea3f
parent 810029 e935bc0f51a1e94d22ce8a34359e7e39f31e2be9
child 810031 8c53ad505a7781bf05d09682b5af27723e799da9
push id113864
push userxquan@mozilla.com
push dateMon, 25 Jun 2018 00:30:18 +0000
reviewersspohl
bugs1464722
milestone62.0a1
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: