Recompute viewport-dependent styles on viewport size change

Fixes #8754.
This commit is contained in:
Matt Brubeck 2016-03-04 11:02:45 -08:00
parent 4df7975ed3
commit 25c1bce9f6
9 changed files with 71 additions and 57 deletions

View file

@ -22,7 +22,7 @@ path = "../style_traits"
[dependencies]
app_units = {version = "0.2.3", features = ["plugins"]}
bitflags = "0.3"
cssparser = {version = "0.5.4", features = ["heap_size", "serde-serialization"]}
cssparser = {version = "0.5.5", features = ["heap_size", "serde-serialization"]}
encoding = "0.2"
euclid = {version = "0.6.4", features = ["plugins"]}
fnv = "1.0"

View file

@ -226,12 +226,16 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
if let Some(ref constraints) = self.viewport_constraints {
device = Device::new(MediaType::Screen, constraints.size);
}
let is_device_dirty = self.is_device_dirty || stylesheets.iter()
.flat_map(|stylesheet| stylesheet.rules().media())
.any(|media_rule| media_rule.evaluate(&self.device) != media_rule.evaluate(&device));
let size_changed = device.viewport_size != self.device.viewport_size;
self.is_device_dirty |= stylesheets.iter().any(|stylesheet| {
(size_changed && stylesheet.dirty_on_viewport_size_change) ||
stylesheet.rules().media().any(|media_rule|
media_rule.evaluate(&self.device) != media_rule.evaluate(&device))
});
self.device = device;
self.is_device_dirty |= is_device_dirty;
}
pub fn viewport_constraints(&self) -> &Option<ViewportConstraints> {

View file

@ -46,6 +46,7 @@ pub struct Stylesheet<Impl: SelectorImpl> {
/// List of media associated with the Stylesheet, if any.
pub media: Option<MediaQueryList>,
pub origin: Origin,
pub dirty_on_viewport_size_change: bool,
}
@ -113,27 +114,31 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
_impl: PhantomData,
};
let mut input = Parser::new(css);
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
input.look_for_viewport_percentages();
let mut rules = Vec::new();
while let Some(result) = iter.next() {
match result {
Ok(rule) => {
if let CSSRule::Namespace(ref prefix, ref namespace) = rule {
if let Some(prefix) = prefix.as_ref() {
iter.parser.context.selector_context.namespace_prefixes.insert(
prefix.clone(), namespace.clone());
} else {
iter.parser.context.selector_context.default_namespace =
Some(namespace.clone());
{
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
while let Some(result) = iter.next() {
match result {
Ok(rule) => {
if let CSSRule::Namespace(ref prefix, ref namespace) = rule {
if let Some(prefix) = prefix.as_ref() {
iter.parser.context.selector_context.namespace_prefixes.insert(
prefix.clone(), namespace.clone());
} else {
iter.parser.context.selector_context.default_namespace =
Some(namespace.clone());
}
}
rules.push(rule);
}
Err(range) => {
let pos = range.start;
let message = format!("Invalid rule: '{}'", iter.input.slice(range));
let context = ParserContext::new(origin, &base_url, error_reporter.clone());
log_css_error(iter.input, pos, &*message, &context);
}
rules.push(rule);
}
Err(range) => {
let pos = range.start;
let message = format!("Invalid rule: '{}'", iter.input.slice(range));
let context = ParserContext::new(origin, &base_url, error_reporter.clone());
log_css_error(iter.input, pos, &*message, &context);
}
}
}
@ -141,6 +146,7 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
origin: origin,
rules: rules,
media: None,
dirty_on_viewport_size_change: input.seen_viewport_percentages(),
}
}