Bug 1475033 part 7 - Implement scrollbar-width: thin for Windows. r?jimm draft
authorXidorn Quan <me@upsuper.org>
Mon, 06 Aug 2018 15:18:27 +1000
changeset 829855 9e9a53592fce925d62220fec3253aa3f297c8efa
parent 829854 ee529ab5300d6b89de71bbfe8a14801ff2134c03
child 829856 f0041762b3958a1f3626e403fe3ee344fc482e8d
push id118798
push userxquan@mozilla.com
push dateFri, 17 Aug 2018 01:17:12 +0000
reviewersjimm
bugs1475033
milestone63.0a1
Bug 1475033 part 7 - Implement scrollbar-width: thin for Windows. r?jimm Since Windows doesn't provide native thin scrollbar variant, this patch tries to synthesize one by doing the following: * force to use custom scrollbar, and * hide the scrollbar button by giving them zero size, and * cut the thickness of scrollbar by half. Half thickness is picked randomly, but it seems to work fine. A third of the size also looks fine, but maybe a bit harder to drag. Note: Universal Windows Platform apps seem to have an overlay style of scrollbar by default, but I cannot find any Windows API to render that, so that may be a builtin component of UWP. We may want to do that at some point, but this is probably good enough for now. MozReview-Commit-ID: KfHjy8WdweT
widget/windows/nsNativeThemeWin.cpp
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -1540,31 +1540,46 @@ GetThemeDpiScaleFactor(nsIFrame* aFrame)
     if (rootWidget) {
       double systemScale = WinUtils::SystemScaleFactor();
       return rootWidget->GetDefaultScale().scale / systemScale;
     }
   }
   return 1.0;
 }
 
+static bool
+IsScrollbarWidthThin(ComputedStyle* aStyle)
+{
+  auto scrollbarWidth = aStyle->StyleUIReset()->mScrollbarWidth;
+  return scrollbarWidth == StyleScrollbarWidth::Thin;
+}
+
+static bool
+IsScrollbarWidthThin(nsIFrame* aFrame)
+{
+  ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
+  return IsScrollbarWidthThin(style);
+}
+
 NS_IMETHODIMP
 nsNativeThemeWin::DrawWidgetBackground(gfxContext* aContext,
                                        nsIFrame* aFrame,
                                        WidgetType aWidgetType,
                                        const nsRect& aRect,
                                        const nsRect& aDirtyRect)
 {
   if (aWidgetType == StyleAppearance::MenulistButton &&
       StaticPrefs::layout_css_webkit_appearance_enabled()) {
     aWidgetType = StyleAppearance::Menulist;
   }
 
   if (IsWidgetScrollbarPart(aWidgetType)) {
     ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
-    if (style->StyleUI()->HasCustomScrollbars()) {
+    if (style->StyleUI()->HasCustomScrollbars() ||
+        IsScrollbarWidthThin(style)) {
       return DrawCustomScrollbarPart(aContext, aFrame, style,
                                      aWidgetType, aRect, aDirtyRect);
     }
   }
 
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme)
     return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect); 
@@ -3000,24 +3015,30 @@ nsNativeThemeWin::ClassicGetMinimumWidge
     case StyleAppearance::SpinnerUpbutton:
     case StyleAppearance::SpinnerDownbutton:
       (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
       (*aResult).height = 8; // No good metrics available for this
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScrollbarbuttonUp:
     case StyleAppearance::ScrollbarbuttonDown:
-      (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
-      (*aResult).height = ::GetSystemMetrics(SM_CYVSCROLL);
+      // For scrollbar-width:thin, we don't display the buttons.
+      if (!IsScrollbarWidthThin(aFrame)) {
+        (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
+        (*aResult).height = ::GetSystemMetrics(SM_CYVSCROLL);
+      }
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScrollbarbuttonLeft:
     case StyleAppearance::ScrollbarbuttonRight:
-      (*aResult).width = ::GetSystemMetrics(SM_CXHSCROLL);
-      (*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
+      // For scrollbar-width:thin, we don't display the buttons.
+      if (!IsScrollbarWidthThin(aFrame)) {
+        (*aResult).width = ::GetSystemMetrics(SM_CXHSCROLL);
+        (*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
+      }
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScrollbarVertical:
       // XXX HACK We should be able to have a minimum height for the scrollbar
       // track.  However, this causes problems when uncollapsing a scrollbar
       // inside a tree.  See bug 201379 for details.
 
         //      (*aResult).height = ::GetSystemMetrics(SM_CYVTHUMB) << 1;
@@ -3084,27 +3105,39 @@ nsNativeThemeWin::ClassicGetMinimumWidge
         (*aResult).width = (*aResult).height = 15;
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScrollbarthumbVertical:
       (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
       (*aResult).height = ::GetSystemMetrics(SM_CYVTHUMB);
       // Without theming, divide the thumb size by two in order to look more
       // native
-      if (!GetTheme(aWidgetType))
+      if (!GetTheme(aWidgetType)) {
         (*aResult).height >>= 1;
+      }
+      // If scrollbar-width is thin, divide the thickness by two to make
+      // it look more compact.
+      if (IsScrollbarWidthThin(aFrame)) {
+        aResult->width >>= 1;
+      }
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScrollbarthumbHorizontal:
       (*aResult).width = ::GetSystemMetrics(SM_CXHTHUMB);
       (*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
       // Without theming, divide the thumb size by two in order to look more
       // native
-      if (!GetTheme(aWidgetType))
+      if (!GetTheme(aWidgetType)) {
         (*aResult).width >>= 1;
+      }
+      // If scrollbar-width is thin, divide the thickness by two to make
+      // it look more compact.
+      if (IsScrollbarWidthThin(aFrame)) {
+        aResult->height >>= 1;
+      }
       *aIsOverridable = false;
       break;
     case StyleAppearance::ScrollbarHorizontal:
       (*aResult).width = ::GetSystemMetrics(SM_CXHTHUMB) << 1;
       break;
     }
     case StyleAppearance::Menuseparator:
     {
@@ -4221,17 +4254,18 @@ nsresult
 nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
                                           nsIFrame* aFrame,
                                           ComputedStyle* aStyle,
                                           WidgetType aWidgetType,
                                           const nsRect& aRect,
                                           const nsRect& aClipRect)
 {
   MOZ_ASSERT(!aStyle->StyleUI()->mScrollbarFaceColor.IsAuto() ||
-             !aStyle->StyleUI()->mScrollbarTrackColor.IsAuto());
+             !aStyle->StyleUI()->mScrollbarTrackColor.IsAuto() ||
+             IsScrollbarWidthThin(aStyle));
 
   gfxRect tr(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height()),
           dr(aClipRect.X(), aClipRect.Y(),
              aClipRect.Width(), aClipRect.Height());
 
   nscolor trackColor =
     GetScrollbarTrackColor(aStyle, &GetScrollbarTrackColorForAuto);
   HBRUSH dcBrush = (HBRUSH) GetStockObject(DC_BRUSH);