Constrain the viewport & zoom when reflowing

This commit is contained in:
James Gilbertson 2015-03-24 23:46:47 -06:00
parent 8977316d3e
commit 138596e861
13 changed files with 100 additions and 13 deletions

View file

@ -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 = "*"

View file

@ -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,
}

View file

@ -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);
}

View file

@ -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();

View file

@ -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
}

View file

@ -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;