Bug 1705605 - Implement accent-color in nsNativeBasicTheme. r=mstange

This is a new addition for CSS UI Level 4:

  https://drafts.csswg.org/css-ui-4/#widget-accent

I want to provide feedback on some spec issues, and thought it was a
kinda neat thing to prototype (it also makes testing contrast and such
with random GTK themes easier).

For now enable for Nightly only.

Differential Revision: https://phabricator.services.mozilla.com/D112312
This commit is contained in:
Emilio Cobos Álvarez 2021-04-27 10:41:00 +00:00
parent ed370e6a5f
commit 34a9a0f457
22 changed files with 447 additions and 162 deletions

View File

@ -244,6 +244,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"border-left-color",
"border-right-color",
"border-top-color",
"accent-color",
"caret-color",
"color",
"column-rule-color",

View File

@ -2621,6 +2621,29 @@ exports.CSS_PROPERTIES = {
"unset"
]
},
"accent-color": {
"isInherited": true,
"subproperties": [
"accent-color"
],
"supports": [
"color"
],
"values": [
"COLOR",
"auto",
"currentColor",
"hsl",
"hsla",
"inherit",
"initial",
"revert",
"rgb",
"rgba",
"transparent",
"unset"
]
},
"align-content": {
"isInherited": false,
"subproperties": [
@ -2976,6 +2999,7 @@ exports.CSS_PROPERTIES = {
"-moz-user-modify",
"-moz-user-focus",
"caret-color",
"accent-color",
"scrollbar-color",
"list-style-position",
"list-style-type",
@ -10971,6 +10995,10 @@ exports.PREFERENCES = [
"overscroll-behavior-y",
"layout.css.overscroll-behavior.enabled"
],
[
"accent-color",
"layout.css.accent-color.enabled"
],
[
"align-tracks",
"layout.css.grid-template-masonry-value.enabled"

View File

@ -491,6 +491,7 @@ cbindgen-types = [
{ gecko = "StyleGenericBorderRadius", servo = "crate::values::generics::border::BorderRadius" },
{ gecko = "StyleLetterSpacing", servo = "crate::values::computed::text::LetterSpacing" },
{ gecko = "StyleGenericLineHeight", servo = "crate::values::generics::text::LineHeight" },
{ gecko = "StyleCaretColor", servo = "crate::values::computed::color::CaretColor" },
{ gecko = "StyleContain", servo = "crate::values::computed::Contain" },
{ gecko = "StyleRestyleHint", servo = "crate::invalidation::element::restyle_hints::RestyleHint" },
{ gecko = "StyleTouchAction", servo = "crate::values::computed::TouchAction" },

View File

@ -3066,6 +3066,7 @@ nsStyleUI::nsStyleUI(const Document& aDocument)
mUserFocus(StyleUserFocus::None),
mPointerEvents(StylePointerEvents::Auto),
mCursor{{}, StyleCursorKind::Auto},
mAccentColor(StyleColorOrAuto::Auto()),
mCaretColor(StyleColorOrAuto::Auto()),
mScrollbarColor(StyleScrollbarColor::Auto()) {
MOZ_COUNT_CTOR(nsStyleUI);
@ -3078,6 +3079,7 @@ nsStyleUI::nsStyleUI(const nsStyleUI& aSource)
mUserFocus(aSource.mUserFocus),
mPointerEvents(aSource.mPointerEvents),
mCursor(aSource.mCursor),
mAccentColor(aSource.mAccentColor),
mCaretColor(aSource.mCaretColor),
mScrollbarColor(aSource.mScrollbarColor) {
MOZ_COUNT_CTOR(nsStyleUI);
@ -3128,6 +3130,7 @@ nsChangeHint nsStyleUI::CalcDifference(const nsStyleUI& aNewData) const {
}
if (mCaretColor != aNewData.mCaretColor ||
mAccentColor != aNewData.mAccentColor ||
mScrollbarColor != aNewData.mScrollbarColor) {
hint |= nsChangeHint_RepaintFrame;
}

View File

@ -1747,7 +1747,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUI {
mozilla::StyleCursor mCursor;
mozilla::StyleColorOrAuto mCaretColor;
mozilla::StyleColorOrAuto mAccentColor;
mozilla::StyleCaretColor mCaretColor;
mozilla::StyleScrollbarColor mScrollbarColor;
inline mozilla::StylePointerEvents GetEffectivePointerEvents(

View File

@ -9282,6 +9282,22 @@ var gCSSProperties = {
other_values: ["drag", "no-drag"],
invalid_values: ["none"],
},
"accent-color": {
domProp: "accentColor",
inherited: true,
type: CSS_TYPE_LONGHAND,
prerequisites: { color: "black" },
initial_values: ["auto"],
other_values: [
"currentcolor",
"black",
"green",
"transparent",
"rgba(128,128,128,.5)",
"#123",
],
invalid_values: ["#0", "#00", "#00000", "cc00ff"],
},
"align-content": {
domProp: "alignContent",
inherited: false,

View File

@ -130,6 +130,9 @@ var supported_properties = {
"bottom": [ test_length_transition, test_percent_transition,
test_length_percent_calc_transition,
test_length_unclamped, test_percent_unclamped ],
"accent-color": [ test_color_transition,
test_currentcolor_transition,
test_auto_color_transition ],
"caret-color": [ test_color_transition,
test_currentcolor_transition,
test_auto_color_transition ],

View File

@ -6557,6 +6557,13 @@
mirror: always
rust: true
# Whether the `accent-color` css property is enabled.
- name: layout.css.accent-color.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
mirror: always
rust: true
# Whether the `aspect-ratio` in css-sizing-4 is enabled.
- name: layout.css.aspect-ratio.enabled
type: bool

View File

@ -73,13 +73,26 @@ ${helpers.single_keyword(
${helpers.predefined_type(
"caret-color",
"color::CaretColor",
"generics::color::CaretColor::auto()",
engines="gecko",
spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="CaretColor",
boxed=True,
ignored_when_colors_disabled=True,
)}
${helpers.predefined_type(
"accent-color",
"ColorOrAuto",
"generics::color::ColorOrAuto::Auto",
engines="gecko",
spec="https://drafts.csswg.org/css-ui/#caret-color",
animation_value_type="AnimatedCaretColor",
spec="https://drafts.csswg.org/css-ui-4/#widget-accent",
gecko_pref="layout.css.accent-color.enabled",
animation_value_type="ColorOrAuto",
boxed=True,
ignored_when_colors_disabled=True,
has_effect_on_gecko_scrollbars=False,
)}
${helpers.predefined_type(

View File

@ -6,7 +6,7 @@
use crate::values::animated::color::RGBA as AnimatedRGBA;
use crate::values::animated::ToAnimatedValue;
use crate::values::generics::color::{Color as GenericColor, ColorOrAuto as GenericColorOrAuto};
use crate::values::generics::color::{GenericColor, GenericColorOrAuto, GenericCaretColor};
use cssparser::{Color as CSSParserColor, RGBA};
use std::fmt;
use style_traits::{CssWriter, ToCss};
@ -112,3 +112,6 @@ impl ToAnimatedValue for RGBA {
/// auto | <color>
pub type ColorOrAuto = GenericColorOrAuto<Color>;
/// caret-color
pub type CaretColor = GenericCaretColor<Color>;

View File

@ -96,6 +96,7 @@ impl<RGBA> From<RGBA> for Color<RGBA> {
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToResolvedValue,
ToCss,
ToShmem,
)]
@ -108,3 +109,32 @@ pub enum GenericColorOrAuto<C> {
}
pub use self::GenericColorOrAuto as ColorOrAuto;
/// Caret color is effectively a ColorOrAuto, but resolves `auto` to
/// currentColor.
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToShmem,
)]
#[repr(transparent)]
pub struct GenericCaretColor<C>(pub GenericColorOrAuto<C>);
impl<C> GenericCaretColor<C> {
/// Returns the `auto` value.
pub fn auto() -> Self {
GenericCaretColor(GenericColorOrAuto::Auto)
}
}
pub use self::GenericCaretColor as CaretColor;

View File

@ -6,7 +6,7 @@
use super::{Context, ToResolvedValue};
use crate::values::computed;
use crate::values::computed::color as computed;
use crate::values::generics::color as generics;
impl ToResolvedValue for computed::Color {
@ -24,14 +24,14 @@ impl ToResolvedValue for computed::Color {
}
}
impl ToResolvedValue for computed::ColorOrAuto {
impl ToResolvedValue for computed::CaretColor {
// A resolved caret-color value is an rgba color, with auto resolving to
// currentcolor.
type ResolvedValue = cssparser::RGBA;
#[inline]
fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
let color = match self {
let color = match self.0 {
generics::ColorOrAuto::Color(color) => color,
generics::ColorOrAuto::Auto => generics::Color::currentcolor(),
};
@ -40,6 +40,6 @@ impl ToResolvedValue for computed::ColorOrAuto {
#[inline]
fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
generics::ColorOrAuto::Color(computed::Color::from_resolved_value(resolved))
generics::CaretColor(generics::ColorOrAuto::Color(computed::Color::from_resolved_value(resolved)))
}
}

View File

@ -9,7 +9,7 @@ use super::AllowQuirks;
use crate::gecko_bindings::structs::nscolor;
use crate::parser::{Parse, ParserContext};
use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue};
use crate::values::generics::color::ColorOrAuto as GenericColorOrAuto;
use crate::values::generics::color::{GenericColorOrAuto, GenericCaretColor};
use crate::values::specified::calc::CalcNode;
use crate::values::specified::Percentage;
use cssparser::{AngleOrNumber, Color as CSSParserColor, Parser, Token, RGBA};
@ -789,3 +789,15 @@ impl Parse for ColorPropertyValue {
/// auto | <color>
pub type ColorOrAuto = GenericColorOrAuto<Color>;
/// caret-color
pub type CaretColor = GenericCaretColor<Color>;
impl Parse for CaretColor {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
ColorOrAuto::parse(context, input).map(GenericCaretColor)
}
}

View File

@ -158,6 +158,7 @@ include = [
"OwnedOrNull",
"Strong",
"ScrollbarColor",
"CaretColor",
"Color",
"ColorOrAuto",
"SystemColor",

View File

@ -0,0 +1,2 @@
<!doctype html>
<input type=checkbox style="accent-color: blue">

View File

@ -0,0 +1,9 @@
<!doctype html>
<title>Accent color changes colors of a checked checkbox</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" title="https://drafts.csswg.org/css-ui-4/#widget-accent">
<link rel="help" title="https://bugzilla.mozilla.org/show_bug.cgi?id=1705605">
<link rel="mismatch" href="accent-color-checkbox-checked-001-notref.html">
<input type=checkbox checked style="accent-color: red">

View File

@ -0,0 +1,17 @@
<!doctype html>
<link rel="help" href="https://drafts.csswg.org/css-ui-4/#widget-accent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<style>
#outer { accent-color: red; }
</style>
<div id="outer">
<div id="target"></div>
</div>
<script>
test_computed_value('accent-color', 'initial', 'auto');
test_computed_value('accent-color', 'inherit', 'rgb(255, 0, 0)');
test_computed_value('accent-color', 'red', 'rgb(255, 0, 0)');
test_computed_value('accent-color', 'blue', 'rgb(0, 0, 255)');
</script>

View File

@ -0,0 +1,20 @@
<!doctype html>
<title>Parsing of accent-color</title>
<link rel="help" href="https://drafts.csswg.org/css-ui-4/#widget-accent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<div id="target"></div>
<script>
test_valid_value('accent-color', 'initial');
test_valid_value('accent-color', 'inherit');
test_valid_value('accent-color', 'unset');
test_valid_value('accent-color', 'revert');
test_valid_value('accent-color', 'auto');
test_valid_value('accent-color', 'red');
test_valid_value('accent-color', 'blue');
test_valid_value('accent-color', 'currentcolor');
test_valid_value('accent-color', '#fff', 'rgb(255, 255, 255)');
test_invalid_value('accent-color', 'auto auto');
</script>

View File

@ -70,29 +70,155 @@ static LayoutDeviceIntCoord SnapBorderWidth(
return aLuminance >= 0.18f ? aLuminance * aFactor : aLuminance / aFactor;
}
struct ColorPalette {
ColorPalette(nscolor aAccent, nscolor aForeground);
constexpr ColorPalette(sRGBColor aAccent, sRGBColor aForeground,
sRGBColor aLight, sRGBColor aDark, sRGBColor aDarker)
: mAccent(aAccent),
mForeground(aForeground),
mAccentLight(aLight),
mAccentDark(aDark),
mAccentDarker(aDarker) {}
constexpr static ColorPalette Default() {
return ColorPalette(
sRGBColor::UnusualFromARGB(0xff0060df), // Luminance: 13.69346%
sColorWhite,
sRGBColor::UnusualFromARGB(0x4d008deb), // Luminance: 25.04791%
sRGBColor::UnusualFromARGB(0xff0250bb), // Luminance: 9.33808%
sRGBColor::UnusualFromARGB(0xff054096) // Luminance: 5.90106%
);
}
// Ensure accent color is opaque by blending with white. This serves two
// purposes: On one hand, it avoids surprises if we overdraw. On the other, it
// makes our math below make more sense, as we want to match the browser
// style, which has an opaque accent color.
static nscolor EnsureOpaque(nscolor aAccent) {
if (NS_GET_A(aAccent) != 0xff) {
return NS_ComposeColors(NS_RGB(0xff, 0xff, 0xff), aAccent);
}
return aAccent;
}
static nscolor GetLight(nscolor aAccent) {
// The luminance from the light color divided by the one of the accent color
// in the default palette.
constexpr float kLightLuminanceScale = 25.048f / 13.693f;
const float lightLuminanceAdjust = ScaleLuminanceBy(
RelativeLuminanceUtils::Compute(aAccent), kLightLuminanceScale);
nscolor lightColor =
RelativeLuminanceUtils::Adjust(aAccent, lightLuminanceAdjust);
return NS_RGBA(NS_GET_R(lightColor), NS_GET_G(lightColor),
NS_GET_B(lightColor), 0x4d);
}
static nscolor GetDark(nscolor aAccent) {
// Same deal as above (but without the alpha).
constexpr float kDarkLuminanceScale = 9.338f / 13.693f;
const float darkLuminanceAdjust = ScaleLuminanceBy(
RelativeLuminanceUtils::Compute(aAccent), kDarkLuminanceScale);
return RelativeLuminanceUtils::Adjust(aAccent, darkLuminanceAdjust);
}
static nscolor GetDarker(nscolor aAccent) {
// Same deal as above.
constexpr float kDarkerLuminanceScale = 5.901f / 13.693f;
const float darkerLuminanceAdjust = ScaleLuminanceBy(
RelativeLuminanceUtils::Compute(aAccent), kDarkerLuminanceScale);
return RelativeLuminanceUtils::Adjust(aAccent, darkerLuminanceAdjust);
}
sRGBColor mAccent;
sRGBColor mForeground;
// Note that depending on the exact accent color, lighter/darker might really
// be inverted.
sRGBColor mAccentLight;
sRGBColor mAccentDark;
sRGBColor mAccentDarker;
};
static nscolor ThemedAccentColor(bool aBackground) {
MOZ_ASSERT(StaticPrefs::widget_non_native_theme_use_theme_accent());
// TODO(emilio): In the future we should probably add dark-color-scheme
// support for non-native form controls.
nscolor color = LookAndFeel::Color(
return ColorPalette::EnsureOpaque(LookAndFeel::Color(
aBackground ? LookAndFeel::ColorID::MozAccentColor
: LookAndFeel::ColorID::MozAccentColorForeground,
LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No);
if (NS_GET_A(color) != 0xff) {
// Blend with white, ensuring the color is opaque to avoid surprises if we
// overdraw.
color = NS_ComposeColors(NS_RGB(0xff, 0xff, 0xff), color);
}
return color;
LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No));
}
static ColorPalette sDefaultPalette = ColorPalette::Default();
ColorPalette::ColorPalette(nscolor aAccent, nscolor aForeground) {
mAccent = sRGBColor::FromABGR(aAccent);
mForeground = sRGBColor::FromABGR(aForeground);
mAccentLight = sRGBColor::FromABGR(GetLight(aAccent));
mAccentDark = sRGBColor::FromABGR(GetDark(aAccent));
mAccentDarker = sRGBColor::FromABGR(GetDarker(aAccent));
}
} // namespace
sRGBColor nsNativeBasicTheme::sAccentColor = sRGBColor::OpaqueWhite();
sRGBColor nsNativeBasicTheme::sAccentColorForeground = sRGBColor::OpaqueWhite();
sRGBColor nsNativeBasicTheme::sAccentColorLight = sRGBColor::OpaqueWhite();
sRGBColor nsNativeBasicTheme::sAccentColorDark = sRGBColor::OpaqueWhite();
sRGBColor nsNativeBasicTheme::sAccentColorDarker = sRGBColor::OpaqueWhite();
class nsNativeBasicTheme::AccentColor {
Maybe<nscolor> mAccentColor;
public:
AccentColor() = default;
explicit AccentColor(const ComputedStyle& aStyle) {
const auto& color = aStyle.StyleUI()->mAccentColor;
if (color.IsColor()) {
mAccentColor.emplace(
ColorPalette::EnsureOpaque(color.AsColor().CalcColor(aStyle)));
} else {
MOZ_ASSERT(color.IsAuto());
}
}
sRGBColor Get() const {
if (!mAccentColor) {
return sDefaultPalette.mAccent;
}
return sRGBColor::FromABGR(*mAccentColor);
}
sRGBColor GetForeground() const {
if (!mAccentColor) {
return sDefaultPalette.mForeground;
}
// TODO(emilio): Maybe sColorBlack is too dark.
//
// TODO(emilio): We should probably allow the page to specify this one too:
// https://github.com/w3c/csswg-drafts/issues/6159
return nsNativeTheme::IsDarkColor(*mAccentColor) ? sColorWhite
: sColorBlack;
}
sRGBColor GetLight() const {
if (!mAccentColor) {
return sDefaultPalette.mAccentLight;
}
return sRGBColor::FromABGR(ColorPalette::GetLight(*mAccentColor));
}
sRGBColor GetDark() const {
if (!mAccentColor) {
return sDefaultPalette.mAccentDark;
}
return sRGBColor::FromABGR(ColorPalette::GetDark(*mAccentColor));
}
sRGBColor GetDarker() const {
if (!mAccentColor) {
return sDefaultPalette.mAccentDarker;
}
return sRGBColor::FromABGR(ColorPalette::GetDarker(*mAccentColor));
}
};
CSSIntCoord nsNativeBasicTheme::sHorizontalScrollbarHeight = CSSIntCoord(0);
CSSIntCoord nsNativeBasicTheme::sVerticalScrollbarWidth = CSSIntCoord(0);
bool nsNativeBasicTheme::sOverlayScrollbars = false;
@ -125,47 +251,12 @@ void nsNativeBasicTheme::RecomputeAccentColors() {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
if (!StaticPrefs::widget_non_native_theme_use_theme_accent()) {
sAccentColorForeground = sColorWhite;
sAccentColor =
sRGBColor::UnusualFromARGB(0xff0060df); // Luminance: 13.69346%
sAccentColorLight =
sRGBColor::UnusualFromARGB(0x4d008deb); // Luminance: 25.04791%
sAccentColorDark =
sRGBColor::UnusualFromARGB(0xff0250bb); // Luminance: 9.33808%
sAccentColorDarker =
sRGBColor::UnusualFromARGB(0xff054096); // Luminance: 5.90106%
sDefaultPalette = ColorPalette::Default();
return;
}
sAccentColorForeground = sRGBColor::FromABGR(ThemedAccentColor(false));
const nscolor accent = ThemedAccentColor(true);
const float luminance = RelativeLuminanceUtils::Compute(accent);
constexpr float kLightLuminanceScale = 25.048f / 13.693f;
constexpr float kDarkLuminanceScale = 9.338f / 13.693f;
constexpr float kDarkerLuminanceScale = 5.901f / 13.693f;
const float lightLuminanceAdjust =
ScaleLuminanceBy(luminance, kLightLuminanceScale);
const float darkLuminanceAdjust =
ScaleLuminanceBy(luminance, kDarkLuminanceScale);
const float darkerLuminanceAdjust =
ScaleLuminanceBy(luminance, kDarkerLuminanceScale);
sAccentColor = sRGBColor::FromABGR(accent);
{
nscolor lightColor =
RelativeLuminanceUtils::Adjust(accent, lightLuminanceAdjust);
lightColor = NS_RGBA(NS_GET_R(lightColor), NS_GET_G(lightColor),
NS_GET_B(lightColor), 0x4d);
sAccentColorLight = sRGBColor::FromABGR(lightColor);
}
sAccentColorDark = sRGBColor::FromABGR(
RelativeLuminanceUtils::Adjust(accent, darkLuminanceAdjust));
sAccentColorDarker = sRGBColor::FromABGR(
RelativeLuminanceUtils::Adjust(accent, darkerLuminanceAdjust));
sDefaultPalette =
ColorPalette(ThemedAccentColor(true), ThemedAccentColor(false));
}
void nsNativeBasicTheme::RecomputeScrollbarParams() {
@ -277,7 +368,7 @@ static LayoutDeviceRect CheckBoxRadioRect(const LayoutDeviceRect& aRect) {
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeCheckboxColors(
const EventStates& aState, StyleAppearance aAppearance,
UseSystemColors aUseSystemColors) {
const AccentColor& aAccent, UseSystemColors aUseSystemColors) {
MOZ_ASSERT(aAppearance == StyleAppearance::Checkbox ||
aAppearance == StyleAppearance::Radio);
bool isDisabled = aState.HasState(NS_EVENT_STATE_DISABLED);
@ -311,9 +402,9 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeCheckboxColors(
backgroundColor = borderColor;
}
} else if (isChecked || isIndeterminate) {
const auto& color = isPressed ? sAccentColorDarker
: isHovered ? sAccentColorDark
: sAccentColor;
const auto& color = isPressed ? aAccent.GetDarker()
: isHovered ? aAccent.GetDark()
: aAccent.Get();
backgroundColor = borderColor = color;
} else if (isPressed) {
backgroundColor = sColorGrey20;
@ -327,14 +418,15 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeCheckboxColors(
}
sRGBColor nsNativeBasicTheme::ComputeCheckmarkColor(
const EventStates& aState, UseSystemColors aUseSystemColors) {
const EventStates& aState, const AccentColor& aAccent,
UseSystemColors aUseSystemColors) {
if (bool(aUseSystemColors)) {
return SystemColor(StyleSystemColor::Highlighttext);
}
if (aState.HasState(NS_EVENT_STATE_DISABLED)) {
return sColorWhiteAlpha80;
}
return sAccentColorForeground;
return aAccent.GetForeground();
}
sRGBColor nsNativeBasicTheme::ComputeBorderColor(
@ -417,7 +509,8 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeTextfieldColors(
}
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeProgressColors(
const EventStates& aState, UseSystemColors aUseSystemColors) {
const EventStates& aState, const AccentColor& aAccent,
UseSystemColors aUseSystemColors) {
if (bool(aUseSystemColors)) {
return SystemColorPair(StyleSystemColor::Highlight,
StyleSystemColor::Buttontext);
@ -432,9 +525,9 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeProgressColors(
return std::make_pair(sColorGrey40Alpha50, sColorGrey40Alpha50);
}
if (isActive || isHovered) {
return std::make_pair(sAccentColorDark, sAccentColorDarker);
return std::make_pair(aAccent.GetDark(), aAccent.GetDarker());
}
return std::make_pair(sAccentColor, sAccentColorDark);
return std::make_pair(aAccent.Get(), aAccent.GetDark());
}
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeTrackColors(
@ -458,7 +551,8 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeTrackColors(
}
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeThumbColors(
const EventStates& aState, UseSystemColors aUseSystemColors) {
const EventStates& aState, const AccentColor& aAccent,
UseSystemColors aUseSystemColors) {
if (bool(aUseSystemColors)) {
return SystemColorPair(StyleSystemColor::Highlighttext,
StyleSystemColor::Highlight);
@ -474,7 +568,7 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeThumbColors(
return sColorGrey40;
}
if (isActive) {
return sAccentColor;
return aAccent.Get();
}
if (isHovered) {
return sColorGrey60;
@ -488,12 +582,12 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeRangeThumbColors(
}
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeProgressColors(
UseSystemColors aUseSystemColors) {
const AccentColor& aAccent, UseSystemColors aUseSystemColors) {
if (bool(aUseSystemColors)) {
return SystemColorPair(StyleSystemColor::Highlight,
StyleSystemColor::Buttontext);
}
return std::make_pair(sAccentColor, sAccentColorDark);
return std::make_pair(aAccent.Get(), aAccent.GetDark());
}
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeProgressTrackColors(
@ -508,7 +602,8 @@ std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeProgressTrackColors(
std::pair<sRGBColor, sRGBColor> nsNativeBasicTheme::ComputeMeterchunkColors(
const EventStates& aMeterState, UseSystemColors aUseSystemColors) {
if (bool(aUseSystemColors)) {
return ComputeProgressColors(aUseSystemColors);
// Accent color doesn't matter when using system colors.
return ComputeProgressColors(AccentColor(), aUseSystemColors);
}
sRGBColor borderColor = sColorMeterGreen20;
sRGBColor chunkColor = sColorMeterGreen10;
@ -535,14 +630,14 @@ sRGBColor nsNativeBasicTheme::ComputeMenulistArrowButtonColor(
}
std::array<sRGBColor, 3> nsNativeBasicTheme::ComputeFocusRectColors(
UseSystemColors aUseSystemColors) {
const AccentColor& aAccent, UseSystemColors aUseSystemColors) {
if (bool(aUseSystemColors)) {
return {SystemColor(StyleSystemColor::Highlight),
SystemColor(StyleSystemColor::Buttontext),
SystemColor(StyleSystemColor::TextBackground)};
}
return {sAccentColor, sColorWhiteAlpha80, sAccentColorLight};
return {aAccent.Get(), sColorWhiteAlpha80, aAccent.GetLight()};
}
sRGBColor nsNativeBasicTheme::ComputeScrollbarTrackColor(
@ -761,16 +856,14 @@ nsNativeBasicTheme::ComputeScrollbarButtonColors(
static const CSSCoord kInnerFocusOutlineWidth = 2.0f;
template <typename PaintBackendData>
void nsNativeBasicTheme::PaintRoundedFocusRect(PaintBackendData& aBackendData,
const LayoutDeviceRect& aRect,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio,
CSSCoord aRadius,
CSSCoord aOffset) {
void nsNativeBasicTheme::PaintRoundedFocusRect(
PaintBackendData& aBackendData, const LayoutDeviceRect& aRect,
const AccentColor& aAccent, UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio, CSSCoord aRadius, CSSCoord aOffset) {
// NOTE(emilio): If the widths or offsets here change, make sure to tweak
// the GetWidgetOverflow path for FocusOutline.
auto [innerColor, middleColor, outerColor] =
ComputeFocusRectColors(aUseSystemColors);
ComputeFocusRectColors(aAccent, aUseSystemColors);
LayoutDeviceRect focusRect(aRect);
@ -946,10 +1039,11 @@ void nsNativeBasicTheme::PaintRoundedRectWithRadius(
void nsNativeBasicTheme::PaintCheckboxControl(DrawTarget& aDrawTarget,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
auto [backgroundColor, borderColor] = ComputeCheckboxColors(
aState, StyleAppearance::Checkbox, aUseSystemColors);
aState, StyleAppearance::Checkbox, aAccent, aUseSystemColors);
{
const CSSCoord radius = 2.0f;
CSSCoord borderWidth = kCheckboxRadioBorderWidth;
@ -961,14 +1055,15 @@ void nsNativeBasicTheme::PaintCheckboxControl(DrawTarget& aDrawTarget,
}
if (aState.HasState(NS_EVENT_STATE_INDETERMINATE)) {
PaintIndeterminateMark(aDrawTarget, aRect, aState, aUseSystemColors);
PaintIndeterminateMark(aDrawTarget, aRect, aState, aAccent,
aUseSystemColors);
} else if (aState.HasState(NS_EVENT_STATE_CHECKED)) {
PaintCheckMark(aDrawTarget, aRect, aState, aUseSystemColors);
PaintCheckMark(aDrawTarget, aRect, aState, aAccent, aUseSystemColors);
}
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aDrawTarget, aRect, aUseSystemColors, aDpiRatio, 5.0f,
1.0f);
PaintRoundedFocusRect(aDrawTarget, aRect, aAccent, aUseSystemColors,
aDpiRatio, 5.0f, 1.0f);
}
}
@ -985,6 +1080,7 @@ static float ScaleToFillRect(const LayoutDeviceRect& aRect, const float aSize) {
void nsNativeBasicTheme::PaintCheckMark(DrawTarget& aDrawTarget,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors) {
// Points come from the coordinates on a 14X14 (kCheckboxRadioBorderBoxSize)
// unit box centered at 0,0
@ -1005,13 +1101,15 @@ void nsNativeBasicTheme::PaintCheckMark(DrawTarget& aDrawTarget,
}
RefPtr<Path> path = builder->Finish();
sRGBColor fillColor = ComputeCheckmarkColor(aState, aUseSystemColors);
sRGBColor fillColor =
ComputeCheckmarkColor(aState, aAccent, aUseSystemColors);
aDrawTarget.Fill(path, ColorPattern(ToDeviceColor(fillColor)));
}
void nsNativeBasicTheme::PaintIndeterminateMark(
DrawTarget& aDrawTarget, const LayoutDeviceRect& aRect,
const EventStates& aState, UseSystemColors aUseSystemColors) {
const EventStates& aState, const AccentColor& aAccent,
UseSystemColors aUseSystemColors) {
const CSSCoord borderWidth = 2.0f;
const float scale = ScaleToFillRect(aRect, kCheckboxRadioBorderBoxSize);
@ -1021,7 +1119,8 @@ void nsNativeBasicTheme::PaintIndeterminateMark(
rect.x += (borderWidth * scale) + (borderWidth * scale / 8);
rect.width -= ((borderWidth * scale) + (borderWidth * scale / 8)) * 2;
sRGBColor fillColor = ComputeCheckmarkColor(aState, aUseSystemColors);
sRGBColor fillColor =
ComputeCheckmarkColor(aState, aAccent, aUseSystemColors);
aDrawTarget.FillRect(rect, ColorPattern(ToDeviceColor(fillColor)));
}
@ -1115,10 +1214,11 @@ template <typename PaintBackendData>
void nsNativeBasicTheme::PaintRadioControl(PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
auto [backgroundColor, borderColor] =
ComputeCheckboxColors(aState, StyleAppearance::Radio, aUseSystemColors);
auto [backgroundColor, borderColor] = ComputeCheckboxColors(
aState, StyleAppearance::Radio, aAccent, aUseSystemColors);
{
CSSCoord borderWidth = kCheckboxRadioBorderWidth;
if (backgroundColor == borderColor) {
@ -1132,14 +1232,14 @@ void nsNativeBasicTheme::PaintRadioControl(PaintBackendData& aPaintData,
LayoutDeviceRect rect(aRect);
rect.Deflate(SnapBorderWidth(kCheckboxRadioBorderWidth, aDpiRatio));
auto checkColor = ComputeCheckmarkColor(aState, aUseSystemColors);
auto checkColor = ComputeCheckmarkColor(aState, aAccent, aUseSystemColors);
PaintStrokedCircle(aPaintData, rect, backgroundColor, checkColor,
kCheckboxRadioBorderWidth, aDpiRatio);
}
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aPaintData, aRect, aUseSystemColors, aDpiRatio, 5.0f,
1.0f);
PaintRoundedFocusRect(aPaintData, aRect, aAccent, aUseSystemColors,
aDpiRatio, 5.0f, 1.0f);
}
}
@ -1147,6 +1247,7 @@ template <typename PaintBackendData>
void nsNativeBasicTheme::PaintTextField(PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
auto [backgroundColor, borderColor] =
@ -1158,8 +1259,8 @@ void nsNativeBasicTheme::PaintTextField(PaintBackendData& aPaintData,
kTextFieldBorderWidth, radius, aDpiRatio);
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aPaintData, aRect, aUseSystemColors, aDpiRatio,
radius + kTextFieldBorderWidth,
PaintRoundedFocusRect(aPaintData, aRect, aAccent, aUseSystemColors,
aDpiRatio, radius + kTextFieldBorderWidth,
-kTextFieldBorderWidth);
}
}
@ -1168,6 +1269,7 @@ template <typename PaintBackendData>
void nsNativeBasicTheme::PaintListbox(PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
const CSSCoord radius = 2.0f;
@ -1178,8 +1280,9 @@ void nsNativeBasicTheme::PaintListbox(PaintBackendData& aPaintData,
kMenulistBorderWidth, radius, aDpiRatio);
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aPaintData, aRect, aUseSystemColors, aDpiRatio,
radius + kMenulistBorderWidth, -kMenulistBorderWidth);
PaintRoundedFocusRect(aPaintData, aRect, aAccent, aUseSystemColors,
aDpiRatio, radius + kMenulistBorderWidth,
-kMenulistBorderWidth);
}
}
@ -1187,6 +1290,7 @@ template <typename PaintBackendData>
void nsNativeBasicTheme::PaintMenulist(PaintBackendData& aDrawTarget,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
const CSSCoord radius = 4.0f;
@ -1197,8 +1301,9 @@ void nsNativeBasicTheme::PaintMenulist(PaintBackendData& aDrawTarget,
kMenulistBorderWidth, radius, aDpiRatio);
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aDrawTarget, aRect, aUseSystemColors, aDpiRatio,
radius + kMenulistBorderWidth, -kMenulistBorderWidth);
PaintRoundedFocusRect(aDrawTarget, aRect, aAccent, aUseSystemColors,
aDpiRatio, radius + kMenulistBorderWidth,
-kMenulistBorderWidth);
}
}
@ -1273,6 +1378,7 @@ void nsNativeBasicTheme::PaintRange(nsIFrame* aFrame,
PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio, bool aHorizontal) {
nsRangeFrame* rangeFrame = do_QueryFrame(aFrame);
@ -1320,7 +1426,7 @@ void nsNativeBasicTheme::PaintRange(nsIFrame* aFrame,
const CSSCoord radius = 3.0f;
auto [progressColor, progressBorderColor] =
ComputeRangeProgressColors(aState, aUseSystemColors);
ComputeRangeProgressColors(aState, aAccent, aUseSystemColors);
auto [trackColor, trackBorderColor] =
ComputeRangeTrackColors(aState, aUseSystemColors);
@ -1344,14 +1450,14 @@ void nsNativeBasicTheme::PaintRange(nsIFrame* aFrame,
// Draw the thumb on top.
const CSSCoord thumbBorderWidth = 2.0f;
auto [thumbColor, thumbBorderColor] =
ComputeRangeThumbColors(aState, aUseSystemColors);
ComputeRangeThumbColors(aState, aAccent, aUseSystemColors);
PaintStrokedCircle(aPaintData, thumbRect, thumbColor, thumbBorderColor,
thumbBorderWidth, aDpiRatio);
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aPaintData, aRect, aUseSystemColors, aDpiRatio,
radius, 1.0f);
PaintRoundedFocusRect(aPaintData, aRect, aAccent, aUseSystemColors,
aDpiRatio, radius, 1.0f);
}
}
@ -1360,6 +1466,7 @@ void nsNativeBasicTheme::PaintProgress(nsIFrame* aFrame,
PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio, bool aIsMeter) {
const CSSCoord borderWidth = 1.0f;
@ -1448,7 +1555,7 @@ void nsNativeBasicTheme::PaintProgress(nsIFrame* aFrame,
auto [backgroundColor, borderColor] =
aIsMeter ? ComputeMeterchunkColors(aState, aUseSystemColors)
: ComputeProgressColors(aUseSystemColors);
: ComputeProgressColors(aAccent, aUseSystemColors);
PaintRoundedRectWithRadius(aPaintData, rect, clipRect, backgroundColor,
borderColor, borderWidth, radius, aDpiRatio);
}
@ -1458,6 +1565,7 @@ void nsNativeBasicTheme::PaintButton(nsIFrame* aFrame,
PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const EventStates& aState,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
const CSSCoord radius = 4.0f;
@ -1468,8 +1576,9 @@ void nsNativeBasicTheme::PaintButton(nsIFrame* aFrame,
kButtonBorderWidth, radius, aDpiRatio);
if (aState.HasState(NS_EVENT_STATE_FOCUSRING)) {
PaintRoundedFocusRect(aPaintData, aRect, aUseSystemColors, aDpiRatio,
radius + kButtonBorderWidth, -kButtonBorderWidth);
PaintRoundedFocusRect(aPaintData, aRect, aAccent, aUseSystemColors,
aDpiRatio, radius + kButtonBorderWidth,
-kButtonBorderWidth);
}
}
@ -1713,12 +1822,14 @@ bool nsNativeBasicTheme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
}
}
const AccentColor accent(*aFrame->Style());
DPIRatio dpiRatio = GetDPIRatio(aFrame, aAppearance);
switch (aAppearance) {
case StyleAppearance::Radio: {
auto rect = CheckBoxRadioRect(devPxRect);
PaintRadioControl(aPaintData, rect, eventState, useSystemColors,
PaintRadioControl(aPaintData, rect, eventState, accent, useSystemColors,
dpiRatio);
break;
}
@ -1728,24 +1839,24 @@ bool nsNativeBasicTheme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
return false;
} else {
auto rect = CheckBoxRadioRect(devPxRect);
PaintCheckboxControl(aPaintData, rect, eventState, useSystemColors,
dpiRatio);
PaintCheckboxControl(aPaintData, rect, eventState, accent,
useSystemColors, dpiRatio);
}
break;
}
case StyleAppearance::Textarea:
case StyleAppearance::Textfield:
case StyleAppearance::NumberInput:
PaintTextField(aPaintData, devPxRect, eventState, useSystemColors,
PaintTextField(aPaintData, devPxRect, eventState, accent, useSystemColors,
dpiRatio);
break;
case StyleAppearance::Listbox:
PaintListbox(aPaintData, devPxRect, eventState, useSystemColors,
PaintListbox(aPaintData, devPxRect, eventState, accent, useSystemColors,
dpiRatio);
break;
case StyleAppearance::MenulistButton:
case StyleAppearance::Menulist:
PaintMenulist(aPaintData, devPxRect, eventState, useSystemColors,
PaintMenulist(aPaintData, devPxRect, eventState, accent, useSystemColors,
dpiRatio);
break;
case StyleAppearance::MozMenulistArrowButton:
@ -1768,23 +1879,23 @@ bool nsNativeBasicTheme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
}
break;
case StyleAppearance::Range:
PaintRange(aFrame, aPaintData, devPxRect, eventState, useSystemColors,
dpiRatio, IsRangeHorizontal(aFrame));
PaintRange(aFrame, aPaintData, devPxRect, eventState, accent,
useSystemColors, dpiRatio, IsRangeHorizontal(aFrame));
break;
case StyleAppearance::RangeThumb:
// Painted as part of StyleAppearance::Range.
break;
case StyleAppearance::ProgressBar:
PaintProgress(aFrame, aPaintData, devPxRect, eventState, useSystemColors,
dpiRatio,
PaintProgress(aFrame, aPaintData, devPxRect, eventState, accent,
useSystemColors, dpiRatio,
/* aIsMeter = */ false);
break;
case StyleAppearance::Progresschunk:
/* Painted as part of the progress bar */
break;
case StyleAppearance::Meter:
PaintProgress(aFrame, aPaintData, devPxRect, eventState, useSystemColors,
dpiRatio, /* aIsMeter = */ true);
PaintProgress(aFrame, aPaintData, devPxRect, eventState, accent,
useSystemColors, dpiRatio, /* aIsMeter = */ true);
break;
case StyleAppearance::Meterchunk:
/* Painted as part of the meter bar */
@ -1834,12 +1945,12 @@ bool nsNativeBasicTheme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
}
break;
case StyleAppearance::Button:
PaintButton(aFrame, aPaintData, devPxRect, eventState, useSystemColors,
dpiRatio);
PaintButton(aFrame, aPaintData, devPxRect, eventState, accent,
useSystemColors, dpiRatio);
break;
case StyleAppearance::FocusOutline:
PaintAutoStyleOutline(aFrame, aPaintData, devPxRect, useSystemColors,
dpiRatio);
PaintAutoStyleOutline(aFrame, aPaintData, devPxRect, accent,
useSystemColors, dpiRatio);
break;
default:
// Various appearance values are used for XUL elements. Normally these
@ -1857,10 +1968,11 @@ template <typename PaintBackendData>
void nsNativeBasicTheme::PaintAutoStyleOutline(nsIFrame* aFrame,
PaintBackendData& aPaintData,
const LayoutDeviceRect& aRect,
const AccentColor& aAccent,
UseSystemColors aUseSystemColors,
DPIRatio aDpiRatio) {
auto [innerColor, middleColor, outerColor] =
ComputeFocusRectColors(aUseSystemColors);
ComputeFocusRectColors(aAccent, aUseSystemColors);
Unused << middleColor;
Unused << outerColor;

View File

@ -100,6 +100,7 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
using RectCornerRadii = mozilla::gfx::RectCornerRadii;
using LayoutDeviceCoord = mozilla::LayoutDeviceCoord;
using LayoutDeviceRect = mozilla::LayoutDeviceRect;
class AccentColor;
public:
static void Init();
@ -187,8 +188,10 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
std::pair<sRGBColor, sRGBColor> ComputeCheckboxColors(const EventStates&,
StyleAppearance,
const AccentColor&,
UseSystemColors);
sRGBColor ComputeCheckmarkColor(const EventStates&, UseSystemColors);
sRGBColor ComputeCheckmarkColor(const EventStates&, const AccentColor&,
UseSystemColors);
sRGBColor ComputeBorderColor(const EventStates&, UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeButtonColors(const EventStates&,
@ -197,18 +200,22 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
std::pair<sRGBColor, sRGBColor> ComputeTextfieldColors(const EventStates&,
UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeRangeProgressColors(const EventStates&,
const AccentColor&,
UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeRangeTrackColors(const EventStates&,
UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeRangeThumbColors(const EventStates&,
const AccentColor&,
UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeProgressColors(UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeProgressColors(const AccentColor&,
UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeProgressTrackColors(UseSystemColors);
std::pair<sRGBColor, sRGBColor> ComputeMeterchunkColors(
const EventStates& aMeterState, UseSystemColors);
sRGBColor ComputeMenulistArrowButtonColor(const EventStates&,
UseSystemColors);
std::array<sRGBColor, 3> ComputeFocusRectColors(UseSystemColors);
std::array<sRGBColor, 3> ComputeFocusRectColors(const AccentColor&,
UseSystemColors);
static bool ShouldUseDarkScrollbar(nsIFrame*, const ComputedStyle&);
sRGBColor ComputeScrollbarTrackColor(nsIFrame*, const ComputedStyle&,
@ -226,12 +233,12 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
template <typename PaintBackendData>
void PaintRoundedFocusRect(PaintBackendData&, const LayoutDeviceRect&,
UseSystemColors, DPIRatio, CSSCoord aRadius,
CSSCoord aOffset);
const AccentColor&, UseSystemColors, DPIRatio,
CSSCoord aRadius, CSSCoord aOffset);
template <typename PaintBackendData>
void PaintAutoStyleOutline(nsIFrame*, PaintBackendData&,
const LayoutDeviceRect&, UseSystemColors,
DPIRatio);
const LayoutDeviceRect&, const AccentColor&,
UseSystemColors, DPIRatio);
static void PaintRoundedRectWithRadius(DrawTarget&,
const LayoutDeviceRect& aRect,
@ -263,11 +270,13 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
const sRGBColor&);
void PaintCheckboxControl(DrawTarget& aDrawTarget, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio);
const EventStates&, const AccentColor&,
UseSystemColors, DPIRatio);
void PaintCheckMark(DrawTarget&, const LayoutDeviceRect&, const EventStates&,
UseSystemColors);
const AccentColor&, UseSystemColors);
void PaintIndeterminateMark(DrawTarget&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors);
const EventStates&, const AccentColor&,
UseSystemColors);
template <typename PaintBackendData>
void PaintStrokedCircle(PaintBackendData&, const LayoutDeviceRect&,
@ -285,19 +294,23 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
CSSCoord aShadowBlurStdDev, DPIRatio);
template <typename PaintBackendData>
void PaintRadioControl(PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio);
const EventStates&, const AccentColor&,
UseSystemColors, DPIRatio);
template <typename PaintBackendData>
void PaintRadioCheckmark(PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, DPIRatio);
template <typename PaintBackendData>
void PaintTextField(PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio);
const EventStates&, const AccentColor& aAccent,
UseSystemColors, DPIRatio);
template <typename PaintBackendData>
void PaintListbox(PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio);
const EventStates&, const AccentColor&, UseSystemColors,
DPIRatio);
template <typename PaintBackendData>
void PaintMenulist(PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio);
const EventStates&, const AccentColor&, UseSystemColors,
DPIRatio);
void PaintArrow(DrawTarget&, const LayoutDeviceRect&,
const float aArrowPolygonX[], const float aArrowPolygonY[],
const float aArrowPolygonSize, const int32_t aArrowNumPoints,
@ -309,15 +322,16 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
DPIRatio);
template <typename PaintBackendData>
void PaintRange(nsIFrame*, PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio,
bool aHorizontal);
const EventStates&, const AccentColor&, UseSystemColors,
DPIRatio, bool aHorizontal);
template <typename PaintBackendData>
void PaintProgress(nsIFrame*, PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio,
bool aIsMeter);
const EventStates&, const AccentColor&, UseSystemColors,
DPIRatio, bool aIsMeter);
template <typename PaintBackendData>
void PaintButton(nsIFrame*, PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, UseSystemColors, DPIRatio);
const EventStates&, const AccentColor&, UseSystemColors,
DPIRatio);
void PaintScrollbarButton(DrawTarget&, StyleAppearance,
const LayoutDeviceRect&, nsIFrame*,
@ -395,14 +409,6 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
const EventStates& aDocumentState,
UseSystemColors, DPIRatio);
static sRGBColor sAccentColor;
static sRGBColor sAccentColorForeground;
// Note that depending on the exact accent color, lighter/darker might really
// be inverted.
static sRGBColor sAccentColorLight;
static sRGBColor sAccentColorDark;
static sRGBColor sAccentColorDarker;
static CSSIntCoord sHorizontalScrollbarHeight;
static CSSIntCoord sVerticalScrollbarWidth;
static bool sOverlayScrollbars;

View File

@ -650,12 +650,7 @@ bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) {
}
if (const auto* style = GetBackgroundStyle(scrollFrame->GetScrolledFrame())) {
nscolor bgColor = style->StyleBackground()->BackgroundColor(style);
// Consider the background color dark if the sum of the r, g and b values is
// less than 384 in a semi-transparent document. This heuristic matches
// what WebKit does, and we can improve it later if needed.
return NS_GET_A(bgColor) > 127 &&
NS_GET_R(bgColor) + NS_GET_G(bgColor) + NS_GET_B(bgColor) < 384;
return IsDarkColor(style->StyleBackground()->BackgroundColor(style));
}
return false;
}

View File

@ -184,10 +184,15 @@ class nsNativeTheme : public nsITimerCallback, public nsINamed {
bool IsRangeHorizontal(nsIFrame* aFrame);
// scrollbar
static bool IsDarkBackground(nsIFrame* aFrame);
// custom scrollbar
typedef nscolor (*AutoColorGetter)(mozilla::ComputedStyle*);
static bool IsDarkColor(nscolor aColor) {
// Consider a color dark if the sum of the r, g and b values is less than
// 384 in a semi-transparent document. This heuristic matches what WebKit
// does, and we can improve it later if needed.
return NS_GET_A(aColor) > 127 &&
NS_GET_R(aColor) + NS_GET_G(aColor) + NS_GET_B(aColor) < 384;
}
static bool IsWidgetScrollbarPart(mozilla::StyleAppearance aAppearance);
private: