style: Make media feature evaluation take a computed::Context

This has no behavior change right now, but will simplify sharing code
with container queries.

Container queries will have container information in the
computed::Context (this is necessary anyways for container-based units),
so this avoids having to have different code for media and container
queries.

Differential Revision: https://phabricator.services.mozilla.com/D144152
This commit is contained in:
Emilio Cobos Álvarez 2023-08-11 02:05:08 +02:00 committed by Martin Robinson
parent 6279504ddb
commit 8d8b5942be
6 changed files with 119 additions and 125 deletions

View file

@ -9,9 +9,7 @@ use crate::gecko_bindings::structs;
use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
use crate::media_queries::{Device, MediaType};
use crate::values::computed::CSSPixelLength;
use crate::values::computed::Ratio;
use crate::values::computed::Resolution;
use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution};
use app_units::Au;
use euclid::default::Size2D;
@ -25,46 +23,46 @@ fn device_size(device: &Device) -> Size2D<Au> {
}
/// https://drafts.csswg.org/mediaqueries-4/#width
fn eval_width(device: &Device) -> CSSPixelLength {
CSSPixelLength::new(device.au_viewport_size().width.to_f32_px())
fn eval_width(context: &Context) -> CSSPixelLength {
CSSPixelLength::new(context.device().au_viewport_size().width.to_f32_px())
}
/// https://drafts.csswg.org/mediaqueries-4/#device-width
fn eval_device_width(device: &Device) -> CSSPixelLength {
CSSPixelLength::new(device_size(device).width.to_f32_px())
fn eval_device_width(context: &Context) -> CSSPixelLength {
CSSPixelLength::new(device_size(context.device()).width.to_f32_px())
}
/// https://drafts.csswg.org/mediaqueries-4/#height
fn eval_height(device: &Device) -> CSSPixelLength {
CSSPixelLength::new(device.au_viewport_size().height.to_f32_px())
fn eval_height(context: &Context) -> CSSPixelLength {
CSSPixelLength::new(context.device().au_viewport_size().height.to_f32_px())
}
/// https://drafts.csswg.org/mediaqueries-4/#device-height
fn eval_device_height(device: &Device) -> CSSPixelLength {
CSSPixelLength::new(device_size(device).height.to_f32_px())
fn eval_device_height(context: &Context) -> CSSPixelLength {
CSSPixelLength::new(device_size(context.device()).height.to_f32_px())
}
fn eval_aspect_ratio_for<F>(device: &Device, get_size: F) -> Ratio
fn eval_aspect_ratio_for<F>(context: &Context, get_size: F) -> Ratio
where
F: FnOnce(&Device) -> Size2D<Au>,
{
let size = get_size(device);
let size = get_size(context.device());
Ratio::new(size.width.0 as f32, size.height.0 as f32)
}
/// https://drafts.csswg.org/mediaqueries-4/#aspect-ratio
fn eval_aspect_ratio(device: &Device) -> Ratio {
eval_aspect_ratio_for(device, Device::au_viewport_size)
fn eval_aspect_ratio(context: &Context) -> Ratio {
eval_aspect_ratio_for(context, Device::au_viewport_size)
}
/// https://drafts.csswg.org/mediaqueries-4/#device-aspect-ratio
fn eval_device_aspect_ratio(device: &Device) -> Ratio {
eval_aspect_ratio_for(device, device_size)
fn eval_device_aspect_ratio(context: &Context) -> Ratio {
eval_aspect_ratio_for(context, device_size)
}
/// https://compat.spec.whatwg.org/#css-media-queries-webkit-device-pixel-ratio
fn eval_device_pixel_ratio(device: &Device) -> f32 {
eval_resolution(device).dppx()
fn eval_device_pixel_ratio(context: &Context) -> f32 {
eval_resolution(context).dppx()
}
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
@ -74,7 +72,7 @@ enum Orientation {
Portrait,
}
fn eval_orientation_for<F>(device: &Device, value: Option<Orientation>, get_size: F) -> bool
fn eval_orientation_for<F>(context: &Context, value: Option<Orientation>, get_size: F) -> bool
where
F: FnOnce(&Device) -> Size2D<Au>,
{
@ -83,7 +81,7 @@ where
None => return true,
};
let size = get_size(device);
let size = get_size(context.device());
// Per spec, square viewports should be 'portrait'
let is_landscape = size.width > size.height;
@ -94,13 +92,13 @@ where
}
/// https://drafts.csswg.org/mediaqueries-4/#orientation
fn eval_orientation(device: &Device, value: Option<Orientation>) -> bool {
eval_orientation_for(device, value, Device::au_viewport_size)
fn eval_orientation(context: &Context, value: Option<Orientation>) -> bool {
eval_orientation_for(context, value, Device::au_viewport_size)
}
/// FIXME: There's no spec for `-moz-device-orientation`.
fn eval_device_orientation(device: &Device, value: Option<Orientation>) -> bool {
eval_orientation_for(device, value, device_size)
fn eval_device_orientation(context: &Context, value: Option<Orientation>) -> bool {
eval_orientation_for(context, value, device_size)
}
/// Values for the display-mode media feature.
@ -115,22 +113,22 @@ pub enum DisplayMode {
}
/// https://w3c.github.io/manifest/#the-display-mode-media-feature
fn eval_display_mode(device: &Device, query_value: Option<DisplayMode>) -> bool {
fn eval_display_mode(context: &Context, query_value: Option<DisplayMode>) -> bool {
match query_value {
Some(v) => v == unsafe { bindings::Gecko_MediaFeatures_GetDisplayMode(device.document()) },
Some(v) => v == unsafe { bindings::Gecko_MediaFeatures_GetDisplayMode(context.device().document()) },
None => true,
}
}
/// https://drafts.csswg.org/mediaqueries-4/#grid
fn eval_grid(_: &Device) -> bool {
fn eval_grid(_: &Context) -> bool {
// Gecko doesn't support grid devices (e.g., ttys), so the 'grid' feature
// is always 0.
false
}
/// https://compat.spec.whatwg.org/#css-media-queries-webkit-transform-3d
fn eval_transform_3d(_: &Device) -> bool {
fn eval_transform_3d(_: &Context) -> bool {
true
}
@ -142,32 +140,32 @@ enum Scan {
}
/// https://drafts.csswg.org/mediaqueries-4/#scan
fn eval_scan(_: &Device, _: Option<Scan>) -> bool {
fn eval_scan(_: &Context, _: Option<Scan>) -> bool {
// Since Gecko doesn't support the 'tv' media type, the 'scan' feature never
// matches.
false
}
/// https://drafts.csswg.org/mediaqueries-4/#color
fn eval_color(device: &Device) -> u32 {
unsafe { bindings::Gecko_MediaFeatures_GetColorDepth(device.document()) }
fn eval_color(context: &Context) -> u32 {
unsafe { bindings::Gecko_MediaFeatures_GetColorDepth(context.device().document()) }
}
/// https://drafts.csswg.org/mediaqueries-4/#color-index
fn eval_color_index(_: &Device) -> u32 {
fn eval_color_index(_: &Context) -> u32 {
// We should return zero if the device does not use a color lookup table.
0
}
/// https://drafts.csswg.org/mediaqueries-4/#monochrome
fn eval_monochrome(device: &Device) -> u32 {
fn eval_monochrome(context: &Context) -> u32 {
// For color devices we should return 0.
unsafe { bindings::Gecko_MediaFeatures_GetMonochromeBitsPerPixel(device.document()) }
unsafe { bindings::Gecko_MediaFeatures_GetMonochromeBitsPerPixel(context.device().document()) }
}
/// https://drafts.csswg.org/mediaqueries-4/#resolution
fn eval_resolution(device: &Device) -> Resolution {
let resolution_dppx = unsafe { bindings::Gecko_MediaFeatures_GetResolution(device.document()) };
fn eval_resolution(context: &Context) -> Resolution {
let resolution_dppx = unsafe { bindings::Gecko_MediaFeatures_GetResolution(context.device().document()) };
Resolution::from_dppx(resolution_dppx)
}
@ -200,9 +198,9 @@ pub enum DynamicRange {
}
/// https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-motion
fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReducedMotion>) -> bool {
fn eval_prefers_reduced_motion(context: &Context, query_value: Option<PrefersReducedMotion>) -> bool {
let prefers_reduced =
unsafe { bindings::Gecko_MediaFeatures_PrefersReducedMotion(device.document()) };
unsafe { bindings::Gecko_MediaFeatures_PrefersReducedMotion(context.device().document()) };
let query_value = match query_value {
Some(v) => v,
None => return prefers_reduced,
@ -230,9 +228,9 @@ pub enum PrefersContrast {
}
/// https://drafts.csswg.org/mediaqueries-5/#prefers-contrast
fn eval_prefers_contrast(device: &Device, query_value: Option<PrefersContrast>) -> bool {
fn eval_prefers_contrast(context: &Context, query_value: Option<PrefersContrast>) -> bool {
let prefers_contrast =
unsafe { bindings::Gecko_MediaFeatures_PrefersContrast(device.document()) };
unsafe { bindings::Gecko_MediaFeatures_PrefersContrast(context.device().document()) };
match query_value {
Some(v) => v == prefers_contrast,
None => prefers_contrast != PrefersContrast::NoPreference,
@ -251,8 +249,8 @@ pub enum ForcedColors {
}
/// https://drafts.csswg.org/mediaqueries-5/#forced-colors
fn eval_forced_colors(device: &Device, query_value: Option<ForcedColors>) -> bool {
let forced = !device.use_document_colors();
fn eval_forced_colors(context: &Context, query_value: Option<ForcedColors>) -> bool {
let forced = !context.device().use_document_colors();
match query_value {
Some(query_value) => forced == (query_value == ForcedColors::Active),
None => forced,
@ -269,7 +267,7 @@ enum OverflowBlock {
}
/// https://drafts.csswg.org/mediaqueries-4/#mf-overflow-block
fn eval_overflow_block(device: &Device, query_value: Option<OverflowBlock>) -> bool {
fn eval_overflow_block(context: &Context, query_value: Option<OverflowBlock>) -> bool {
// For the time being, assume that printing (including previews)
// is the only time when we paginate, and we are otherwise always
// scrolling. This is true at the moment in Firefox, but may need
@ -277,7 +275,7 @@ fn eval_overflow_block(device: &Device, query_value: Option<OverflowBlock>) -> b
// billboard mode that doesn't support overflow at all).
//
// If this ever changes, don't forget to change eval_overflow_inline too.
let scrolling = device.media_type() != MediaType::print();
let scrolling = context.device().media_type() != MediaType::print();
let query_value = match query_value {
Some(v) => v,
None => return true,
@ -298,9 +296,9 @@ enum OverflowInline {
}
/// https://drafts.csswg.org/mediaqueries-4/#mf-overflow-inline
fn eval_overflow_inline(device: &Device, query_value: Option<OverflowInline>) -> bool {
fn eval_overflow_inline(context: &Context, query_value: Option<OverflowInline>) -> bool {
// See the note in eval_overflow_block.
let scrolling = device.media_type() != MediaType::print();
let scrolling = context.device().media_type() != MediaType::print();
let query_value = match query_value {
Some(v) => v,
None => return scrolling,
@ -313,12 +311,12 @@ fn eval_overflow_inline(device: &Device, query_value: Option<OverflowInline>) ->
}
fn do_eval_prefers_color_scheme(
device: &Device,
context: &Context,
use_content: bool,
query_value: Option<PrefersColorScheme>,
) -> bool {
let prefers_color_scheme =
unsafe { bindings::Gecko_MediaFeatures_PrefersColorScheme(device.document(), use_content) };
unsafe { bindings::Gecko_MediaFeatures_PrefersColorScheme(context.device().document(), use_content) };
match query_value {
Some(v) => prefers_color_scheme == v,
None => true,
@ -326,30 +324,30 @@ fn do_eval_prefers_color_scheme(
}
/// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
fn eval_prefers_color_scheme(device: &Device, query_value: Option<PrefersColorScheme>) -> bool {
do_eval_prefers_color_scheme(device, /* use_content = */ false, query_value)
fn eval_prefers_color_scheme(context: &Context, query_value: Option<PrefersColorScheme>) -> bool {
do_eval_prefers_color_scheme(context, /* use_content = */ false, query_value)
}
fn eval_content_prefers_color_scheme(
device: &Device,
context: &Context,
query_value: Option<PrefersColorScheme>,
) -> bool {
do_eval_prefers_color_scheme(device, /* use_content = */ true, query_value)
do_eval_prefers_color_scheme(context, /* use_content = */ true, query_value)
}
/// https://drafts.csswg.org/mediaqueries-5/#dynamic-range
fn eval_dynamic_range(device: &Device, query_value: Option<DynamicRange>) -> bool {
fn eval_dynamic_range(context: &Context, query_value: Option<DynamicRange>) -> bool {
let dynamic_range =
unsafe { bindings::Gecko_MediaFeatures_DynamicRange(device.document()) };
unsafe { bindings::Gecko_MediaFeatures_DynamicRange(context.device().document()) };
match query_value {
Some(v) => dynamic_range >= v,
None => false,
}
}
/// https://drafts.csswg.org/mediaqueries-5/#video-dynamic-range
fn eval_video_dynamic_range(device: &Device, query_value: Option<DynamicRange>) -> bool {
fn eval_video_dynamic_range(context: &Context, query_value: Option<DynamicRange>) -> bool {
let dynamic_range =
unsafe { bindings::Gecko_MediaFeatures_VideoDynamicRange(device.document()) };
unsafe { bindings::Gecko_MediaFeatures_VideoDynamicRange(context.device().document()) };
match query_value {
Some(v) => dynamic_range >= v,
None => false,
@ -365,15 +363,15 @@ bitflags! {
}
}
fn primary_pointer_capabilities(device: &Device) -> PointerCapabilities {
fn primary_pointer_capabilities(context: &Context) -> PointerCapabilities {
PointerCapabilities::from_bits_truncate(unsafe {
bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(device.document())
bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(context.device().document())
})
}
fn all_pointer_capabilities(device: &Device) -> PointerCapabilities {
fn all_pointer_capabilities(context: &Context) -> PointerCapabilities {
PointerCapabilities::from_bits_truncate(unsafe {
bindings::Gecko_MediaFeatures_AllPointerCapabilities(device.document())
bindings::Gecko_MediaFeatures_AllPointerCapabilities(context.device().document())
})
}
@ -402,13 +400,13 @@ fn eval_pointer_capabilities(
}
/// https://drafts.csswg.org/mediaqueries-4/#pointer
fn eval_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
eval_pointer_capabilities(query_value, primary_pointer_capabilities(device))
fn eval_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
eval_pointer_capabilities(query_value, primary_pointer_capabilities(context))
}
/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-pointer
fn eval_any_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
eval_pointer_capabilities(query_value, all_pointer_capabilities(device))
fn eval_any_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
eval_pointer_capabilities(query_value, all_pointer_capabilities(context))
}
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
@ -435,33 +433,33 @@ fn eval_hover_capabilities(
}
/// https://drafts.csswg.org/mediaqueries-4/#hover
fn eval_hover(device: &Device, query_value: Option<Hover>) -> bool {
eval_hover_capabilities(query_value, primary_pointer_capabilities(device))
fn eval_hover(context: &Context, query_value: Option<Hover>) -> bool {
eval_hover_capabilities(query_value, primary_pointer_capabilities(context))
}
/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-hover
fn eval_any_hover(device: &Device, query_value: Option<Hover>) -> bool {
eval_hover_capabilities(query_value, all_pointer_capabilities(device))
fn eval_any_hover(context: &Context, query_value: Option<Hover>) -> bool {
eval_hover_capabilities(query_value, all_pointer_capabilities(context))
}
fn eval_moz_is_glyph(device: &Device) -> bool {
device.document().mIsSVGGlyphsDocument()
fn eval_moz_is_glyph(context: &Context) -> bool {
context.device().document().mIsSVGGlyphsDocument()
}
fn eval_moz_print_preview(device: &Device) -> bool {
let is_print_preview = device.is_print_preview();
fn eval_moz_print_preview(context: &Context) -> bool {
let is_print_preview = context.device().is_print_preview();
if is_print_preview {
debug_assert_eq!(device.media_type(), MediaType::print());
debug_assert_eq!(context.device().media_type(), MediaType::print());
}
is_print_preview
}
fn eval_moz_non_native_content_theme(device: &Device) -> bool {
unsafe { bindings::Gecko_MediaFeatures_ShouldAvoidNativeTheme(device.document()) }
fn eval_moz_non_native_content_theme(context: &Context) -> bool {
unsafe { bindings::Gecko_MediaFeatures_ShouldAvoidNativeTheme(context.device().document()) }
}
fn eval_moz_is_resource_document(device: &Device) -> bool {
unsafe { bindings::Gecko_MediaFeatures_IsResourceDocument(device.document()) }
fn eval_moz_is_resource_document(context: &Context) -> bool {
unsafe { bindings::Gecko_MediaFeatures_IsResourceDocument(context.device().document()) }
}
/// Allows front-end CSS to discern platform via media queries.
@ -487,7 +485,7 @@ pub enum Platform {
WindowsWin10,
}
fn eval_moz_platform(_: &Device, query_value: Option<Platform>) -> bool {
fn eval_moz_platform(_: &Context, query_value: Option<Platform>) -> bool {
let query_value = match query_value {
Some(v) => v,
None => return false,
@ -496,13 +494,13 @@ fn eval_moz_platform(_: &Device, query_value: Option<Platform>) -> bool {
unsafe { bindings::Gecko_MediaFeatures_MatchesPlatform(query_value) }
}
fn eval_moz_windows_non_native_menus(device: &Device) -> bool {
fn eval_moz_windows_non_native_menus(context: &Context) -> bool {
let use_non_native_menus = match static_prefs::pref!("browser.display.windows.non_native_menus")
{
0 => false,
1 => true,
_ => {
eval_moz_platform(device, Some(Platform::WindowsWin10)) &&
eval_moz_platform(context, Some(Platform::WindowsWin10)) &&
get_lnf_int_as_bool(bindings::LookAndFeel_IntID::WindowsDefaultTheme as i32)
},
};
@ -510,8 +508,8 @@ fn eval_moz_windows_non_native_menus(device: &Device) -> bool {
use_non_native_menus
}
fn eval_moz_overlay_scrollbars(device: &Device) -> bool {
unsafe { bindings::Gecko_MediaFeatures_UseOverlayScrollbars(device.document()) }
fn eval_moz_overlay_scrollbars(context: &Context) -> bool {
unsafe { bindings::Gecko_MediaFeatures_UseOverlayScrollbars(context.device().document()) }
}
fn get_lnf_int(int_id: i32) -> i32 {
@ -540,7 +538,7 @@ fn get_scrollbar_end_forward(int_id: i32) -> bool {
macro_rules! lnf_int_feature {
($feature_name:expr, $int_id:ident, $get_value:ident) => {{
fn __eval(_: &Device) -> bool {
fn __eval(_: &Context) -> bool {
$get_value(bindings::LookAndFeel_IntID::$int_id as i32)
}
@ -567,7 +565,7 @@ macro_rules! lnf_int_feature {
/// you also need to add them to kMediaQueryPrefs in nsXPLookAndFeel.cpp
macro_rules! bool_pref_feature {
($feature_name:expr, $pref:tt) => {{
fn __eval(_: &Device) -> bool {
fn __eval(_: &Context) -> bool {
static_prefs::pref!($pref)
}