Bug 1475033 part 7 - Implement scrollbar-width: thin for Windows. r=jimm
authorXidorn Quan <me@upsuper.org>
Mon, 06 Aug 2018 15:18:27 +1000
changeset 432085 dbfd2f2016a4538b96863a16a96ffe43a6e9eceb
parent 432084 1972d9de2b1014ffd032565578d4ca1d5016e846
child 432086 b63992dfe51dec6006fe1d07b98902a398e20129
push id106627
push userebalazs@mozilla.com
push dateFri, 17 Aug 2018 09:52:13 +0000
treeherdermozilla-inbound@b84213ec5a4d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1475033
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 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);