mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #13453 - metajack:media-query-list, r=jdm
Implement matchMedia and MediaQueryList <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #13376 (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Fixes #13376. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13453) <!-- Reviewable:end -->
This commit is contained in:
commit
6ef46ab9e4
22 changed files with 500 additions and 20 deletions
|
@ -137,6 +137,8 @@ pub mod values;
|
|||
pub mod viewport;
|
||||
pub mod workqueue;
|
||||
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The CSS properties supported by the style system.
|
||||
|
@ -176,3 +178,16 @@ pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
|
|||
let b: &T = &**b;
|
||||
(a as *const T) == (b as *const T)
|
||||
}
|
||||
|
||||
pub fn serialize_comma_separated_list<W, T>(dest: &mut W, list: &[T])
|
||||
-> fmt::Result where W: fmt::Write, T: ToCss {
|
||||
if list.len() > 0 {
|
||||
for item in &list[..list.len()-1] {
|
||||
try!(item.to_css(dest));
|
||||
try!(write!(dest, ", "));
|
||||
}
|
||||
list[list.len()-1].to_css(dest)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
//! [mq]: https://drafts.csswg.org/mediaqueries/
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::{Delimiter, Parser, Token};
|
||||
use cssparser::{Delimiter, Parser, ToCss, Token};
|
||||
use euclid::size::{Size2D, TypedSize2D};
|
||||
use properties::longhands;
|
||||
use serialize_comma_separated_list;
|
||||
use std::fmt::{self, Write};
|
||||
use string_cache::Atom;
|
||||
use style_traits::ViewportPx;
|
||||
use values::specified;
|
||||
|
||||
|
@ -20,6 +23,14 @@ pub struct MediaQueryList {
|
|||
pub media_queries: Vec<MediaQuery>
|
||||
}
|
||||
|
||||
impl ToCss for MediaQueryList {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write
|
||||
{
|
||||
serialize_comma_separated_list(dest, &self.media_queries)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum Range<T> {
|
||||
|
@ -104,20 +115,58 @@ impl MediaQuery {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToCss for MediaQuery {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write
|
||||
{
|
||||
if self.qualifier == Some(Qualifier::Not) {
|
||||
try!(write!(dest, "not "));
|
||||
}
|
||||
|
||||
let mut type_ = String::new();
|
||||
match self.media_type {
|
||||
MediaQueryType::All => try!(write!(type_, "all")),
|
||||
MediaQueryType::MediaType(MediaType::Screen) => try!(write!(type_, "screen")),
|
||||
MediaQueryType::MediaType(MediaType::Print) => try!(write!(type_, "print")),
|
||||
MediaQueryType::MediaType(MediaType::Unknown(ref desc)) => try!(write!(type_, "{}", desc)),
|
||||
};
|
||||
if self.expressions.is_empty() {
|
||||
return write!(dest, "{}", type_)
|
||||
} else if type_ != "all" || self.qualifier == Some(Qualifier::Not) {
|
||||
try!(write!(dest, "{} and ", type_));
|
||||
}
|
||||
for (i, &e) in self.expressions.iter().enumerate() {
|
||||
try!(write!(dest, "("));
|
||||
let (mm, l) = match e {
|
||||
Expression::Width(Range::Min(ref l)) => ("min", l),
|
||||
Expression::Width(Range::Max(ref l)) => ("max", l),
|
||||
};
|
||||
try!(write!(dest, "{}-width: ", mm));
|
||||
try!(l.to_css(dest));
|
||||
if i == self.expressions.len() - 1 {
|
||||
try!(write!(dest, ")"));
|
||||
} else {
|
||||
try!(write!(dest, ") and "));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// http://dev.w3.org/csswg/mediaqueries-3/#media0
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum MediaQueryType {
|
||||
All, // Always true
|
||||
MediaType(MediaType),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum MediaType {
|
||||
Screen,
|
||||
Print,
|
||||
Unknown,
|
||||
Unknown(Atom),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -181,7 +230,7 @@ impl MediaQuery {
|
|||
"screen" => MediaQueryType::MediaType(MediaType::Screen),
|
||||
"print" => MediaQueryType::MediaType(MediaType::Print),
|
||||
"all" => MediaQueryType::All,
|
||||
_ => MediaQueryType::MediaType(MediaType::Unknown)
|
||||
_ => MediaQueryType::MediaType(MediaType::Unknown(Atom::from(&*ident)))
|
||||
}
|
||||
} else {
|
||||
// Media type is only optional if qualifier is not specified.
|
||||
|
@ -233,8 +282,8 @@ impl MediaQueryList {
|
|||
self.media_queries.iter().any(|mq| {
|
||||
// Check if media matches. Unknown media never matches.
|
||||
let media_match = match mq.media_type {
|
||||
MediaQueryType::MediaType(MediaType::Unknown) => false,
|
||||
MediaQueryType::MediaType(media_type) => media_type == device.media_type,
|
||||
MediaQueryType::MediaType(MediaType::Unknown(_)) => false,
|
||||
MediaQueryType::MediaType(ref media_type) => *media_type == device.media_type,
|
||||
MediaQueryType::All => true,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue