diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 321669ce1af..ed0dac47795 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -17,18 +17,6 @@ use crate::Atom; use app_units::Au; use euclid::default::Size2D; -fn viewport_size(device: &Device) -> Size2D { - if let Some(pc) = device.pres_context() { - if pc.mIsRootPaginatedDocument() != 0 { - // We want the page size, including unprintable areas and margins. - // FIXME(emilio, bug 1414600): Not quite! - let area = &pc.mPageSize; - return Size2D::new(Au(area.width), Au(area.height)); - } - } - device.au_viewport_size() -} - fn device_size(device: &Device) -> Size2D { let mut width = 0; let mut height = 0; @@ -47,7 +35,7 @@ fn eval_width( RangeOrOperator::evaluate( range_or_operator, value.map(Au::from), - viewport_size(device).width, + device.au_viewport_size().width, ) } @@ -73,7 +61,7 @@ fn eval_height( RangeOrOperator::evaluate( range_or_operator, value.map(Au::from), - viewport_size(device).height, + device.au_viewport_size().height, ) } @@ -115,7 +103,7 @@ fn eval_aspect_ratio( query_value: Option, range_or_operator: Option, ) -> bool { - eval_aspect_ratio_for(device, query_value, range_or_operator, viewport_size) + eval_aspect_ratio_for(device, query_value, range_or_operator, Device::au_viewport_size) } /// https://drafts.csswg.org/mediaqueries-4/#device-aspect-ratio @@ -168,7 +156,7 @@ where /// https://drafts.csswg.org/mediaqueries-4/#orientation fn eval_orientation(device: &Device, value: Option) -> bool { - eval_orientation_for(device, value, viewport_size) + eval_orientation_for(device, value, Device::au_viewport_size) } /// FIXME: There's no spec for `-moz-device-orientation`. diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 663acae7b6e..cf28002e621 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -19,7 +19,7 @@ use cssparser::RGBA; use euclid::default::Size2D; use euclid::{Scale, SideOffsets2D}; use servo_arc::Arc; -use std::fmt; +use std::{cmp, fmt}; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}; use style_traits::viewport::ViewportConstraints; use style_traits::{CSSPixel, DevicePixel}; @@ -223,12 +223,29 @@ impl Device { MediaType(CustomIdent(unsafe { Atom::from_raw(medium_to_use) })) } + // It may make sense to account for @page rule margins here somehow, however + // it's not clear how that'd work, see: + // https://github.com/w3c/csswg-drafts/issues/5437 + fn page_size_minus_default_margin(&self, pc: &structs::nsPresContext) -> Size2D { + debug_assert!(pc.mIsRootPaginatedDocument() != 0); + let area = &pc.mPageSize; + let margin = &pc.mDefaultPageMargin; + let width = area.width - margin.left - margin.right; + let height = area.height - margin.top - margin.bottom; + Size2D::new(Au(cmp::max(width, 0)), Au(cmp::max(height, 0))) + } + /// Returns the current viewport size in app units. pub fn au_viewport_size(&self) -> Size2D { let pc = match self.pres_context() { Some(pc) => pc, None => return Size2D::new(Au(0), Au(0)), }; + + if pc.mIsRootPaginatedDocument() != 0 { + return self.page_size_minus_default_margin(pc); + } + let area = &pc.mVisibleArea; Size2D::new(Au(area.width), Au(area.height)) } @@ -237,11 +254,15 @@ impl Device { /// used for viewport unit resolution. pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> Size2D { self.used_viewport_size.store(true, Ordering::Relaxed); - let pc = match self.pres_context() { Some(pc) => pc, None => return Size2D::new(Au(0), Au(0)), }; + + if pc.mIsRootPaginatedDocument() != 0 { + return self.page_size_minus_default_margin(pc) + } + let size = &pc.mSizeForViewportUnits; Size2D::new(Au(size.width), Au(size.height)) }