diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 6f8d6de9fde..3500c3aa73d 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -131,6 +131,20 @@ impl ToCss for ColorMix { } } +/// The color scheme for a specific system color. +#[cfg(feature = "gecko")] +#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)] +#[repr(u8)] +pub enum SystemColorScheme { + /// The default color-scheme for the document. + #[css(skip)] + Default, + /// A light color scheme. + Light, + /// A dark color scheme. + Dark, +} + /// Specified color value #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] pub enum Color { @@ -145,9 +159,10 @@ pub enum Color { }, /// A complex color value from computed value Complex(ComputedColor), - /// A system color + /// Either a system color, or a `-moz-system-color(, light|dark)` + /// function which allows chrome code to choose between color schemes. #[cfg(feature = "gecko")] - System(SystemColor), + System(SystemColor, SystemColorScheme), /// A color mix. ColorMix(Box), /// Quirksmode-only rule for inheriting color from the body @@ -390,7 +405,7 @@ pub enum SystemColor { #[cfg(feature = "gecko")] impl SystemColor { #[inline] - fn compute(&self, cx: &Context) -> ComputedColor { + fn compute(&self, cx: &Context, scheme: SystemColorScheme) -> ComputedColor { use crate::gecko_bindings::bindings; let prefs = cx.device().pref_sheet_prefs(); @@ -403,7 +418,7 @@ impl SystemColor { SystemColor::Visitedtext => prefs.mVisitedLinkColor, _ => unsafe { - bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document()) + bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document(), scheme) }, }) } @@ -479,6 +494,20 @@ impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponen } } +fn parse_moz_system_color<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, +) -> Result<(SystemColor, SystemColorScheme), ParseError<'i>> { + debug_assert!(context.chrome_rules_enabled()); + input.expect_function_matching("-moz-system-color")?; + input.parse_nested_block(|input| { + let color = SystemColor::parse(context, input)?; + input.expect_comma()?; + let scheme = SystemColorScheme::parse(input)?; + Ok((color, scheme)) + }) +} + impl Parse for Color { fn parse<'i, 't>( context: &ParserContext, @@ -504,7 +533,13 @@ impl Parse for Color { #[cfg(feature = "gecko")] { if let Ok(system) = input.try_parse(|i| SystemColor::parse(context, i)) { - return Ok(Color::System(system)); + return Ok(Color::System(system, SystemColorScheme::Default)); + } + + if context.chrome_rules_enabled() { + if let Ok((color, scheme)) = input.try_parse(|i| parse_moz_system_color(context, i)) { + return Ok(Color::System(color, scheme)); + } } } @@ -543,7 +578,17 @@ impl ToCss for Color { Color::Complex(_) => Ok(()), Color::ColorMix(ref mix) => mix.to_css(dest), #[cfg(feature = "gecko")] - Color::System(system) => system.to_css(dest), + Color::System(system, scheme) => { + if scheme == SystemColorScheme::Default { + system.to_css(dest) + } else { + dest.write_str("-moz-system-color(")?; + system.to_css(dest)?; + dest.write_str(", ")?; + scheme.to_css(dest)?; + dest.write_char(')') + } + } #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => Ok(()), } @@ -709,7 +754,7 @@ impl Color { )) }, #[cfg(feature = "gecko")] - Color::System(system) => system.compute(context?), + Color::System(system, scheme) => system.compute(context?, scheme), #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => ComputedColor::rgba(context?.device().body_text_color()), })