1use crate::derives::*;
8use crate::queries::feature::{AllowsRanges, Evaluator, FeatureFlags, QueryFeatureDescription};
9use crate::queries::values::PrefersColorScheme;
10use crate::values::computed::{CSSPixelLength, Context, Resolution};
11use std::fmt::Debug;
12
13fn eval_width(context: &Context) -> CSSPixelLength {
15 CSSPixelLength::new(context.device().au_viewport_size().width.to_f32_px())
16}
17
18#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
19#[repr(u8)]
20enum Scan {
21 Progressive,
22 Interlace,
23}
24
25fn eval_scan(_: &Context, _: Option<Scan>) -> bool {
27 false
30}
31
32fn eval_resolution(context: &Context) -> Resolution {
34 Resolution::from_dppx(context.device().device_pixel_ratio().0)
35}
36
37fn eval_device_pixel_ratio(context: &Context) -> f32 {
39 eval_resolution(context).dppx()
40}
41
42fn eval_prefers_color_scheme(context: &Context, query_value: Option<PrefersColorScheme>) -> bool {
43 match query_value {
44 Some(v) => context.device().color_scheme() == v,
45 None => true,
46 }
47}
48
49bitflags! {
50 #[derive(Debug, Clone, Copy)]
52 pub struct PointerCapabilities: u8 {
53 const COARSE = 0b001;
55 const FINE = 0b010;
57 const HOVER = 0b100;
59 }
60}
61
62impl Default for PointerCapabilities {
63 #[cfg(any(target_os = "ios", target_os = "android", target_env = "ohos"))]
64 fn default() -> Self {
65 PointerCapabilities::COARSE
66 }
67 #[cfg(not(any(target_os = "ios", target_os = "android", target_env = "ohos")))]
68 fn default() -> Self {
69 PointerCapabilities::FINE | PointerCapabilities::HOVER
70 }
71}
72
73#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
74#[repr(u8)]
75enum Pointer {
76 None,
77 Coarse,
78 Fine,
79}
80
81fn eval_pointer_capabilities(
82 query_value: Option<Pointer>,
83 pointer_capabilities: PointerCapabilities,
84) -> bool {
85 match query_value {
86 None => !pointer_capabilities.is_empty(),
87 Some(Pointer::None) => pointer_capabilities.is_empty(),
88 Some(Pointer::Coarse) => pointer_capabilities.intersects(PointerCapabilities::COARSE),
89 Some(Pointer::Fine) => pointer_capabilities.intersects(PointerCapabilities::FINE),
90 }
91}
92
93fn eval_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
95 eval_pointer_capabilities(query_value, context.device().primary_pointer_capabilities())
96}
97
98fn eval_any_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
100 eval_pointer_capabilities(query_value, context.device().all_pointer_capabilities())
101}
102
103#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
104#[repr(u8)]
105enum Hover {
106 None,
107 Hover,
108}
109
110fn eval_hover_capabilities(
111 query_value: Option<Hover>,
112 pointer_capabilities: PointerCapabilities,
113) -> bool {
114 let can_hover = pointer_capabilities.intersects(PointerCapabilities::HOVER);
115 match query_value {
116 Some(Hover::None) => !can_hover,
117 Some(Hover::Hover) => can_hover,
118 None => return can_hover,
119 }
120}
121
122fn eval_hover(context: &Context, query_value: Option<Hover>) -> bool {
124 eval_hover_capabilities(query_value, context.device().primary_pointer_capabilities())
125}
126
127fn eval_any_hover(context: &Context, query_value: Option<Hover>) -> bool {
129 eval_hover_capabilities(query_value, context.device().all_pointer_capabilities())
130}
131
132pub static MEDIA_FEATURES: [QueryFeatureDescription; 10] = [
134 feature!(
135 atom!("width"),
136 AllowsRanges::Yes,
137 Evaluator::Length(eval_width),
138 FeatureFlags::empty(),
139 ),
140 feature!(
141 atom!("pointer"),
142 AllowsRanges::No,
143 keyword_evaluator!(eval_pointer, Pointer),
144 FeatureFlags::empty(),
145 ),
146 feature!(
147 atom!("any-pointer"),
148 AllowsRanges::No,
149 keyword_evaluator!(eval_any_pointer, Pointer),
150 FeatureFlags::empty(),
151 ),
152 feature!(
153 atom!("hover"),
154 AllowsRanges::No,
155 keyword_evaluator!(eval_hover, Hover),
156 FeatureFlags::empty(),
157 ),
158 feature!(
159 atom!("any-hover"),
160 AllowsRanges::No,
161 keyword_evaluator!(eval_any_hover, Hover),
162 FeatureFlags::empty(),
163 ),
164 feature!(
165 atom!("scan"),
166 AllowsRanges::No,
167 keyword_evaluator!(eval_scan, Scan),
168 FeatureFlags::empty(),
169 ),
170 feature!(
171 atom!("resolution"),
172 AllowsRanges::Yes,
173 Evaluator::Resolution(eval_resolution),
174 FeatureFlags::empty(),
175 ),
176 feature!(
177 atom!("device-pixel-ratio"),
178 AllowsRanges::Yes,
179 Evaluator::Float(eval_device_pixel_ratio),
180 FeatureFlags::WEBKIT_PREFIX,
181 ),
182 feature!(
183 atom!("-moz-device-pixel-ratio"),
184 AllowsRanges::Yes,
185 Evaluator::Float(eval_device_pixel_ratio),
186 FeatureFlags::empty(),
187 ),
188 feature!(
189 atom!("prefers-color-scheme"),
190 AllowsRanges::No,
191 keyword_evaluator!(eval_prefers_color_scheme, PrefersColorScheme),
192 FeatureFlags::empty(),
193 ),
194];