servo: Merge #20071 - Use typed coordinates more (from paulrouget:typedsize); r=glennw
authorPaul Rouget <me@paulrouget.com>
Fri, 16 Mar 2018 17:18:24 -0400
changeset 408694 6c397982f283e459e1623b2b0c7b0c5546981f5c
parent 408662 0665d23d7e8788a07048f1454ea4457c0197b9d0
child 408695 36bfb71a88eaf31a1e89f69920287e3fb74d4065
push id101011
push usernerli@mozilla.com
push dateSat, 17 Mar 2018 22:28:18 +0000
treeherdermozilla-inbound@efce78e62b6d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglennw
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #20071 - Use typed coordinates more (from paulrouget:typedsize); r=glennw Requires https://github.com/servo/servo/pull/19895 We use Size2D and Point2D across compositing, constellation and script, loosing the type of pixels we use (DevicePixel, DeviceIndepententPixel or CSSPixel) along the way, which might lead to bugs like `window.outerHeight` not taking into account the page zoom (using DeviceIndepententPixel instead of CSSPixel). This should make the situation a bit better. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because we can't zoom in a test <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: fc90e613d8851b663e3304d713b2ca08aa397bf4
servo/Cargo.lock
servo/components/compositing/compositor.rs
servo/components/compositing/compositor_thread.rs
servo/components/compositing/windowing.rs
servo/components/geometry/Cargo.toml
servo/components/geometry/lib.rs
servo/components/script/dom/screen.rs
servo/components/script/dom/window.rs
servo/components/script_traits/lib.rs
servo/components/script_traits/script_msg.rs
servo/components/servo/lib.rs
servo/components/webdriver_server/lib.rs
servo/ports/servo/glutin_app/window.rs
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -2810,16 +2810,17 @@ dependencies = [
 [[package]]
 name = "servo_geometry"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
+ "style_traits 0.0.1",
  "webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "servo_rand"
 version = "0.0.1"
 dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.rs
@@ -16,30 +16,30 @@ use msg::constellation_msg::{PipelineId,
 use net_traits::image::base::{Image, PixelFormat};
 use nonzero::NonZero;
 use profile_traits::time::{self, ProfilerCategory, profile};
 use script_traits::{AnimationState, AnimationTickType, ConstellationMsg, LayoutControlMsg};
 use script_traits::{MouseButton, MouseEventType, ScrollState, TouchEventType, TouchId};
 use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
 use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
 use servo_config::opts;
-use servo_geometry::DeviceIndependentPixel;
+use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
 use std::collections::HashMap;
 use std::env;
 use std::fs::File;
 use std::rc::Rc;
 use std::sync::mpsc::Sender;
 use std::time::{Duration, Instant};
 use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
 use style_traits::cursor::CursorKind;
 use style_traits::viewport::ViewportConstraints;
 use time::{now, precise_time_ns, precise_time_s};
 use touch::{TouchHandler, TouchAction};
 use webrender;
-use webrender_api::{self, DeviceUintRect, DeviceUintSize, HitTestFlags, HitTestResult};
+use webrender_api::{self, DeviceIntPoint, DevicePoint, DeviceUintRect, DeviceUintSize, HitTestFlags, HitTestResult};
 use webrender_api::{LayoutVector2D, ScrollEventPhase, ScrollLocation};
 use windowing::{self, MouseWindowEvent, WebRenderDebugOption, WindowMethods};
 
 #[derive(Debug, PartialEq)]
 enum UnableToComposite {
     WindowUnprepared,
     NotReadyToPaintImage(NotReadyToPaint),
 }
@@ -197,17 +197,17 @@ pub struct IOCompositor<Window: WindowMe
 
 #[derive(Clone, Copy)]
 struct ScrollZoomEvent {
     /// Change the pinch zoom level by this factor
     magnification: f32,
     /// Scroll by this offset, or to Start or End
     scroll_location: ScrollLocation,
     /// Apply changes to the frame at this location
-    cursor: TypedPoint2D<i32, DevicePixel>,
+    cursor: DeviceIntPoint,
     /// The scroll event phase.
     phase: ScrollEventPhase,
     /// The number of OS events that have been coalesced together into this one event.
     event_count: u32,
 }
 
 #[derive(Debug, PartialEq)]
 enum CompositionRequest {
@@ -270,40 +270,40 @@ impl RenderTargetInfo {
         RenderTargetInfo {
             framebuffer_ids: Vec::new(),
             renderbuffer_ids: Vec::new(),
             texture_ids: Vec::new(),
         }
     }
 }
 
-fn initialize_png(gl: &gl::Gl, width: usize, height: usize) -> RenderTargetInfo {
+fn initialize_png(gl: &gl::Gl, width: DeviceUintLength, height: DeviceUintLength) -> RenderTargetInfo {
     let framebuffer_ids = gl.gen_framebuffers(1);
     gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
 
     let texture_ids = gl.gen_textures(1);
     gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]);
 
-    gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as gl::GLint, width as gl::GLsizei,
-                    height as gl::GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None);
+    gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as gl::GLint, width.get() as gl::GLsizei,
+                    height.get() as gl::GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None);
     gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as gl::GLint);
     gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as gl::GLint);
 
     gl.framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D,
                               texture_ids[0], 0);
 
     gl.bind_texture(gl::TEXTURE_2D, 0);
 
     let renderbuffer_ids = gl.gen_renderbuffers(1);
     let depth_rb = renderbuffer_ids[0];
     gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
     gl.renderbuffer_storage(gl::RENDERBUFFER,
                             gl::DEPTH_COMPONENT24,
-                            width as gl::GLsizei,
-                            height as gl::GLsizei);
+                            width.get() as gl::GLsizei,
+                            height.get() as gl::GLsizei);
     gl.framebuffer_renderbuffer(gl::FRAMEBUFFER,
                                 gl::DEPTH_ATTACHMENT,
                                 gl::RENDERBUFFER,
                                 depth_rb);
 
     RenderTargetInfo {
         framebuffer_ids: framebuffer_ids,
         renderbuffer_ids: renderbuffer_ids,
@@ -642,19 +642,21 @@ impl<Window: WindowMethods> IOCompositor
                                                  self.hidpi_factor().get());
 
         let initial_viewport = self.window_rect.size.to_f32() / dppx;
 
         let data = WindowSizeData {
             device_pixel_ratio: dppx,
             initial_viewport: initial_viewport,
         };
+
         let top_level_browsing_context_id = self.root_pipeline.as_ref().map(|pipeline| {
             pipeline.top_level_browsing_context_id
         });
+
         let msg = ConstellationMsg::WindowSize(top_level_browsing_context_id, data, size_type);
 
         if let Err(e) = self.constellation_chan.send(msg) {
             warn!("Sending window resize to constellation failed ({}).", e);
         }
     }
 
     pub fn on_resize_window_event(&mut self) {
@@ -723,40 +725,40 @@ impl<Window: WindowMethods> IOCompositor
 
         let pipeline_id = PipelineId::from_webrender(result.pipeline);
         let msg = ConstellationMsg::ForwardEvent(pipeline_id, event_to_send);
         if let Err(e) = self.constellation_chan.send(msg) {
             warn!("Sending event to constellation failed ({}).", e);
         }
     }
 
