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
--- 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);