aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/compositing/Cargo.toml4
-rw-r--r--components/compositing/compositor.rs38
-rw-r--r--components/compositing/compositor_task.rs5
-rw-r--r--components/compositing/constellation.rs10
-rw-r--r--components/compositing/headless.rs5
-rw-r--r--components/compositing/lib.rs2
-rw-r--r--components/layout/layout_task.rs25
-rw-r--r--components/msg/constellation_msg.rs5
-rw-r--r--components/msg/lib.rs1
-rw-r--r--components/servo/Cargo.lock3
-rw-r--r--components/style/selector_matching.rs9
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();