-    fn hit_test_at_point(&self, point: TypedPoint2D<f32, DevicePixel>) -> HitTestResult {
+    fn hit_test_at_point(&self, point: DevicePoint) -> HitTestResult {
         let dppx = self.page_zoom * self.hidpi_factor();
         let scaled_point = (point / dppx).to_untyped();
 
         let world_cursor = webrender_api::WorldPoint::from_untyped(&scaled_point);
         self.webrender_api.hit_test(
             self.webrender_document,
             None,
             world_cursor,
             HitTestFlags::empty()
         )
 
     }
 
-    pub fn on_mouse_window_move_event_class(&mut self, cursor: TypedPoint2D<f32, DevicePixel>) {
+    pub fn on_mouse_window_move_event_class(&mut self, cursor: DevicePoint) {
         if opts::get().convert_mouse_to_touch {
             self.on_touch_move(TouchId(0), cursor);
             return
         }
 
         self.dispatch_mouse_window_move_event_class(cursor);
     }
 
-    fn dispatch_mouse_window_move_event_class(&mut self, cursor: TypedPoint2D<f32, DevicePixel>) {
+    fn dispatch_mouse_window_move_event_class(&mut self, cursor: DevicePoint) {
         let root_pipeline_id = match self.get_root_pipeline_id() {
             Some(root_pipeline_id) => root_pipeline_id,
             None => return,
         };
         if self.pipeline(root_pipeline_id).is_none() {
             return;
         }
 
@@ -778,17 +780,17 @@ impl<Window: WindowMethods> IOCompositor
             }
         }
     }
 
     fn send_touch_event(
         &self,
         event_type: TouchEventType,
         identifier: TouchId,
-        point: TypedPoint2D<f32, DevicePixel>)
+        point: DevicePoint)
     {
         let results = self.hit_test_at_point(point);
         if let Some(item) = results.items.first() {
             let event = TouchEvent(
                 event_type,
                 identifier,
                 item.point_in_viewport.to_untyped(),
                 Some(UntrustedNodeAddress(item.tag.0 as *const c_void)),
@@ -799,31 +801,31 @@ impl<Window: WindowMethods> IOCompositor
                 warn!("Sending event to constellation failed ({}).", e);
             }
         }
     }
 
     pub fn on_touch_event(&mut self,
                           event_type: TouchEventType,
                           identifier: TouchId,
-                          location: TypedPoint2D<f32, DevicePixel>) {
+                          location: DevicePoint) {
         match event_type {
             TouchEventType::Down => self.on_touch_down(identifier, location),
             TouchEventType::Move => self.on_touch_move(identifier, location),
             TouchEventType::Up => self.on_touch_up(identifier, location),
             TouchEventType::Cancel => self.on_touch_cancel(identifier, location),
         }
     }
 
-    fn on_touch_down(&mut self, identifier: TouchId, point: TypedPoint2D<f32, DevicePixel>) {
+    fn on_touch_down(&mut self, identifier: TouchId, point: DevicePoint) {
         self.touch_handler.on_touch_down(identifier, point);
         self.send_touch_event(TouchEventType::Down, identifier, point);
     }
 
-    fn on_touch_move(&mut self, identifier: TouchId, point: TypedPoint2D<f32, DevicePixel>) {
+    fn on_touch_move(&mut self, identifier: TouchId, point: DevicePoint) {
         match self.touch_handler.on_touch_move(identifier, point) {
             TouchAction::Scroll(delta) => {
                 match point.cast() {
                     Some(point) => self.on_scroll_window_event(
                         ScrollLocation::Delta(
                             LayoutVector2D::from_untyped(&delta.to_untyped())
                         ),
                         point
@@ -844,57 +846,57 @@ impl<Window: WindowMethods> IOCompositor
             }
             TouchAction::DispatchEvent => {
                 self.send_touch_event(TouchEventType::Move, identifier, point);
             }
             _ => {}
         }
     }
 
-    fn on_touch_up(&mut self, identifier: TouchId, point: TypedPoint2D<f32, DevicePixel>) {
+    fn on_touch_up(&mut self, identifier: TouchId, point: DevicePoint) {
         self.send_touch_event(TouchEventType::Up, identifier, point);
 
         if let TouchAction::Click = self.touch_handler.on_touch_up(identifier, point) {
             self.simulate_mouse_click(point);
         }
     }
 
-    fn on_touch_cancel(&mut self, identifier: TouchId, point: TypedPoint2D<f32, DevicePixel>) {
+    fn on_touch_cancel(&mut self, identifier: TouchId, point: DevicePoint) {
         // Send the event to script.
         self.touch_handler.on_touch_cancel(identifier, point);
         self.send_touch_event(TouchEventType::Cancel, identifier, point);
     }
 
     /// <http://w3c.github.io/touch-events/#mouse-events>
-    fn simulate_mouse_click(&mut self, p: TypedPoint2D<f32, DevicePixel>) {
+    fn simulate_mouse_click(&mut self, p: DevicePoint) {
         let button = MouseButton::Left;
         self.dispatch_mouse_window_move_event_class(p);
         self.dispatch_mouse_window_event_class(MouseWindowEvent::MouseDown(button, p));
         self.dispatch_mouse_window_event_class(MouseWindowEvent::MouseUp(button, p));
         self.dispatch_mouse_window_event_class(MouseWindowEvent::Click(button, p));
     }
 
     pub fn on_scroll_event(&mut self,
                            delta: ScrollLocation,
-                           cursor: TypedPoint2D<i32, DevicePixel>,
+                           cursor: DeviceIntPoint,
                            phase: TouchEventType) {
         match phase {
             TouchEventType::Move => self.on_scroll_window_event(delta, cursor),
             TouchEventType::Up | TouchEventType::Cancel => {
                 self.on_scroll_end_window_event(delta, cursor);
             }
             TouchEventType::Down => {
                 self.on_scroll_start_window_event(delta, cursor);
             }
         }
     }
 
     fn on_scroll_window_event(&mut self,
                               scroll_location: ScrollLocation,
-                              cursor: TypedPoint2D<i32, DevicePixel>) {
+                              cursor: DeviceIntPoint) {
         let event_phase = match (self.scroll_in_progress, self.in_scroll_transaction) {
             (false, None) => ScrollEventPhase::Start,
             (false, Some(last_scroll)) if last_scroll.elapsed() > Duration::from_millis(80) =>
                 ScrollEventPhase::Start,
             (_, _) => ScrollEventPhase::Move(self.scroll_in_progress),
         };
         self.in_scroll_transaction = Some(Instant::now());
         self.pending_scroll_zoom_events.push(ScrollZoomEvent {
@@ -903,30 +905,30 @@ impl<Window: WindowMethods> IOCompositor
             cursor: cursor,
             phase: event_phase,
             event_count: 1,
         });
     }
 
     fn on_scroll_start_window_event(&mut self,
                                     scroll_location: ScrollLocation,
-                                    cursor: TypedPoint2D<i32, DevicePixel>) {
+                                    cursor: DeviceIntPoint) {
         self.scroll_in_progress = true;
         self.pending_scroll_zoom_events.push(ScrollZoomEvent {
             magnification: 1.0,
             scroll_location: scroll_location,
             cursor: cursor,
             phase: ScrollEventPhase::Start,
             event_count: 1,
         });
     }
 
     fn on_scroll_end_window_event(&mut self,
                                   scroll_location: ScrollLocation,
-                                  cursor: TypedPoint2D<i32, DevicePixel>) {
+                                  cursor: DeviceIntPoint) {
         self.scroll_in_progress = false;
         self.pending_scroll_zoom_events.push(ScrollZoomEvent {
             magnification: 1.0,
             scroll_location: scroll_location,
             cursor: cursor,
             phase: ScrollEventPhase::End,
             event_count: 1,
         });
@@ -1249,18 +1251,17 @@ impl<Window: WindowMethods> IOCompositor
     /// Composite either to the screen or to a png image or both.
     /// Returns Ok if composition was performed or Err if it was not possible to composite
     /// for some reason. If CompositeTarget is Window or Png no image data is returned;
     /// in the latter case the image is written directly to a file. If CompositeTarget
     /// is WindowAndPng Ok(Some(png::Image)) is returned.
     fn composite_specific_target(&mut self,
                                  target: CompositeTarget)
                                  -> Result<Option<Image>, UnableToComposite> {
-        let (width, height) =
-            (self.frame_size.width as usize, self.frame_size.height as usize);
+        let (width, height) = (self.frame_size.width_typed(), self.frame_size.height_typed());
         if !self.window.prepare_for_composite(width, height) {
             return Err(UnableToComposite::WindowUnprepared)
         }
 
         self.webrender.update();
 
         let wait_for_stable_image = match target {
             CompositeTarget::WindowAndPng | CompositeTarget::PngFile => true,
@@ -1370,19 +1371,21 @@ impl<Window: WindowMethods> IOCompositor
         self.start_scrolling_bounce_if_necessary();
         self.waiting_for_results_of_scroll = false;
 
         Ok(rv)
     }
 
     fn draw_img(&self,
                 render_target_info: RenderTargetInfo,
-                width: usize,
-                height: usize)
+                width: DeviceUintLength,
+                height: DeviceUintLength)
                 -> RgbImage {
+        let width = width.get() as usize;
+        let height = height.get() as usize;
         // For some reason, OSMesa fails to render on the 3rd
         // attempt in headless mode, under some conditions.
         // I think this can only be some kind of synchronization
         // bug in OSMesa, but explicitly un-binding any vertex
         // array here seems to work around that bug.
         // See https://github.com/servo/servo/issues/18606.
         self.gl.bind_vertex_array(0);
 
--- a/servo/components/compositing/compositor_thread.rs
+++ b/servo/components/compositing/compositor_thread.rs
@@ -1,31 +1,30 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Communication with the compositor thread.
 
 use SendableFrameTree;
 use compositor::CompositingReason;
-use euclid::{Point2D, Size2D};
 use gfx_traits::Epoch;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId};
 use net_traits::image::base::Image;
 use profile_traits::mem;
 use profile_traits::time;
 use script_traits::{AnimationState, ConstellationMsg, EventResult, LoadData};
 use servo_url::ServoUrl;
 use std::fmt::{Debug, Error, Formatter};
 use std::sync::mpsc::{Receiver, Sender};
 use style_traits::cursor::CursorKind;
 use style_traits::viewport::ViewportConstraints;
 use webrender;
-use webrender_api;
+use webrender_api::{self, DeviceIntPoint, DeviceUintSize};
 
 
 /// Used to wake up the event loop, provided by the servo port/embedder.
 pub trait EventLoopWaker : 'static + Send {
     fn clone(&self) -> Box<EventLoopWaker + Send>;
     fn wake(&self);
 }
 
@@ -114,25 +113,26 @@ impl CompositorProxy {
 }
 
 pub enum EmbedderMsg {
     /// A status message to be displayed by the browser chrome.
     Status(TopLevelBrowsingContextId, Option<String>),
     /// Alerts the embedder that the current page has changed its title.
     ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
     /// Move the window to a point
-    MoveTo(TopLevelBrowsingContextId, Point2D<i32>),
+    MoveTo(TopLevelBrowsingContextId, DeviceIntPoint),
     /// Resize the window to size
-    ResizeTo(TopLevelBrowsingContextId, Size2D<u32>),
+    ResizeTo(TopLevelBrowsingContextId, DeviceUintSize),
     /// Get Window Informations size and position
-    GetClientWindow(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>, Point2D<i32>)>),
+    GetClientWindow(TopLevelBrowsingContextId,
+                    IpcSender<(DeviceUintSize, DeviceIntPoint)>),
     /// Get screen size (pixel)
-    GetScreenSize(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>)>),
+    GetScreenSize(TopLevelBrowsingContextId, IpcSender<(DeviceUintSize)>),
     /// Get screen available size (pixel)
-    GetScreenAvailSize(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>)>),
+    GetScreenAvailSize(TopLevelBrowsingContextId, IpcSender<(DeviceUintSize)>),
     /// Wether or not to follow a link
     AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
     /// Sends an unconsumed key event back to the embedder.
     KeyEvent(Option<TopLevelBrowsingContextId>, Option<char>, Key, KeyState, KeyModifiers),
     /// Changes the cursor.
     SetCursor(CursorKind),
     /// A favicon was detected
     NewFavicon(TopLevelBrowsingContextId, ServoUrl),
--- a/servo/components/compositing/windowing.rs
+++ b/servo/components/compositing/windowing.rs
@@ -1,35 +1,34 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
 
 use compositor_thread::EventLoopWaker;
-use euclid::{Point2D, Size2D};
-use euclid::{TypedScale, TypedPoint2D, TypedSize2D};
+use euclid::TypedScale;
 use gleam::gl;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection};
 use net_traits::net_error_list::NetError;
 use script_traits::{LoadData, MouseButton, TouchEventType, TouchId};
-use servo_geometry::DeviceIndependentPixel;
+use servo_geometry::{DeviceIndependentPixel, DeviceUintLength};
 use servo_url::ServoUrl;
 use std::fmt::{Debug, Error, Formatter};
 use std::rc::Rc;
 use style_traits::DevicePixel;
 use style_traits::cursor::CursorKind;
-use webrender_api::{DeviceUintSize, DeviceUintRect, ScrollLocation};
+use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation};
 
 #[derive(Clone)]
 pub enum MouseWindowEvent {
-    Click(MouseButton, TypedPoint2D<f32, DevicePixel>),
-    MouseDown(MouseButton, TypedPoint2D<f32, DevicePixel>),
-    MouseUp(MouseButton, TypedPoint2D<f32, DevicePixel>),
+    Click(MouseButton, DevicePoint),
+    MouseDown(MouseButton, DevicePoint),
+    MouseUp(MouseButton, DevicePoint),
 }
 
 /// Various debug and profiling flags that WebRender supports.
 #[derive(Clone)]
 pub enum WebRenderDebugOption {
     Profiler,
     TextureCacheDebug,
     RenderTargetDebug,
@@ -50,22 +49,22 @@ pub enum WindowEvent {
     Refresh,
     /// Sent when the window is resized.
     Resize,
     /// Sent when a new URL is to be loaded.
     LoadUrl(TopLevelBrowsingContextId, ServoUrl),
     /// Sent when a mouse hit test is to be performed.
     MouseWindowEventClass(MouseWindowEvent),
     /// Sent when a mouse move.
-    MouseWindowMoveEventClass(TypedPoint2D<f32, DevicePixel>),
+    MouseWindowMoveEventClass(DevicePoint),
     /// Touch event: type, identifier, point
-    Touch(TouchEventType, TouchId, TypedPoint2D<f32, DevicePixel>),
+    Touch(TouchEventType, TouchId, DevicePoint),
     /// Sent when the user scrolls. The first point is the delta and the second point is the
     /// origin.
-    Scroll(ScrollLocation, TypedPoint2D<i32, DevicePixel>, TouchEventType),
+    Scroll(ScrollLocation, DeviceIntPoint, TouchEventType),
     /// Sent when the user zooms.
     Zoom(f32),
     /// Simulated "pinch zoom" gesture for non-touch platforms (e.g. ctrl-scrollwheel).
     PinchZoom(f32),
     /// Sent when the user resets zoom to default.
     ResetZoom,
     /// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace).
     Navigation(TopLevelBrowsingContextId, TraversalDirection),
@@ -121,31 +120,29 @@ pub enum AnimationState {
     Animating,
 }
 
 pub trait WindowMethods {
     /// Returns the rendering area size in hardware pixels.
     fn framebuffer_size(&self) -> DeviceUintSize;
     /// Returns the position and size of the window within the rendering area.
     fn window_rect(&self) -> DeviceUintRect;
-    /// Returns the size of the window in density-independent "px" units.
-    fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel>;
     /// Presents the window to the screen (perhaps by page flipping).
     fn present(&self);
 
     /// Return the size of the window with head and borders and position of the window values
-    fn client_window(&self, ctx: TopLevelBrowsingContextId) -> (Size2D<u32>, Point2D<i32>);
-    /// Return the size of the screen (pixel)
-    fn screen_size(&self, ctx: TopLevelBrowsingContextId) -> Size2D<u32>;
-    /// Return the available size of the screen (pixel)
-    fn screen_avail_size(&self, ctx: TopLevelBrowsingContextId) -> Size2D<u32>;
+    fn client_window(&self, ctx: TopLevelBrowsingContextId) -> (DeviceUintSize, DeviceIntPoint);
+    /// Return the size of the screen.
+    fn screen_size(&self, ctx: TopLevelBrowsingContextId) -> DeviceUintSize;
+    /// Return the available size of the screen.
+    fn screen_avail_size(&self, ctx: TopLevelBrowsingContextId) -> DeviceUintSize;
     /// Set the size inside of borders and head
-    fn set_inner_size(&self, ctx: TopLevelBrowsingContextId, size: Size2D<u32>);
+    fn set_inner_size(&self, ctx: TopLevelBrowsingContextId, size: DeviceUintSize);
     /// Set the window position
-    fn set_position(&self, ctx: TopLevelBrowsingContextId, point: Point2D<i32>);
+    fn set_position(&self, ctx: TopLevelBrowsingContextId, point: DeviceIntPoint);
     /// Set fullscreen state
     fn set_fullscreen_state(&self, ctx: TopLevelBrowsingContextId, state: bool);
 
     /// Sets the page title for the current page.
     fn set_page_title(&self, ctx: TopLevelBrowsingContextId, title: Option<String>);
     /// Called when the browser chrome should display a status message.
     fn status(&self, ctx: TopLevelBrowsingContextId, Option<String>);
     /// Called when the browser has started loading a frame.
@@ -165,17 +162,17 @@ pub trait WindowMethods {
     fn hidpi_factor(&self) -> TypedScale<f32, DeviceIndependentPixel, DevicePixel>;
 
     /// Returns a thread-safe object to wake up the window's event loop.
     fn create_event_loop_waker(&self) -> Box<EventLoopWaker>;
 
     /// Requests that the window system prepare a composite. Typically this will involve making
     /// some type of platform-specific graphics context current. Returns true if the composite may
     /// proceed and false if it should not.
-    fn prepare_for_composite(&self, width: usize, height: usize) -> bool;
+    fn prepare_for_composite(&self, width: DeviceUintLength, height: DeviceUintLength) -> bool;
 
     /// Sets the cursor to be used in the window.
     fn set_cursor(&self, cursor: CursorKind);
 
     /// Process a key event.
     fn handle_key(&self, ctx: Option<TopLevelBrowsingContextId>, ch: Option<char>, key: Key, mods: KeyModifiers);
 
     /// Does this window support a clipboard
--- a/servo/components/geometry/Cargo.toml
+++ b/servo/components/geometry/Cargo.toml
@@ -9,9 +9,10 @@ publish = false
 name = "servo_geometry"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.6"
 euclid = "0.17"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
+style_traits = { path = "../style_traits" }
 webrender_api = { git = "https://github.com/servo/webrender" }
--- a/servo/components/geometry/lib.rs
+++ b/servo/components/geometry/lib.rs
@@ -1,25 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 extern crate app_units;
 extern crate euclid;
 extern crate malloc_size_of;
+extern crate style_traits;
 #[macro_use] extern crate malloc_size_of_derive;
 extern crate webrender_api;
 
 use app_units::{Au, MAX_AU, MIN_AU};
-use euclid::{Point2D, Rect, Size2D};
+use euclid::{Length, Point2D, Rect, Size2D};
 use std::f32;
+use style_traits::DevicePixel;
 use webrender_api::{LayoutPoint, LayoutRect, LayoutSize};
 
 // Units for use with euclid::length and euclid::scale_factor.
 
+pub type DeviceUintLength = Length<u32, 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 DeviceIndependentPixel is defined by the OS.  On most low-dpi
 /// screens, one DeviceIndependentPixel is equal to one DevicePixel.  But on high-density screens it can be
--- a/servo/components/script/dom/screen.rs
+++ b/servo/components/script/dom/screen.rs
@@ -6,19 +6,21 @@ use dom::bindings::codegen::Bindings::Sc
 use dom::bindings::codegen::Bindings::ScreenBinding::ScreenMethods;
 use dom::bindings::inheritance::Castable;
 use dom::bindings::num::Finite;
 use dom::bindings::reflector::{Reflector, reflect_dom_object};
 use dom::bindings::root::{Dom, DomRoot};
 use dom::globalscope::GlobalScope;
 use dom::window::Window;
 use dom_struct::dom_struct;
-use euclid::Size2D;
+use euclid::TypedSize2D;
 use ipc_channel::ipc;
 use script_traits::ScriptMsg;
+use style_traits::CSSPixel;
+use webrender_api::DeviceUintSize;
 
 #[dom_struct]
 pub struct Screen {
     reflector_: Reflector,
     window: Dom<Window>,
 }
 
 impl Screen {
@@ -30,28 +32,32 @@ impl Screen {
     }
 
     pub fn new(window: &Window) -> DomRoot<Screen> {
         reflect_dom_object(Box::new(Screen::new_inherited(window)),
                            window,
                            ScreenBinding::Wrap)
     }
 
-    fn screen_size(&self) -> Size2D<u32> {
-        let (send, recv) = ipc::channel::<(Size2D<u32>)>().unwrap();
+    fn screen_size(&self) -> TypedSize2D<u32, CSSPixel> {
+        let (send, recv) = ipc::channel::<DeviceUintSize>().unwrap();
         self.window.upcast::<GlobalScope>()
             .script_to_constellation_chan().send(ScriptMsg::GetScreenSize(send)).unwrap();
-        recv.recv().unwrap_or(Size2D::zero())
+        let dpr = self.window.device_pixel_ratio();
+        let screen = recv.recv().unwrap_or(TypedSize2D::zero());
+        (screen.to_f32() / dpr).to_u32()
     }
 
-    fn screen_avail_size(&self) -> Size2D<u32> {
-        let (send, recv) = ipc::channel::<(Size2D<u32>)>().unwrap();
+    fn screen_avail_size(&self) -> TypedSize2D<u32, CSSPixel> {
+        let (send, recv) = ipc::channel::<DeviceUintSize>().unwrap();
         self.window.upcast::<GlobalScope>()
             .script_to_constellation_chan().send(ScriptMsg::GetScreenAvailSize(send)).unwrap();
-        recv.recv().unwrap_or(Size2D::zero())
+        let dpr = self.window.device_pixel_ratio();
+        let screen = recv.recv().unwrap_or(TypedSize2D::zero());
+        (screen.to_f32() / dpr).to_u32()
     }
 }
 
 impl ScreenMethods for Screen {
     // https://drafts.csswg.org/cssom-view/#dom-screen-availwidth
     fn AvailWidth(&self) -> Finite<f64> {
         Finite::wrap(self.screen_avail_size().width as f64)
     }
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -43,17 +43,17 @@ use dom::performance::Performance;
 use dom::promise::Promise;
 use dom::screen::Screen;
 use dom::storage::Storage;
 use dom::testrunner::TestRunner;
 use dom::windowproxy::WindowProxy;
 use dom::worklet::Worklet;
 use dom::workletglobalscope::WorkletGlobalScopeType;
 use dom_struct::dom_struct;
-use euclid::{Point2D, Vector2D, Rect, Size2D};
+use euclid::{Point2D, Vector2D, Rect, Size2D, TypedPoint2D, TypedScale, TypedSize2D};
 use fetch;
 use ipc_channel::ipc::{self, IpcSender};
 use ipc_channel::router::ROUTER;
 use js::jsapi::{HandleValue, JSAutoCompartment, JSContext};
 use js::jsapi::{JS_GC, JS_GetRuntime};
 use js::jsval::UndefinedValue;
 use layout_image::fetch_image_for_layout;
 use microtask::MicrotaskQueue;
@@ -97,31 +97,31 @@ use std::sync::atomic::{AtomicBool, Orde
 use std::sync::mpsc::{Sender, channel};
 use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
 use style::media_queries;
 use style::parser::ParserContext as CssParserContext;
 use style::properties::{ComputedValues, PropertyId};
 use style::selector_parser::PseudoElement;
 use style::str::HTML_SPACE_CHARACTERS;
 use style::stylesheets::CssRuleType;
-use style_traits::ParsingMode;
+use style_traits::{CSSPixel, DevicePixel, ParsingMode};
 use task::TaskCanceller;
 use task_source::dom_manipulation::DOMManipulationTaskSource;
 use task_source::file_reading::FileReadingTaskSource;
 use task_source::history_traversal::HistoryTraversalTaskSource;
 use task_source::networking::NetworkingTaskSource;
 use task_source::performance_timeline::PerformanceTimelineTaskSource;
 use task_source::user_interaction::UserInteractionTaskSource;
 use time;
 use timers::{IsInterval, TimerCallback};
 #[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
 use tinyfiledialogs::{self, MessageBoxIcon};
 use url::Position;
 use webdriver_handlers::jsval_to_webdriver;
-use webrender_api::{ExternalScrollId, DocumentId};
+use webrender_api::{ExternalScrollId, DeviceIntPoint, DeviceUintSize, DocumentId};
 use webvr_traits::WebVRMsg;
 
 /// Current state of the window object
 #[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)]
 enum WindowState {
     Alive,
     Zombie,     // Pipeline is closed, but the window hasn't been GCed yet.
 }
@@ -925,36 +925,38 @@ impl WindowMethods for Window {
         // Step 4
         let top =  y + self.ScrollY() as f64;
 
         // Step 5
         self.scroll(left, top, ScrollBehavior::Auto);
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-window-resizeto
-    fn ResizeTo(&self, x: i32, y: i32) {
+    fn ResizeTo(&self, width: i32, height: i32) {
         // Step 1
         //TODO determine if this operation is allowed
-        let size = Size2D::new(x.to_u32().unwrap_or(1), y.to_u32().unwrap_or(1));
-        self.send_to_constellation(ScriptMsg::ResizeTo(size));
+        let dpr = self.device_pixel_ratio();
+        let size = TypedSize2D::new(width, height).to_f32() * dpr;
+        self.send_to_constellation(ScriptMsg::ResizeTo(size.to_u32()));
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-window-resizeby
     fn ResizeBy(&self, x: i32, y: i32) {
         let (size, _) = self.client_window();
         // Step 1
         self.ResizeTo(x + size.width.to_i32().unwrap_or(1), y + size.height.to_i32().unwrap_or(1))
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-window-moveto
     fn MoveTo(&self, x: i32, y: i32) {
         // Step 1
         //TODO determine if this operation is allowed
-        let point = Point2D::new(x, y);
-        self.send_to_constellation(ScriptMsg::MoveTo(point));
+        let dpr = self.device_pixel_ratio();
+        let point = TypedPoint2D::new(x, y).to_f32() * dpr;
+        self.send_to_constellation(ScriptMsg::MoveTo(point.to_i32()));
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-window-moveby
     fn MoveBy(&self, x: i32, y: i32) {
         let (_, origin) = self.client_window();
         // Step 1
         self.MoveTo(x + origin.x, y + origin.y)
     }
@@ -980,18 +982,17 @@ impl WindowMethods for Window {
     // https://drafts.csswg.org/cssom-view/#dom-window-outerwidth
     fn OuterWidth(&self) -> i32 {
         let (size, _) = self.client_window();
         size.width.to_i32().unwrap_or(1)
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-window-devicepixelratio
     fn DevicePixelRatio(&self) -> Finite<f64> {
-        let dpr = self.window_size.get().map_or(1.0f32, |data| data.device_pixel_ratio.get());
-        Finite::wrap(dpr as f64)
+        Finite::wrap(self.device_pixel_ratio().get() as f64)
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-window-status
     fn Status(&self) -> DOMString {
         self.status.borrow().clone()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-window-status
@@ -1169,20 +1170,26 @@ impl Window {
     }
 
     pub fn update_viewport_for_scroll(&self, x: f32, y: f32) {
         let size = self.current_viewport.get().size;
         let new_viewport = Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size);
         self.current_viewport.set(new_viewport)
     }
 
-    pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) {
-        let (send, recv) = ipc::channel::<(Size2D<u32>, Point2D<i32>)>().unwrap();
+    pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
+        self.window_size.get().map_or(TypedScale::new(1.0), |data| data.device_pixel_ratio)
+    }
+
+    fn client_window(&self) -> (TypedSize2D<u32, CSSPixel>, TypedPoint2D<i32, CSSPixel>) {
+        let (send, recv) = ipc::channel::<(DeviceUintSize, DeviceIntPoint)>().unwrap();
         self.send_to_constellation(ScriptMsg::GetClientWindow(send));
-        recv.recv().unwrap_or((Size2D::zero(), Point2D::zero()))
+        let (size, point) = recv.recv().unwrap_or((TypedSize2D::zero(), TypedPoint2D::zero()));
+        let dpr = self.device_pixel_ratio();
+        ((size.to_f32() / dpr).to_u32(), (point.to_f32() / dpr).to_i32())
     }
 
     /// Advances the layout animation clock by `delta` milliseconds, and then
     /// forces a reflow if `tick` is true.
     pub fn advance_animation_clock(&self, delta: i32, tick: bool) {
         self.layout_chan.send(Msg::AdvanceClockMs(delta, tick)).unwrap();
     }
 
--- a/servo/components/script_traits/lib.rs
+++ b/servo/components/script_traits/lib.rs
@@ -36,17 +36,17 @@ extern crate webrender_api;
 extern crate webvr_traits;
 
 mod script_msg;
 pub mod webdriver_msg;
 
 use bluetooth_traits::BluetoothRequest;
 use canvas_traits::webgl::WebGLPipeline;
 use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
-use euclid::{Size2D, Length, Point2D, Vector2D, Rect, TypedScale, TypedSize2D};
+use euclid::{Length, Point2D, Vector2D, Rect, TypedSize2D, TypedScale};
 use gfx_traits::Epoch;
 use hyper::header::Headers;
 use hyper::method::Method;
 use ipc_channel::{Error as IpcError};
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
 use libc::c_void;
 use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, Key, KeyModifiers, KeyState};
 use msg::constellation_msg::{PipelineId, PipelineNamespaceId, TraversalDirection};
@@ -64,17 +64,17 @@ use servo_url::ServoUrl;
 use std::collections::HashMap;
 use std::fmt;
 use std::sync::Arc;
 use std::sync::mpsc::{Receiver, Sender, RecvTimeoutError};
 use style_traits::CSSPixel;
 use style_traits::SpeculativePainter;
 use style_traits::cursor::CursorKind;
 use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
-use webrender_api::{ExternalScrollId, DevicePixel, DocumentId, ImageKey};
+use webrender_api::{ExternalScrollId, DevicePixel, DeviceUintSize, DocumentId, ImageKey};
 use webvr_traits::{WebVREvent, WebVRMsg};
 
 pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
 pub use script_msg::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders, DOMMessage};
 
 /// The address of a node. Layout sends these back. They must be validated via
 /// `from_untrusted_node_address` before they can be used, because we do not trust layout.
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -645,17 +645,17 @@ pub enum WebDriverCommandMsg {
     /// Refresh the top-level browsing context with the given ID.
     Refresh(TopLevelBrowsingContextId, IpcSender<LoadStatus>),
     /// Pass a webdriver command to the script thread of the current pipeline
     /// of a browsing context.
     ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
     /// Act as if keys were pressed in the browsing context with the given ID.
     SendKeys(BrowsingContextId, Vec<(Key, KeyModifiers, KeyState)>),
     /// Set the window size.
-    SetWindowSize(TopLevelBrowsingContextId, Size2D<u32>, IpcSender<WindowSizeData>),
+    SetWindowSize(TopLevelBrowsingContextId, DeviceUintSize, IpcSender<WindowSizeData>),
     /// Take a screenshot of the window.
     TakeScreenshot(TopLevelBrowsingContextId, IpcSender<Option<Image>>),
 }
 
 /// Messages to the constellation.
 #[derive(Deserialize, Serialize)]
 pub enum ConstellationMsg {
     /// Exit the constellation.
--- a/servo/components/script_traits/script_msg.rs
+++ b/servo/components/script_traits/script_msg.rs
@@ -8,29 +8,30 @@ use DocumentState;
 use IFrameLoadInfo;
 use IFrameLoadInfoWithData;
 use LayoutControlMsg;
 use LoadData;
 use WorkerGlobalScopeInit;
 use WorkerScriptLoadOrigin;
 use canvas_traits::canvas::CanvasMsg;
 use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
-use euclid::{Point2D, Size2D, TypedSize2D};
+use euclid::{Size2D, TypedSize2D};
 use gfx_traits::Epoch;
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
 use msg::constellation_msg::{BrowsingContextId, PipelineId, TraversalDirection};
 use msg::constellation_msg::{Key, KeyModifiers, KeyState};
 use net_traits::CoreResourceMsg;
 use net_traits::request::RequestInit;
 use net_traits::storage_thread::StorageType;
 use servo_url::ImmutableOrigin;
 use servo_url::ServoUrl;
 use style_traits::CSSPixel;
 use style_traits::cursor::CursorKind;
 use style_traits::viewport::ViewportConstraints;
+use webrender_api::{DeviceIntPoint, DeviceUintSize};
 
 /// Messages from the layout to the constellation.
 #[derive(Deserialize, Serialize)]
 pub enum LayoutMsg {
     /// Indicates whether this pipeline is currently running animations.
     ChangeRunningAnimationsState(PipelineId, AnimationState),
     /// Inform the constellation of the size of the iframe's viewport.
     IFrameSizes(Vec<(BrowsingContextId, TypedSize2D<f32, CSSPixel>)>),
@@ -131,38 +132,38 @@ pub enum ScriptMsg {
     /// Check if an alert dialog box should be presented
     Alert(String, IpcSender<bool>),
     /// Set title of current page
     /// <https://html.spec.whatwg.org/multipage/#document.title>
     SetTitle(Option<String>),
     /// Send a key event
     SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers),
     /// Get Window Informations size and position
-    GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>),
+    GetClientWindow(IpcSender<(DeviceUintSize, DeviceIntPoint)>),
     /// Move the window to a point
-    MoveTo(Point2D<i32>),
+    MoveTo(DeviceIntPoint),
     /// Resize the window to size
-    ResizeTo(Size2D<u32>),
+    ResizeTo(DeviceUintSize),
     /// Script has handled a touch event, and either prevented or allowed default actions.
     TouchEventProcessed(EventResult),
     /// A log entry, with the top-level browsing context id and thread name
     LogEntry(Option<String>, LogEntry),
     /// Notifies the constellation that this pipeline has exited.
     PipelineExited,
     /// Send messages from postMessage calls from serviceworker
     /// to constellation for storing in service worker manager
     ForwardDOMMessage(DOMMessage, ServoUrl),
     /// Store the data required to activate a service worker for the given scope
     RegisterServiceWorker(ScopeThings, ServoUrl),
     /// Enter or exit fullscreen
     SetFullscreenState(bool),
     /// Get the screen size (pixel)
-    GetScreenSize(IpcSender<(Size2D<u32>)>),
+    GetScreenSize(IpcSender<(DeviceUintSize)>),
     /// Get the available screen size (pixel)
-    GetScreenAvailSize(IpcSender<(Size2D<u32>)>),
+    GetScreenAvailSize(IpcSender<(DeviceUintSize)>),
     /// Requests that the compositor shut down.
     Exit,
 }
 
 /// Entities required to spawn service workers
 #[derive(Clone, Deserialize, Serialize)]
 pub struct ScopeThings {
     /// script resource url
--- a/servo/components/servo/lib.rs
+++ b/servo/components/servo/lib.rs
@@ -76,16 +76,17 @@ use compositing::compositor_thread::{sel
 use compositing::compositor_thread::{EmbedderMsg, EmbedderProxy, EmbedderReceiver};
 use compositing::windowing::WindowEvent;
 use compositing::windowing::WindowMethods;
 use constellation::{Constellation, InitialConstellationState, UnprivilegedPipelineContent};
 use constellation::{FromCompositorLogger, FromScriptLogger};
 #[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
 use constellation::content_process_sandbox_profile;
 use env_logger::Logger as EnvLogger;
+use euclid::Length;
 #[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
 use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
 use gfx::font_cache_thread::FontCacheThread;
 use ipc_channel::ipc::{self, IpcSender};
 use log::{Log, LogMetadata, LogRecord};
 use msg::constellation_msg::KeyState;
 use net::resource_thread::new_resource_threads;
 use net_traits::IpcSend;
@@ -128,17 +129,17 @@ pub struct Servo<Window: WindowMethods +
 }
 
 impl<Window> Servo<Window> where Window: WindowMethods + 'static {
     pub fn new(window: Rc<Window>) -> Servo<Window> {
         // Global configuration options, parsed from the command line.
         let opts = opts::get();
 
         // Make sure the gl context is made current.
-        window.prepare_for_composite(0, 0);
+        window.prepare_for_composite(Length::new(0), Length::new(0));
 
         // Get both endpoints of a special channel for communication between
         // the client window and the compositor. This channel is unique because
         // messages to client may need to pump a platform-specific event loop
         // to deliver the message.
         let (compositor_proxy, compositor_receiver) =
             create_compositor_channel(window.create_event_loop_waker());
         let (embedder_proxy, embedder_receiver) =
--- a/servo/components/webdriver_server/lib.rs
+++ b/servo/components/webdriver_server/lib.rs
@@ -22,17 +22,17 @@ extern crate rustc_serialize;
 extern crate script_traits;
 extern crate servo_config;
 extern crate servo_url;
 extern crate uuid;
 extern crate webdriver;
 
 mod keys;
 
-use euclid::Size2D;
+use euclid::TypedSize2D;
 use hyper::method::Method::{self, Post};
 use image::{DynamicImage, ImageFormat, RgbImage};
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
 use keys::keycodes_to_keys;
 use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection};
 use net_traits::image::base::PixelFormat;
 use regex::Captures;
 use rustc_serialize::json::{Json, ToJson};
@@ -413,17 +413,17 @@ impl Handler {
         let width = match params.width {
             Nullable::Value(v) => v,
             Nullable::Null => 0,
         };
         let height = match params.height {
             Nullable::Value(v) => v,
             Nullable::Null => 0,
         };
-        let size = Size2D::new(width as u32, height as u32);
+        let size = TypedSize2D::new(width as u32, height as u32);
         let top_level_browsing_context_id = self.session()?.top_level_browsing_context_id;
         let cmd_msg = WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, sender.clone());
 
         self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
 
         let timeout = self.resize_timeout;
         let constellation_chan = self.constellation_chan.clone();
         thread::spawn(move || {
--- a/servo/ports/servo/glutin_app/window.rs
+++ b/servo/ports/servo/glutin_app/window.rs
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! A windowing implementation using glutin.
 
 use compositing::compositor_thread::EventLoopWaker;
 use compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
 use compositing::windowing::{WebRenderDebugOption, WindowMethods};
-use euclid::{Point2D, Size2D, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
+use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
 #[cfg(target_os = "windows")]
 use gdi32;
 use gleam::gl;
 use glutin;
 use glutin::{Api, GlContext, GlRequest};
 use msg::constellation_msg::{self, Key, TopLevelBrowsingContextId as BrowserId};
 use msg::constellation_msg::{KeyModifiers, KeyState, TraversalDirection};
 use net_traits::net_error_list::NetError;
@@ -35,17 +35,17 @@ use std::rc::Rc;
 use std::sync::Arc;
 use std::thread;
 use std::time;
 use style_traits::DevicePixel;
 use style_traits::cursor::CursorKind;
 use tinyfiledialogs;
 #[cfg(target_os = "windows")]
 use user32;
-use webrender_api::{DeviceUintRect, DeviceUintSize, ScrollLocation};
+use webrender_api::{DeviceIntPoint, DeviceUintRect, DeviceUintSize, ScrollLocation};
 #[cfg(target_os = "windows")]
 use winapi;
 use winit;
 use winit::{ElementState, Event, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
 #[cfg(target_os = "macos")]
 use winit::os::macos::{ActivationPolicy, WindowBuilderExt};
 
 
@@ -172,28 +172,28 @@ impl HeadlessContext {
 enum WindowKind {
     Window(glutin::GlWindow, RefCell<winit::EventsLoop>),
     Headless(HeadlessContext),
 }
 
 /// The type of a window.
 pub struct Window {
     kind: WindowKind,
-    screen_size: Size2D<u32>,
+    screen_size: TypedSize2D<u32, DeviceIndependentPixel>,
     inner_size: Cell<TypedSize2D<u32, DeviceIndependentPixel>>,
 
     mouse_down_button: Cell<Option<winit::MouseButton>>,
-    mouse_down_point: Cell<Point2D<i32>>,
+    mouse_down_point: Cell<TypedPoint2D<i32, DeviceIndependentPixel>>,
     event_queue: RefCell<Vec<WindowEvent>>,
 
     /// id of the top level browsing context. It is unique as tabs
     /// are not supported yet. None until created.
     browser_id: Cell<Option<BrowserId>>,
 
-    mouse_pos: Cell<Point2D<i32>>,
+    mouse_pos: Cell<TypedPoint2D<i32, DeviceIndependentPixel>>,
     key_modifiers: Cell<GlutinKeyModifiers>,
     current_url: RefCell<Option<ServoUrl>>,
 
     last_pressed_key: Cell<Option<constellation_msg::Key>>,
 
     animation_state: Cell<AnimationState>,
 
     fullscreen: Cell<bool>,
@@ -217,32 +217,30 @@ fn window_creation_scale_factor() -> Typ
 
 impl Window {
     pub fn set_browser_id(&self, browser_id: BrowserId) {
         self.browser_id.set(Some(browser_id));
     }
 
     pub fn new(is_foreground: bool,
                window_size: TypedSize2D<u32, DeviceIndependentPixel>) -> Rc<Window> {
-        let win_size: TypedSize2D<u32, DevicePixel> =
-            (window_size.to_f32() * window_creation_scale_factor())
-                .to_usize().cast().expect("Window size should fit in u32");
+        let win_size: DeviceUintSize = (window_size.to_f32() * window_creation_scale_factor()).to_u32();
         let width = win_size.to_untyped().width;
         let height = win_size.to_untyped().height;
 
         // If there's no chrome, start off with the window invisible. It will be set to visible in
         // `load_end()`. This avoids an ugly flash of unstyled content (especially important since
         // unstyled content is white and chrome often has a transparent background). See issue
         // #9996.
         let visible = is_foreground && !opts::get().no_native_titlebar;
 
         let screen_size;
         let inner_size;
         let window_kind = if opts::get().headless {
-            screen_size = Size2D::new(width, height);
+            screen_size = TypedSize2D::new(width, height);
             inner_size = TypedSize2D::new(width, height);
             WindowKind::Headless(HeadlessContext::new(width, height))
         } else {
             let events_loop = winit::EventsLoop::new();
             let mut window_builder = winit::WindowBuilder::new()
                 .with_title("Servo".to_string())
                 .with_decorations(!opts::get().no_native_titlebar)
                 .with_transparency(opts::get().no_native_titlebar)
@@ -263,17 +261,17 @@ impl Window {
             let glutin_window = glutin::GlWindow::new(window_builder, context_builder, &events_loop)
                 .expect("Failed to create window.");
 
             unsafe {
                 glutin_window.context().make_current().expect("Couldn't make window current");
             }
 
             let (screen_width, screen_height) = events_loop.get_primary_monitor().get_dimensions();
-            screen_size = Size2D::new(screen_width, screen_height);
+            screen_size = TypedSize2D::new(screen_width, screen_height);
             // TODO(ajeffrey): can this fail?
             let (width, height) = glutin_window.get_inner_size().expect("Failed to get window inner size.");
             inner_size = TypedSize2D::new(width, height);
 
             glutin_window.show();
 
             WindowKind::Window(glutin_window, RefCell::new(events_loop))
         };
@@ -311,21 +309,21 @@ impl Window {
         gl.clear_color(0.6, 0.6, 0.6, 1.0);
         gl.clear(gl::COLOR_BUFFER_BIT);
         gl.finish();
 
         let window = Window {
             kind: window_kind,
             event_queue: RefCell::new(vec!()),
             mouse_down_button: Cell::new(None),
-            mouse_down_point: Cell::new(Point2D::new(0, 0)),
+            mouse_down_point: Cell::new(TypedPoint2D::new(0, 0)),
 
             browser_id: Cell::new(None),
 
-            mouse_pos: Cell::new(Point2D::new(0, 0)),
+            mouse_pos: Cell::new(TypedPoint2D::new(0, 0)),
             key_modifiers: Cell::new(GlutinKeyModifiers::empty()),
             current_url: RefCell::new(None),
 
             last_pressed_key: Cell::new(None),
             gl: gl.clone(),
             animation_state: Cell::new(AnimationState::Idle),
             fullscreen: Cell::new(false),
             inner_size: Cell::new(inner_size),
@@ -417,28 +415,27 @@ impl Window {
                 }, ..
             } => self.handle_keyboard_input(state, virtual_keycode),
             Event::WindowEvent {
                 event: winit::WindowEvent::MouseInput {
                     state, button, ..
                 }, ..
             } => {
                 if button == MouseButton::Left || button == MouseButton::Right {
-                    let mouse_pos = self.mouse_pos.get();
-                    self.handle_mouse(button, state, mouse_pos.x, mouse_pos.y);
+                    self.handle_mouse(button, state, self.mouse_pos.get());
                 }
             },
             Event::WindowEvent {
                 event: winit::WindowEvent::CursorMoved {
                     position: (x, y),
                     ..
                 },
                 ..
             } => {
-                self.mouse_pos.set(Point2D::new(x as i32, y as i32));
+                self.mouse_pos.set(TypedPoint2D::new(x as i32, y as i32));
                 self.event_queue.borrow_mut().push(
                     WindowEvent::MouseWindowMoveEventClass(TypedPoint2D::new(x as f32, y as f32)));
             }
             Event::WindowEvent {
                 event: winit::WindowEvent::MouseWheel { delta, phase, .. },
                 ..
             } => {
                 let (dx, dy) = match delta {
@@ -476,17 +473,17 @@ impl Window {
             } => {
                 // width and height are DevicePixel.
                 // window.resize() takes DevicePixel.
                 if let WindowKind::Window(ref window, _) = self.kind {
                     window.resize(width, height);
                 }
                 // window.set_inner_size() takes DeviceIndependentPixel.
                 let new_size = TypedSize2D::new(width as f32, height as f32);
-                let new_size = (new_size / self.hidpi_factor()).cast().expect("Window size should fit in u32");
+                let new_size = (new_size / self.hidpi_factor()).to_u32();
                 if self.inner_size.get() != new_size {
                     self.inner_size.set(new_size);
                     self.event_queue.borrow_mut().push(WindowEvent::Resize);
                 }
             }
             Event::Suspended(suspended) => {
                 self.suspended.set(suspended);
                 if !suspended {
@@ -513,47 +510,47 @@ impl Window {
         if let ScrollLocation::Delta(ref mut delta) = scroll_location {
             if delta.y.abs() >= delta.x.abs() {
                 delta.x = 0.0;
             } else {
                 delta.y = 0.0;
             }
         }
 
-        let mouse_pos = self.mouse_pos.get();
-        let event = WindowEvent::Scroll(scroll_location,
-                                        TypedPoint2D::new(mouse_pos.x as i32, mouse_pos.y as i32),
-                                        phase);
+        let pos = self.mouse_pos.get().to_f32() * self.hidpi_factor();
+        let event = WindowEvent::Scroll(scroll_location, pos.to_i32(), phase);
         self.event_queue.borrow_mut().push(event);
     }
 
     /// Helper function to handle a click
-    fn handle_mouse(&self, button: winit::MouseButton, action: winit::ElementState, x: i32, y: i32) {
+    fn handle_mouse(&self, button: winit::MouseButton,
+                    action: winit::ElementState,
+                    coords: TypedPoint2D<i32, DeviceIndependentPixel>) {
         use script_traits::MouseButton;
 
         // FIXME(tkuehn): max pixel dist should be based on pixel density
         let max_pixel_dist = 10f64;
+        let scaled_coords = coords.to_f32() * self.hidpi_factor();
         let event = match action {
             ElementState::Pressed => {
-                self.mouse_down_point.set(Point2D::new(x, y));
+                self.mouse_down_point.set(coords);
                 self.mouse_down_button.set(Some(button));
-                MouseWindowEvent::MouseDown(MouseButton::Left, TypedPoint2D::new(x as f32, y as f32))
+                MouseWindowEvent::MouseDown(MouseButton::Left, scaled_coords)
             }
             ElementState::Released => {
-                let mouse_up_event = MouseWindowEvent::MouseUp(MouseButton::Left,
-                                                               TypedPoint2D::new(x as f32, y as f32));
+                let mouse_up_event = MouseWindowEvent::MouseUp(MouseButton::Left, scaled_coords);
                 match self.mouse_down_button.get() {
                     None => mouse_up_event,
                     Some(but) if button == but => {
-                        let pixel_dist = self.mouse_down_point.get() - Point2D::new(x, y);
+                        let pixel_dist = self.mouse_down_point.get() - coords;
                         let pixel_dist = ((pixel_dist.x * pixel_dist.x +
                                            pixel_dist.y * pixel_dist.y) as f64).sqrt();
                         if pixel_dist < max_pixel_dist {
                             self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(mouse_up_event));
-                            MouseWindowEvent::Click(MouseButton::Left, TypedPoint2D::new(x as f32, y as f32))
+                            MouseWindowEvent::Click(MouseButton::Left, scaled_coords)
                         } else {
                             mouse_up_event
                         }
                     },
                     Some(_) => mouse_up_event,
                 }
             }
         };
@@ -866,74 +863,74 @@ impl Window {
 }
 
 impl WindowMethods for Window {
     fn gl(&self) -> Rc<gl::Gl> {
         self.gl.clone()
     }
 
     fn framebuffer_size(&self) -> DeviceUintSize {
-        (self.inner_size.get().to_f32() * self.hidpi_factor()).to_usize().cast().expect("Window size should fit in u32")
+        (self.inner_size.get().to_f32() * self.hidpi_factor()).to_u32()
     }
 
     fn window_rect(&self) -> DeviceUintRect {
         let size = self.framebuffer_size();
         let origin = TypedPoint2D::zero();
         DeviceUintRect::new(origin, size)
     }
 
-    fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel> {
-        self.inner_size.get().to_f32()
-    }
-
-    fn client_window(&self, _: BrowserId) -> (Size2D<u32>, Point2D<i32>) {
-        match self.kind {
+    fn client_window(&self, _: BrowserId) -> (DeviceUintSize, DeviceIntPoint) {
+        let (size, point) = match self.kind {
             WindowKind::Window(ref window, ..) => {
                 // TODO(ajeffrey): can this fail?
                 let (width, height) = window.get_outer_size().expect("Failed to get window outer size.");
-                let size = Size2D::new(width, height);
+                let size = TypedSize2D::new(width as f32, height as f32);
                 // TODO(ajeffrey): can this fail?
                 let (x, y) = window.get_position().expect("Failed to get window position.");
-                let origin = Point2D::new(x as i32, y as i32);
+                let origin = TypedPoint2D::new(x as f32, y as f32);
                 (size, origin)
             }
             WindowKind::Headless(ref context) => {
-                let size = TypedSize2D::new(context.width, context.height);
-                (size, Point2D::zero())
+                let size = TypedSize2D::new(context.width as f32, context.height as f32);
+                let origin = TypedPoint2D::zero();
+                (size, origin)
             }
-        }
-
+        };
+        let dpr = self.hidpi_factor();
+        ((size * dpr).to_u32(), (point * dpr).to_i32())
     }
 
-    fn screen_size(&self, _: BrowserId) -> Size2D<u32> {
-        self.screen_size
+    fn screen_size(&self, _: BrowserId) -> DeviceUintSize {
+        (self.screen_size.to_f32() * self.hidpi_factor()).to_u32()
     }
 
-    fn screen_avail_size(&self, browser_id: BrowserId) -> Size2D<u32> {
+    fn screen_avail_size(&self, browser_id: BrowserId) -> DeviceUintSize {
         // FIXME: Glutin doesn't have API for available size. Fallback to screen size
         self.screen_size(browser_id)
     }
 
     fn set_animation_state(&self, state: AnimationState) {
         self.animation_state.set(state);
     }
 
-    fn set_inner_size(&self, _: BrowserId, size: Size2D<u32>) {
+    fn set_inner_size(&self, _: BrowserId, size: DeviceUintSize) {
         match self.kind {
             WindowKind::Window(ref window, ..) => {
+                let size = size.to_f32() / self.hidpi_factor();
                 window.set_inner_size(size.width as u32, size.height as u32)
             }
             WindowKind::Headless(..) => {}
         }
     }
 
-    fn set_position(&self, _: BrowserId, point: Point2D<i32>) {
+    fn set_position(&self, _: BrowserId, point: DeviceIntPoint) {
         match self.kind {
             WindowKind::Window(ref window, ..) => {
-                window.set_position(point.x, point.y)
+                let point = point.to_f32() / self.hidpi_factor();
+                window.set_position(point.x as i32, point.y as i32)
             }
             WindowKind::Headless(..) => {}
         }
     }
 
     fn set_fullscreen_state(&self, _: BrowserId, state: bool) {
         match self.kind {
             WindowKind::Window(ref window, ..) => {
@@ -1107,17 +1104,17 @@ impl WindowMethods for Window {
             }
             WindowKind::Headless(..) => {}
         }
     }
 
     fn set_favicon(&self, _: BrowserId, _: ServoUrl) {
     }
 
-    fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
+    fn prepare_for_composite(&self, _width: Length<u32, DevicePixel>, _height: Length<u32, DevicePixel>) -> bool {
         true
     }
 
     /// Helper function to handle keyboard events.
     fn handle_key(&self, _: Option<BrowserId>, ch: Option<char>, key: Key, mods: constellation_msg::KeyModifiers) {
         let browser_id = match self.browser_id.get() {
             Some(id) => id,
             None => { unreachable!("Can't get keys without a browser"); }