mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
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:
parent
ed370e6a5f
commit
34a9a0f457
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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" },
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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 ],
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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>;
|
||||
|
@ -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;
|
||||
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -158,6 +158,7 @@ include = [
|
||||
"OwnedOrNull",
|
||||
"Strong",
|
||||
"ScrollbarColor",
|
||||
"CaretColor",
|
||||
"Color",
|
||||
"ColorOrAuto",
|
||||
"SystemColor",
|
||||
|
@ -0,0 +1,2 @@
|
||||
<!doctype html>
|
||||
<input type=checkbox style="accent-color: blue">
|
@ -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">
|
@ -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>
|
@ -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>
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user