servo: Merge #2603 - Use some typed units in compositor and windowing (from mbrubeck:units); r=pcwalton

This is a rebased, squashed, and updated version of #2444.

Source-Repo: https://github.com/servo/servo
Source-Revision: 6c382243c4b3de9f0eec9cd71c757897ffd1b2e0
This commit is contained in:
Matt Brubeck 2014-06-06 16:04:34 -04:00
Родитель 50c03a2fec
Коммит 67ff35687f
7 изменённых файлов: 213 добавлений и 132 удалений

Просмотреть файл

@ -16,9 +16,10 @@ use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
use azure::azure_hl::{SourceSurfaceMethods, Color};
use azure::azure_hl;
use geom::matrix::identity;
use geom::point::Point2D;
use geom::point::{Point2D, TypedPoint2D};
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::platform::surface::NativeCompositingGraphicsContext;
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::{PipelineId, ResizedWindowMsg};
use servo_msg::constellation_msg;
use servo_util::geometry::{DevicePixel, PagePx, ScreenPx};
use servo_util::opts::Opts;
use servo_util::time::{profile, ProfilerChan};
use servo_util::{time, url};
@ -60,7 +62,10 @@ pub struct IOCompositor {
scene: Scene,
/// 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.
graphics_context: NativeCompositingGraphicsContext,
@ -78,7 +83,7 @@ pub struct IOCompositor {
recomposite: bool,
/// Keeps track of the current zoom factor.
world_zoom: f32,
world_zoom: ScaleFactor<PagePx, ScreenPx, f32>,
/// Tracks whether the zoom action has happend recently.
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.
let root_layer = Rc::new(ContainerLayer());
let window_size = window.size();
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));
let hidpi_factor = window.hidpi_factor();
IOCompositor {
window: window,
@ -142,14 +138,15 @@ impl IOCompositor {
context: rendergl::init_render_context(),
root_layer: root_layer.clone(),
root_pipeline: None,
scene: Scene(ContainerLayerKind(root_layer), window_size, identity()),
window_size: Size2D(window_size.width as uint, window_size.height as uint),
scene: Scene(ContainerLayerKind(root_layer), window_size.to_untyped(), identity()),
window_size: window_size.as_uint(),
hidpi_factor: hidpi_factor,
graphics_context: CompositorTask::create_graphics_context(),
composite_ready: false,
shutting_down: false,
done: false,
recomposite: false,
world_zoom: hidpi_factor,
world_zoom: ScaleFactor(1.0),
zoom_action: false,
zoom_time: 0f64,
ready_state: Blank,
@ -171,6 +168,7 @@ impl IOCompositor {
port,
constellation_chan,
profiler_chan);
compositor.update_zoom_transform();
// Starts the compositor, which listens for messages on the specified port.
compositor.run();
@ -180,7 +178,7 @@ impl IOCompositor {
// Tell the constellation about the initial window size.
{
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.
@ -341,12 +339,10 @@ impl IOCompositor {
self.root_pipeline = Some(frame_tree.pipeline.clone());
// Initialize the new constellation channel by sending it the root window size.
let window_size = self.window.size();
let window_size = Size2D(window_size.width as uint,
window_size.height as uint);
let window_size = self.window.size().as_uint();
{
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;
@ -424,17 +420,19 @@ impl IOCompositor {
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,
pipeline_id: PipelineId,
layer_id: LayerId,
new_size: Size2D<f32>,
epoch: Epoch) {
let page_window = self.page_window();
let (ask, move): (bool, bool) = match self.compositor_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);
let move = self.fragment_point.take().map_or(false, |point| {
layer.move(pipeline_id, layer_id, point, page_window)
@ -503,13 +501,9 @@ impl IOCompositor {
pipeline_id: PipelineId,
layer_id: LayerId,
point: Point2D<f32>) {
let world_zoom = self.world_zoom;
let page_window = Size2D(self.window_size.width as f32 / world_zoom,
self.window_size.height as f32 / world_zoom);
let page_window = self.page_window();
let (ask, move): (bool, bool) = match self.compositor_layer {
Some(ref mut layer) if layer.pipeline.id == pipeline_id && !layer.hidden => {
(true, layer.move(pipeline_id, layer_id, point, page_window))
}
Some(_) | None => {
@ -581,15 +575,21 @@ impl IOCompositor {
}
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 {
debug!("osmain: window resized to {:u}x{:u}", width, height);
self.window_size = new_size;
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ResizedWindowMsg(new_size))
chan.send(ResizedWindowMsg(new_size.to_untyped()))
} else {
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) {
@ -606,31 +606,32 @@ impl IOCompositor {
}
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 {
MouseWindowClickEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
MouseWindowMouseDownEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
MouseWindowMouseUpEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
MouseWindowClickEvent(_, p) => p / scale,
MouseWindowMouseDownEvent(_, p) => p / scale,
MouseWindowMouseUpEvent(_, p) => p / scale,
};
for layer in self.compositor_layer.iter() {
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() {
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>) {
let world_zoom = self.world_zoom;
fn on_scroll_window_event(&mut self,
delta: TypedPoint2D<DevicePixel, f32>,
cursor: TypedPoint2D<DevicePixel, i32>) {
let scale = self.device_pixels_per_page_px();
// 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_cursor: Point2D<f32> = Point2D(cursor.x as f32 / world_zoom,
cursor.y as f32 / world_zoom);
let page_window = Size2D(self.window_size.width as f32 / world_zoom,
self.window_size.height as f32 / world_zoom);
let page_delta = delta / scale;
let page_cursor = cursor.as_f32() / scale;
let page_window = self.page_window();
let mut scroll = false;
for layer in self.compositor_layer.mut_iter() {
scroll = layer.handle_scroll_event(page_delta, page_cursor, page_window) || scroll;
@ -639,27 +640,45 @@ impl IOCompositor {
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) {
self.zoom_action = true;
self.zoom_time = precise_time_s();
let old_world_zoom = self.world_zoom;
let window_size = &self.window_size;
let window_size = self.window_size.as_f32();
// 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;
{
self.root_layer.common.borrow_mut().set_transform(identity().scale(world_zoom, world_zoom, 1f32));
}
self.update_zoom_transform();
// Scroll as needed
let page_delta = Point2D(window_size.width as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5,
window_size.height as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5);
let page_delta = TypedPoint2D(
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.
let page_cursor = Point2D(-1f32, -1f32); // Make sure this hits the base layer
let page_window = Size2D(window_size.width as f32 / world_zoom,
window_size.height as f32 / world_zoom);
let page_cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer
let page_window = self.page_window();
for layer in self.compositor_layer.mut_iter() {
layer.handle_scroll_event(page_delta, page_cursor, page_window);
}
@ -678,15 +697,14 @@ impl IOCompositor {
/// Get BufferRequests from each layer.
fn ask_for_tiles(&mut self) {
let world_zoom = self.world_zoom;
let window_size_page = Size2D(self.window_size.width as f32 / world_zoom,
self.window_size.height as f32 / world_zoom);
let scale = self.device_pixels_per_page_px();
let page_window = self.page_window();
for layer in self.compositor_layer.mut_iter() {
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,
rect,
world_zoom) ||
scale.get()) ||
self.recomposite;
self.recomposite = recomposite;
} else {
@ -699,7 +717,7 @@ impl IOCompositor {
profile(time::CompositingCategory, self.profiler_chan.clone(), || {
debug!("compositor: compositing");
// 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.
match self.compositor_layer {
Some(ref mut layer) => {
@ -717,7 +735,7 @@ impl IOCompositor {
// self.window.present()) as OpenGL ES 2 does not have glReadBuffer().
if self.load_complete && self.ready_state == FinishedLoading
&& 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 mut pixels = gl2::read_pixels(0, 0,
width as gl2::GLsizei,

Просмотреть файл

@ -8,10 +8,11 @@ use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEve
use windowing::{MouseWindowMouseUpEvent};
use azure::azure_hl::Color;
use geom::length::Length;
use geom::matrix::identity;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use geom::point::{Point2D, TypedPoint2D};
use geom::rect::{Rect, TypedRect};
use geom::size::{Size2D, TypedSize2D};
use gfx::render_task::{ReRenderMsg, UnusedBufferMsg};
use gfx;
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::{ScrollPolicy, Tile};
use servo_msg::constellation_msg::PipelineId;
use servo_util::geometry::PagePx;
use std::rc::Rc;
#[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
/// 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
/// differs in scroll behavior from its parent. Each is associated with a
@ -169,7 +171,7 @@ impl CompositorLayer {
id: layer_id,
bounds: bounds,
page_size: page_size,
scroll_offset: Point2D(0f32, 0f32),
scroll_offset: TypedPoint2D(0f32, 0f32),
children: vec!(),
quadtree: match page_size {
None => NoTree(tile_size, Some(MAX_TILE_MEMORY_PER_LAYER)),
@ -202,7 +204,7 @@ impl CompositorLayer {
id: LayerId::null(),
bounds: Rect(Point2D(0f32, 0f32), page_size),
page_size: Some(page_size),
scroll_offset: Point2D(0f32, 0f32),
scroll_offset: TypedPoint2D(0f32, 0f32),
children: vec!(),
quadtree: NoTree(tile_size, Some(MAX_TILE_MEMORY_PER_LAYER)),
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
/// returns false, so a parent layer can scroll instead.
pub fn handle_scroll_event(&mut self,
delta: Point2D<f32>,
cursor: Point2D<f32>,
window_size: Size2D<f32>)
delta: TypedPoint2D<PagePx, f32>,
cursor: TypedPoint2D<PagePx, f32>,
window_size: TypedSize2D<PagePx, f32>)
-> bool {
// If this layer is hidden, neither it nor its children will scroll.
if self.hidden {
@ -308,6 +310,7 @@ impl CompositorLayer {
error!("CompositorLayer: unable to perform cursor hit test for layer");
}
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
&& cursor.y >= rect.origin.y && cursor.y < rect.origin.y + rect.size.height
&& child.child.handle_scroll_event(delta,
@ -329,12 +332,17 @@ impl CompositorLayer {
Some(size) => size,
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
}
@ -358,7 +366,7 @@ impl CompositorLayer {
/// 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.
fn scroll(&mut self, scroll_offset: Point2D<f32>) -> bool {
fn scroll(&mut self, scroll_offset: TypedPoint2D<PagePx, f32>) -> bool {
let mut result = false;
// Only scroll this layer if it's not fixed-positioned.
@ -367,7 +375,7 @@ impl CompositorLayer {
self.scroll_offset = scroll_offset;
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
}
@ -382,7 +390,7 @@ impl CompositorLayer {
// 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
// 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;
for child in self.children.iter().filter(|&x| !x.child.hidden) {
match *child.container.scissor.borrow() {
@ -390,6 +398,7 @@ impl CompositorLayer {
error!("CompositorLayer: unable to perform cursor hit test for layer");
}
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
&& cursor.y >= rect.origin.y && cursor.y < rect.origin.y + rect.size.height {
child.child.send_mouse_event(event, cursor - rect.origin);
@ -401,16 +410,16 @@ impl CompositorLayer {
// This mouse event is mine!
let message = match event {
MouseWindowClickEvent(button, _) => ClickEvent(button, cursor),
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor),
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor),
MouseWindowClickEvent(button, _) => ClickEvent(button, cursor.to_untyped()),
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor.to_untyped()),
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor.to_untyped()),
};
let ScriptChan(ref chan) = self.pipeline.script_chan;
let _ = chan.send_opt(SendEventMsg(self.pipeline.id.clone(), message));
}
pub fn send_mouse_move_event(&self, cursor: Point2D<f32>) {
let message = MouseMoveEvent(cursor);
pub fn send_mouse_move_event(&self, cursor: TypedPoint2D<PagePx, f32>) {
let message = MouseMoveEvent(cursor.to_untyped());
let ScriptChan(ref chan) = self.pipeline.script_chan;
let _ = chan.send_opt(SendEventMsg(self.pipeline.id.clone(), message));
}
@ -453,8 +462,9 @@ impl CompositorLayer {
match *x.container.scissor.borrow() {
Some(scissor) => {
let mut new_rect = window_rect;
new_rect.origin.x = new_rect.origin.x - x.child.scroll_offset.x;
new_rect.origin.y = new_rect.origin.y - x.child.scroll_offset.y;
let offset = x.child.scroll_offset.to_untyped();
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) {
Some(new_rect) => {
// Child layers act as if they are rendered at (0,0), so we
@ -535,7 +545,7 @@ impl CompositorLayer {
pipeline_id: PipelineId,
layer_id: LayerId,
new_size: Size2D<f32>,
window_size: Size2D<f32>,
window_size: TypedSize2D<PagePx, f32>,
epoch: Epoch)
-> bool {
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
// 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.set_occlusions();
true
@ -572,7 +582,7 @@ impl CompositorLayer {
pipeline_id: PipelineId,
layer_id: LayerId,
origin: Point2D<f32>,
window_size: Size2D<f32>)
window_size: TypedSize2D<PagePx, f32>)
-> bool {
// Search children for the right layer to move.
if self.pipeline.id != pipeline_id || self.id != layer_id {
@ -587,20 +597,23 @@ impl CompositorLayer {
// Scroll this layer!
let old_origin = self.scroll_offset;
self.scroll_offset = Point2D(0f32, 0f32) - origin;
self.scroll_offset = Point2D::from_untyped(&(origin * -1.0));
// bounds checking
let page_size = match self.page_size {
Some(size) => size,
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);
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);
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
if old_origin - self.scroll_offset == Point2D(0f32, 0f32) {
if old_origin - self.scroll_offset == TypedPoint2D(0f32, 0f32) {
return false;
}
@ -669,9 +682,10 @@ impl CompositorLayer {
Some(scissor) => {
// 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.
child.handle_scroll_event(Point2D(0f32, 0f32),
Point2D(-1f32, -1f32),
scissor.size);
let size: TypedSize2D<PagePx, f32> = Size2D::from_untyped(&scissor.size);
child.handle_scroll_event(TypedPoint2D(0f32, 0f32),
TypedPoint2D(-1f32, -1f32),
size);
child.hidden = false;
}
None => {} // Nothing to do

Просмотреть файл

@ -19,10 +19,12 @@ use std::cell::{Cell, RefCell};
use std::comm::Receiver;
use std::rc::Rc;
use geom::point::Point2D;
use geom::size::Size2D;
use geom::point::{Point2D, TypedPoint2D};
use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
use servo_util::geometry::{ScreenPx, DevicePixel};
use glfw;
use glfw::Context;
@ -144,9 +146,9 @@ impl WindowMethods<Application> for 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();
Size2D(width as f32, height as f32)
TypedSize2D(width as f32, height as f32)
}
/// Presents the window to the screen (perhaps by page flipping).
@ -193,10 +195,10 @@ impl WindowMethods<Application> for Window {
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 (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) => {
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) => {
let dx = (xpos as f32) * 30.0;
@ -241,7 +244,8 @@ impl Window {
let x = x 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 => {
self.mouse_down_point.set(Point2D(x, y));
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 => {
match self.mouse_down_button.get() {
@ -318,13 +322,13 @@ impl Window {
pixel_dist.y * pixel_dist.y) as f64).sqrt();
if pixel_dist < max_pixel_dist {
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));
}
}
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. :-(")
};

Просмотреть файл

@ -14,10 +14,12 @@ use alert::{Alert, AlertMethods};
use libc::{c_int, c_uchar};
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use geom::point::Point2D;
use geom::size::Size2D;
use geom::point::{Point2D, TypedPoint2D};
use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
use servo_msg::compositor_msg::{FinishedLoading, Blank, ReadyState};
use servo_util::geometry::{ScreenPx, DevicePixel};
use glut::glut::{ACTIVE_SHIFT, DOUBLE, WindowHeight};
use glut::glut::WindowWidth;
@ -118,11 +120,15 @@ impl WindowMethods<Application> for Window {
match button {
3 => {
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 => {
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.
fn size(&self) -> Size2D<f32> {
Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
fn size(&self) -> TypedSize2D<DevicePixel, f32> {
TypedSize2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
}
/// Presents the window to the screen (perhaps by page flipping).
@ -179,9 +185,9 @@ impl WindowMethods<Application> for Window {
//self.update_window_title()
}
fn hidpi_factor(&self) -> f32 {
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
//FIXME: Do nothing in GLUT now.
1f32
ScaleFactor(1.0)
}
}
@ -218,8 +224,10 @@ impl Window {
42 => self.load_url(),
43 => self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1)),
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))),
50 => 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),
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 => {
if (modifiers & ACTIVE_SHIFT) != 0 {
self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
@ -240,7 +248,7 @@ impl Window {
glut::MOUSE_DOWN => {
self.mouse_down_point.set(Point2D(x, y));
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 => {
if self.mouse_down_button.get() == button {
@ -249,11 +257,11 @@ impl Window {
pixel_dist.y * pixel_dist.y) as f32).sqrt();
if pixel_dist < max_pixel_dist {
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));
}
}
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. :-(")
};

Просмотреть файл

@ -4,15 +4,17 @@
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
use geom::point::Point2D;
use geom::size::Size2D;
use geom::point::TypedPoint2D;
use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use servo_msg::compositor_msg::{ReadyState, RenderState};
use servo_util::geometry::{ScreenPx, DevicePixel};
use std::rc::Rc;
pub enum MouseWindowEvent {
MouseWindowClickEvent(uint, Point2D<f32>),
MouseWindowMouseDownEvent(uint, Point2D<f32>),
MouseWindowMouseUpEvent(uint, Point2D<f32>),
MouseWindowClickEvent(uint, TypedPoint2D<DevicePixel, f32>),
MouseWindowMouseDownEvent(uint, TypedPoint2D<DevicePixel, f32>),
MouseWindowMouseUpEvent(uint, TypedPoint2D<DevicePixel, f32>),
}
pub enum WindowNavigateMsg {
@ -36,9 +38,9 @@ pub enum WindowEvent {
/// Sent when a mouse hit test is to be performed.
MouseWindowEventClass(MouseWindowEvent),
/// Sent when a mouse move.
MouseWindowMoveEventClass(Point2D<f32>),
MouseWindowMoveEventClass(TypedPoint2D<DevicePixel, f32>),
/// 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.
ZoomWindowEvent(f32),
/// 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.
fn new(app: &A, is_foreground: bool) -> Rc<Self>;
/// 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).
fn present(&self);
@ -71,6 +73,6 @@ pub trait WindowMethods<A> {
fn set_render_state(&self, render_state: RenderState);
/// 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::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
// 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.
//
// FIXME: Implement Au using Length and ScaleFactor instead of a custom type.
#[deriving(Clone, Eq, Ord, Zero)]
pub struct Au(pub i32);

Просмотреть файл

@ -5,8 +5,11 @@
//! Configuration options for a single run of the servo application. Created
//! from command line arguments.
use geometry::{DevicePixel, ScreenPx};
use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
use geom::scale_factor::ScaleFactor;
use getopts;
use std::cmp;
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
/// 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
/// 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|
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") {