style: Implement the prefers-contrast media-query.

Differential Revision: https://phabricator.services.mozilla.com/D79553
This commit is contained in:
Zeke Medley 2020-06-29 17:46:12 +00:00 committed by Emilio Cobos Álvarez
parent 46df06b3e2
commit 8ff565c86b
3 changed files with 71 additions and 4 deletions

View file

@ -308,6 +308,53 @@ fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReduc
}
}
/// Possible values for prefers-contrast media query.
/// https://drafts.csswg.org/mediaqueries-5/#prefers-contrast
#[derive(Clone, Copy, Debug, FromPrimitive, PartialEq, Parse, ToCss)]
#[repr(u8)]
#[allow(missing_docs)]
enum PrefersContrast {
High,
Low,
NoPreference,
Forced,
}
/// Represents the parts of prefers-contrast that explicitly deal with
/// contrast. Used in combination with information about rather or not
/// forced colors are active this allows for evaluation of the
/// prefers-contrast media query.
#[derive(Clone, Copy, Debug, FromPrimitive, PartialEq)]
#[repr(u8)]
pub enum ContrastPref {
/// High contrast is prefered. Corresponds to an accessibility theme
/// being enabled or firefox forcing high contrast colors.
High,
/// Low contrast is prefered. Corresponds to the
/// browser.display.prefers_low_contrast pref being true.
Low,
/// The default value if neither high or low contrast is enabled.
NoPreference,
}
/// https://drafts.csswg.org/mediaqueries-5/#prefers-contrast
fn eval_prefers_contrast(device: &Device, query_value: Option<PrefersContrast>) -> bool {
let forced_colors = !device.use_document_colors();
let contrast_pref =
unsafe { bindings::Gecko_MediaFeatures_PrefersContrast(device.document(), forced_colors) };
if let Some(query_value) = query_value {
match query_value {
PrefersContrast::Forced => forced_colors,
PrefersContrast::High => contrast_pref == ContrastPref::High,
PrefersContrast::Low => contrast_pref == ContrastPref::Low,
PrefersContrast::NoPreference => contrast_pref == ContrastPref::NoPreference,
}
} else {
// Only prefers-contrast: no-preference evaluates to false.
forced_colors || (contrast_pref != ContrastPref::NoPreference)
}
}
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
#[repr(u8)]
enum OverflowBlock {
@ -548,7 +595,7 @@ macro_rules! system_metric_feature {
/// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change.
pub static MEDIA_FEATURES: [MediaFeatureDescription; 53] = [
pub static MEDIA_FEATURES: [MediaFeatureDescription; 54] = [
feature!(
atom!("width"),
AllowsRanges::Yes,
@ -666,6 +713,17 @@ pub static MEDIA_FEATURES: [MediaFeatureDescription; 53] = [
keyword_evaluator!(eval_prefers_reduced_motion, PrefersReducedMotion),
ParsingRequirements::empty(),
),
feature!(
atom!("prefers-contrast"),
AllowsRanges::No,
keyword_evaluator!(eval_prefers_contrast, PrefersContrast),
// Note: by default this is only enabled in browser chrome and
// ua. It can be enabled on the web via the
// layout.css.prefers-contrast.enabled preference. See
// disabed_by_pref in media_feature_expression.rs for how that
// is done.
ParsingRequirements::empty(),
),
feature!(
atom!("overflow-block"),
AllowsRanges::No,

View file

@ -218,12 +218,18 @@ fn consume_operation_or_colon(input: &mut Parser) -> Result<Option<Operator>, ()
}
#[allow(unused_variables)]
fn disabled_by_pref(feature: &Atom) -> bool {
fn disabled_by_pref(feature: &Atom, context: &ParserContext) -> bool {
#[cfg(feature = "gecko")]
{
if *feature == atom!("-moz-touch-enabled") {
return !static_prefs::pref!("layout.css.moz-touch-enabled.enabled");
}
// prefers-contrast is always enabled in the ua and chrome. On
// the web it is hidden behind a preference.
if *feature == atom!("prefers-contrast") {
return !context.in_ua_or_chrome_sheet() &&
!static_prefs::pref!("layout.css.prefers-contrast.enabled");
}
}
false
}
@ -305,7 +311,7 @@ impl MediaFeatureExpression {
},
};
if disabled_by_pref(&feature.name) ||
if disabled_by_pref(&feature.name, context) ||
!requirements.contains(feature.requirements) ||
(range.is_some() && !feature.allows_ranges())
{

View file

@ -2089,7 +2089,9 @@ pub fn assert_initial_values_match(data: &PerDocumentStyleData) {
let data = data.borrow();
let cv = data.stylist.device().default_computed_values();
<%
# Skip properties with initial values that change at computed value time.
# Skip properties with initial values that change at computed
# value time, or whose initial value depends on the document
# / other prefs.
SKIPPED = [
"border-top-width",
"border-bottom-width",
@ -2098,6 +2100,7 @@ pub fn assert_initial_values_match(data: &PerDocumentStyleData) {
"font-family",
"font-size",
"outline-width",
"color",
]
TO_TEST = [p for p in data.longhands if p.enabled_in != "" and not p.logical and not p.name in SKIPPED]
%>