Bug 1703604 - When using a transparent scrollbar button / track color, use the thumb color to paint the scrollbar arrow. r=spohl

This improves the rendering of youtube.com on Windows, and I think should be uncontroversial.

scrollbar-color: transparent transparent will still get you the fully transparent scrollbar.

Differential Revision: https://phabricator.services.mozilla.com/D111137
This commit is contained in:
Emilio Cobos Alvarez 2021-04-08 09:48:01 +00:00
parent fd668cd57a
commit 9ac846cb5c
4 changed files with 46 additions and 22 deletions

View File

@ -33,7 +33,7 @@ nsITheme::Transparency nsNativeBasicThemeGTK::GetWidgetTransparency(
const auto useSystemColors = ShouldUseSystemColors(*pc->Document());
const auto* style = nsLayoutUtils::StyleForScrollbar(aFrame);
auto trackColor =
ComputeScrollbarColor(aFrame, *style, docState, useSystemColors);
ComputeScrollbarTrackColor(aFrame, *style, docState, useSystemColors);
return trackColor.a == 1.0 ? eOpaque : eTransparent;
}
}

View File

@ -545,7 +545,7 @@ std::array<sRGBColor, 3> nsNativeBasicTheme::ComputeFocusRectColors(
return {sAccentColor, sColorWhiteAlpha80, sAccentColorLight};
}
sRGBColor nsNativeBasicTheme::ComputeScrollbarColor(
sRGBColor nsNativeBasicTheme::ComputeScrollbarTrackColor(
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, UseSystemColors aUseSystemColors) {
const nsStyleUI* ui = aStyle.StyleUI();
@ -624,7 +624,8 @@ nscolor nsNativeBasicTheme::GetScrollbarButtonColor(nscolor aTrackColor,
}
/*static*/
nscolor nsNativeBasicTheme::GetScrollbarArrowColor(nscolor aButtonColor) {
Maybe<nscolor> nsNativeBasicTheme::GetScrollbarArrowColor(
nscolor aButtonColor) {
// In Windows 10 scrollbar, there are several gray colors used:
//
// State | Background (lum) | Arrow | Contrast
@ -638,6 +639,14 @@ nscolor nsNativeBasicTheme::GetScrollbarArrowColor(nscolor aButtonColor) {
//
// This function is written based on these values.
if (NS_GET_A(aButtonColor) == 0) {
// If the button color is transparent, because of e.g.
// scrollbar-color: <something> transparent, then use
// the thumb color, which is expected to have enough
// contrast.
return Nothing();
}
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
@ -646,15 +655,19 @@ nscolor nsNativeBasicTheme::GetScrollbarArrowColor(nscolor aButtonColor) {
// ComputeRelativeLuminanceFromComponents(96). That function cannot
// be constexpr because of std::pow.
const float GRAY96_LUMINANCE = 0.117f;
return RelativeLuminanceUtils::Adjust(aButtonColor, GRAY96_LUMINANCE);
return Some(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,
// thus the value below. It's the lumanince of gray 118.
//
// TODO(emilio): Maybe the button alpha is not the best thing to use here and
// we should use the thumb alpha? It seems weird that the color of the arrow
// depends on the opacity of the scrollbar thumb...
if (luminance >= 0.18) {
return NS_RGBA(0, 0, 0, NS_GET_A(aButtonColor));
return Some(NS_RGBA(0, 0, 0, NS_GET_A(aButtonColor)));
}
return NS_RGBA(255, 255, 255, NS_GET_A(aButtonColor));
return Some(NS_RGBA(255, 255, 255, NS_GET_A(aButtonColor)));
}
bool nsNativeBasicTheme::ShouldUseDarkScrollbar(nsIFrame* aFrame,
@ -731,12 +744,18 @@ nsNativeBasicTheme::ComputeScrollbarButtonColors(
StyleSystemColor::TextForeground);
}
auto trackColor =
ComputeScrollbarColor(aFrame, aStyle, aDocumentState, aUseSystemColors);
auto trackColor = ComputeScrollbarTrackColor(aFrame, aStyle, aDocumentState,
aUseSystemColors);
nscolor buttonColor =
GetScrollbarButtonColor(trackColor.ToABGR(), aElementState);
nscolor arrowColor = GetScrollbarArrowColor(buttonColor);
return {sRGBColor::FromABGR(buttonColor), sRGBColor::FromABGR(arrowColor)};
auto arrowColor =
GetScrollbarArrowColor(buttonColor)
.map(sRGBColor::FromABGR)
.valueOrFrom([&] {
return ComputeScrollbarThumbColor(aFrame, aStyle, aElementState,
aDocumentState, aUseSystemColors);
});
return {sRGBColor::FromABGR(buttonColor), arrowColor};
}
static const CSSCoord kInnerFocusOutlineWidth = 2.0f;
@ -1496,8 +1515,8 @@ bool nsNativeBasicTheme::DoPaintDefaultScrollbar(
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) {
return true;
}
auto scrollbarColor =
ComputeScrollbarColor(aFrame, aStyle, aDocumentState, aUseSystemColors);
auto scrollbarColor = ComputeScrollbarTrackColor(
aFrame, aStyle, aDocumentState, aUseSystemColors);
FillRect(aPaintData, aRect, scrollbarColor);
return true;
}
@ -1528,8 +1547,8 @@ bool nsNativeBasicTheme::DoPaintDefaultScrollCorner(
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
auto scrollbarColor =
ComputeScrollbarColor(aFrame, aStyle, aDocumentState, aUseSystemColors);
auto scrollbarColor = ComputeScrollbarTrackColor(
aFrame, aStyle, aDocumentState, aUseSystemColors);
FillRect(aPaintData, aRect, scrollbarColor);
return true;
}

View File

@ -167,7 +167,7 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
Overlay) override;
static nscolor AdjustUnthemedScrollbarThumbColor(nscolor, EventStates);
static nscolor GetScrollbarButtonColor(nscolor aTrackColor, EventStates);
static nscolor GetScrollbarArrowColor(nscolor aButtonColor);
static mozilla::Maybe<nscolor> GetScrollbarArrowColor(nscolor aButtonColor);
nscoord GetCheckboxRadioPrefSize() override;
@ -211,12 +211,13 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
std::array<sRGBColor, 3> ComputeFocusRectColors(UseSystemColors);
static bool ShouldUseDarkScrollbar(nsIFrame*, const ComputedStyle&);
virtual sRGBColor ComputeScrollbarColor(nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
UseSystemColors);
virtual sRGBColor ComputeScrollbarThumbColor(
nsIFrame*, const ComputedStyle&, const EventStates& aElementState,
const EventStates& aDocumentState, UseSystemColors);
sRGBColor ComputeScrollbarTrackColor(nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
UseSystemColors);
sRGBColor ComputeScrollbarThumbColor(nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
UseSystemColors);
// Returned colors are button, arrow.
std::pair<sRGBColor, sRGBColor> ComputeScrollbarButtonColors(
nsIFrame*, StyleAppearance, const ComputedStyle&,

View File

@ -4004,7 +4004,11 @@ bool nsNativeThemeWin::MayDrawCustomScrollbarPart(gfxContext* aContext,
ctx->ClosePath();
// And paint the arrow.
nscolor arrowColor =
nsNativeBasicTheme::GetScrollbarArrowColor(buttonColor);
nsNativeBasicTheme::GetScrollbarArrowColor(buttonColor)
.valueOrFrom([&] {
return ScrollbarUtil::GetScrollbarThumbColor(aFrame,
eventStates);
});
ctx->SetColor(sRGBColor::FromABGR(arrowColor));
ctx->Fill();
break;