Use typed coordinates.

We use Size2D and Point2D across compositing, constellation and script,
losing 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 commit is contained in:
Paul Rouget 2018-03-01 07:41:00 +01:00
parent b93f153ed5
commit ac4614d6ce
10 changed files with 122 additions and 102 deletions

View file

@ -6,7 +6,7 @@ use CompositionPipeline;
use SendableFrameTree; use SendableFrameTree;
use compositor_thread::{CompositorProxy, CompositorReceiver}; use compositor_thread::{CompositorProxy, CompositorReceiver};
use compositor_thread::{InitialCompositorState, Msg}; use compositor_thread::{InitialCompositorState, Msg};
use euclid::{TypedPoint2D, TypedVector2D, TypedScale}; use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale};
use gfx_traits::Epoch; use gfx_traits::Epoch;
use gleam::gl; use gleam::gl;
use image::{DynamicImage, ImageFormat, RgbImage}; use image::{DynamicImage, ImageFormat, RgbImage};
@ -274,15 +274,15 @@ impl RenderTargetInfo {
} }
} }
fn initialize_png(gl: &gl::Gl, width: usize, height: usize) -> RenderTargetInfo { fn initialize_png(gl: &gl::Gl, width: Length<u32, DevicePixel>, height: Length<u32, DevicePixel>) -> RenderTargetInfo {
let framebuffer_ids = gl.gen_framebuffers(1); let framebuffer_ids = gl.gen_framebuffers(1);
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]); gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
let texture_ids = gl.gen_textures(1); let texture_ids = gl.gen_textures(1);
gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]); 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, gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as gl::GLint, width.get() as gl::GLsizei,
height as gl::GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None); 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_MAG_FILTER, gl::NEAREST as gl::GLint);
gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as gl::GLint); gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as gl::GLint);
@ -296,8 +296,8 @@ fn initialize_png(gl: &gl::Gl, width: usize, height: usize) -> RenderTargetInfo
gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb); gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
gl.renderbuffer_storage(gl::RENDERBUFFER, gl.renderbuffer_storage(gl::RENDERBUFFER,
gl::DEPTH_COMPONENT24, gl::DEPTH_COMPONENT24,
width as gl::GLsizei, width.get() as gl::GLsizei,
height as gl::GLsizei); height.get() as gl::GLsizei);
gl.framebuffer_renderbuffer(gl::FRAMEBUFFER, gl.framebuffer_renderbuffer(gl::FRAMEBUFFER,
gl::DEPTH_ATTACHMENT, gl::DEPTH_ATTACHMENT,
gl::RENDERBUFFER, gl::RENDERBUFFER,
@ -646,9 +646,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
device_pixel_ratio: dppx, device_pixel_ratio: dppx,
initial_viewport: initial_viewport, initial_viewport: initial_viewport,
}; };
let top_level_browsing_context_id = self.root_pipeline.as_ref().map(|pipeline| { let top_level_browsing_context_id = self.root_pipeline.as_ref().map(|pipeline| {
pipeline.top_level_browsing_context_id pipeline.top_level_browsing_context_id
}); });
let msg = ConstellationMsg::WindowSize(top_level_browsing_context_id, data, size_type); let msg = ConstellationMsg::WindowSize(top_level_browsing_context_id, data, size_type);
if let Err(e) = self.constellation_chan.send(msg) { if let Err(e) = self.constellation_chan.send(msg) {
@ -1253,8 +1255,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn composite_specific_target(&mut self, fn composite_specific_target(&mut self,
target: CompositeTarget) target: CompositeTarget)
-> Result<Option<Image>, UnableToComposite> { -> Result<Option<Image>, UnableToComposite> {
let (width, height) = let (width, height) = (self.frame_size.width_typed(), self.frame_size.height_typed());
(self.frame_size.width as usize, self.frame_size.height as usize);
if !self.window.prepare_for_composite(width, height) { if !self.window.prepare_for_composite(width, height) {
return Err(UnableToComposite::WindowUnprepared) return Err(UnableToComposite::WindowUnprepared)
} }
@ -1374,9 +1375,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn draw_img(&self, fn draw_img(&self,
render_target_info: RenderTargetInfo, render_target_info: RenderTargetInfo,
width: usize, width: Length<u32, DevicePixel>,
height: usize) height: Length<u32, DevicePixel>)
-> RgbImage { -> RgbImage {
let width = width.get() as usize;
let height = height.get() as usize;
// For some reason, OSMesa fails to render on the 3rd // For some reason, OSMesa fails to render on the 3rd
// attempt in headless mode, under some conditions. // attempt in headless mode, under some conditions.
// I think this can only be some kind of synchronization // I think this can only be some kind of synchronization

View file

@ -6,7 +6,7 @@
use SendableFrameTree; use SendableFrameTree;
use compositor::CompositingReason; use compositor::CompositingReason;
use euclid::{Point2D, Size2D}; use euclid::{TypedPoint2D, TypedSize2D};
use gfx_traits::Epoch; use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId};
@ -17,6 +17,7 @@ use script_traits::{AnimationState, ConstellationMsg, EventResult, LoadData};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::fmt::{Debug, Error, Formatter}; use std::fmt::{Debug, Error, Formatter};
use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc::{Receiver, Sender};
use style_traits::DevicePixel;
use style_traits::cursor::CursorKind; use style_traits::cursor::CursorKind;
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
use webrender; use webrender;
@ -119,15 +120,16 @@ pub enum EmbedderMsg {
/// Alerts the embedder that the current page has changed its title. /// Alerts the embedder that the current page has changed its title.
ChangePageTitle(TopLevelBrowsingContextId, Option<String>), ChangePageTitle(TopLevelBrowsingContextId, Option<String>),
/// Move the window to a point /// Move the window to a point
MoveTo(TopLevelBrowsingContextId, Point2D<i32>), MoveTo(TopLevelBrowsingContextId, TypedPoint2D<i32, DevicePixel>),
/// Resize the window to size /// Resize the window to size
ResizeTo(TopLevelBrowsingContextId, Size2D<u32>), ResizeTo(TopLevelBrowsingContextId, TypedSize2D<u32, DevicePixel>),
/// Get Window Informations size and position /// Get Window Informations size and position
GetClientWindow(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>, Point2D<i32>)>), GetClientWindow(TopLevelBrowsingContextId,
IpcSender<(TypedSize2D<u32, DevicePixel>, TypedPoint2D<i32, DevicePixel>)>),
/// Get screen size (pixel) /// Get screen size (pixel)
GetScreenSize(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>)>), GetScreenSize(TopLevelBrowsingContextId, IpcSender<(TypedSize2D<u32, DevicePixel>)>),
/// Get screen available size (pixel) /// Get screen available size (pixel)
GetScreenAvailSize(TopLevelBrowsingContextId, IpcSender<(Size2D<u32>)>), GetScreenAvailSize(TopLevelBrowsingContextId, IpcSender<(TypedSize2D<u32, DevicePixel>)>),
/// Wether or not to follow a link /// Wether or not to follow a link
AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>), AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender<bool>),
/// Sends an unconsumed key event back to the embedder. /// Sends an unconsumed key event back to the embedder.

View file

@ -5,8 +5,7 @@
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`. //! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
use compositor_thread::EventLoopWaker; use compositor_thread::EventLoopWaker;
use euclid::{Point2D, Size2D}; use euclid::{Length, TypedScale, TypedPoint2D, TypedSize2D};
use euclid::{TypedScale, TypedPoint2D, TypedSize2D};
use gleam::gl; use gleam::gl;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection};
@ -123,21 +122,22 @@ pub trait WindowMethods {
fn framebuffer_size(&self) -> DeviceUintSize; fn framebuffer_size(&self) -> DeviceUintSize;
/// Returns the position and size of the window within the rendering area. /// Returns the position and size of the window within the rendering area.
fn window_rect(&self) -> DeviceUintRect; fn window_rect(&self) -> DeviceUintRect;
/// Returns the size of the window in density-independent "px" units. /// Returns the size of the window.
fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel>; fn size(&self) -> TypedSize2D<f32, DevicePixel>;
/// Presents the window to the screen (perhaps by page flipping). /// Presents the window to the screen (perhaps by page flipping).
fn present(&self); fn present(&self);
/// Return the size of the window with head and borders and position of the window values /// 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>); fn client_window(&self, ctx: TopLevelBrowsingContextId) ->
/// Return the size of the screen (pixel) (TypedSize2D<u32, DevicePixel>, TypedPoint2D<i32, DevicePixel>);
fn screen_size(&self, ctx: TopLevelBrowsingContextId) -> Size2D<u32>; /// Return the size of the screen.
/// Return the available size of the screen (pixel) fn screen_size(&self, ctx: TopLevelBrowsingContextId) -> TypedSize2D<u32, DevicePixel>;
fn screen_avail_size(&self, ctx: TopLevelBrowsingContextId) -> Size2D<u32>; /// Return the available size of the screen.
fn screen_avail_size(&self, ctx: TopLevelBrowsingContextId) -> TypedSize2D<u32, DevicePixel>;
/// Set the size inside of borders and head /// 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: TypedSize2D<u32, DevicePixel>);
/// Set the window position /// Set the window position
fn set_position(&self, ctx: TopLevelBrowsingContextId, point: Point2D<i32>); fn set_position(&self, ctx: TopLevelBrowsingContextId, point: TypedPoint2D<i32, DevicePixel>);
/// Set fullscreen state /// Set fullscreen state
fn set_fullscreen_state(&self, ctx: TopLevelBrowsingContextId, state: bool); fn set_fullscreen_state(&self, ctx: TopLevelBrowsingContextId, state: bool);
@ -167,7 +167,7 @@ pub trait WindowMethods {
/// Requests that the window system prepare a composite. Typically this will involve making /// 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 /// some type of platform-specific graphics context current. Returns true if the composite may
/// proceed and false if it should not. /// proceed and false if it should not.
fn prepare_for_composite(&self, width: usize, height: usize) -> bool; fn prepare_for_composite(&self, width: Length<u32, DevicePixel>, height: Length<u32, DevicePixel>) -> bool;
/// Sets the cursor to be used in the window. /// Sets the cursor to be used in the window.
fn set_cursor(&self, cursor: CursorKind); fn set_cursor(&self, cursor: CursorKind);

View file

@ -11,9 +11,10 @@ use dom::bindings::root::{Dom, DomRoot};
use dom::globalscope::GlobalScope; use dom::globalscope::GlobalScope;
use dom::window::Window; use dom::window::Window;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::Size2D; use euclid::TypedSize2D;
use ipc_channel::ipc; use ipc_channel::ipc;
use script_traits::ScriptMsg; use script_traits::ScriptMsg;
use style_traits::{CSSPixel, DevicePixel};
#[dom_struct] #[dom_struct]
pub struct Screen { pub struct Screen {
@ -35,18 +36,22 @@ impl Screen {
ScreenBinding::Wrap) ScreenBinding::Wrap)
} }
fn screen_size(&self) -> Size2D<u32> { fn screen_size(&self) -> TypedSize2D<u32, CSSPixel> {
let (send, recv) = ipc::channel::<(Size2D<u32>)>().unwrap(); let (send, recv) = ipc::channel::<(TypedSize2D<u32, DevicePixel>)>().unwrap();
self.window.upcast::<GlobalScope>() self.window.upcast::<GlobalScope>()
.script_to_constellation_chan().send(ScriptMsg::GetScreenSize(send)).unwrap(); .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> { fn screen_avail_size(&self) -> TypedSize2D<u32, CSSPixel> {
let (send, recv) = ipc::channel::<(Size2D<u32>)>().unwrap(); let (send, recv) = ipc::channel::<(TypedSize2D<u32, DevicePixel>)>().unwrap();
self.window.upcast::<GlobalScope>() self.window.upcast::<GlobalScope>()
.script_to_constellation_chan().send(ScriptMsg::GetScreenAvailSize(send)).unwrap(); .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()
} }
} }

View file

@ -48,7 +48,7 @@ use dom::windowproxy::WindowProxy;
use dom::worklet::Worklet; use dom::worklet::Worklet;
use dom::workletglobalscope::WorkletGlobalScopeType; use dom::workletglobalscope::WorkletGlobalScopeType;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::{Point2D, Vector2D, Rect, Size2D}; use euclid::{Point2D, Vector2D, Rect, Size2D, TypedPoint2D, TypedScale, TypedSize2D};
use fetch; use fetch;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
@ -102,7 +102,7 @@ use style::properties::{ComputedValues, PropertyId};
use style::selector_parser::PseudoElement; use style::selector_parser::PseudoElement;
use style::str::HTML_SPACE_CHARACTERS; use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::CssRuleType; use style::stylesheets::CssRuleType;
use style_traits::ParsingMode; use style_traits::{CSSPixel, DevicePixel, ParsingMode};
use task::TaskCanceller; use task::TaskCanceller;
use task_source::dom_manipulation::DOMManipulationTaskSource; use task_source::dom_manipulation::DOMManipulationTaskSource;
use task_source::file_reading::FileReadingTaskSource; use task_source::file_reading::FileReadingTaskSource;
@ -930,11 +930,12 @@ impl WindowMethods for Window {
} }
// https://drafts.csswg.org/cssom-view/#dom-window-resizeto // 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 // Step 1
//TODO determine if this operation is allowed //TODO determine if this operation is allowed
let size = Size2D::new(x.to_u32().unwrap_or(1), y.to_u32().unwrap_or(1)); let dpr = self.device_pixel_ratio();
self.send_to_constellation(ScriptMsg::ResizeTo(size)); 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 // https://drafts.csswg.org/cssom-view/#dom-window-resizeby
@ -948,8 +949,9 @@ impl WindowMethods for Window {
fn MoveTo(&self, x: i32, y: i32) { fn MoveTo(&self, x: i32, y: i32) {
// Step 1 // Step 1
//TODO determine if this operation is allowed //TODO determine if this operation is allowed
let point = Point2D::new(x, y); let dpr = self.device_pixel_ratio();
self.send_to_constellation(ScriptMsg::MoveTo(point)); 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 // https://drafts.csswg.org/cssom-view/#dom-window-moveby
@ -985,8 +987,7 @@ impl WindowMethods for Window {
// https://drafts.csswg.org/cssom-view/#dom-window-devicepixelratio // https://drafts.csswg.org/cssom-view/#dom-window-devicepixelratio
fn DevicePixelRatio(&self) -> Finite<f64> { fn DevicePixelRatio(&self) -> Finite<f64> {
let dpr = self.window_size.get().map_or(1.0f32, |data| data.device_pixel_ratio.get()); Finite::wrap(self.device_pixel_ratio().get() as f64)
Finite::wrap(dpr as f64)
} }
// https://html.spec.whatwg.org/multipage/#dom-window-status // https://html.spec.whatwg.org/multipage/#dom-window-status
@ -1174,10 +1175,16 @@ impl Window {
self.current_viewport.set(new_viewport) self.current_viewport.set(new_viewport)
} }
pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
let (send, recv) = ipc::channel::<(Size2D<u32>, Point2D<i32>)>().unwrap(); 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::<(TypedSize2D<u32, DevicePixel>, TypedPoint2D<i32, DevicePixel>)>().unwrap();
self.send_to_constellation(ScriptMsg::GetClientWindow(send)); 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 /// Advances the layout animation clock by `delta` milliseconds, and then

View file

@ -41,7 +41,7 @@ pub mod webdriver_msg;
use bluetooth_traits::BluetoothRequest; use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLPipeline; use canvas_traits::webgl::WebGLPipeline;
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId}; 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 gfx_traits::Epoch;
use hyper::header::Headers; use hyper::header::Headers;
use hyper::method::Method; use hyper::method::Method;
@ -650,7 +650,7 @@ pub enum WebDriverCommandMsg {
/// Act as if keys were pressed in the browsing context with the given ID. /// Act as if keys were pressed in the browsing context with the given ID.
SendKeys(BrowsingContextId, Vec<(Key, KeyModifiers, KeyState)>), SendKeys(BrowsingContextId, Vec<(Key, KeyModifiers, KeyState)>),
/// Set the window size. /// Set the window size.
SetWindowSize(TopLevelBrowsingContextId, Size2D<u32>, IpcSender<WindowSizeData>), SetWindowSize(TopLevelBrowsingContextId, TypedSize2D<u32, DevicePixel>, IpcSender<WindowSizeData>),
/// Take a screenshot of the window. /// Take a screenshot of the window.
TakeScreenshot(TopLevelBrowsingContextId, IpcSender<Option<Image>>), TakeScreenshot(TopLevelBrowsingContextId, IpcSender<Option<Image>>),
} }

View file

@ -13,7 +13,7 @@ use WorkerGlobalScopeInit;
use WorkerScriptLoadOrigin; use WorkerScriptLoadOrigin;
use canvas_traits::canvas::CanvasMsg; use canvas_traits::canvas::CanvasMsg;
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use euclid::{Point2D, Size2D, TypedSize2D}; use euclid::{Size2D, TypedPoint2D, TypedSize2D};
use gfx_traits::Epoch; use gfx_traits::Epoch;
use ipc_channel::ipc::{IpcReceiver, IpcSender}; use ipc_channel::ipc::{IpcReceiver, IpcSender};
use msg::constellation_msg::{BrowsingContextId, PipelineId, TraversalDirection}; use msg::constellation_msg::{BrowsingContextId, PipelineId, TraversalDirection};
@ -23,7 +23,7 @@ use net_traits::request::RequestInit;
use net_traits::storage_thread::StorageType; use net_traits::storage_thread::StorageType;
use servo_url::ImmutableOrigin; use servo_url::ImmutableOrigin;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use style_traits::CSSPixel; use style_traits::{DevicePixel, CSSPixel};
use style_traits::cursor::CursorKind; use style_traits::cursor::CursorKind;
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
@ -136,11 +136,11 @@ pub enum ScriptMsg {
/// Send a key event /// Send a key event
SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers), SendKeyEvent(Option<char>, Key, KeyState, KeyModifiers),
/// Get Window Informations size and position /// Get Window Informations size and position
GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>), GetClientWindow(IpcSender<(TypedSize2D<u32, DevicePixel>, TypedPoint2D<i32, DevicePixel>)>),
/// Move the window to a point /// Move the window to a point
MoveTo(Point2D<i32>), MoveTo(TypedPoint2D<i32, DevicePixel>),
/// Resize the window to size /// Resize the window to size
ResizeTo(Size2D<u32>), ResizeTo(TypedSize2D<u32, DevicePixel>),
/// Script has handled a touch event, and either prevented or allowed default actions. /// Script has handled a touch event, and either prevented or allowed default actions.
TouchEventProcessed(EventResult), TouchEventProcessed(EventResult),
/// A log entry, with the top-level browsing context id and thread name /// A log entry, with the top-level browsing context id and thread name
@ -155,9 +155,9 @@ pub enum ScriptMsg {
/// Enter or exit fullscreen /// Enter or exit fullscreen
SetFullscreenState(bool), SetFullscreenState(bool),
/// Get the screen size (pixel) /// Get the screen size (pixel)
GetScreenSize(IpcSender<(Size2D<u32>)>), GetScreenSize(IpcSender<(TypedSize2D<u32, DevicePixel>)>),
/// Get the available screen size (pixel) /// Get the available screen size (pixel)
GetScreenAvailSize(IpcSender<(Size2D<u32>)>), GetScreenAvailSize(IpcSender<(TypedSize2D<u32, DevicePixel>)>),
/// Requests that the compositor shut down. /// Requests that the compositor shut down.
Exit, Exit,
} }

View file

@ -81,6 +81,7 @@ use constellation::{FromCompositorLogger, FromScriptLogger};
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] #[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
use constellation::content_process_sandbox_profile; use constellation::content_process_sandbox_profile;
use env_logger::Logger as EnvLogger; use env_logger::Logger as EnvLogger;
use euclid::Length;
#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] #[cfg(all(not(target_os = "windows"), not(target_os = "ios")))]
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods}; use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread; use gfx::font_cache_thread::FontCacheThread;
@ -133,7 +134,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
let opts = opts::get(); let opts = opts::get();
// Make sure the gl context is made current. // 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 // Get both endpoints of a special channel for communication between
// the client window and the compositor. This channel is unique because // the client window and the compositor. This channel is unique because

View file

@ -27,7 +27,7 @@ extern crate webdriver;
mod keys; mod keys;
use euclid::Size2D; use euclid::TypedSize2D;
use hyper::method::Method::{self, Post}; use hyper::method::Method::{self, Post};
use image::{DynamicImage, ImageFormat, RgbImage}; use image::{DynamicImage, ImageFormat, RgbImage};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
@ -418,7 +418,7 @@ impl Handler {
Nullable::Value(v) => v, Nullable::Value(v) => v,
Nullable::Null => 0, 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 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()); let cmd_msg = WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, sender.clone());

View file

@ -7,7 +7,7 @@
use compositing::compositor_thread::EventLoopWaker; use compositing::compositor_thread::EventLoopWaker;
use compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent}; use compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
use compositing::windowing::{WebRenderDebugOption, WindowMethods}; use compositing::windowing::{WebRenderDebugOption, WindowMethods};
use euclid::{Point2D, Size2D, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D}; use euclid::{Length, TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use gdi32; use gdi32;
use gleam::gl; use gleam::gl;
@ -177,18 +177,18 @@ enum WindowKind {
/// The type of a window. /// The type of a window.
pub struct Window { pub struct Window {
kind: WindowKind, kind: WindowKind,
screen_size: Size2D<u32>, screen_size: TypedSize2D<u32, DeviceIndependentPixel>,
inner_size: Cell<TypedSize2D<u32, DeviceIndependentPixel>>, inner_size: Cell<TypedSize2D<u32, DeviceIndependentPixel>>,
mouse_down_button: Cell<Option<winit::MouseButton>>, 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>>, event_queue: RefCell<Vec<WindowEvent>>,
/// id of the top level browsing context. It is unique as tabs /// id of the top level browsing context. It is unique as tabs
/// are not supported yet. None until created. /// are not supported yet. None until created.
browser_id: Cell<Option<BrowserId>>, browser_id: Cell<Option<BrowserId>>,
mouse_pos: Cell<Point2D<i32>>, mouse_pos: Cell<TypedPoint2D<i32, DeviceIndependentPixel>>,
key_modifiers: Cell<GlutinKeyModifiers>, key_modifiers: Cell<GlutinKeyModifiers>,
current_url: RefCell<Option<ServoUrl>>, current_url: RefCell<Option<ServoUrl>>,
@ -223,8 +223,7 @@ impl Window {
pub fn new(is_foreground: bool, pub fn new(is_foreground: bool,
window_size: TypedSize2D<u32, DeviceIndependentPixel>) -> Rc<Window> { window_size: TypedSize2D<u32, DeviceIndependentPixel>) -> Rc<Window> {
let win_size: TypedSize2D<u32, DevicePixel> = let win_size: TypedSize2D<u32, DevicePixel> =
(window_size.to_f32() * window_creation_scale_factor()) (window_size.to_f32() * window_creation_scale_factor()).to_u32();
.to_usize().cast().expect("Window size should fit in u32");
let width = win_size.to_untyped().width; let width = win_size.to_untyped().width;
let height = win_size.to_untyped().height; let height = win_size.to_untyped().height;
@ -237,7 +236,7 @@ impl Window {
let screen_size; let screen_size;
let inner_size; let inner_size;
let window_kind = if opts::get().headless { 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); inner_size = TypedSize2D::new(width, height);
WindowKind::Headless(HeadlessContext::new(width, height)) WindowKind::Headless(HeadlessContext::new(width, height))
} else { } else {
@ -268,7 +267,7 @@ impl Window {
} }
let (screen_width, screen_height) = events_loop.get_primary_monitor().get_dimensions(); 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? // TODO(ajeffrey): can this fail?
let (width, height) = glutin_window.get_inner_size().expect("Failed to get window inner size."); let (width, height) = glutin_window.get_inner_size().expect("Failed to get window inner size.");
inner_size = TypedSize2D::new(width, height); inner_size = TypedSize2D::new(width, height);
@ -316,11 +315,11 @@ impl Window {
kind: window_kind, kind: window_kind,
event_queue: RefCell::new(vec!()), event_queue: RefCell::new(vec!()),
mouse_down_button: Cell::new(None), 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), 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()), key_modifiers: Cell::new(GlutinKeyModifiers::empty()),
current_url: RefCell::new(None), current_url: RefCell::new(None),
@ -422,8 +421,7 @@ impl Window {
}, .. }, ..
} => { } => {
if button == MouseButton::Left || button == MouseButton::Right { if button == MouseButton::Left || button == MouseButton::Right {
let mouse_pos = self.mouse_pos.get(); self.handle_mouse(button, state, self.mouse_pos.get());
self.handle_mouse(button, state, mouse_pos.x, mouse_pos.y);
} }
}, },
Event::WindowEvent { Event::WindowEvent {
@ -433,7 +431,7 @@ impl Window {
}, },
.. ..
} => { } => {
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( self.event_queue.borrow_mut().push(
WindowEvent::MouseWindowMoveEventClass(TypedPoint2D::new(x as f32, y as f32))); WindowEvent::MouseWindowMoveEventClass(TypedPoint2D::new(x as f32, y as f32)));
} }
@ -481,7 +479,7 @@ impl Window {
} }
// window.set_inner_size() takes DeviceIndependentPixel. // window.set_inner_size() takes DeviceIndependentPixel.
let new_size = TypedSize2D::new(width as f32, height as f32); 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 { if self.inner_size.get() != new_size {
self.inner_size.set(new_size); self.inner_size.set(new_size);
self.event_queue.borrow_mut().push(WindowEvent::Resize); self.event_queue.borrow_mut().push(WindowEvent::Resize);
@ -518,37 +516,37 @@ impl Window {
} }
} }
let mouse_pos = self.mouse_pos.get(); let pos = self.mouse_pos.get().to_f32() * self.hidpi_factor();
let event = WindowEvent::Scroll(scroll_location, let event = WindowEvent::Scroll(scroll_location, pos.to_i32(), phase);
TypedPoint2D::new(mouse_pos.x as i32, mouse_pos.y as i32),
phase);
self.event_queue.borrow_mut().push(event); self.event_queue.borrow_mut().push(event);
} }
/// Helper function to handle a click /// 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; use script_traits::MouseButton;
// FIXME(tkuehn): max pixel dist should be based on pixel density // FIXME(tkuehn): max pixel dist should be based on pixel density
let max_pixel_dist = 10f64; let max_pixel_dist = 10f64;
let scaled_coords = coords.to_f32() * self.hidpi_factor();
let event = match action { let event = match action {
ElementState::Pressed => { ElementState::Pressed => {
self.mouse_down_point.set(Point2D::new(x, y)); self.mouse_down_point.set(coords);
self.mouse_down_button.set(Some(button)); 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 => { ElementState::Released => {
let mouse_up_event = MouseWindowEvent::MouseUp(MouseButton::Left, let mouse_up_event = MouseWindowEvent::MouseUp(MouseButton::Left, scaled_coords);
TypedPoint2D::new(x as f32, y as f32));
match self.mouse_down_button.get() { match self.mouse_down_button.get() {
None => mouse_up_event, None => mouse_up_event,
Some(but) if button == but => { 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 + let pixel_dist = ((pixel_dist.x * pixel_dist.x +
pixel_dist.y * pixel_dist.y) as f64).sqrt(); pixel_dist.y * pixel_dist.y) as f64).sqrt();
if pixel_dist < max_pixel_dist { if pixel_dist < max_pixel_dist {
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(mouse_up_event)); 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 { } else {
mouse_up_event mouse_up_event
} }
@ -871,7 +869,7 @@ impl WindowMethods for Window {
} }
fn framebuffer_size(&self) -> DeviceUintSize { 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.size().to_u32()
} }
fn window_rect(&self) -> DeviceUintRect { fn window_rect(&self) -> DeviceUintRect {
@ -880,34 +878,36 @@ impl WindowMethods for Window {
DeviceUintRect::new(origin, size) DeviceUintRect::new(origin, size)
} }
fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel> { fn size(&self) -> TypedSize2D<f32, DevicePixel> {
self.inner_size.get().to_f32() self.inner_size.get().to_f32() * self.hidpi_factor()
} }
fn client_window(&self, _: BrowserId) -> (Size2D<u32>, Point2D<i32>) { fn client_window(&self, _: BrowserId) -> (TypedSize2D<u32, DevicePixel>, TypedPoint2D<i32, DevicePixel>) {
match self.kind { let (size, point) = match self.kind {
WindowKind::Window(ref window, ..) => { WindowKind::Window(ref window, ..) => {
// TODO(ajeffrey): can this fail? // TODO(ajeffrey): can this fail?
let (width, height) = window.get_outer_size().expect("Failed to get window outer size."); 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? // TODO(ajeffrey): can this fail?
let (x, y) = window.get_position().expect("Failed to get window position."); 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) (size, origin)
} }
WindowKind::Headless(ref context) => { WindowKind::Headless(ref context) => {
let size = TypedSize2D::new(context.width, context.height); let size = TypedSize2D::new(context.width as f32, context.height as f32);
(size, Point2D::zero()) 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> { fn screen_size(&self, _: BrowserId) -> TypedSize2D<u32, DevicePixel> {
self.screen_size (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) -> TypedSize2D<u32, DevicePixel> {
// FIXME: Glutin doesn't have API for available size. Fallback to screen size // FIXME: Glutin doesn't have API for available size. Fallback to screen size
self.screen_size(browser_id) self.screen_size(browser_id)
} }
@ -916,19 +916,21 @@ impl WindowMethods for Window {
self.animation_state.set(state); self.animation_state.set(state);
} }
fn set_inner_size(&self, _: BrowserId, size: Size2D<u32>) { fn set_inner_size(&self, _: BrowserId, size: TypedSize2D<u32, DevicePixel>) {
match self.kind { match self.kind {
WindowKind::Window(ref window, ..) => { WindowKind::Window(ref window, ..) => {
let size = size.to_f32() / self.hidpi_factor();
window.set_inner_size(size.width as u32, size.height as u32) window.set_inner_size(size.width as u32, size.height as u32)
} }
WindowKind::Headless(..) => {} WindowKind::Headless(..) => {}
} }
} }
fn set_position(&self, _: BrowserId, point: Point2D<i32>) { fn set_position(&self, _: BrowserId, point: TypedPoint2D<i32, DevicePixel>) {
match self.kind { match self.kind {
WindowKind::Window(ref window, ..) => { 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(..) => {} WindowKind::Headless(..) => {}
} }
@ -1112,7 +1114,7 @@ impl WindowMethods for Window {
fn set_favicon(&self, _: BrowserId, _: ServoUrl) { 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 true
} }