Bug 1371395 Part 2: Servo: Allow emulation of supported media types.
MozReview-Commit-ID: kn3rDbQmn5
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -13,30 +13,31 @@ use euclid::Size2D;
use font_metrics::get_metrics_provider_for_product;
use gecko::values::convert_nscolor_to_rgba;
use gecko_bindings::bindings;
use gecko_bindings::structs;
use gecko_bindings::structs::{nsCSSKeyword, nsCSSProps_KTableEntry, nsCSSValue, nsCSSUnit, nsStringBuffer};
use gecko_bindings::structs::{nsMediaExpression_Range, nsMediaFeature};
use gecko_bindings::structs::{nsMediaFeature_ValueType, nsMediaFeature_RangeType, nsMediaFeature_RequirementFlags};
use gecko_bindings::structs::{nsPresContext, RawGeckoPresContextOwned};
+use gecko_bindings::structs::nsIAtom;
use media_queries::MediaType;
use parser::ParserContext;
use properties::{ComputedValues, StyleBuilder};
use properties::longhands::font_size;
use selectors::parser::SelectorParseError;
use servo_arc::Arc;
use std::fmt::{self, Write};
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
use str::starts_with_ignore_ascii_case;
use string_cache::Atom;
use style_traits::{CSSPixel, DevicePixel};
use style_traits::{ToCss, ParseError, StyleParseError};
use style_traits::viewport::ViewportConstraints;
-use values::{CSSFloat, specified};
+use values::{CSSFloat, specified, CustomIdent};
use values::computed::{self, ToComputedValue};
/// The `Device` in Gecko wraps a pres context, has a default values computed,
/// and contains all the viewport rule state.
pub struct Device {
/// NB: The pres context lifetime is tied to the styleset, who owns the
/// stylist, and thus the `Device`, so having a raw pres context pointer
/// here is fine.
@@ -135,25 +136,26 @@ impl Device {
/// default computed values.
pub fn reset(&mut self) {
self.reset_computed_values();
}
/// Returns the current media type of the device.
pub fn media_type(&self) -> MediaType {
unsafe {
- // FIXME(emilio): Gecko allows emulating random media with
- // mIsEmulatingMedia / mMediaEmulated . Refactor both sides so that
- // is supported (probably just making MediaType an Atom).
- if self.pres_context().mMedium == atom!("screen").as_ptr() {
- MediaType::Screen
+ // Gecko allows emulating random media with mIsEmulatingMedia and
+ // mMediaEmulated.
+ let context = self.pres_context();
+ let medium_to_use = if context.mIsEmulatingMedia() != 0 {
+ context.mMediaEmulated.raw::<nsIAtom>()
} else {
- debug_assert!(self.pres_context().mMedium == atom!("print").as_ptr());
- MediaType::Print
- }
+ context.mMedium
+ };
+
+ MediaType(CustomIdent(Atom::from(medium_to_use)))
}
}
/// Returns the current viewport size in app units.
pub fn au_viewport_size(&self) -> Size2D<Au> {
self.used_viewport_size.store(true, Ordering::Relaxed);
unsafe {
// TODO(emilio): Need to take into account scrollbars.
--- a/servo/components/style/media_queries.rs
+++ b/servo/components/style/media_queries.rs
@@ -8,17 +8,19 @@
use Atom;
use context::QuirksMode;
use cssparser::{Delimiter, Parser, Token, ParserInput};
use parser::ParserContext;
use selectors::parser::SelectorParseError;
use serialize_comma_separated_list;
use std::fmt;
+use str::string_as_ascii_lowercase;
use style_traits::{ToCss, ParseError, StyleParseError};
+use values::CustomIdent;
#[cfg(feature = "servo")]
pub use servo::media_queries::{Device, Expression};
#[cfg(feature = "gecko")]
pub use gecko::media_queries::{Device, Expression};
/// A type that encapsulates a media query list.
#[derive(Debug, Clone)]
@@ -103,19 +105,17 @@ impl ToCss for MediaQuery {
// just an empty list of expressions.
//
// Otherwise, we'd serialize media queries like "(min-width:
// 40px)" in "all (min-width: 40px)", which is unexpected.
if self.qualifier.is_some() || self.expressions.is_empty() {
write!(dest, "all")?;
}
},
- MediaQueryType::Known(MediaType::Screen) => write!(dest, "screen")?,
- MediaQueryType::Known(MediaType::Print) => write!(dest, "print")?,
- MediaQueryType::Unknown(ref desc) => write!(dest, "{}", desc)?,
+ MediaQueryType::Concrete(MediaType(ref desc)) => desc.to_css(dest)?,
}
if self.expressions.is_empty() {
return Ok(());
}
if self.media_type != MediaQueryType::All || self.qualifier.is_some() {
write!(dest, " and ")?;
@@ -132,66 +132,56 @@ impl ToCss for MediaQuery {
}
/// http://dev.w3.org/csswg/mediaqueries-3/#media0
#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum MediaQueryType {
/// A media type that matches every device.
All,
- /// A known media type, that we parse and understand.
- Known(MediaType),
- /// An unknown media type.
- Unknown(Atom),
+ /// A specific media type.
+ Concrete(MediaType),
}
impl MediaQueryType {
fn parse(ident: &str) -> Result<Self, ()> {
match_ignore_ascii_case! { ident,
"all" => return Ok(MediaQueryType::All),
- // From https://drafts.csswg.org/mediaqueries/#mq-syntax:
- //
- // The <media-type> production does not include the keywords only,
- // not, and, and or.
- "not" | "or" | "and" | "only" => return Err(()),
_ => (),
};
- Ok(match MediaType::parse(ident) {
- Some(media_type) => MediaQueryType::Known(media_type),
- None => MediaQueryType::Unknown(Atom::from(ident)),
- })
+ // If parseable, accept this type as a concrete type.
+ MediaType::parse(ident).map(MediaQueryType::Concrete)
}
fn matches(&self, other: MediaType) -> bool {
match *self {
MediaQueryType::All => true,
- MediaQueryType::Known(ref known_type) => *known_type == other,
- MediaQueryType::Unknown(..) => false,
+ MediaQueryType::Concrete(ref known_type) => *known_type == other,
}
}
}
/// https://drafts.csswg.org/mediaqueries/#media-types
#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum MediaType {
- /// The "screen" media type.
- Screen,
- /// The "print" media type.
- Print,
-}
+pub struct MediaType(pub CustomIdent);
impl MediaType {
- fn parse(name: &str) -> Option<Self> {
- Some(match_ignore_ascii_case! { name,
- "screen" => MediaType::Screen,
- "print" => MediaType::Print,
- _ => return None
- })
+ fn parse(name: &str) -> Result<Self, ()> {
+ // From https://drafts.csswg.org/mediaqueries/#mq-syntax:
+ //
+ // The <media-type> production does not include the keywords not, or, and, and only.
+ //
+ // Here we also perform the to-ascii-lowercase part of the serialization
+ // algorithm: https://drafts.csswg.org/cssom/#serializing-media-queries
+ match_ignore_ascii_case! { name,
+ "not" | "or" | "and" | "only" => Err(()),
+ _ => Ok(MediaType(CustomIdent(Atom::from(string_as_ascii_lowercase(name))))),
+ }
}
}
impl MediaQuery {
/// Parse a media query given css input.
///
/// Returns an error if any of the expressions is unknown.
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<MediaQuery, ParseError<'i>> {