mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Merge pull request #2666 from mbrubeck/pinch
Separate "desktop" and "mobile" zoom calculations.
This commit is contained in:
commit
6c150724f4
13 changed files with 149 additions and 66 deletions
|
@ -12,6 +12,7 @@ use windowing::{MouseWindowEvent, MouseWindowEventClass, MouseWindowMouseDownEve
|
||||||
use windowing::{MouseWindowMouseUpEvent, MouseWindowMoveEventClass, NavigationWindowEvent};
|
use windowing::{MouseWindowMouseUpEvent, MouseWindowMoveEventClass, NavigationWindowEvent};
|
||||||
use windowing::{QuitWindowEvent, RefreshWindowEvent, ResizeWindowEvent, ScrollWindowEvent};
|
use windowing::{QuitWindowEvent, RefreshWindowEvent, ResizeWindowEvent, ScrollWindowEvent};
|
||||||
use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
|
use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
|
||||||
|
use windowing::PinchZoomWindowEvent;
|
||||||
|
|
||||||
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
||||||
use azure::azure_hl;
|
use azure::azure_hl;
|
||||||
|
@ -30,9 +31,9 @@ use png;
|
||||||
use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdleRenderState, LayerBufferSet};
|
use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdleRenderState, LayerBufferSet};
|
||||||
use servo_msg::compositor_msg::{LayerId, ReadyState, RenderState, ScrollPolicy, Scrollable};
|
use servo_msg::compositor_msg::{LayerId, ReadyState, RenderState, ScrollPolicy, Scrollable};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg, NavigateMsg};
|
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg, NavigateMsg};
|
||||||
use servo_msg::constellation_msg::{PipelineId, ResizedWindowMsg};
|
use servo_msg::constellation_msg::{PipelineId, ResizedWindowMsg, WindowSizeData};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
use servo_util::geometry::{DevicePixel, PagePx, ScreenPx};
|
use servo_util::geometry::{DevicePixel, PagePx, ScreenPx, ViewportPx};
|
||||||
use servo_util::opts::Opts;
|
use servo_util::opts::Opts;
|
||||||
use servo_util::time::{profile, ProfilerChan};
|
use servo_util::time::{profile, ProfilerChan};
|
||||||
use servo_util::{time, url};
|
use servo_util::{time, url};
|
||||||
|
@ -64,6 +65,13 @@ pub struct IOCompositor {
|
||||||
/// The application window size.
|
/// The application window size.
|
||||||
window_size: TypedSize2D<DevicePixel, uint>,
|
window_size: TypedSize2D<DevicePixel, uint>,
|
||||||
|
|
||||||
|
/// "Mobile-style" zoom that does not reflow the page.
|
||||||
|
viewport_zoom: 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>,
|
||||||
|
|
||||||
/// The device pixel ratio for this window.
|
/// The device pixel ratio for this window.
|
||||||
hidpi_factor: ScaleFactor<ScreenPx, DevicePixel, f32>,
|
hidpi_factor: ScaleFactor<ScreenPx, DevicePixel, f32>,
|
||||||
|
|
||||||
|
@ -82,9 +90,6 @@ pub struct IOCompositor {
|
||||||
/// Tracks whether we need to re-composite a page.
|
/// Tracks whether we need to re-composite a page.
|
||||||
recomposite: bool,
|
recomposite: bool,
|
||||||
|
|
||||||
/// Keeps track of the current zoom factor.
|
|
||||||
world_zoom: ScaleFactor<PagePx, ScreenPx, f32>,
|
|
||||||
|
|
||||||
/// Tracks whether the zoom action has happend recently.
|
/// Tracks whether the zoom action has happend recently.
|
||||||
zoom_action: bool,
|
zoom_action: bool,
|
||||||
|
|
||||||
|
@ -146,7 +151,8 @@ impl IOCompositor {
|
||||||
shutting_down: false,
|
shutting_down: false,
|
||||||
done: false,
|
done: false,
|
||||||
recomposite: false,
|
recomposite: false,
|
||||||
world_zoom: ScaleFactor(1.0),
|
page_zoom: ScaleFactor(1.0),
|
||||||
|
viewport_zoom: ScaleFactor(1.0),
|
||||||
zoom_action: false,
|
zoom_action: false,
|
||||||
zoom_time: 0f64,
|
zoom_time: 0f64,
|
||||||
ready_state: Blank,
|
ready_state: Blank,
|
||||||
|
@ -417,10 +423,17 @@ impl IOCompositor {
|
||||||
self.window_size.as_f32() / self.device_pixels_per_page_px()
|
self.window_size.as_f32() / self.device_pixels_per_page_px()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The size of the window in screen px.
|
|
||||||
fn send_window_size(&self) {
|
fn send_window_size(&self) {
|
||||||
|
let dppx = self.page_zoom * self.device_pixels_per_screen_px();
|
||||||
|
let initial_viewport = self.window_size.as_f32() / dppx;
|
||||||
|
let visible_viewport = initial_viewport / self.viewport_zoom;
|
||||||
|
|
||||||
let ConstellationChan(ref chan) = self.constellation_chan;
|
let ConstellationChan(ref chan) = self.constellation_chan;
|
||||||
chan.send(ResizedWindowMsg(self.page_window()));
|
chan.send(ResizedWindowMsg(WindowSizeData {
|
||||||
|
device_pixel_ratio: dppx,
|
||||||
|
initial_viewport: initial_viewport,
|
||||||
|
visible_viewport: visible_viewport,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_layer_page_size(&mut self,
|
fn set_layer_page_size(&mut self,
|
||||||
|
@ -549,6 +562,10 @@ impl IOCompositor {
|
||||||
self.on_zoom_window_event(magnification);
|
self.on_zoom_window_event(magnification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PinchZoomWindowEvent(magnification) => {
|
||||||
|
self.on_pinch_zoom_window_event(magnification);
|
||||||
|
}
|
||||||
|
|
||||||
NavigationWindowEvent(direction) => {
|
NavigationWindowEvent(direction) => {
|
||||||
self.on_navigation_window_event(direction);
|
self.on_navigation_window_event(direction);
|
||||||
}
|
}
|
||||||
|
@ -647,7 +664,7 @@ impl IOCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_pixels_per_page_px(&self) -> ScaleFactor<PagePx, DevicePixel, f32> {
|
fn device_pixels_per_page_px(&self) -> ScaleFactor<PagePx, DevicePixel, f32> {
|
||||||
self.world_zoom * self.device_pixels_per_screen_px()
|
self.viewport_zoom * self.page_zoom * self.device_pixels_per_screen_px()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_zoom_transform(&mut self) {
|
fn update_zoom_transform(&mut self) {
|
||||||
|
@ -656,21 +673,26 @@ impl IOCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_zoom_window_event(&mut self, magnification: f32) {
|
fn on_zoom_window_event(&mut self, magnification: f32) {
|
||||||
|
self.page_zoom = ScaleFactor((self.page_zoom.get() * magnification).max(1.0));
|
||||||
|
self.update_zoom_transform();
|
||||||
|
self.send_window_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
|
||||||
self.zoom_action = true;
|
self.zoom_action = true;
|
||||||
self.zoom_time = precise_time_s();
|
self.zoom_time = precise_time_s();
|
||||||
let old_world_zoom = self.world_zoom;
|
let old_viewport_zoom = self.viewport_zoom;
|
||||||
let window_size = self.window_size.as_f32();
|
let window_size = self.window_size.as_f32();
|
||||||
|
|
||||||
// Determine zoom amount
|
self.viewport_zoom = ScaleFactor((self.viewport_zoom.get() * magnification).max(1.0));
|
||||||
self.world_zoom = ScaleFactor((self.world_zoom.get() * magnification).max(1.0));
|
let viewport_zoom = self.viewport_zoom;
|
||||||
let world_zoom = self.world_zoom;
|
|
||||||
|
|
||||||
self.update_zoom_transform();
|
self.update_zoom_transform();
|
||||||
|
|
||||||
// Scroll as needed
|
// Scroll as needed
|
||||||
let page_delta = TypedPoint2D(
|
let page_delta = TypedPoint2D(
|
||||||
window_size.width.get() * (world_zoom.inv() - old_world_zoom.inv()).get() * 0.5,
|
window_size.width.get() * (viewport_zoom.inv() - old_viewport_zoom.inv()).get() * 0.5,
|
||||||
window_size.height.get() * (world_zoom.inv() - old_world_zoom.inv()).get() * 0.5);
|
window_size.height.get() * (viewport_zoom.inv() - old_viewport_zoom.inv()).get() * 0.5);
|
||||||
// TODO: modify delta to snap scroll to pixels.
|
// TODO: modify delta to snap scroll to pixels.
|
||||||
let page_cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer
|
let page_cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer
|
||||||
let page_window = self.page_window();
|
let page_window = self.page_window();
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
use compositing::*;
|
use compositing::*;
|
||||||
|
|
||||||
|
use geom::scale_factor::ScaleFactor;
|
||||||
use geom::size::TypedSize2D;
|
use geom::size::TypedSize2D;
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, ResizedWindowMsg};
|
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, ResizedWindowMsg, WindowSizeData};
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
|
|
||||||
|
@ -33,7 +34,11 @@ impl NullCompositor {
|
||||||
// Tell the constellation about the initial fake size.
|
// Tell the constellation about the initial fake size.
|
||||||
{
|
{
|
||||||
let ConstellationChan(ref chan) = constellation_chan;
|
let ConstellationChan(ref chan) = constellation_chan;
|
||||||
chan.send(ResizedWindowMsg(TypedSize2D(640_f32, 480_f32)));
|
chan.send(ResizedWindowMsg(WindowSizeData {
|
||||||
|
initial_viewport: TypedSize2D(640_f32, 480_f32),
|
||||||
|
visible_viewport: TypedSize2D(640_f32, 480_f32),
|
||||||
|
device_pixel_ratio: ScaleFactor(1.0),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
compositor.handle_message(constellation_chan);
|
compositor.handle_message(constellation_chan);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ use compositing::{CompositorChan, LoadComplete, SetIds, SetLayerClipRect, Shutdo
|
||||||
|
|
||||||
use collections::hashmap::{HashMap, HashSet};
|
use collections::hashmap::{HashMap, HashSet};
|
||||||
use geom::rect::{Rect, TypedRect};
|
use geom::rect::{Rect, TypedRect};
|
||||||
|
use geom::scale_factor::ScaleFactor;
|
||||||
use geom::size::TypedSize2D;
|
use geom::size::TypedSize2D;
|
||||||
use gfx::render_task;
|
use gfx::render_task;
|
||||||
use libc;
|
use libc;
|
||||||
|
@ -19,7 +20,7 @@ use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, Failu
|
||||||
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
||||||
use servo_msg::constellation_msg::{LoadCompleteMsg, LoadIframeUrlMsg, LoadUrlMsg, Msg, NavigateMsg};
|
use servo_msg::constellation_msg::{LoadCompleteMsg, LoadIframeUrlMsg, LoadUrlMsg, Msg, NavigateMsg};
|
||||||
use servo_msg::constellation_msg::{NavigationType, PipelineId, RendererReadyMsg, ResizedWindowMsg};
|
use servo_msg::constellation_msg::{NavigationType, PipelineId, RendererReadyMsg, ResizedWindowMsg};
|
||||||
use servo_msg::constellation_msg::SubpageId;
|
use servo_msg::constellation_msg::{SubpageId, WindowSizeData};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
|
@ -48,7 +49,7 @@ pub struct Constellation {
|
||||||
pending_frames: Vec<FrameChange>,
|
pending_frames: Vec<FrameChange>,
|
||||||
pending_sizes: HashMap<(PipelineId, SubpageId), TypedRect<PagePx, f32>>,
|
pending_sizes: HashMap<(PipelineId, SubpageId), TypedRect<PagePx, f32>>,
|
||||||
pub profiler_chan: ProfilerChan,
|
pub profiler_chan: ProfilerChan,
|
||||||
pub window_size: TypedSize2D<PagePx, f32>,
|
pub window_size: WindowSizeData,
|
||||||
pub opts: Opts,
|
pub opts: Opts,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +262,11 @@ impl Constellation {
|
||||||
pending_frames: vec!(),
|
pending_frames: vec!(),
|
||||||
pending_sizes: HashMap::new(),
|
pending_sizes: HashMap::new(),
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
window_size: TypedSize2D(800_f32, 600_f32),
|
window_size: WindowSizeData {
|
||||||
|
visible_viewport: TypedSize2D(800_f32, 600_f32),
|
||||||
|
initial_viewport: TypedSize2D(800_f32, 600_f32),
|
||||||
|
device_pixel_ratio: ScaleFactor(1.0),
|
||||||
|
},
|
||||||
opts: opts_clone,
|
opts: opts_clone,
|
||||||
};
|
};
|
||||||
constellation.run();
|
constellation.run();
|
||||||
|
@ -491,7 +496,11 @@ impl Constellation {
|
||||||
if !already_sent.contains(&pipeline.id) {
|
if !already_sent.contains(&pipeline.id) {
|
||||||
if is_active {
|
if is_active {
|
||||||
let ScriptChan(ref script_chan) = pipeline.script_chan;
|
let ScriptChan(ref script_chan) = pipeline.script_chan;
|
||||||
script_chan.send(ResizeMsg(pipeline.id, rect.size));
|
script_chan.send(ResizeMsg(pipeline.id, WindowSizeData {
|
||||||
|
visible_viewport: rect.size,
|
||||||
|
initial_viewport: rect.size * ScaleFactor(1.0),
|
||||||
|
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
||||||
|
}));
|
||||||
self.compositor_chan.send(SetLayerClipRect(pipeline.id,
|
self.compositor_chan.send(SetLayerClipRect(pipeline.id,
|
||||||
LayerId::null(),
|
LayerId::null(),
|
||||||
rect.to_untyped()));
|
rect.to_untyped()));
|
||||||
|
@ -788,7 +797,7 @@ impl Constellation {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the window is resized.
|
/// Called when the window is resized.
|
||||||
fn handle_resized_window_msg(&mut self, new_size: TypedSize2D<PagePx, f32>) {
|
fn handle_resized_window_msg(&mut self, new_size: WindowSizeData) {
|
||||||
let mut already_seen = HashSet::new();
|
let mut already_seen = HashSet::new();
|
||||||
for frame_tree in self.current_frame().iter() {
|
for frame_tree in self.current_frame().iter() {
|
||||||
debug!("constellation sending resize message to active frame");
|
debug!("constellation sending resize message to active frame");
|
||||||
|
|
|
@ -581,8 +581,12 @@ impl LayoutTask {
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
|
|
||||||
let current_screen_size = Size2D(Au::from_page_px(data.window_size.width),
|
// TODO: Calculate the "actual viewport":
|
||||||
Au::from_page_px(data.window_size.height));
|
// http://www.w3.org/TR/css-device-adapt/#actual-viewport
|
||||||
|
let viewport_size = data.window_size.initial_viewport;
|
||||||
|
|
||||||
|
let current_screen_size = Size2D(Au::from_frac32_px(viewport_size.width.get()),
|
||||||
|
Au::from_frac32_px(viewport_size.height.get()));
|
||||||
if self.screen_size != current_screen_size {
|
if self.screen_size != current_screen_size {
|
||||||
all_style_damage = true
|
all_style_damage = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
use compositing::CompositorChan;
|
use compositing::CompositorChan;
|
||||||
use layout::layout_task::LayoutTask;
|
use layout::layout_task::LayoutTask;
|
||||||
|
|
||||||
use geom::size::TypedSize2D;
|
|
||||||
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
|
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
|
||||||
use gfx::render_task::{RenderChan, RenderTask};
|
use gfx::render_task::{RenderChan, RenderTask};
|
||||||
use script::layout_interface::LayoutChan;
|
use script::layout_interface::LayoutChan;
|
||||||
|
@ -13,9 +12,9 @@ use script::script_task::LoadMsg;
|
||||||
use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan};
|
use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan};
|
||||||
use script::script_task;
|
use script::script_task;
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, SubpageId};
|
||||||
|
use servo_msg::constellation_msg::WindowSizeData;
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::geometry::PagePx;
|
|
||||||
use servo_util::opts::Opts;
|
use servo_util::opts::Opts;
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -113,7 +112,7 @@ impl Pipeline {
|
||||||
image_cache_task: ImageCacheTask,
|
image_cache_task: ImageCacheTask,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
window_size: TypedSize2D<PagePx, f32>,
|
window_size: WindowSizeData,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
url: Url)
|
url: Url)
|
||||||
-> Pipeline {
|
-> Pipeline {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
||||||
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass, MouseWindowMoveEventClass};
|
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass, MouseWindowMoveEventClass};
|
||||||
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
use windowing::{ScrollWindowEvent, ZoomWindowEvent, PinchZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
||||||
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
||||||
use windowing::RefreshWindowEvent;
|
use windowing::RefreshWindowEvent;
|
||||||
use windowing::{Forward, Back};
|
use windowing::{Forward, Back};
|
||||||
|
@ -240,19 +240,33 @@ impl Window {
|
||||||
MouseWindowMoveEventClass(TypedPoint2D(xpos as f32, ypos as f32)));
|
MouseWindowMoveEventClass(TypedPoint2D(xpos as f32, ypos as f32)));
|
||||||
},
|
},
|
||||||
glfw::ScrollEvent(xpos, ypos) => {
|
glfw::ScrollEvent(xpos, ypos) => {
|
||||||
let dx = (xpos as f32) * 30.0;
|
match (window.get_key(glfw::KeyLeftControl),
|
||||||
let dy = (ypos as f32) * 30.0;
|
window.get_key(glfw::KeyRightControl)) {
|
||||||
|
(glfw::Press, _) | (_, glfw::Press) => {
|
||||||
|
// Ctrl-Scrollwheel simulates a "pinch zoom" gesture.
|
||||||
|
if ypos < 0.0 {
|
||||||
|
self.event_queue.borrow_mut().push(PinchZoomWindowEvent(1.0/1.1));
|
||||||
|
} else if ypos > 0.0 {
|
||||||
|
self.event_queue.borrow_mut().push(PinchZoomWindowEvent(1.1));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
let dx = (xpos as f32) * 30.0;
|
||||||
|
let dy = (ypos as f32) * 30.0;
|
||||||
|
|
||||||
let (x, y) = window.get_cursor_pos();
|
let (x, y) = window.get_cursor_pos();
|
||||||
//handle hidpi displays, since GLFW returns non-hi-def coordinates.
|
//handle hidpi displays, since GLFW returns non-hi-def coordinates.
|
||||||
let (backing_size, _) = window.get_framebuffer_size();
|
let (backing_size, _) = window.get_framebuffer_size();
|
||||||
let (window_size, _) = window.get_size();
|
let (window_size, _) = window.get_size();
|
||||||
let hidpi = (backing_size as f32) / (window_size as f32);
|
let hidpi = (backing_size as f32) / (window_size as f32);
|
||||||
let x = x as f32 * hidpi;
|
let x = x as f32 * hidpi;
|
||||||
let y = y as f32 * hidpi;
|
let y = y as f32 * hidpi;
|
||||||
|
|
||||||
|
self.event_queue.borrow_mut().push(ScrollWindowEvent(TypedPoint2D(dx, dy),
|
||||||
|
TypedPoint2D(x as i32, y as i32)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.event_queue.borrow_mut().push(ScrollWindowEvent(TypedPoint2D(dx, dy),
|
|
||||||
TypedPoint2D(x as i32, y as i32)));
|
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +312,7 @@ impl Window {
|
||||||
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1));
|
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1));
|
||||||
}
|
}
|
||||||
glfw::KeyMinus if mods.contains(glfw::Control) => { // Ctrl--
|
glfw::KeyMinus if mods.contains(glfw::Control) => { // Ctrl--
|
||||||
self.event_queue.borrow_mut().push(ZoomWindowEvent(0.90909090909));
|
self.event_queue.borrow_mut().push(ZoomWindowEvent(1.0/1.1));
|
||||||
}
|
}
|
||||||
glfw::KeyBackspace if mods.contains(glfw::Shift) => { // Shift-Backspace
|
glfw::KeyBackspace if mods.contains(glfw::Shift) => { // Shift-Backspace
|
||||||
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
|
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
|
||||||
|
|
|
@ -43,6 +43,8 @@ pub enum WindowEvent {
|
||||||
ScrollWindowEvent(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>),
|
ScrollWindowEvent(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>),
|
||||||
/// Sent when the user zooms.
|
/// Sent when the user zooms.
|
||||||
ZoomWindowEvent(f32),
|
ZoomWindowEvent(f32),
|
||||||
|
/// Simulated "pinch zoom" gesture for non-touch platforms (e.g. ctrl-scrollwheel).
|
||||||
|
PinchZoomWindowEvent(f32),
|
||||||
/// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace).
|
/// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace).
|
||||||
NavigationWindowEvent(WindowNavigateMsg),
|
NavigationWindowEvent(WindowNavigateMsg),
|
||||||
/// Sent when rendering is finished.
|
/// Sent when rendering is finished.
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::TypedSize2D;
|
use geom::size::TypedSize2D;
|
||||||
use servo_util::geometry::PagePx;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
use servo_util::geometry::{DevicePixel, PagePx, ViewportPx};
|
||||||
use std::comm::{channel, Sender, Receiver};
|
use std::comm::{channel, Sender, Receiver};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -34,6 +35,18 @@ pub struct Failure {
|
||||||
pub subpage_id: Option<SubpageId>,
|
pub subpage_id: Option<SubpageId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WindowSizeData {
|
||||||
|
/// The size of the initial layout viewport, before parsing an
|
||||||
|
/// http://www.w3.org/TR/css-device-adapt/#initial-viewport
|
||||||
|
pub initial_viewport: TypedSize2D<ViewportPx, f32>,
|
||||||
|
|
||||||
|
/// The "viewing area" in page px. See `PagePx` documentation for details.
|
||||||
|
pub visible_viewport: TypedSize2D<PagePx, f32>,
|
||||||
|
|
||||||
|
/// The resolution of the window in dppx, not including any "pinch zoom" factor.
|
||||||
|
pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Messages from the compositor and script to the constellation.
|
/// Messages from the compositor and script to the constellation.
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
ExitMsg,
|
ExitMsg,
|
||||||
|
@ -45,7 +58,7 @@ pub enum Msg {
|
||||||
LoadIframeUrlMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
|
LoadIframeUrlMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
|
||||||
NavigateMsg(NavigationDirection),
|
NavigateMsg(NavigationDirection),
|
||||||
RendererReadyMsg(PipelineId),
|
RendererReadyMsg(PipelineId),
|
||||||
ResizedWindowMsg(TypedSize2D<PagePx, f32>),
|
ResizedWindowMsg(WindowSizeData),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the two different ways to which a page can be navigated
|
/// Represents the two different ways to which a page can be navigated
|
||||||
|
|
|
@ -10,17 +10,16 @@ use dom::bindings::trace::Traceable;
|
||||||
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
|
use servo_msg::constellation_msg::WindowSizeData;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
use servo_util::geometry::PagePx;
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::TypedSize2D;
|
|
||||||
|
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
pub enum Event_ {
|
pub enum Event_ {
|
||||||
ResizeEvent(TypedSize2D<PagePx, f32>),
|
ResizeEvent(WindowSizeData),
|
||||||
ReflowEvent,
|
ReflowEvent,
|
||||||
ClickEvent(uint, Point2D<f32>),
|
ClickEvent(uint, Point2D<f32>),
|
||||||
MouseDownEvent(uint, Point2D<f32>),
|
MouseDownEvent(uint, Point2D<f32>),
|
||||||
|
|
|
@ -11,10 +11,10 @@ use dom::node::{Node, LayoutDataRef};
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::TypedSize2D;
|
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use script_task::{ScriptChan};
|
use script_task::{ScriptChan};
|
||||||
use servo_util::geometry::{Au, PagePx};
|
use servo_msg::constellation_msg::WindowSizeData;
|
||||||
|
use servo_util::geometry::Au;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::comm::{channel, Receiver, Sender};
|
use std::comm::{channel, Receiver, Sender};
|
||||||
use style::Stylesheet;
|
use style::Stylesheet;
|
||||||
|
@ -137,7 +137,7 @@ pub struct Reflow {
|
||||||
/// The channel through which messages can be sent back to the script task.
|
/// The channel through which messages can be sent back to the script task.
|
||||||
pub script_chan: ScriptChan,
|
pub script_chan: ScriptChan,
|
||||||
/// The current window size.
|
/// The current window size.
|
||||||
pub window_size: TypedSize2D<PagePx, f32>,
|
pub window_size: WindowSizeData,
|
||||||
/// The channel that we send a notification to.
|
/// The channel that we send a notification to.
|
||||||
pub script_join_chan: Sender<()>,
|
pub script_join_chan: Sender<()>,
|
||||||
/// Unique identifier
|
/// Unique identifier
|
||||||
|
|
|
@ -19,14 +19,12 @@ use layout_interface::UntrustedNodeAddress;
|
||||||
use script_task::ScriptChan;
|
use script_task::ScriptChan;
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::TypedSize2D;
|
|
||||||
use js::rust::Cx;
|
use js::rust::Cx;
|
||||||
use servo_msg::compositor_msg::PerformingLayout;
|
use servo_msg::compositor_msg::PerformingLayout;
|
||||||
use servo_msg::compositor_msg::ScriptListener;
|
use servo_msg::compositor_msg::ScriptListener;
|
||||||
use servo_msg::constellation_msg::ConstellationChan;
|
use servo_msg::constellation_msg::{ConstellationChan, WindowSizeData};
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::geometry::PagePx;
|
|
||||||
use servo_util::namespace::Null;
|
use servo_util::namespace::Null;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
use std::cell::{Cell, RefCell, Ref, RefMut};
|
use std::cell::{Cell, RefCell, Ref, RefMut};
|
||||||
|
@ -62,7 +60,7 @@ pub struct Page {
|
||||||
damage: Traceable<RefCell<Option<DocumentDamage>>>,
|
damage: Traceable<RefCell<Option<DocumentDamage>>>,
|
||||||
|
|
||||||
/// The current size of the window, in pixels.
|
/// The current size of the window, in pixels.
|
||||||
pub window_size: Untraceable<Cell<TypedSize2D<PagePx, f32>>>,
|
pub window_size: Untraceable<Cell<WindowSizeData>>,
|
||||||
|
|
||||||
js_info: Traceable<RefCell<Option<JSPageInfo>>>,
|
js_info: Traceable<RefCell<Option<JSPageInfo>>>,
|
||||||
|
|
||||||
|
@ -75,7 +73,7 @@ pub struct Page {
|
||||||
next_subpage_id: Untraceable<Cell<SubpageId>>,
|
next_subpage_id: Untraceable<Cell<SubpageId>>,
|
||||||
|
|
||||||
/// Pending resize event, if any.
|
/// Pending resize event, if any.
|
||||||
pub resize_event: Untraceable<Cell<Option<TypedSize2D<PagePx, f32>>>>,
|
pub resize_event: Untraceable<Cell<Option<WindowSizeData>>>,
|
||||||
|
|
||||||
/// Pending scroll to fragment event, if any
|
/// Pending scroll to fragment event, if any
|
||||||
pub fragment_node: Cell<Option<JS<Element>>>,
|
pub fragment_node: Cell<Option<JS<Element>>>,
|
||||||
|
@ -119,7 +117,8 @@ impl IterablePage for Rc<Page> {
|
||||||
impl Page {
|
impl Page {
|
||||||
pub fn new(id: PipelineId, subpage_id: Option<SubpageId>,
|
pub fn new(id: PipelineId, subpage_id: Option<SubpageId>,
|
||||||
layout_chan: LayoutChan,
|
layout_chan: LayoutChan,
|
||||||
window_size: TypedSize2D<PagePx, f32>, resource_task: ResourceTask,
|
window_size: WindowSizeData,
|
||||||
|
resource_task: ResourceTask,
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
js_context: Rc<Cx>) -> Page {
|
js_context: Rc<Cx>) -> Page {
|
||||||
let js_info = JSPageInfo {
|
let js_info = JSPageInfo {
|
||||||
|
|
|
@ -32,7 +32,6 @@ use layout_interface;
|
||||||
use page::{Page, IterablePage, Frame};
|
use page::{Page, IterablePage, Frame};
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::TypedSize2D;
|
|
||||||
use js::jsapi::JS_CallFunctionValue;
|
use js::jsapi::JS_CallFunctionValue;
|
||||||
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
|
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
|
||||||
use js::jsapi::{JSContext, JSRuntime};
|
use js::jsapi::{JSContext, JSRuntime};
|
||||||
|
@ -43,11 +42,11 @@ use js;
|
||||||
use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading};
|
use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading};
|
||||||
use servo_msg::compositor_msg::{ScriptListener};
|
use servo_msg::compositor_msg::{ScriptListener};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg, LoadUrlMsg, NavigationDirection};
|
use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg, LoadUrlMsg, NavigationDirection};
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId, Failure, FailureMsg};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId, Failure, FailureMsg, WindowSizeData};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::geometry::{PagePx, to_frac_px};
|
use servo_util::geometry::to_frac_px;
|
||||||
use servo_util::task::send_on_failure;
|
use servo_util::task::send_on_failure;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::comm::{channel, Sender, Receiver};
|
use std::comm::{channel, Sender, Receiver};
|
||||||
|
@ -76,13 +75,13 @@ pub enum ScriptMsg {
|
||||||
/// Sends a DOM event.
|
/// Sends a DOM event.
|
||||||
SendEventMsg(PipelineId, Event_),
|
SendEventMsg(PipelineId, Event_),
|
||||||
/// Window resized. Sends a DOM event eventually, but first we combine events.
|
/// Window resized. Sends a DOM event eventually, but first we combine events.
|
||||||
ResizeMsg(PipelineId, TypedSize2D<PagePx, f32>),
|
ResizeMsg(PipelineId, WindowSizeData),
|
||||||
/// Fires a JavaScript timeout.
|
/// Fires a JavaScript timeout.
|
||||||
FireTimerMsg(PipelineId, TimerId),
|
FireTimerMsg(PipelineId, TimerId),
|
||||||
/// Notifies script that reflow is finished.
|
/// Notifies script that reflow is finished.
|
||||||
ReflowCompleteMsg(PipelineId, uint),
|
ReflowCompleteMsg(PipelineId, uint),
|
||||||
/// Notifies script that window has been resized but to not take immediate action.
|
/// Notifies script that window has been resized but to not take immediate action.
|
||||||
ResizeInactiveMsg(PipelineId, TypedSize2D<PagePx, f32>),
|
ResizeInactiveMsg(PipelineId, WindowSizeData),
|
||||||
/// Notifies the script that a pipeline should be closed.
|
/// Notifies the script that a pipeline should be closed.
|
||||||
ExitPipelineMsg(PipelineId),
|
ExitPipelineMsg(PipelineId),
|
||||||
/// Notifies the script that a window associated with a particular pipeline should be closed.
|
/// Notifies the script that a window associated with a particular pipeline should be closed.
|
||||||
|
@ -208,7 +207,7 @@ impl ScriptTask {
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
img_cache_task: ImageCacheTask,
|
img_cache_task: ImageCacheTask,
|
||||||
window_size: TypedSize2D<PagePx, f32>)
|
window_size: WindowSizeData)
|
||||||
-> Rc<ScriptTask> {
|
-> Rc<ScriptTask> {
|
||||||
let (js_runtime, js_context) = ScriptTask::new_rt_and_cx();
|
let (js_runtime, js_context) = ScriptTask::new_rt_and_cx();
|
||||||
let page = Page::new(id, None, layout_chan, window_size,
|
let page = Page::new(id, None, layout_chan, window_size,
|
||||||
|
@ -289,7 +288,7 @@ impl ScriptTask {
|
||||||
failure_msg: Failure,
|
failure_msg: Failure,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask,
|
image_cache_task: ImageCacheTask,
|
||||||
window_size: TypedSize2D<PagePx, f32>) {
|
window_size: WindowSizeData) {
|
||||||
let mut builder = TaskBuilder::new().named("ScriptTask");
|
let mut builder = TaskBuilder::new().named("ScriptTask");
|
||||||
let ConstellationChan(const_chan) = constellation_chan.clone();
|
let ConstellationChan(const_chan) = constellation_chan.clone();
|
||||||
send_on_failure(&mut builder, FailureMsg(failure_msg), const_chan);
|
send_on_failure(&mut builder, FailureMsg(failure_msg), const_chan);
|
||||||
|
@ -463,7 +462,7 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Window was resized, but this script was not active, so don't reflow yet
|
/// Window was resized, but this script was not active, so don't reflow yet
|
||||||
fn handle_resize_inactive_msg(&self, id: PipelineId, new_size: TypedSize2D<PagePx, f32>) {
|
fn handle_resize_inactive_msg(&self, id: PipelineId, new_size: WindowSizeData) {
|
||||||
let mut page = self.page.borrow_mut();
|
let mut page = self.page.borrow_mut();
|
||||||
let page = page.find(id).expect("Received resize message for PipelineId not associated
|
let page = page.find(id).expect("Received resize message for PipelineId not associated
|
||||||
with a page in the page tree. This is a bug.");
|
with a page in the page tree. This is a bug.");
|
||||||
|
|
|
@ -33,14 +33,32 @@ pub enum DevicePixel {}
|
||||||
/// `servo::windowing::WindowMethods::hidpi_factor`.
|
/// `servo::windowing::WindowMethods::hidpi_factor`.
|
||||||
pub enum ScreenPx {}
|
pub enum ScreenPx {}
|
||||||
|
|
||||||
|
/// One CSS "px" in the coordinate system of the "initial viewport":
|
||||||
|
/// http://www.w3.org/TR/css-device-adapt/#initial-viewport
|
||||||
|
///
|
||||||
|
/// ViewportPx is equal to ScreenPx times a "page zoom" factor controlled by the user. This is
|
||||||
|
/// the desktop-style "full page" zoom that enlarges content but then reflows the layout viewport
|
||||||
|
/// so it still exactly fits the visible area.
|
||||||
|
///
|
||||||
|
/// At the default zoom level of 100%, one PagePx is equal to one ScreenPx. However, if the
|
||||||
|
/// document is zoomed in or out then this scale may be larger or smaller.
|
||||||
|
pub enum ViewportPx {}
|
||||||
|
|
||||||
/// One CSS "px" in the root coordinate system for the content document.
|
/// One CSS "px" in the root coordinate system for the content document.
|
||||||
///
|
///
|
||||||
///
|
/// PagePx is equal to ViewportPx multiplied by a "viewport zoom" factor controlled by the user.
|
||||||
/// PagePx is equal to ScreenPx multiplied by a "zoom" factor controlled by the user. At the
|
/// This is the mobile-style "pinch zoom" that enlarges content without reflowing it. When the
|
||||||
/// default zoom level of 100%, one PagePx is equal to one ScreenPx. However, if the document
|
/// viewport zoom is not equal to 1.0, then the layout viewport is no longer the same physical size
|
||||||
/// is zoomed in or out then this scale may be larger or smaller.
|
/// as the viewable area.
|
||||||
pub enum PagePx {}
|
pub enum PagePx {}
|
||||||
|
|
||||||
|
// In summary, the hierarchy of pixel units and the factors to convert from one to the next:
|
||||||
|
//
|
||||||
|
// DevicePixel
|
||||||
|
// / hidpi_ratio => ScreenPx
|
||||||
|
// / desktop_zoom => ViewportPx
|
||||||
|
// / pinch_zoom => PagePx
|
||||||
|
|
||||||
// An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was
|
// An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was
|
||||||
// originally proposed in 2002 as a standard unit of measure in Gecko.
|
// originally proposed in 2002 as a standard unit of measure in Gecko.
|
||||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue