Bug 1471086 - Derive hover and active color for custom scrollbars. r=jmathies

Differential Revision: https://phabricator.services.mozilla.com/D4398

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Xidorn Quan 2018-08-31 21:33:41 +00:00
Родитель db22ef8d8a
Коммит 20de9cdfc6
1 изменённых файлов: 89 добавлений и 14 удалений

Просмотреть файл

@ -4212,7 +4212,36 @@ ToColorRef(nscolor aColor)
}
static nscolor
GetScrollbarArrowColor(nscolor aTrackColor)
GetScrollbarButtonColor(nscolor aTrackColor, EventStates aStates)
{
// See numbers in GetScrollbarArrowColor.
// This function is written based on ratios between values listed there.
bool isActive = aStates.HasState(NS_EVENT_STATE_ACTIVE);
bool isHover = aStates.HasState(NS_EVENT_STATE_HOVER);
if (!isActive && !isHover) {
return aTrackColor;
}
float luminance = RelativeLuminanceUtils::Compute(aTrackColor);
if (isActive) {
if (luminance >= 0.18) {
luminance *= 0.134;
} else {
luminance /= 0.134;
luminance = std::min(luminance, 1.0f);
}
} else {
if (luminance >= 0.18) {
luminance *= 0.805;
} else {
luminance /= 0.805;
}
}
return RelativeLuminanceUtils::Adjust(aTrackColor, luminance);
}
static nscolor
GetScrollbarArrowColor(nscolor aButtonColor)
{
// In Windows 10 scrollbar, there are several gray colors used:
//
@ -4227,7 +4256,7 @@ GetScrollbarArrowColor(nscolor aTrackColor)
//
// This function is written based on these values.
float luminance = RelativeLuminanceUtils::Compute(aTrackColor);
float luminance = RelativeLuminanceUtils::Compute(aButtonColor);
// Color with luminance larger than 0.72 has contrast ratio over 4.6
// to color with luminance of gray 96, so this value is chosen for
// this range. It is the luminance of gray 221.
@ -4235,7 +4264,7 @@ GetScrollbarArrowColor(nscolor aTrackColor)
// ComputeRelativeLuminanceFromComponents(96). That function cannot
// be constexpr because of std::pow.
const float GRAY96_LUMINANCE = 0.117f;
return RelativeLuminanceUtils::Adjust(aTrackColor, GRAY96_LUMINANCE);
return RelativeLuminanceUtils::Adjust(aButtonColor, GRAY96_LUMINANCE);
}
// The contrast ratio of a color to black equals that to white when its
// luminance is around 0.18, with a contrast ratio ~4.6 to both sides,
@ -4246,6 +4275,41 @@ GetScrollbarArrowColor(nscolor aTrackColor)
return NS_RGB(255, 255, 255);
}
static nscolor
AdjustScrollbarFaceColor(nscolor aFaceColor, EventStates aStates)
{
// In Windows 10, scrollbar thumb has the following colors:
//
// State | Color | Luminance
// -------+----------+----------
// Normal | Gray 205 | 61.0%
// Hover | Gray 166 | 38.1%
// Active | Gray 96 | 11.7%
//
// This function is written based on the ratios between the values.
bool isActive = aStates.HasState(NS_EVENT_STATE_ACTIVE);
bool isHover = aStates.HasState(NS_EVENT_STATE_HOVER);
if (!isActive && !isHover) {
return aFaceColor;
}
float luminance = RelativeLuminanceUtils::Compute(aFaceColor);
if (isActive) {
if (luminance >= 0.18) {
luminance *= 0.192;
} else {
luminance /= 0.192;
}
} else {
if (luminance >= 0.18) {
luminance *= 0.625;
} else {
luminance /= 0.625;
}
}
return RelativeLuminanceUtils::Adjust(aFaceColor, luminance);
}
// This tries to draw a Windows 10 style scrollbar with given colors.
nsresult
nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
@ -4259,6 +4323,8 @@ nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
!aStyle->StyleUI()->mScrollbarTrackColor.IsAuto() ||
IsScrollbarWidthThin(aStyle));
EventStates eventStates = GetContentState(aFrame, aWidgetType);
gfxRect tr(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height()),
dr(aClipRect.X(), aClipRect.Y(),
aClipRect.Width(), aClipRect.Height());
@ -4288,28 +4354,37 @@ nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
::SelectObject(hdc, dcBrush);
::FillRect(hdc, &widgetRect, dcBrush);
RECT componentRect;
// Scrollbar thumb and button are two CSS pixels thinner than the track.
gfxRect tr2 = tr;
gfxFloat dev2css = round(AppUnitsPerCSSPixel() / p2a);
if (aWidgetType == StyleAppearance::ScrollbarthumbVertical ||
aWidgetType == StyleAppearance::ScrollbarbuttonUp ||
aWidgetType == StyleAppearance::ScrollbarbuttonDown) {
tr2.Deflate(dev2css, 0);
} else {
tr2.Deflate(0, dev2css);
}
nativeDrawing.TransformToNativeRect(tr2, componentRect);
switch (aWidgetType) {
case StyleAppearance::ScrollbarthumbVertical:
case StyleAppearance::ScrollbarthumbHorizontal: {
// Scrollbar thumb is two CSS pixels thinner than the track.
gfxRect tr2 = tr;
gfxFloat dev2css = round(AppUnitsPerCSSPixel() / p2a);
if (aWidgetType == StyleAppearance::ScrollbarthumbVertical) {
tr2.Deflate(dev2css, 0);
} else {
tr2.Deflate(0, dev2css);
}
nativeDrawing.TransformToNativeRect(tr2, widgetRect);
nscolor faceColor =
GetScrollbarFaceColor(aStyle, &GetScrollbarFaceColorForAuto);
faceColor = AdjustScrollbarFaceColor(faceColor, eventStates);
::SetDCBrushColor(hdc, ToColorRef(faceColor));
::FillRect(hdc, &widgetRect, dcBrush);
::FillRect(hdc, &componentRect, dcBrush);
break;
}
case StyleAppearance::ScrollbarbuttonUp:
case StyleAppearance::ScrollbarbuttonDown:
case StyleAppearance::ScrollbarbuttonLeft:
case StyleAppearance::ScrollbarbuttonRight: {
nscolor buttonColor = GetScrollbarButtonColor(trackColor, eventStates);
::SetDCBrushColor(hdc, ToColorRef(buttonColor));
::FillRect(hdc, &componentRect, dcBrush);
// kPath is the path of scrollbar up arrow on Windows 10
// in a 17x17 area.
const LONG kSize = 17;
@ -4344,7 +4419,7 @@ nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
path[i].y = top + (LONG) round(unit * path[i].y);
}
// Paint the arrow.
COLORREF arrowColor = ToColorRef(GetScrollbarArrowColor(trackColor));
COLORREF arrowColor = ToColorRef(GetScrollbarArrowColor(buttonColor));
// XXX Somehow we need to paint with both pen and brush to get
// the desired shape. Can we do so only with brush?
::SetDCPenColor(hdc, arrowColor);