diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/compositing/Cargo.toml | 4 | ||||
-rw-r--r-- | components/compositing/compositor.rs | 38 | ||||
-rw-r--r-- | components/compositing/compositor_task.rs | 5 | ||||
-rw-r--r-- | components/compositing/constellation.rs | 10 | ||||
-rw-r--r-- | components/compositing/headless.rs | 5 | ||||
-rw-r--r-- | components/compositing/lib.rs | 2 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 25 | ||||
-rw-r--r-- | components/msg/constellation_msg.rs | 5 | ||||
-rw-r--r-- | components/msg/lib.rs | 1 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 3 | ||||
-rw-r--r-- | components/style/selector_matching.rs | 9 |
11 files changed, 94 insertions, 13 deletions
diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index f035bc4ef17..a16df45f0ed 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -28,6 +28,9 @@ path = "../profile_traits" [dependencies.net_traits] path = "../net_traits" +[dependencies.style] +path = "../style" + [dependencies.util] path = "../util" @@ -62,6 +65,7 @@ git = "https://github.com/servo/gleam" git = "https://github.com/servo/rust-x11-clipboard" [dependencies] +num = "0.1.24" url = "0.2.16" time = "0.1.17" libc = "*" diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index e09b0685d41..65e7848413f 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -42,6 +42,7 @@ use std::mem as std_mem; use std::rc::Rc; use std::slice::bytes::copy_memory; use std::sync::mpsc::Sender; +use style::viewport::ViewportConstraints; use time::{precise_time_ns, precise_time_s}; use url::Url; use util::geometry::{PagePx, ScreenPx, ViewportPx}; @@ -74,6 +75,10 @@ pub struct IOCompositor<Window: WindowMethods> { /// "Mobile-style" zoom that does not reflow the page. viewport_zoom: ScaleFactor<PagePx, ViewportPx, f32>, + /// Viewport zoom constraints provided by @viewport. + min_viewport_zoom: Option<ScaleFactor<PagePx, ViewportPx, f32>>, + max_viewport_zoom: Option<ScaleFactor<PagePx, ViewportPx, f32>>, + /// "Desktop-style" zoom that resizes the viewport to fit the window. /// See `ViewportPx` docs in util/geom.rs for details. page_zoom: ScaleFactor<ViewportPx, ScreenPx, f32>, @@ -214,6 +219,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { shutdown_state: ShutdownState::NotShuttingDown, page_zoom: ScaleFactor::new(1.0), viewport_zoom: ScaleFactor::new(1.0), + min_viewport_zoom: None, + max_viewport_zoom: None, zoom_action: false, zoom_time: 0f64, got_load_complete_message: false, @@ -384,6 +391,10 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } + (Msg::ViewportConstrained(pipeline_id, constraints), ShutdownState::NotShuttingDown) => { + self.constrain_viewport(pipeline_id, constraints); + } + // When we are shutting_down, we need to avoid performing operations // such as Paint that may crash because we have begun tearing down // the rest of our resources. @@ -928,6 +939,21 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } + fn constrain_viewport(&mut self, pipeline_id: PipelineId, constraints: ViewportConstraints) { + let is_root = self.root_pipeline.as_ref().map_or(false, |root_pipeline| { + root_pipeline.id == pipeline_id + }); + + if is_root { + // TODO: actual viewport size + + self.viewport_zoom = constraints.initial_zoom; + self.min_viewport_zoom = constraints.min_zoom; + self.max_viewport_zoom = constraints.max_zoom; + self.update_zoom_transform(); + } + } + fn device_pixels_per_screen_px(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> { match opts::get().device_pixels_per_px { Some(device_pixels_per_px) => device_pixels_per_px, @@ -959,12 +985,19 @@ impl<Window: WindowMethods> IOCompositor<Window> { // TODO(pcwalton): I think this should go through the same queuing as scroll events do. fn on_pinch_zoom_window_event(&mut self, magnification: f32) { + use num::Float; + self.zoom_action = true; self.zoom_time = precise_time_s(); let old_viewport_zoom = self.viewport_zoom; - self.viewport_zoom = ScaleFactor::new((self.viewport_zoom.get() * magnification).max(1.0)); - let viewport_zoom = self.viewport_zoom; + let mut viewport_zoom = self.viewport_zoom.get() * magnification; + if let Some(min_zoom) = self.min_viewport_zoom.as_ref() { + viewport_zoom = min_zoom.get().max(viewport_zoom) + } + let viewport_zoom = self.max_viewport_zoom.as_ref().map_or(1., |z| z.get()).min(viewport_zoom); + let viewport_zoom = ScaleFactor::new(viewport_zoom); + self.viewport_zoom = viewport_zoom; self.update_zoom_transform(); @@ -1435,4 +1468,3 @@ pub enum CompositingReason { /// The window has been zoomed. Zoom, } - diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index acafbbc8f9b..8c68009b678 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -26,6 +26,7 @@ use profile_traits::time; use std::sync::mpsc::{channel, Sender, Receiver}; use std::fmt::{Error, Formatter, Debug}; use std::rc::Rc; +use style::viewport::ViewportConstraints; use url::Url; use util::cursor::Cursor; @@ -219,6 +220,8 @@ pub enum Msg { SetCursor(Cursor), /// Informs the compositor that the paint task for the given pipeline has exited. PaintTaskExited(PipelineId), + /// Alerts the compositor that the viewport has been constrained in some manner + ViewportConstrained(PipelineId, ViewportConstraints), } impl Debug for Msg { @@ -245,6 +248,7 @@ impl Debug for Msg { Msg::KeyEvent(..) => write!(f, "KeyEvent"), Msg::SetCursor(..) => write!(f, "SetCursor"), Msg::PaintTaskExited(..) => write!(f, "PaintTaskExited"), + Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"), } } } @@ -303,4 +307,3 @@ pub trait CompositorEventListener { /// Requests that the compositor send the title for the main frame as soon as possible. fn get_title_for_main_frame(&self); } - diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index a9271bc0cfd..9b98eb47af9 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -33,6 +33,7 @@ use std::io::{self, Write}; use std::marker::PhantomData; use std::mem::replace; use std::sync::mpsc::{Sender, Receiver, channel}; +use style::viewport::ViewportConstraints; use url::Url; use util::cursor::Cursor; use util::geometry::PagePx; @@ -417,6 +418,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { self.handle_webdriver_command_msg(pipeline_id, command); } + ConstellationMsg::ViewportConstrained(pipeline_id, constraints) => { + debug!("constellation got viewport-constrained event message"); + self.handle_viewport_constrained_msg(pipeline_id, constraints); + } } true } @@ -912,6 +917,11 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { self.window_size = new_size; } + /// Handle updating actual viewport / zoom due to @viewport rules + fn handle_viewport_constrained_msg(&mut self, pipeline_id: PipelineId, constraints: ViewportConstraints) { + self.compositor_proxy.send(CompositorMsg::ViewportConstrained(pipeline_id, constraints)); + } + // Close a frame (and all children) fn close_frame(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) { let frame = self.frames.remove(&frame_id).unwrap(); diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index e0c5c1fad1c..e61b8290aec 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -107,8 +107,9 @@ impl CompositorEventListener for NullCompositor { Msg::ChangePageTitle(..) | Msg::ChangePageUrl(..) | Msg::KeyEvent(..) | - Msg::SetCursor(..) => {} - Msg::PaintTaskExited(..) => {} + Msg::SetCursor(..) | + Msg::PaintTaskExited(..) | + Msg::ViewportConstrained(..) => {} } true } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index 2b3a4172403..de013523827 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -19,8 +19,10 @@ extern crate png; extern crate script_traits; extern crate msg; extern crate net; +extern crate num; extern crate profile_traits; extern crate net_traits; +extern crate style; #[macro_use] extern crate util; extern crate gleam; diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index b98c7f99957..324c765280e 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -847,19 +847,32 @@ impl LayoutTask { let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - // TODO: Calculate the "actual viewport": - // http://www.w3.org/TR/css-device-adapt/#actual-viewport - let viewport_size = data.window_size.initial_viewport; + let initial_viewport = data.window_size.initial_viewport; let old_screen_size = rw_data.screen_size; - let current_screen_size = Size2D(Au::from_f32_px(viewport_size.width.get()), - Au::from_f32_px(viewport_size.height.get())); + let current_screen_size = Size2D(Au::from_f32_px(initial_viewport.width.get()), + Au::from_f32_px(initial_viewport.height.get())); rw_data.screen_size = current_screen_size; // Handle conditions where the entire flow tree is invalid. let screen_size_changed = current_screen_size != old_screen_size; if screen_size_changed { - let device = Device::new(MediaType::Screen, data.window_size.initial_viewport); + // Calculate the actual viewport as per DEVICE-ADAPT § 6 + let device = Device::new(MediaType::Screen, initial_viewport); rw_data.stylist.set_device(device); + + if let Some(constraints) = rw_data.stylist.constrain_viewport() { + debug!("Viewport constraints: {:?}", constraints); + + // other rules are evaluated against the actual viewport + rw_data.screen_size = Size2D(Au::from_f32_px(constraints.size.width.get()), + Au::from_f32_px(constraints.size.height.get())); + let device = Device::new(MediaType::Screen, constraints.size); + rw_data.stylist.set_device(device); + + // let the constellation know about the viewport constraints + let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; + constellation_chan.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); + } } // If the entire flow tree is invalid, then it will be reflowed anyhow. diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 40ddb0161dd..d6a543f9b1c 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -14,6 +14,7 @@ use layers::geometry::DevicePixel; use util::cursor::Cursor; use util::geometry::{PagePx, ViewportPx}; use std::sync::mpsc::{channel, Sender, Receiver}; +use style::viewport::ViewportConstraints; use webdriver_traits::WebDriverScriptCommand; use url::Url; @@ -233,7 +234,9 @@ pub enum Msg { /// Requests that the constellation retrieve the current contents of the clipboard GetClipboardContents(Sender<String>), // Dispatch a webdriver command - WebDriverCommand(PipelineId, WebDriverScriptCommand) + WebDriverCommand(PipelineId, WebDriverScriptCommand), + /// Notifies the constellation that the viewport has been constrained in some manner + ViewportConstrained(PipelineId, ViewportConstraints), } // https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events diff --git a/components/msg/lib.rs b/components/msg/lib.rs index fc125583e95..558ccf55a96 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -9,6 +9,7 @@ extern crate hyper; extern crate layers; extern crate util; extern crate url; +extern crate style; extern crate webdriver_traits; #[cfg(target_os="macos")] diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index ac3a7c801c2..373b1c8eeb5 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -122,9 +122,11 @@ dependencies = [ "msg 0.0.1", "net 0.0.1", "net_traits 0.0.1", + "num 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "png 0.1.0 (git+https://github.com/servo/rust-png)", "profile_traits 0.0.1", "script_traits 0.0.1", + "style 0.0.1", "time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -1119,6 +1121,7 @@ dependencies = [ "lazy_static 0.1.10 (git+https://github.com/Kimundi/lazy-static.rs)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mod_path 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.1.0 (git+https://github.com/servo/rust-selectors)", diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 211ae3dbe56..a9c0839f5e8 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -17,6 +17,7 @@ use media_queries::Device; use node::TElementAttributes; use properties::{PropertyDeclaration, PropertyDeclarationBlock}; use stylesheets::{Stylesheet, CSSRuleIteratorExt, Origin}; +use viewport::{ViewportConstraints, ViewportRuleCascade}; pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>; @@ -69,6 +70,14 @@ impl Stylist { stylist } + pub fn constrain_viewport(&self) -> Option<ViewportConstraints> { + let cascaded_rule = self.stylesheets.iter() + .flat_map(|s| s.effective_rules(&self.device).viewport()) + .cascade(); + + ViewportConstraints::maybe_new(self.device.viewport_size, &cascaded_rule) + } + pub fn update(&mut self) -> bool { if self.is_dirty { self.element_map = PerPseudoElementSelectorMap::new(); |