mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
auto merge of #2603 : mbrubeck/servo/units, r=pcwalton
This is a rebased, squashed, and updated version of #2444.
This commit is contained in:
commit
6c382243c4
7 changed files with 213 additions and 132 deletions
|
@ -16,9 +16,10 @@ use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
|
||||||
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
||||||
use azure::azure_hl;
|
use azure::azure_hl;
|
||||||
use geom::matrix::identity;
|
use geom::matrix::identity;
|
||||||
use geom::point::Point2D;
|
use geom::point::{Point2D, TypedPoint2D};
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::{Size2D, TypedSize2D};
|
||||||
|
use geom::scale_factor::ScaleFactor;
|
||||||
use layers::layers::{ContainerLayer, ContainerLayerKind};
|
use layers::layers::{ContainerLayer, ContainerLayerKind};
|
||||||
use layers::platform::surface::NativeCompositingGraphicsContext;
|
use layers::platform::surface::NativeCompositingGraphicsContext;
|
||||||
use layers::rendergl;
|
use layers::rendergl;
|
||||||
|
@ -31,6 +32,7 @@ use servo_msg::compositor_msg::{LayerId, ReadyState, RenderState, ScrollPolicy,
|
||||||
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};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
|
use servo_util::geometry::{DevicePixel, PagePx, ScreenPx};
|
||||||
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};
|
||||||
|
@ -60,7 +62,10 @@ pub struct IOCompositor {
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
|
|
||||||
/// The application window size.
|
/// The application window size.
|
||||||
window_size: Size2D<uint>,
|
window_size: TypedSize2D<DevicePixel, uint>,
|
||||||
|
|
||||||
|
/// The device pixel ratio for this window.
|
||||||
|
hidpi_factor: ScaleFactor<ScreenPx, DevicePixel, f32>,
|
||||||
|
|
||||||
/// The platform-specific graphics context.
|
/// The platform-specific graphics context.
|
||||||
graphics_context: NativeCompositingGraphicsContext,
|
graphics_context: NativeCompositingGraphicsContext,
|
||||||
|
@ -78,7 +83,7 @@ pub struct IOCompositor {
|
||||||
recomposite: bool,
|
recomposite: bool,
|
||||||
|
|
||||||
/// Keeps track of the current zoom factor.
|
/// Keeps track of the current zoom factor.
|
||||||
world_zoom: f32,
|
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,
|
||||||
|
@ -124,16 +129,7 @@ impl IOCompositor {
|
||||||
// list. This is only here because we don't have that logic in the renderer yet.
|
// list. This is only here because we don't have that logic in the renderer yet.
|
||||||
let root_layer = Rc::new(ContainerLayer());
|
let root_layer = Rc::new(ContainerLayer());
|
||||||
let window_size = window.size();
|
let window_size = window.size();
|
||||||
|
let hidpi_factor = window.hidpi_factor();
|
||||||
let hidpi_factor = match opts.device_pixels_per_px {
|
|
||||||
Some(dppx) => dppx,
|
|
||||||
None => match opts.output_file {
|
|
||||||
Some(_) => 1.0,
|
|
||||||
None => window.hidpi_factor(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
root_layer.common.borrow_mut().set_transform(identity().scale(hidpi_factor, hidpi_factor, 1f32));
|
|
||||||
|
|
||||||
IOCompositor {
|
IOCompositor {
|
||||||
window: window,
|
window: window,
|
||||||
|
@ -142,14 +138,15 @@ impl IOCompositor {
|
||||||
context: rendergl::init_render_context(),
|
context: rendergl::init_render_context(),
|
||||||
root_layer: root_layer.clone(),
|
root_layer: root_layer.clone(),
|
||||||
root_pipeline: None,
|
root_pipeline: None,
|
||||||
scene: Scene(ContainerLayerKind(root_layer), window_size, identity()),
|
scene: Scene(ContainerLayerKind(root_layer), window_size.to_untyped(), identity()),
|
||||||
window_size: Size2D(window_size.width as uint, window_size.height as uint),
|
window_size: window_size.as_uint(),
|
||||||
|
hidpi_factor: hidpi_factor,
|
||||||
graphics_context: CompositorTask::create_graphics_context(),
|
graphics_context: CompositorTask::create_graphics_context(),
|
||||||
composite_ready: false,
|
composite_ready: false,
|
||||||
shutting_down: false,
|
shutting_down: false,
|
||||||
done: false,
|
done: false,
|
||||||
recomposite: false,
|
recomposite: false,
|
||||||
world_zoom: hidpi_factor,
|
world_zoom: ScaleFactor(1.0),
|
||||||
zoom_action: false,
|
zoom_action: false,
|
||||||
zoom_time: 0f64,
|
zoom_time: 0f64,
|
||||||
ready_state: Blank,
|
ready_state: Blank,
|
||||||
|
@ -171,6 +168,7 @@ impl IOCompositor {
|
||||||
port,
|
port,
|
||||||
constellation_chan,
|
constellation_chan,
|
||||||
profiler_chan);
|
profiler_chan);
|
||||||
|
compositor.update_zoom_transform();
|
||||||
|
|
||||||
// Starts the compositor, which listens for messages on the specified port.
|
// Starts the compositor, which listens for messages on the specified port.
|
||||||
compositor.run();
|
compositor.run();
|
||||||
|
@ -180,7 +178,7 @@ impl IOCompositor {
|
||||||
// Tell the constellation about the initial window size.
|
// Tell the constellation about the initial window size.
|
||||||
{
|
{
|
||||||
let ConstellationChan(ref chan) = self.constellation_chan;
|
let ConstellationChan(ref chan) = self.constellation_chan;
|
||||||
chan.send(ResizedWindowMsg(self.window_size));
|
chan.send(ResizedWindowMsg(self.window_size.to_untyped()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter the main event loop.
|
// Enter the main event loop.
|
||||||
|
@ -341,12 +339,10 @@ impl IOCompositor {
|
||||||
self.root_pipeline = Some(frame_tree.pipeline.clone());
|
self.root_pipeline = Some(frame_tree.pipeline.clone());
|
||||||
|
|
||||||
// Initialize the new constellation channel by sending it the root window size.
|
// Initialize the new constellation channel by sending it the root window size.
|
||||||
let window_size = self.window.size();
|
let window_size = self.window.size().as_uint();
|
||||||
let window_size = Size2D(window_size.width as uint,
|
|
||||||
window_size.height as uint);
|
|
||||||
{
|
{
|
||||||
let ConstellationChan(ref chan) = new_constellation_chan;
|
let ConstellationChan(ref chan) = new_constellation_chan;
|
||||||
chan.send(ResizedWindowMsg(window_size));
|
chan.send(ResizedWindowMsg(window_size.to_untyped()));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.constellation_chan = new_constellation_chan;
|
self.constellation_chan = new_constellation_chan;
|
||||||
|
@ -424,17 +420,19 @@ impl IOCompositor {
|
||||||
self.ask_for_tiles();
|
self.ask_for_tiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The size of the content area in CSS px at the current zoom level
|
||||||
|
fn page_window(&self) -> TypedSize2D<PagePx, f32> {
|
||||||
|
self.window_size.as_f32() / self.device_pixels_per_page_px()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_layer_page_size(&mut self,
|
fn set_layer_page_size(&mut self,
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
layer_id: LayerId,
|
layer_id: LayerId,
|
||||||
new_size: Size2D<f32>,
|
new_size: Size2D<f32>,
|
||||||
epoch: Epoch) {
|
epoch: Epoch) {
|
||||||
|
let page_window = self.page_window();
|
||||||
let (ask, move): (bool, bool) = match self.compositor_layer {
|
let (ask, move): (bool, bool) = match self.compositor_layer {
|
||||||
Some(ref mut layer) => {
|
Some(ref mut layer) => {
|
||||||
let window_size = &self.window_size;
|
|
||||||
let world_zoom = self.world_zoom;
|
|
||||||
let page_window = Size2D(window_size.width as f32 / world_zoom,
|
|
||||||
window_size.height as f32 / world_zoom);
|
|
||||||
layer.resize(pipeline_id, layer_id, new_size, page_window, epoch);
|
layer.resize(pipeline_id, layer_id, new_size, page_window, epoch);
|
||||||
let move = self.fragment_point.take().map_or(false, |point| {
|
let move = self.fragment_point.take().map_or(false, |point| {
|
||||||
layer.move(pipeline_id, layer_id, point, page_window)
|
layer.move(pipeline_id, layer_id, point, page_window)
|
||||||
|
@ -503,13 +501,9 @@ impl IOCompositor {
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
layer_id: LayerId,
|
layer_id: LayerId,
|
||||||
point: Point2D<f32>) {
|
point: Point2D<f32>) {
|
||||||
let world_zoom = self.world_zoom;
|
let page_window = self.page_window();
|
||||||
let page_window = Size2D(self.window_size.width as f32 / world_zoom,
|
|
||||||
self.window_size.height as f32 / world_zoom);
|
|
||||||
|
|
||||||
let (ask, move): (bool, bool) = match self.compositor_layer {
|
let (ask, move): (bool, bool) = match self.compositor_layer {
|
||||||
Some(ref mut layer) if layer.pipeline.id == pipeline_id && !layer.hidden => {
|
Some(ref mut layer) if layer.pipeline.id == pipeline_id && !layer.hidden => {
|
||||||
|
|
||||||
(true, layer.move(pipeline_id, layer_id, point, page_window))
|
(true, layer.move(pipeline_id, layer_id, point, page_window))
|
||||||
}
|
}
|
||||||
Some(_) | None => {
|
Some(_) | None => {
|
||||||
|
@ -581,15 +575,21 @@ impl IOCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_resize_window_event(&mut self, width: uint, height: uint) {
|
fn on_resize_window_event(&mut self, width: uint, height: uint) {
|
||||||
let new_size = Size2D(width, height);
|
let new_size: TypedSize2D<DevicePixel, uint> = TypedSize2D(width, height);
|
||||||
if self.window_size != new_size {
|
if self.window_size != new_size {
|
||||||
debug!("osmain: window resized to {:u}x{:u}", width, height);
|
debug!("osmain: window resized to {:u}x{:u}", width, height);
|
||||||
self.window_size = new_size;
|
self.window_size = new_size;
|
||||||
let ConstellationChan(ref chan) = self.constellation_chan;
|
let ConstellationChan(ref chan) = self.constellation_chan;
|
||||||
chan.send(ResizedWindowMsg(new_size))
|
chan.send(ResizedWindowMsg(new_size.to_untyped()))
|
||||||
} else {
|
} else {
|
||||||
debug!("osmain: dropping window resize since size is still {:u}x{:u}", width, height);
|
debug!("osmain: dropping window resize since size is still {:u}x{:u}", width, height);
|
||||||
}
|
}
|
||||||
|
// A size change could also mean a resolution change.
|
||||||
|
let new_hidpi_factor = self.window.hidpi_factor();
|
||||||
|
if self.hidpi_factor != new_hidpi_factor {
|
||||||
|
self.hidpi_factor = new_hidpi_factor;
|
||||||
|
self.update_zoom_transform();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_load_url_window_event(&mut self, url_string: String) {
|
fn on_load_url_window_event(&mut self, url_string: String) {
|
||||||
|
@ -606,31 +606,32 @@ impl IOCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_mouse_window_event_class(&self, mouse_window_event: MouseWindowEvent) {
|
fn on_mouse_window_event_class(&self, mouse_window_event: MouseWindowEvent) {
|
||||||
let world_zoom = self.world_zoom;
|
let scale = self.device_pixels_per_page_px();
|
||||||
let point = match mouse_window_event {
|
let point = match mouse_window_event {
|
||||||
MouseWindowClickEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
MouseWindowClickEvent(_, p) => p / scale,
|
||||||
MouseWindowMouseDownEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
MouseWindowMouseDownEvent(_, p) => p / scale,
|
||||||
MouseWindowMouseUpEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
MouseWindowMouseUpEvent(_, p) => p / scale,
|
||||||
};
|
};
|
||||||
for layer in self.compositor_layer.iter() {
|
for layer in self.compositor_layer.iter() {
|
||||||
layer.send_mouse_event(mouse_window_event, point);
|
layer.send_mouse_event(mouse_window_event, point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_mouse_window_move_event_class(&self, cursor: Point2D<f32>) {
|
fn on_mouse_window_move_event_class(&self, cursor: TypedPoint2D<DevicePixel, f32>) {
|
||||||
|
let scale = self.device_pixels_per_page_px();
|
||||||
for layer in self.compositor_layer.iter() {
|
for layer in self.compositor_layer.iter() {
|
||||||
layer.send_mouse_move_event(cursor);
|
layer.send_mouse_move_event(cursor / scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_scroll_window_event(&mut self, delta: Point2D<f32>, cursor: Point2D<i32>) {
|
fn on_scroll_window_event(&mut self,
|
||||||
let world_zoom = self.world_zoom;
|
delta: TypedPoint2D<DevicePixel, f32>,
|
||||||
|
cursor: TypedPoint2D<DevicePixel, i32>) {
|
||||||
|
let scale = self.device_pixels_per_page_px();
|
||||||
// TODO: modify delta to snap scroll to pixels.
|
// TODO: modify delta to snap scroll to pixels.
|
||||||
let page_delta = Point2D(delta.x as f32 / world_zoom, delta.y as f32 / world_zoom);
|
let page_delta = delta / scale;
|
||||||
let page_cursor: Point2D<f32> = Point2D(cursor.x as f32 / world_zoom,
|
let page_cursor = cursor.as_f32() / scale;
|
||||||
cursor.y as f32 / world_zoom);
|
let page_window = self.page_window();
|
||||||
let page_window = Size2D(self.window_size.width as f32 / world_zoom,
|
|
||||||
self.window_size.height as f32 / world_zoom);
|
|
||||||
let mut scroll = false;
|
let mut scroll = false;
|
||||||
for layer in self.compositor_layer.mut_iter() {
|
for layer in self.compositor_layer.mut_iter() {
|
||||||
scroll = layer.handle_scroll_event(page_delta, page_cursor, page_window) || scroll;
|
scroll = layer.handle_scroll_event(page_delta, page_cursor, page_window) || scroll;
|
||||||
|
@ -639,27 +640,45 @@ impl IOCompositor {
|
||||||
self.ask_for_tiles();
|
self.ask_for_tiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn device_pixels_per_screen_px(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
|
||||||
|
match self.opts.device_pixels_per_px {
|
||||||
|
Some(device_pixels_per_px) => device_pixels_per_px,
|
||||||
|
None => match self.opts.output_file {
|
||||||
|
Some(_) => ScaleFactor(1.0),
|
||||||
|
None => self.hidpi_factor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_pixels_per_page_px(&self) -> ScaleFactor<PagePx, DevicePixel, f32> {
|
||||||
|
self.world_zoom * self.device_pixels_per_screen_px()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_zoom_transform(&mut self) {
|
||||||
|
let scale = self.device_pixels_per_page_px();
|
||||||
|
self.root_layer.common.borrow_mut().set_transform(identity().scale(scale.get(), scale.get(), 1f32));
|
||||||
|
}
|
||||||
|
|
||||||
fn on_zoom_window_event(&mut self, magnification: f32) {
|
fn on_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_world_zoom = self.world_zoom;
|
||||||
let window_size = &self.window_size;
|
let window_size = self.window_size.as_f32();
|
||||||
|
|
||||||
// Determine zoom amount
|
// Determine zoom amount
|
||||||
self.world_zoom = (self.world_zoom * magnification).max(1.0);
|
self.world_zoom = ScaleFactor((self.world_zoom.get() * magnification).max(1.0));
|
||||||
let world_zoom = self.world_zoom;
|
let world_zoom = self.world_zoom;
|
||||||
|
|
||||||
{
|
self.update_zoom_transform();
|
||||||
self.root_layer.common.borrow_mut().set_transform(identity().scale(world_zoom, world_zoom, 1f32));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scroll as needed
|
// Scroll as needed
|
||||||
let page_delta = Point2D(window_size.width as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5,
|
let page_delta = TypedPoint2D(
|
||||||
window_size.height as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5);
|
window_size.width.get() * (world_zoom.inv() - old_world_zoom.inv()).get() * 0.5,
|
||||||
|
window_size.height.get() * (world_zoom.inv() - old_world_zoom.inv()).get() * 0.5);
|
||||||
// TODO: modify delta to snap scroll to pixels.
|
// TODO: modify delta to snap scroll to pixels.
|
||||||
let page_cursor = Point2D(-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 = Size2D(window_size.width as f32 / world_zoom,
|
let page_window = self.page_window();
|
||||||
window_size.height as f32 / world_zoom);
|
|
||||||
for layer in self.compositor_layer.mut_iter() {
|
for layer in self.compositor_layer.mut_iter() {
|
||||||
layer.handle_scroll_event(page_delta, page_cursor, page_window);
|
layer.handle_scroll_event(page_delta, page_cursor, page_window);
|
||||||
}
|
}
|
||||||
|
@ -678,15 +697,14 @@ impl IOCompositor {
|
||||||
|
|
||||||
/// Get BufferRequests from each layer.
|
/// Get BufferRequests from each layer.
|
||||||
fn ask_for_tiles(&mut self) {
|
fn ask_for_tiles(&mut self) {
|
||||||
let world_zoom = self.world_zoom;
|
let scale = self.device_pixels_per_page_px();
|
||||||
let window_size_page = Size2D(self.window_size.width as f32 / world_zoom,
|
let page_window = self.page_window();
|
||||||
self.window_size.height as f32 / world_zoom);
|
|
||||||
for layer in self.compositor_layer.mut_iter() {
|
for layer in self.compositor_layer.mut_iter() {
|
||||||
if !layer.hidden {
|
if !layer.hidden {
|
||||||
let rect = Rect(Point2D(0f32, 0f32), window_size_page);
|
let rect = Rect(Point2D(0f32, 0f32), page_window.to_untyped());
|
||||||
let recomposite = layer.get_buffer_request(&self.graphics_context,
|
let recomposite = layer.get_buffer_request(&self.graphics_context,
|
||||||
rect,
|
rect,
|
||||||
world_zoom) ||
|
scale.get()) ||
|
||||||
self.recomposite;
|
self.recomposite;
|
||||||
self.recomposite = recomposite;
|
self.recomposite = recomposite;
|
||||||
} else {
|
} else {
|
||||||
|
@ -699,7 +717,7 @@ impl IOCompositor {
|
||||||
profile(time::CompositingCategory, self.profiler_chan.clone(), || {
|
profile(time::CompositingCategory, self.profiler_chan.clone(), || {
|
||||||
debug!("compositor: compositing");
|
debug!("compositor: compositing");
|
||||||
// Adjust the layer dimensions as necessary to correspond to the size of the window.
|
// Adjust the layer dimensions as necessary to correspond to the size of the window.
|
||||||
self.scene.size = self.window.size();
|
self.scene.size = self.window.size().to_untyped();
|
||||||
// Render the scene.
|
// Render the scene.
|
||||||
match self.compositor_layer {
|
match self.compositor_layer {
|
||||||
Some(ref mut layer) => {
|
Some(ref mut layer) => {
|
||||||
|
@ -717,7 +735,7 @@ impl IOCompositor {
|
||||||
// self.window.present()) as OpenGL ES 2 does not have glReadBuffer().
|
// self.window.present()) as OpenGL ES 2 does not have glReadBuffer().
|
||||||
if self.load_complete && self.ready_state == FinishedLoading
|
if self.load_complete && self.ready_state == FinishedLoading
|
||||||
&& self.opts.output_file.is_some() {
|
&& self.opts.output_file.is_some() {
|
||||||
let (width, height) = (self.window_size.width as uint, self.window_size.height as uint);
|
let (width, height) = (self.window_size.width.get(), self.window_size.height.get());
|
||||||
let path = from_str::<Path>(self.opts.output_file.get_ref().as_slice()).unwrap();
|
let path = from_str::<Path>(self.opts.output_file.get_ref().as_slice()).unwrap();
|
||||||
let mut pixels = gl2::read_pixels(0, 0,
|
let mut pixels = gl2::read_pixels(0, 0,
|
||||||
width as gl2::GLsizei,
|
width as gl2::GLsizei,
|
||||||
|
|
|
@ -8,10 +8,11 @@ use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEve
|
||||||
use windowing::{MouseWindowMouseUpEvent};
|
use windowing::{MouseWindowMouseUpEvent};
|
||||||
|
|
||||||
use azure::azure_hl::Color;
|
use azure::azure_hl::Color;
|
||||||
|
use geom::length::Length;
|
||||||
use geom::matrix::identity;
|
use geom::matrix::identity;
|
||||||
use geom::point::Point2D;
|
use geom::point::{Point2D, TypedPoint2D};
|
||||||
use geom::rect::Rect;
|
use geom::rect::{Rect, TypedRect};
|
||||||
use geom::size::Size2D;
|
use geom::size::{Size2D, TypedSize2D};
|
||||||
use gfx::render_task::{ReRenderMsg, UnusedBufferMsg};
|
use gfx::render_task::{ReRenderMsg, UnusedBufferMsg};
|
||||||
use gfx;
|
use gfx;
|
||||||
use layers::layers::{ContainerLayerKind, ContainerLayer, Flip, NoFlip, TextureLayer};
|
use layers::layers::{ContainerLayerKind, ContainerLayer, Flip, NoFlip, TextureLayer};
|
||||||
|
@ -23,6 +24,7 @@ use script::script_task::{ScriptChan, SendEventMsg};
|
||||||
use servo_msg::compositor_msg::{Epoch, FixedPosition, LayerBuffer, LayerBufferSet, LayerId};
|
use servo_msg::compositor_msg::{Epoch, FixedPosition, LayerBuffer, LayerBufferSet, LayerId};
|
||||||
use servo_msg::compositor_msg::{ScrollPolicy, Tile};
|
use servo_msg::compositor_msg::{ScrollPolicy, Tile};
|
||||||
use servo_msg::constellation_msg::PipelineId;
|
use servo_msg::constellation_msg::PipelineId;
|
||||||
|
use servo_util::geometry::PagePx;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(target_os="macos")]
|
#[cfg(target_os="macos")]
|
||||||
|
@ -59,7 +61,7 @@ pub struct CompositorLayer {
|
||||||
|
|
||||||
/// The offset of the page due to scrolling. (0,0) is when the window sees the
|
/// The offset of the page due to scrolling. (0,0) is when the window sees the
|
||||||
/// top left corner of the page.
|
/// top left corner of the page.
|
||||||
pub scroll_offset: Point2D<f32>,
|
pub scroll_offset: TypedPoint2D<PagePx, f32>,
|
||||||
|
|
||||||
/// This layer's children. These could be iframes or any element which
|
/// This layer's children. These could be iframes or any element which
|
||||||
/// differs in scroll behavior from its parent. Each is associated with a
|
/// differs in scroll behavior from its parent. Each is associated with a
|
||||||
|
@ -169,7 +171,7 @@ impl CompositorLayer {
|
||||||
id: layer_id,
|
id: layer_id,
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
page_size: page_size,
|
page_size: page_size,
|
||||||
scroll_offset: Point2D(0f32, 0f32),
|
scroll_offset: TypedPoint2D(0f32, 0f32),
|
||||||
children: vec!(),
|
children: vec!(),
|
||||||
quadtree: match page_size {
|
quadtree: match page_size {
|
||||||
None => NoTree(tile_size, Some(MAX_TILE_MEMORY_PER_LAYER)),
|
None => NoTree(tile_size, Some(MAX_TILE_MEMORY_PER_LAYER)),
|
||||||
|
@ -202,7 +204,7 @@ impl CompositorLayer {
|
||||||
id: LayerId::null(),
|
id: LayerId::null(),
|
||||||
bounds: Rect(Point2D(0f32, 0f32), page_size),
|
bounds: Rect(Point2D(0f32, 0f32), page_size),
|
||||||
page_size: Some(page_size),
|
page_size: Some(page_size),
|
||||||
scroll_offset: Point2D(0f32, 0f32),
|
scroll_offset: TypedPoint2D(0f32, 0f32),
|
||||||
children: vec!(),
|
children: vec!(),
|
||||||
quadtree: NoTree(tile_size, Some(MAX_TILE_MEMORY_PER_LAYER)),
|
quadtree: NoTree(tile_size, Some(MAX_TILE_MEMORY_PER_LAYER)),
|
||||||
root_layer: Rc::new(ContainerLayer()),
|
root_layer: Rc::new(ContainerLayer()),
|
||||||
|
@ -285,9 +287,9 @@ impl CompositorLayer {
|
||||||
/// mouse is over child layers first. If a layer successfully scrolled, returns true; otherwise
|
/// mouse is over child layers first. If a layer successfully scrolled, returns true; otherwise
|
||||||
/// returns false, so a parent layer can scroll instead.
|
/// returns false, so a parent layer can scroll instead.
|
||||||
pub fn handle_scroll_event(&mut self,
|
pub fn handle_scroll_event(&mut self,
|
||||||
delta: Point2D<f32>,
|
delta: TypedPoint2D<PagePx, f32>,
|
||||||
cursor: Point2D<f32>,
|
cursor: TypedPoint2D<PagePx, f32>,
|
||||||
window_size: Size2D<f32>)
|
window_size: TypedSize2D<PagePx, f32>)
|
||||||
-> bool {
|
-> bool {
|
||||||
// If this layer is hidden, neither it nor its children will scroll.
|
// If this layer is hidden, neither it nor its children will scroll.
|
||||||
if self.hidden {
|
if self.hidden {
|
||||||
|
@ -308,6 +310,7 @@ impl CompositorLayer {
|
||||||
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
||||||
}
|
}
|
||||||
Some(rect) => {
|
Some(rect) => {
|
||||||
|
let rect: TypedRect<PagePx, f32> = Rect::from_untyped(&rect);
|
||||||
if cursor.x >= rect.origin.x && cursor.x < rect.origin.x + rect.size.width
|
if cursor.x >= rect.origin.x && cursor.x < rect.origin.x + rect.size.width
|
||||||
&& cursor.y >= rect.origin.y && cursor.y < rect.origin.y + rect.size.height
|
&& cursor.y >= rect.origin.y && cursor.y < rect.origin.y + rect.size.height
|
||||||
&& child.child.handle_scroll_event(delta,
|
&& child.child.handle_scroll_event(delta,
|
||||||
|
@ -329,12 +332,17 @@ impl CompositorLayer {
|
||||||
Some(size) => size,
|
Some(size) => size,
|
||||||
None => fail!("CompositorLayer: tried to scroll with no page size set"),
|
None => fail!("CompositorLayer: tried to scroll with no page size set"),
|
||||||
};
|
};
|
||||||
let min_x = (window_size.width - page_size.width).min(0.0);
|
|
||||||
self.scroll_offset.x = self.scroll_offset.x.clamp(&min_x, &0.0);
|
|
||||||
let min_y = (window_size.height - page_size.height).min(0.0);
|
|
||||||
self.scroll_offset.y = self.scroll_offset.y.clamp(&min_y, &0.0);
|
|
||||||
|
|
||||||
if old_origin - self.scroll_offset == Point2D(0f32, 0f32) {
|
let window_size = window_size.to_untyped();
|
||||||
|
let scroll_offset = self.scroll_offset.to_untyped();
|
||||||
|
|
||||||
|
let min_x = (window_size.width - page_size.width).min(0.0);
|
||||||
|
self.scroll_offset.x = Length(scroll_offset.x.clamp(&min_x, &0.0));
|
||||||
|
|
||||||
|
let min_y = (window_size.height - page_size.height).min(0.0);
|
||||||
|
self.scroll_offset.y = Length(scroll_offset.y.clamp(&min_y, &0.0));
|
||||||
|
|
||||||
|
if old_origin - self.scroll_offset == TypedPoint2D(0f32, 0f32) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +366,7 @@ impl CompositorLayer {
|
||||||
|
|
||||||
/// Actually scrolls the descendants of a layer that scroll. This is called by
|
/// Actually scrolls the descendants of a layer that scroll. This is called by
|
||||||
/// `handle_scroll_event` above when it determines that a layer wants to scroll.
|
/// `handle_scroll_event` above when it determines that a layer wants to scroll.
|
||||||
fn scroll(&mut self, scroll_offset: Point2D<f32>) -> bool {
|
fn scroll(&mut self, scroll_offset: TypedPoint2D<PagePx, f32>) -> bool {
|
||||||
let mut result = false;
|
let mut result = false;
|
||||||
|
|
||||||
// Only scroll this layer if it's not fixed-positioned.
|
// Only scroll this layer if it's not fixed-positioned.
|
||||||
|
@ -367,7 +375,7 @@ impl CompositorLayer {
|
||||||
self.scroll_offset = scroll_offset;
|
self.scroll_offset = scroll_offset;
|
||||||
|
|
||||||
self.root_layer.common.borrow_mut().set_transform(
|
self.root_layer.common.borrow_mut().set_transform(
|
||||||
identity().translate(self.scroll_offset.x, self.scroll_offset.y, 0.0));
|
identity().translate(self.scroll_offset.x.get(), self.scroll_offset.y.get(), 0.0));
|
||||||
|
|
||||||
result = true
|
result = true
|
||||||
}
|
}
|
||||||
|
@ -382,7 +390,7 @@ impl CompositorLayer {
|
||||||
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
||||||
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
||||||
// page coordinates.
|
// page coordinates.
|
||||||
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: Point2D<f32>) {
|
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: TypedPoint2D<PagePx, f32>) {
|
||||||
let cursor = cursor - self.scroll_offset;
|
let cursor = cursor - self.scroll_offset;
|
||||||
for child in self.children.iter().filter(|&x| !x.child.hidden) {
|
for child in self.children.iter().filter(|&x| !x.child.hidden) {
|
||||||
match *child.container.scissor.borrow() {
|
match *child.container.scissor.borrow() {
|
||||||
|
@ -390,6 +398,7 @@ impl CompositorLayer {
|
||||||
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
||||||
}
|
}
|
||||||
Some(rect) => {
|
Some(rect) => {
|
||||||
|
let rect: TypedRect<PagePx, f32> = Rect::from_untyped(&rect);
|
||||||
if cursor.x >= rect.origin.x && cursor.x < rect.origin.x + rect.size.width
|
if cursor.x >= rect.origin.x && cursor.x < rect.origin.x + rect.size.width
|
||||||
&& cursor.y >= rect.origin.y && cursor.y < rect.origin.y + rect.size.height {
|
&& cursor.y >= rect.origin.y && cursor.y < rect.origin.y + rect.size.height {
|
||||||
child.child.send_mouse_event(event, cursor - rect.origin);
|
child.child.send_mouse_event(event, cursor - rect.origin);
|
||||||
|
@ -401,16 +410,16 @@ impl CompositorLayer {
|
||||||
|
|
||||||
// This mouse event is mine!
|
// This mouse event is mine!
|
||||||
let message = match event {
|
let message = match event {
|
||||||
MouseWindowClickEvent(button, _) => ClickEvent(button, cursor),
|
MouseWindowClickEvent(button, _) => ClickEvent(button, cursor.to_untyped()),
|
||||||
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor),
|
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor.to_untyped()),
|
||||||
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor),
|
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor.to_untyped()),
|
||||||
};
|
};
|
||||||
let ScriptChan(ref chan) = self.pipeline.script_chan;
|
let ScriptChan(ref chan) = self.pipeline.script_chan;
|
||||||
let _ = chan.send_opt(SendEventMsg(self.pipeline.id.clone(), message));
|
let _ = chan.send_opt(SendEventMsg(self.pipeline.id.clone(), message));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_mouse_move_event(&self, cursor: Point2D<f32>) {
|
pub fn send_mouse_move_event(&self, cursor: TypedPoint2D<PagePx, f32>) {
|
||||||
let message = MouseMoveEvent(cursor);
|
let message = MouseMoveEvent(cursor.to_untyped());
|
||||||
let ScriptChan(ref chan) = self.pipeline.script_chan;
|
let ScriptChan(ref chan) = self.pipeline.script_chan;
|
||||||
let _ = chan.send_opt(SendEventMsg(self.pipeline.id.clone(), message));
|
let _ = chan.send_opt(SendEventMsg(self.pipeline.id.clone(), message));
|
||||||
}
|
}
|
||||||
|
@ -453,8 +462,9 @@ impl CompositorLayer {
|
||||||
match *x.container.scissor.borrow() {
|
match *x.container.scissor.borrow() {
|
||||||
Some(scissor) => {
|
Some(scissor) => {
|
||||||
let mut new_rect = window_rect;
|
let mut new_rect = window_rect;
|
||||||
new_rect.origin.x = new_rect.origin.x - x.child.scroll_offset.x;
|
let offset = x.child.scroll_offset.to_untyped();
|
||||||
new_rect.origin.y = new_rect.origin.y - x.child.scroll_offset.y;
|
new_rect.origin.x = new_rect.origin.x - offset.x;
|
||||||
|
new_rect.origin.y = new_rect.origin.y - offset.y;
|
||||||
match new_rect.intersection(&scissor) {
|
match new_rect.intersection(&scissor) {
|
||||||
Some(new_rect) => {
|
Some(new_rect) => {
|
||||||
// Child layers act as if they are rendered at (0,0), so we
|
// Child layers act as if they are rendered at (0,0), so we
|
||||||
|
@ -535,7 +545,7 @@ impl CompositorLayer {
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
layer_id: LayerId,
|
layer_id: LayerId,
|
||||||
new_size: Size2D<f32>,
|
new_size: Size2D<f32>,
|
||||||
window_size: Size2D<f32>,
|
window_size: TypedSize2D<PagePx, f32>,
|
||||||
epoch: Epoch)
|
epoch: Epoch)
|
||||||
-> bool {
|
-> bool {
|
||||||
debug!("compositor_layer: starting resize()");
|
debug!("compositor_layer: starting resize()");
|
||||||
|
@ -562,7 +572,7 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the cursor position
|
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the cursor position
|
||||||
// to make sure the scroll isn't propagated downwards.
|
// to make sure the scroll isn't propagated downwards.
|
||||||
self.handle_scroll_event(Point2D(0f32, 0f32), Point2D(-1f32, -1f32), window_size);
|
self.handle_scroll_event(TypedPoint2D(0f32, 0f32), TypedPoint2D(-1f32, -1f32), window_size);
|
||||||
self.hidden = false;
|
self.hidden = false;
|
||||||
self.set_occlusions();
|
self.set_occlusions();
|
||||||
true
|
true
|
||||||
|
@ -572,7 +582,7 @@ impl CompositorLayer {
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
layer_id: LayerId,
|
layer_id: LayerId,
|
||||||
origin: Point2D<f32>,
|
origin: Point2D<f32>,
|
||||||
window_size: Size2D<f32>)
|
window_size: TypedSize2D<PagePx, f32>)
|
||||||
-> bool {
|
-> bool {
|
||||||
// Search children for the right layer to move.
|
// Search children for the right layer to move.
|
||||||
if self.pipeline.id != pipeline_id || self.id != layer_id {
|
if self.pipeline.id != pipeline_id || self.id != layer_id {
|
||||||
|
@ -587,20 +597,23 @@ impl CompositorLayer {
|
||||||
|
|
||||||
// Scroll this layer!
|
// Scroll this layer!
|
||||||
let old_origin = self.scroll_offset;
|
let old_origin = self.scroll_offset;
|
||||||
self.scroll_offset = Point2D(0f32, 0f32) - origin;
|
self.scroll_offset = Point2D::from_untyped(&(origin * -1.0));
|
||||||
|
|
||||||
// bounds checking
|
// bounds checking
|
||||||
let page_size = match self.page_size {
|
let page_size = match self.page_size {
|
||||||
Some(size) => size,
|
Some(size) => size,
|
||||||
None => fail!("CompositorLayer: tried to scroll with no page size set"),
|
None => fail!("CompositorLayer: tried to scroll with no page size set"),
|
||||||
};
|
};
|
||||||
|
let window_size = window_size.to_untyped();
|
||||||
|
let scroll_offset = self.scroll_offset.to_untyped();
|
||||||
|
|
||||||
let min_x = (window_size.width - page_size.width).min(0.0);
|
let min_x = (window_size.width - page_size.width).min(0.0);
|
||||||
self.scroll_offset.x = self.scroll_offset.x.clamp(&min_x, &0.0);
|
self.scroll_offset.x = Length(scroll_offset.x.clamp(&min_x, &0.0));
|
||||||
let min_y = (window_size.height - page_size.height).min(0.0);
|
let min_y = (window_size.height - page_size.height).min(0.0);
|
||||||
self.scroll_offset.y = self.scroll_offset.y.clamp(&min_y, &0.0);
|
self.scroll_offset.y = Length(scroll_offset.y.clamp(&min_y, &0.0));
|
||||||
|
|
||||||
// check to see if we scrolled
|
// check to see if we scrolled
|
||||||
if old_origin - self.scroll_offset == Point2D(0f32, 0f32) {
|
if old_origin - self.scroll_offset == TypedPoint2D(0f32, 0f32) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,9 +682,10 @@ impl CompositorLayer {
|
||||||
Some(scissor) => {
|
Some(scissor) => {
|
||||||
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the
|
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the
|
||||||
// cursor position to make sure the scroll isn't propagated downwards.
|
// cursor position to make sure the scroll isn't propagated downwards.
|
||||||
child.handle_scroll_event(Point2D(0f32, 0f32),
|
let size: TypedSize2D<PagePx, f32> = Size2D::from_untyped(&scissor.size);
|
||||||
Point2D(-1f32, -1f32),
|
child.handle_scroll_event(TypedPoint2D(0f32, 0f32),
|
||||||
scissor.size);
|
TypedPoint2D(-1f32, -1f32),
|
||||||
|
size);
|
||||||
child.hidden = false;
|
child.hidden = false;
|
||||||
}
|
}
|
||||||
None => {} // Nothing to do
|
None => {} // Nothing to do
|
||||||
|
|
|
@ -19,10 +19,12 @@ use std::cell::{Cell, RefCell};
|
||||||
use std::comm::Receiver;
|
use std::comm::Receiver;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::{Point2D, TypedPoint2D};
|
||||||
use geom::size::Size2D;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
use geom::size::TypedSize2D;
|
||||||
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
|
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
|
||||||
use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
|
use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
|
||||||
|
use servo_util::geometry::{ScreenPx, DevicePixel};
|
||||||
|
|
||||||
use glfw;
|
use glfw;
|
||||||
use glfw::Context;
|
use glfw::Context;
|
||||||
|
@ -144,9 +146,9 @@ impl WindowMethods<Application> for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size of the window.
|
/// Returns the size of the window.
|
||||||
fn size(&self) -> Size2D<f32> {
|
fn size(&self) -> TypedSize2D<DevicePixel, f32> {
|
||||||
let (width, height) = self.glfw_window.get_framebuffer_size();
|
let (width, height) = self.glfw_window.get_framebuffer_size();
|
||||||
Size2D(width as f32, height as f32)
|
TypedSize2D(width as f32, height as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Presents the window to the screen (perhaps by page flipping).
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
|
@ -193,10 +195,10 @@ impl WindowMethods<Application> for Window {
|
||||||
self.update_window_title()
|
self.update_window_title()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hidpi_factor(&self) -> f32 {
|
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
|
||||||
let (backing_size, _) = self.glfw_window.get_framebuffer_size();
|
let (backing_size, _) = self.glfw_window.get_framebuffer_size();
|
||||||
let (window_size, _) = self.glfw_window.get_size();
|
let (window_size, _) = self.glfw_window.get_size();
|
||||||
(backing_size as f32) / (window_size as f32)
|
ScaleFactor((backing_size as f32) / (window_size as f32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +229,8 @@ impl Window {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
glfw::CursorPosEvent(xpos, ypos) => {
|
glfw::CursorPosEvent(xpos, ypos) => {
|
||||||
self.event_queue.borrow_mut().push(MouseWindowMoveEventClass(Point2D(xpos as f32, ypos as f32)));
|
self.event_queue.borrow_mut().push(
|
||||||
|
MouseWindowMoveEventClass(TypedPoint2D(xpos as f32, ypos as f32)));
|
||||||
},
|
},
|
||||||
glfw::ScrollEvent(xpos, ypos) => {
|
glfw::ScrollEvent(xpos, ypos) => {
|
||||||
let dx = (xpos as f32) * 30.0;
|
let dx = (xpos as f32) * 30.0;
|
||||||
|
@ -241,7 +244,8 @@ impl Window {
|
||||||
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(Point2D(dx, dy), Point2D(x as i32, y as i32)));
|
self.event_queue.borrow_mut().push(ScrollWindowEvent(TypedPoint2D(dx, dy),
|
||||||
|
TypedPoint2D(x as i32, y as i32)));
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +311,7 @@ impl Window {
|
||||||
glfw::Press => {
|
glfw::Press => {
|
||||||
self.mouse_down_point.set(Point2D(x, y));
|
self.mouse_down_point.set(Point2D(x, y));
|
||||||
self.mouse_down_button.set(Some(button));
|
self.mouse_down_button.set(Some(button));
|
||||||
MouseWindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32))
|
MouseWindowMouseDownEvent(button as uint, TypedPoint2D(x as f32, y as f32))
|
||||||
}
|
}
|
||||||
glfw::Release => {
|
glfw::Release => {
|
||||||
match self.mouse_down_button.get() {
|
match self.mouse_down_button.get() {
|
||||||
|
@ -318,13 +322,13 @@ impl Window {
|
||||||
pixel_dist.y * pixel_dist.y) as f64).sqrt();
|
pixel_dist.y * pixel_dist.y) as f64).sqrt();
|
||||||
if pixel_dist < max_pixel_dist {
|
if pixel_dist < max_pixel_dist {
|
||||||
let click_event = MouseWindowClickEvent(button as uint,
|
let click_event = MouseWindowClickEvent(button as uint,
|
||||||
Point2D(x as f32, y as f32));
|
TypedPoint2D(x as f32, y as f32));
|
||||||
self.event_queue.borrow_mut().push(MouseWindowEventClass(click_event));
|
self.event_queue.borrow_mut().push(MouseWindowEventClass(click_event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(_) => (),
|
Some(_) => (),
|
||||||
}
|
}
|
||||||
MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
|
MouseWindowMouseUpEvent(button as uint, TypedPoint2D(x as f32, y as f32))
|
||||||
}
|
}
|
||||||
_ => fail!("I cannot recognize the type of mouse action that occured. :-(")
|
_ => fail!("I cannot recognize the type of mouse action that occured. :-(")
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,10 +14,12 @@ use alert::{Alert, AlertMethods};
|
||||||
use libc::{c_int, c_uchar};
|
use libc::{c_int, c_uchar};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use geom::point::Point2D;
|
use geom::point::{Point2D, TypedPoint2D};
|
||||||
use geom::size::Size2D;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
use geom::size::TypedSize2D;
|
||||||
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
|
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
|
||||||
use servo_msg::compositor_msg::{FinishedLoading, Blank, ReadyState};
|
use servo_msg::compositor_msg::{FinishedLoading, Blank, ReadyState};
|
||||||
|
use servo_util::geometry::{ScreenPx, DevicePixel};
|
||||||
|
|
||||||
use glut::glut::{ACTIVE_SHIFT, DOUBLE, WindowHeight};
|
use glut::glut::{ACTIVE_SHIFT, DOUBLE, WindowHeight};
|
||||||
use glut::glut::WindowWidth;
|
use glut::glut::WindowWidth;
|
||||||
|
@ -118,11 +120,15 @@ impl WindowMethods<Application> for Window {
|
||||||
match button {
|
match button {
|
||||||
3 => {
|
3 => {
|
||||||
let tmp = local_window();
|
let tmp = local_window();
|
||||||
tmp.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32)));
|
tmp.event_queue.borrow_mut().push(ScrollWindowEvent(
|
||||||
|
TypedPoint2D(0.0, 5.0 as f32),
|
||||||
|
TypedPoint2D(0.0 as i32, 5.0 as i32)));
|
||||||
},
|
},
|
||||||
4 => {
|
4 => {
|
||||||
let tmp = local_window();
|
let tmp = local_window();
|
||||||
tmp.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32)));
|
tmp.event_queue.borrow_mut().push(ScrollWindowEvent(
|
||||||
|
TypedPoint2D(0.0, -5.0 as f32),
|
||||||
|
TypedPoint2D(0.0 as i32, -5.0 as i32)));
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -139,8 +145,8 @@ impl WindowMethods<Application> for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size of the window.
|
/// Returns the size of the window.
|
||||||
fn size(&self) -> Size2D<f32> {
|
fn size(&self) -> TypedSize2D<DevicePixel, f32> {
|
||||||
Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
|
TypedSize2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Presents the window to the screen (perhaps by page flipping).
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
|
@ -179,9 +185,9 @@ impl WindowMethods<Application> for Window {
|
||||||
//self.update_window_title()
|
//self.update_window_title()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hidpi_factor(&self) -> f32 {
|
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
|
||||||
//FIXME: Do nothing in GLUT now.
|
//FIXME: Do nothing in GLUT now.
|
||||||
1f32
|
ScaleFactor(1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +224,10 @@ impl Window {
|
||||||
42 => self.load_url(),
|
42 => self.load_url(),
|
||||||
43 => self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1)),
|
43 => self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1)),
|
||||||
45 => self.event_queue.borrow_mut().push(ZoomWindowEvent(0.909090909)),
|
45 => self.event_queue.borrow_mut().push(ZoomWindowEvent(0.909090909)),
|
||||||
56 => self.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))),
|
56 => self.event_queue.borrow_mut().push(ScrollWindowEvent(TypedPoint2D(0.0, 5.0 as f32),
|
||||||
50 => self.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))),
|
TypedPoint2D(0.0 as i32, 5.0 as i32))),
|
||||||
|
50 => self.event_queue.borrow_mut().push(ScrollWindowEvent(TypedPoint2D(0.0, -5.0 as f32),
|
||||||
|
TypedPoint2D(0.0 as i32, -5.0 as i32))),
|
||||||
127 => {
|
127 => {
|
||||||
if (modifiers & ACTIVE_SHIFT) != 0 {
|
if (modifiers & ACTIVE_SHIFT) != 0 {
|
||||||
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
|
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
|
||||||
|
@ -240,7 +248,7 @@ impl Window {
|
||||||
glut::MOUSE_DOWN => {
|
glut::MOUSE_DOWN => {
|
||||||
self.mouse_down_point.set(Point2D(x, y));
|
self.mouse_down_point.set(Point2D(x, y));
|
||||||
self.mouse_down_button.set(button);
|
self.mouse_down_button.set(button);
|
||||||
MouseWindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32))
|
MouseWindowMouseDownEvent(button as uint, TypedPoint2D(x as f32, y as f32))
|
||||||
}
|
}
|
||||||
glut::MOUSE_UP => {
|
glut::MOUSE_UP => {
|
||||||
if self.mouse_down_button.get() == button {
|
if self.mouse_down_button.get() == button {
|
||||||
|
@ -249,11 +257,11 @@ impl Window {
|
||||||
pixel_dist.y * pixel_dist.y) as f32).sqrt();
|
pixel_dist.y * pixel_dist.y) as f32).sqrt();
|
||||||
if pixel_dist < max_pixel_dist {
|
if pixel_dist < max_pixel_dist {
|
||||||
let click_event = MouseWindowClickEvent(button as uint,
|
let click_event = MouseWindowClickEvent(button as uint,
|
||||||
Point2D(x as f32, y as f32));
|
TypedPoint2D(x as f32, y as f32));
|
||||||
self.event_queue.borrow_mut().push(MouseWindowEventClass(click_event));
|
self.event_queue.borrow_mut().push(MouseWindowEventClass(click_event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
|
MouseWindowMouseUpEvent(button as uint, TypedPoint2D(x as f32, y as f32))
|
||||||
}
|
}
|
||||||
_ => fail!("I cannot recognize the type of mouse action that occured. :-(")
|
_ => fail!("I cannot recognize the type of mouse action that occured. :-(")
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,15 +4,17 @@
|
||||||
|
|
||||||
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::TypedPoint2D;
|
||||||
use geom::size::Size2D;
|
use geom::scale_factor::ScaleFactor;
|
||||||
|
use geom::size::TypedSize2D;
|
||||||
use servo_msg::compositor_msg::{ReadyState, RenderState};
|
use servo_msg::compositor_msg::{ReadyState, RenderState};
|
||||||
|
use servo_util::geometry::{ScreenPx, DevicePixel};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum MouseWindowEvent {
|
pub enum MouseWindowEvent {
|
||||||
MouseWindowClickEvent(uint, Point2D<f32>),
|
MouseWindowClickEvent(uint, TypedPoint2D<DevicePixel, f32>),
|
||||||
MouseWindowMouseDownEvent(uint, Point2D<f32>),
|
MouseWindowMouseDownEvent(uint, TypedPoint2D<DevicePixel, f32>),
|
||||||
MouseWindowMouseUpEvent(uint, Point2D<f32>),
|
MouseWindowMouseUpEvent(uint, TypedPoint2D<DevicePixel, f32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum WindowNavigateMsg {
|
pub enum WindowNavigateMsg {
|
||||||
|
@ -36,9 +38,9 @@ pub enum WindowEvent {
|
||||||
/// Sent when a mouse hit test is to be performed.
|
/// Sent when a mouse hit test is to be performed.
|
||||||
MouseWindowEventClass(MouseWindowEvent),
|
MouseWindowEventClass(MouseWindowEvent),
|
||||||
/// Sent when a mouse move.
|
/// Sent when a mouse move.
|
||||||
MouseWindowMoveEventClass(Point2D<f32>),
|
MouseWindowMoveEventClass(TypedPoint2D<DevicePixel, f32>),
|
||||||
/// Sent when the user scrolls. Includes the current cursor position.
|
/// Sent when the user scrolls. Includes the current cursor position.
|
||||||
ScrollWindowEvent(Point2D<f32>, Point2D<i32>),
|
ScrollWindowEvent(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>),
|
||||||
/// Sent when the user zooms.
|
/// Sent when the user zooms.
|
||||||
ZoomWindowEvent(f32),
|
ZoomWindowEvent(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).
|
||||||
|
@ -58,7 +60,7 @@ pub trait WindowMethods<A> {
|
||||||
/// Creates a new window.
|
/// Creates a new window.
|
||||||
fn new(app: &A, is_foreground: bool) -> Rc<Self>;
|
fn new(app: &A, is_foreground: bool) -> Rc<Self>;
|
||||||
/// Returns the size of the window.
|
/// Returns the size of the window.
|
||||||
fn size(&self) -> Size2D<f32>;
|
fn size(&self) -> TypedSize2D<DevicePixel, f32>;
|
||||||
/// Presents the window to the screen (perhaps by page flipping).
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
fn present(&self);
|
fn present(&self);
|
||||||
|
|
||||||
|
@ -71,6 +73,6 @@ pub trait WindowMethods<A> {
|
||||||
fn set_render_state(&self, render_state: RenderState);
|
fn set_render_state(&self, render_state: RenderState);
|
||||||
|
|
||||||
/// Returns the hidpi factor of the monitor.
|
/// Returns the hidpi factor of the monitor.
|
||||||
fn hidpi_factor(&self) -> f32;
|
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,41 @@ use std::default::Default;
|
||||||
use std::num::{NumCast, One, Zero};
|
use std::num::{NumCast, One, Zero};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
// Units for use with geom::length and geom::scale_factor.
|
||||||
|
|
||||||
|
/// One hardware pixel.
|
||||||
|
///
|
||||||
|
/// This unit corresponds to the smallest addressable element of the display hardware.
|
||||||
|
pub enum DevicePixel {}
|
||||||
|
|
||||||
|
/// A normalized "pixel" at the default resolution for the display.
|
||||||
|
///
|
||||||
|
/// Like the CSS "px" unit, the exact physical size of this unit may vary between devices, but it
|
||||||
|
/// should approximate a device-independent reference length. This unit corresponds to Android's
|
||||||
|
/// "density-independent pixel" (dip), Mac OS X's "point", and Windows "device-independent pixel."
|
||||||
|
///
|
||||||
|
/// The relationship between DevicePixel and ScreenPx is defined by the OS. On most low-dpi
|
||||||
|
/// screens, one ScreenPx is equal to one DevicePixel. But on high-density screens it can be
|
||||||
|
/// some larger number. For example, by default on Apple "retina" displays, one ScreenPx equals
|
||||||
|
/// two DevicePixels. On Android "MDPI" displays, one ScreenPx equals 1.5 device pixels.
|
||||||
|
///
|
||||||
|
/// The ratio between ScreenPx and DevicePixel for a given display be found by calling
|
||||||
|
/// `servo::windowing::WindowMethods::hidpi_factor`.
|
||||||
|
pub enum ScreenPx {}
|
||||||
|
|
||||||
|
/// One CSS "px" in the root coordinate system for the content document.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// PagePx is equal to ScreenPx multiplied by a "zoom" factor controlled by the user. 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 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.
|
||||||
|
//
|
||||||
|
// FIXME: Implement Au using Length and ScaleFactor instead of a custom type.
|
||||||
#[deriving(Clone, Eq, Ord, Zero)]
|
#[deriving(Clone, Eq, Ord, Zero)]
|
||||||
pub struct Au(pub i32);
|
pub struct Au(pub i32);
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
//! Configuration options for a single run of the servo application. Created
|
//! Configuration options for a single run of the servo application. Created
|
||||||
//! from command line arguments.
|
//! from command line arguments.
|
||||||
|
|
||||||
|
use geometry::{DevicePixel, ScreenPx};
|
||||||
|
|
||||||
use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
|
use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
|
||||||
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
|
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
|
||||||
|
use geom::scale_factor::ScaleFactor;
|
||||||
use getopts;
|
use getopts;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -36,7 +39,7 @@ pub struct Opts {
|
||||||
|
|
||||||
/// The ratio of device pixels per px at the default scale. If unspecified, will use the
|
/// The ratio of device pixels per px at the default scale. If unspecified, will use the
|
||||||
/// platform default setting.
|
/// platform default setting.
|
||||||
pub device_pixels_per_px: Option<f32>,
|
pub device_pixels_per_px: Option<ScaleFactor<ScreenPx, DevicePixel, f32>>,
|
||||||
|
|
||||||
/// `None` to disable the profiler or `Some` with an interval in seconds to enable it and cause
|
/// `None` to disable the profiler or `Some` with an interval in seconds to enable it and cause
|
||||||
/// it to produce output on that interval (`-p`).
|
/// it to produce output on that interval (`-p`).
|
||||||
|
@ -136,7 +139,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str|
|
let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str|
|
||||||
from_str(dppx_str.as_slice()).unwrap()
|
ScaleFactor(from_str(dppx_str.as_slice()).unwrap())
|
||||||
);
|
);
|
||||||
|
|
||||||
let n_render_threads: uint = match opt_match.opt_str("t") {
|
let n_render_threads: uint = match opt_match.opt_str("t") {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue