diff options
-rw-r--r-- | components/compositing/compositor.rs | 29 | ||||
-rw-r--r-- | components/compositing/compositor_task.rs | 30 | ||||
-rw-r--r-- | components/compositing/headless.rs | 9 | ||||
-rw-r--r-- | components/compositing/windowing.rs | 8 | ||||
-rw-r--r-- | components/msg/compositor_msg.rs | 10 | ||||
-rw-r--r-- | components/msg/constellation_msg.rs | 3 | ||||
-rw-r--r-- | components/script/dom/webidls/Window.webidl | 53 | ||||
-rw-r--r-- | components/script/dom/window.rs | 267 | ||||
-rw-r--r-- | components/script/script_task.rs | 2 | ||||
-rw-r--r-- | ports/cef/window.rs | 24 | ||||
-rw-r--r-- | ports/glutin/window.rs | 35 | ||||
-rw-r--r-- | ports/gonk/src/window.rs | 16 | ||||
-rw-r--r-- | tests/html/viewport.html | 42 | ||||
-rw-r--r-- | tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini | 1 |
14 files changed, 466 insertions, 63 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 8e4801573a8..dcb45f40791 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -11,11 +11,11 @@ use surface_map::SurfaceMap; use windowing; use windowing::{MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg}; -use euclid::Matrix4; -use euclid::point::{Point2D, TypedPoint2D}; -use euclid::rect::{Rect, TypedRect}; +use euclid::point::TypedPoint2D; +use euclid::rect::TypedRect; use euclid::scale_factor::ScaleFactor; -use euclid::size::{Size2D, TypedSize2D}; +use euclid::size::TypedSize2D; +use euclid::{Size2D, Point2D, Rect, Matrix4}; use gfx::paint_task::{ChromeToPaintMsg, PaintRequest}; use gfx_traits::color; use gleam::gl; @@ -390,7 +390,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.send_buffer_requests_for_all_layers(); } - (Msg::GetNativeDisplay(chan), ShutdownState::NotShuttingDown) => { + (Msg::GetNativeDisplay(chan), + ShutdownState::NotShuttingDown) => { chan.send(Some(self.native_display.clone())).unwrap(); } @@ -415,11 +416,27 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.surface_map.insert_surfaces(&self.native_display, native_surfaces); } - (Msg::ScrollFragmentPoint(pipeline_id, layer_id, point), + (Msg::ScrollFragmentPoint(pipeline_id, layer_id, point, _), ShutdownState::NotShuttingDown) => { self.scroll_fragment_to_point(pipeline_id, layer_id, point); } + (Msg::MoveTo(point), + ShutdownState::NotShuttingDown) => { + self.window.set_position(point); + } + + (Msg::ResizeTo(size), + ShutdownState::NotShuttingDown) => { + self.window.set_inner_size(size); + } + + (Msg::GetClientWindow(send), + ShutdownState::NotShuttingDown) => { + let rect = self.window.client_window(); + send.send(rect).unwrap(); + } + (Msg::Status(message), ShutdownState::NotShuttingDown) => { self.window.status(message); } diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index 86d87f92336..161d8861a9d 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -11,8 +11,7 @@ use compositor; use headless; use windowing::{WindowEvent, WindowMethods}; -use euclid::point::Point2D; -use euclid::rect::Rect; +use euclid::{Size2D, Point2D, Rect}; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use layers::layers::{BufferRequest, LayerBufferSet}; use layers::platform::surface::{NativeDisplay, NativeSurface}; @@ -66,8 +65,20 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati receiver: IpcReceiver<ScriptToCompositorMsg>) { while let Ok(msg) = receiver.recv() { match msg { - ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point) => { - compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point)); + ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point, _smooth) => { + compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point, _smooth)); + } + + ScriptToCompositorMsg::GetClientWindow(send) => { + compositor_proxy.send(Msg::GetClientWindow(send)); + } + + ScriptToCompositorMsg::MoveTo(point) => { + compositor_proxy.send(Msg::MoveTo(point)); + } + + ScriptToCompositorMsg::ResizeTo(size) => { + compositor_proxy.send(Msg::ResizeTo(size)); } ScriptToCompositorMsg::Exit => { @@ -159,7 +170,7 @@ pub enum Msg { /// Alerts the compositor that the specified layer's rect has changed. SetLayerRect(PipelineId, LayerId, Rect<f32>), /// Scroll a page in a window - ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>), + ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool), /// Requests that the compositor assign the painted buffers to the given layers. AssignPaintedBuffers(PipelineId, Epoch, Vec<(LayerId, Box<LayerBufferSet>)>, FrameTreeId), /// Alerts the compositor that the current page has changed its title. @@ -201,6 +212,12 @@ pub enum Msg { CollectMemoryReports(mem::ReportsChan), /// A status message to be displayed by the browser chrome. Status(Option<String>), + /// Get Window Informations size and position + GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>), + /// Move the window to a point + MoveTo(Point2D<i32>), + /// Resize the window to size + ResizeTo(Size2D<u32>), } impl Debug for Msg { @@ -232,6 +249,9 @@ impl Debug for Msg { Msg::ReturnUnusedNativeSurfaces(..) => write!(f, "ReturnUnusedNativeSurfaces"), Msg::CollectMemoryReports(..) => write!(f, "CollectMemoryReports"), Msg::Status(..) => write!(f, "Status"), + Msg::GetClientWindow(..) => write!(f, "GetClientWindow"), + Msg::MoveTo(..) => write!(f, "MoveTo"), + Msg::ResizeTo(..) => write!(f, "ResizeTo"), } } } diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index d8f952beada..513f814078b 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -6,7 +6,7 @@ use compositor_task::{CompositorEventListener, CompositorReceiver, Msg}; use windowing::WindowEvent; use euclid::scale_factor::ScaleFactor; -use euclid::size::Size2D; +use euclid::{Size2D, Point2D}; use msg::constellation_msg::AnimationState; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, WindowSizeData}; @@ -89,6 +89,11 @@ impl CompositorEventListener for NullCompositor { response_chan.send(()).unwrap(); } + Msg::GetClientWindow(send) => { + let rect = (Size2D::zero(), Point2D::zero()); + send.send(rect).unwrap(); + } + Msg::ChangeRunningAnimationsState(pipeline_id, animation_state) => { match animation_state { AnimationState::AnimationsPresent | @@ -121,6 +126,8 @@ impl CompositorEventListener for NullCompositor { Msg::ViewportConstrained(..) => {} Msg::CreatePng(..) | Msg::PaintTaskExited(..) | + Msg::MoveTo(..) | + Msg::ResizeTo(..) | Msg::IsReadyToSaveImageReply(..) => {} Msg::NewFavicon(..) => {} Msg::HeadParsed => {} diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 3efa8ba34b5..99cd0615c25 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -9,6 +9,7 @@ use compositor_task::{CompositorProxy, CompositorReceiver}; use euclid::point::TypedPoint2D; use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; +use euclid::{Size2D, Point2D}; use layers::geometry::DevicePixel; use layers::platform::surface::NativeDisplay; use msg::constellation_msg::{Key, KeyState, KeyModifiers}; @@ -103,6 +104,13 @@ pub trait WindowMethods { /// 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) -> (Size2D<u32>, Point2D<i32>); + /// Set the size inside of borders and head + fn set_inner_size(&self, size: Size2D<u32>); + /// Set the window position + fn set_position(&self, point: Point2D<i32>); + /// Sets the page title for the current page. fn set_page_title(&self, title: Option<String>); /// Sets the load data for the current page. diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index 6dd58b8aae6..90f59b7917c 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -5,8 +5,8 @@ use azure::azure_hl::Color; use constellation_msg::{Key, KeyState, KeyModifiers}; use euclid::Matrix4; -use euclid::point::Point2D; -use euclid::rect::Rect; +use euclid::{Size2D, Point2D, Rect}; +use ipc_channel::ipc::IpcSender; use layers::layers::{BufferRequest, LayerBufferSet}; use layers::platform::surface::NativeDisplay; use std::fmt; @@ -119,9 +119,11 @@ pub trait PaintListener { #[derive(Deserialize, Serialize)] pub enum ScriptToCompositorMsg { - ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>), + ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool), SetTitle(PipelineId, Option<String>), SendKeyEvent(Key, KeyState, KeyModifiers), + GetClientWindow(IpcSender<(Size2D<u32>, Point2D<i32>)>), + MoveTo(Point2D<i32>), + ResizeTo(Size2D<u32>), Exit, } - diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 18044e33ae9..96c8b5a6bbb 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -5,9 +5,8 @@ //! The high-level interface from script to constellation. Using this abstract interface helps //! reduce coupling between these two components. -use compositor_msg::Epoch; - use canvas_traits::CanvasMsg; +use compositor_msg::Epoch; use euclid::rect::Rect; use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl index f744397a379..bd42952f027 100644 --- a/components/script/dom/webidls/Window.webidl +++ b/components/script/dom/webidls/Window.webidl @@ -106,35 +106,52 @@ partial interface Window { }; // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface +enum ScrollBehavior { "auto", "instant", "smooth" }; + +// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface +dictionary ScrollOptions { + ScrollBehavior behavior = "auto"; +}; + +// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface +dictionary ScrollToOptions : ScrollOptions { + unrestricted double left; + unrestricted double top; +}; + +// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface partial interface Window { //MediaQueryList matchMedia(DOMString query); [SameObject] readonly attribute Screen screen; // browsing context - //void moveTo(double x, double y); - //void moveBy(double x, double y); - //void resizeTo(double x, double y); - //void resizeBy(double x, double y); + void moveTo(long x, long y); + void moveBy(long x, long y); + void resizeTo(long x, long y); + void resizeBy(long x, long y); // viewport - //readonly attribute double innerWidth; - //readonly attribute double innerHeight; + readonly attribute long innerWidth; + readonly attribute long innerHeight; // viewport scrolling - //readonly attribute double scrollX; - //readonly attribute double pageXOffset; - //readonly attribute double scrollY; - //readonly attribute double pageYOffset; - //void scroll(double x, double y, optional ScrollOptions options); - //void scrollTo(double x, double y, optional ScrollOptions options); - //void scrollBy(double x, double y, optional ScrollOptions options); + readonly attribute long scrollX; + readonly attribute long pageXOffset; + readonly attribute long scrollY; + readonly attribute long pageYOffset; + void scroll(optional ScrollToOptions options); + void scroll(unrestricted double x, unrestricted double y); + void scrollTo(optional ScrollToOptions options); + void scrollTo(unrestricted double x, unrestricted double y); + void scrollBy(optional ScrollToOptions options); + void scrollBy(unrestricted double x, unrestricted double y); // client - //readonly attribute double screenX; - //readonly attribute double screenY; - //readonly attribute double outerWidth; - //readonly attribute double outerHeight; - //readonly attribute double devicePixelRatio; + readonly attribute long screenX; + readonly attribute long screenY; + readonly attribute long outerWidth; + readonly attribute long outerHeight; + readonly attribute double devicePixelRatio; }; // Proprietary extensions. diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index c463efa9f69..2cfe4cf4868 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -7,6 +7,7 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull}; use dom::bindings::codegen::Bindings::FunctionBinding::Function; +use dom::bindings::codegen::Bindings::WindowBinding::{ScrollToOptions, ScrollBehavior}; use dom::bindings::codegen::Bindings::WindowBinding::{self, WindowMethods, FrameRequestCallback}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, WindowDerived}; use dom::bindings::error::Error::InvalidCharacter; @@ -40,7 +41,7 @@ use timers::{IsInterval, TimerId, TimerManager, TimerCallback}; use webdriver_handlers::jsval_to_webdriver; use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType}; -use msg::compositor_msg::ScriptToCompositorMsg; +use msg::compositor_msg::{ScriptToCompositorMsg, LayerId}; use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData, WorkerId}; use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use net_traits::ResourceTask; @@ -52,8 +53,9 @@ use util::geometry::{self, Au, MAX_RECT}; use util::str::{DOMString, HTML_SPACE_CHARACTERS}; use util::{breakpoint, opts}; +use euclid::scale_factor::ScaleFactor; use euclid::{Point2D, Rect, Size2D}; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{Evaluate2, MutableHandleValue}; use js::jsapi::{JSContext, HandleValue}; use js::jsapi::{JS_GC, JS_GetRuntime, JSAutoCompartment, JSAutoRequest}; @@ -63,6 +65,7 @@ use selectors::parser::PseudoElement; use url::Url; use libc; +use num::traits::ToPrimitive; use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD}; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -103,6 +106,8 @@ pub enum ReflowReason { RequestAnimationFrame, } +pub type ScrollPoint = Point2D<Au>; + #[dom_struct] pub struct Window { eventtarget: EventTarget, @@ -213,6 +218,8 @@ pub struct Window { /// The current state of the window object current_state: Cell<WindowState>, + + current_viewport: Cell<Rect<Au>> } impl Window { @@ -603,8 +610,152 @@ impl WindowMethods for Window { // Step 5. CSSStyleDeclaration::new(self, element, pseudo, CSSModificationAccess::Readonly) } -} + // https://drafts.csswg.org/cssom-view/#dom-window-innerheight + //TODO Include Scrollbar + fn InnerHeight(&self) -> i32 { + let size = self.window_size.get(); + match size { + Some(e) => e.visible_viewport.height.get().to_i32().unwrap_or(0), + None => 0 + } + } + + // https://drafts.csswg.org/cssom-view/#dom-window-innerwidth + //TODO Include Scrollbar + fn InnerWidth(&self) -> i32 { + let size = self.window_size.get(); + match size { + Some(e) => e.visible_viewport.width.get().to_i32().unwrap_or(0), + None => 0 + } + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scrollx + fn ScrollX(&self) -> i32 { + self.current_viewport.get().origin.x.to_px() + } + + // https://drafts.csswg.org/cssom-view/#dom-window-pagexoffset + fn PageXOffset(&self) -> i32 { + self.ScrollX() + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scrolly + fn ScrollY(&self) -> i32 { + self.current_viewport.get().origin.y.to_px() + } + + // https://drafts.csswg.org/cssom-view/#dom-window-pageyoffset + fn PageYOffset(&self) -> i32 { + self.ScrollY() + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scroll + fn Scroll(&self, options: &ScrollToOptions) { + // Step 1 + let left = options.left.unwrap_or(0.0f64); + let top = options.top.unwrap_or(0.0f64); + self.scroll(left, top, options.parent.behavior); + + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scroll + fn Scroll_(&self, x: f64, y: f64) { + self.scroll(x, y, ScrollBehavior::Auto); + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scrollto + fn ScrollTo(&self, options: &ScrollToOptions) { + self.Scroll(options); + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scrollto + fn ScrollTo_(&self, x: f64, y: f64) { + self.scroll(x, y, ScrollBehavior::Auto); + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scrollby + fn ScrollBy(&self, options: &ScrollToOptions) { + // Step 1 + let x = options.left.unwrap_or(0.0f64); + let y = options.top.unwrap_or(0.0f64); + self.ScrollBy_(x, y, ); + self.scroll(x, y, options.parent.behavior); + } + + // https://drafts.csswg.org/cssom-view/#dom-window-scrollby + fn ScrollBy_(&self, x: f64, y: f64) { + // Step 3 + let left = x + self.ScrollX() as f64; + // 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) { + // 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.compositor.send(ScriptToCompositorMsg::ResizeTo(size)).unwrap() + } + + // 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.compositor.send(ScriptToCompositorMsg::MoveTo(point)).unwrap() + } + + // 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) + } + + // https://drafts.csswg.org/cssom-view/#dom-window-screenx + fn ScreenX(&self) -> i32 { + let (_, origin) = self.client_window(); + origin.x + } + + // https://drafts.csswg.org/cssom-view/#dom-window-screeny + fn ScreenY(&self) -> i32 { + let (_, origin) = self.client_window(); + origin.y + } + + // https://drafts.csswg.org/cssom-view/#dom-window-outerheight + fn OuterHeight(&self) -> i32 { + let (size, _) = self.client_window(); + size.height.to_i32().unwrap_or(1) + } + + // 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(|data| data.device_pixel_ratio).unwrap_or(ScaleFactor::new(1.0f32)).get(); + Finite::wrap(dpr as f64) + } +} pub trait ScriptHelpers { fn evaluate_js_on_global_with_result(self, code: &str, @@ -664,6 +815,83 @@ impl Window { *self.browsing_context.borrow_mut() = None; } + /// https://drafts.csswg.org/cssom-view/#dom-window-scroll + pub fn scroll(&self, x_: f64, y_: f64, behavior: ScrollBehavior) { + // Step 3 + let xfinite = if x_.is_finite() { x_ } else { 0.0f64 }; + let yfinite = if y_.is_finite() { y_ } else { 0.0f64 }; + + // Step 4 + if self.window_size.get().is_none() { + return; + } + + // Step 5 + //TODO remove scrollbar width + let width = self.InnerWidth() as f64; + // Step 6 + //TODO remove scrollbar width + let height = self.InnerHeight() as f64; + + // Step 7 & 8 + //TODO use overflow direction + let body = self.Document().GetBody(); + let (x, y) = match body { + Some(e) => { + let node = NodeCast::from_ref(e.r()); + let content_size = node.get_bounding_content_box(); + + let content_height = content_size.size.height.to_f64_px(); + let content_width = content_size.size.width.to_f64_px(); + (xfinite.max(0.0f64).min(content_width - width), + yfinite.max(0.0f64).min(content_height - height)) + }, + None => { + (xfinite.max(0.0f64), yfinite.max(0.0f64)) + } + }; + + // Step 10 + //TODO handling ongoing smoth scrolling + if x == self.ScrollX() as f64 && y == self.ScrollY() as f64 { + return; + } + + //TODO Step 11 + //let document = self.Document(); + // Step 12 + self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32), y.to_f32().unwrap_or(0.0f32), behavior, None); + } + + /// https://drafts.csswg.org/cssom-view/#perform-a-scroll + pub fn perform_a_scroll(&self, x: f32, y: f32, behavior: ScrollBehavior, element: Option<&Element>) { + //TODO Step 1 + let point = Point2D::new(x, y); + let smooth = match behavior { + ScrollBehavior::Auto => { + element.map(|_element| { + // TODO check computed scroll-behaviour CSS property + true + }).unwrap_or(false) + } + ScrollBehavior::Instant => false, + ScrollBehavior::Smooth => true + }; + + // TODO (farodin91): Raise an event to stop the current_viewport + let size = self.current_viewport.get().size; + self.current_viewport.set(Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size)); + + self.compositor.send(ScriptToCompositorMsg::ScrollFragmentPoint( + self.pipeline(), LayerId::null(), point, smooth)).unwrap() + } + + pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { + let (send, recv) = ipc::channel::<(Size2D<u32>, Point2D<i32>)>().unwrap(); + self.compositor.send(ScriptToCompositorMsg::GetClientWindow(send)).unwrap(); + recv.recv().unwrap_or((Size2D::zero(), Point2D::zero())) + } + /// Reflows the page unconditionally. This method will wait for the layout thread to complete /// (but see the `TODO` below). If there is no window size yet, the page is presumed invisible /// and no reflow is performed. @@ -941,28 +1169,30 @@ impl Window { } pub fn set_page_clip_rect_with_new_viewport(&self, viewport: Rect<f32>) -> bool { + let rect = geometry::f32_rect_to_au_rect(viewport.clone()); + self.current_viewport.set(rect); // We use a clipping rectangle that is five times the size of the of the viewport, // so that we don't collect display list items for areas too far outside the viewport, // but also don't trigger reflows every time the viewport changes. static VIEWPORT_EXPANSION: f32 = 2.0; // 2 lengths on each side plus original length is 5 total. - let proposed_clip_rect = geometry::f32_rect_to_au_rect( - viewport.inflate(viewport.size.width * VIEWPORT_EXPANSION, - viewport.size.height * VIEWPORT_EXPANSION)); - let clip_rect = self.page_clip_rect.get(); - if proposed_clip_rect == clip_rect { - return false; - } + let proposed_clip_rect = geometry::f32_rect_to_au_rect( + viewport.inflate(viewport.size.width * VIEWPORT_EXPANSION, + viewport.size.height * VIEWPORT_EXPANSION)); + let clip_rect = self.page_clip_rect.get(); + if proposed_clip_rect == clip_rect { + return false; + } - let had_clip_rect = clip_rect != MAX_RECT; - if had_clip_rect && !should_move_clip_rect(clip_rect, viewport) { - return false; - } + let had_clip_rect = clip_rect != MAX_RECT; + if had_clip_rect && !should_move_clip_rect(clip_rect, viewport) { + return false; + } - self.page_clip_rect.set(proposed_clip_rect); + self.page_clip_rect.set(proposed_clip_rect); - // If we didn't have a clip rect, the previous display doesn't need rebuilding - // because it was built for infinite clip (MAX_RECT). - had_clip_rect + // If we didn't have a clip rect, the previous display doesn't need rebuilding + // because it was built for infinite clip (MAX_RECT). + had_clip_rect } pub fn set_devtools_wants_updates(&self, value: bool) { @@ -1095,6 +1325,7 @@ impl Window { layout_rpc: layout_rpc, layout_join_port: DOMRefCell::new(None), window_size: Cell::new(window_size), + current_viewport: Cell::new(Rect::zero()), pending_reflow_count: Cell::new(0), current_state: Cell::new(WindowState::Alive), diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 1ab86d67570..503673671e4 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -1722,7 +1722,7 @@ impl ScriptTask { // layer the element belongs to, and have it send the scroll message to the // compositor. self.compositor.borrow_mut().send(ScriptToCompositorMsg::ScrollFragmentPoint( - pipeline_id, LayerId::null(), point)).unwrap(); + pipeline_id, LayerId::null(), point, false)).unwrap(); } /// Reflows non-incrementally, rebuilding the entire layout tree in the process. diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 55b329ea202..03796de4ed3 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -20,6 +20,8 @@ use wrappers::CefWrap; use compositing::compositor_task::{self, CompositorProxy, CompositorReceiver}; use compositing::windowing::{WindowEvent, WindowMethods}; +use euclid::point::Point2D; +use euclid::rect::Rect; use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; use gleam::gl; @@ -147,16 +149,16 @@ impl Window { Cursor::TextCursor => msg_send![class("NSCursor"), IBeamCursor], Cursor::GrabCursor | Cursor::AllScrollCursor => msg_send![class("NSCursor"), openHandCursor], - Cursor::NoDropCursor | Cursor::NotAllowedCursor => + Cursor::NoDropCursor | Cursor::NotAllowedCursor => msg_send![class("NSCursor"), operationNotAllowedCursor], Cursor::PointerCursor => msg_send![class("NSCursor"), pointingHandCursor], Cursor::SResizeCursor => msg_send![class("NSCursor"), resizeDownCursor], Cursor::WResizeCursor => msg_send![class("NSCursor"), resizeLeftCursor], - Cursor::EwResizeCursor | Cursor::ColResizeCursor => + Cursor::EwResizeCursor | Cursor::ColResizeCursor => msg_send![class("NSCursor"), resizeLeftRightCursor], Cursor::EResizeCursor => msg_send![class("NSCursor"), resizeRightCursor], Cursor::NResizeCursor => msg_send![class("NSCursor"), resizeUpCursor], - Cursor::NsResizeCursor | Cursor::RowResizeCursor => + Cursor::NsResizeCursor | Cursor::RowResizeCursor => msg_send![class("NSCursor"), resizeUpDownCursor], Cursor::VerticalTextCursor => msg_send![class("NSCursor"), IBeamCursorForVerticalLayout], _ => msg_send![class("NSCursor"), arrowCursor], @@ -223,6 +225,22 @@ impl WindowMethods for Window { } } + fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { + let size = self.size().to_untyped(); + let width = size.width as u32; + let height = size.height as u32; + //TODO get real window position + (Size2D::new(width, height), Point2D::zero()) + } + + fn set_inner_size(&self, size: Size2D<u32>) { + + } + + fn set_position(&self, point: Point2D<i32>) { + + } + fn present(&self) { let browser = self.cef_browser.borrow(); match *browser { diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index ec96727d811..58bd147797f 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -7,7 +7,8 @@ use compositing::compositor_task::{self, CompositorProxy, CompositorReceiver}; use compositing::windowing::{WindowEvent, WindowMethods}; use euclid::scale_factor::ScaleFactor; -use euclid::size::{Size2D, TypedSize2D}; +use euclid::size::TypedSize2D; +use euclid::{Size2D, Point2D}; use gleam::gl; use glutin; use layers::geometry::DevicePixel; @@ -25,8 +26,6 @@ use NestedEventLoopListener; #[cfg(feature = "window")] use compositing::windowing::{MouseWindowEvent, WindowNavigateMsg}; #[cfg(feature = "window")] -use euclid::point::Point2D; -#[cfg(feature = "window")] use glutin::{Api, ElementState, Event, GlRequest, MouseButton, VirtualKeyCode, MouseScrollDelta}; #[cfg(feature = "window")] use msg::constellation_msg::{KeyState, NONE, CONTROL, SHIFT, ALT, SUPER}; @@ -521,6 +520,22 @@ impl WindowMethods for Window { Size2D::typed(width as f32, height as f32) } + fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { + let (width, height) = self.window.get_outer_size().unwrap(); + let size = Size2D::new(width, height); + let (x, y) = self.window.get_position().unwrap(); + let origin = Point2D::new(x as i32, y as i32); + (size, origin) + } + + fn set_inner_size(&self, size: Size2D<u32>) { + self.window.set_inner_size(size.width as u32, size.height as u32) + } + + fn set_position(&self, point: Point2D<i32>) { + self.window.set_position(point.x, point.y) + } + fn present(&self) { self.window.swap_buffers().unwrap(); } @@ -748,6 +763,20 @@ impl WindowMethods for Window { fn present(&self) { } + fn set_inner_size(&self, _: Size2D<u32>) { + + } + + fn set_position(&self, _: Point2D<i32>) { + + } + + fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { + let width = self.width; + let height = self.height; + (Size2D::new(width, height), Point2D::zero()) + } + fn create_compositor_channel(_: &Option<Rc<Window>>) -> (Box<CompositorProxy + Send>, Box<CompositorReceiver>) { let (sender, receiver) = channel(); diff --git a/ports/gonk/src/window.rs b/ports/gonk/src/window.rs index 08589787b90..9c239a4081a 100644 --- a/ports/gonk/src/window.rs +++ b/ports/gonk/src/window.rs @@ -6,6 +6,7 @@ use compositing::compositor_task::{self, CompositorProxy, CompositorReceiver}; use compositing::windowing::{WindowEvent, WindowMethods}; +use euclid::point::Point2D; use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; use gleam::gl; @@ -790,6 +791,20 @@ impl WindowMethods for Window { Size2D::typed(self.width as f32, self.height as f32) } + fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) { + let width = self.width as u32; + let height = self.height as u32; + (Size2D::new(width, height), Point2D::zero()) + } + + fn set_inner_size(&self, _: Size2D<u32>) { + + } + + fn set_position(&self, _: Point2D<i32>) { + + } + /// Presents the window to the screen (perhaps by page flipping). fn present(&self) { let _ = egl::SwapBuffers(self.dpy, self.surf); @@ -870,4 +885,3 @@ impl CompositorProxy for GonkCompositorProxy { } as Box<CompositorProxy + Send> } } - diff --git a/tests/html/viewport.html b/tests/html/viewport.html new file mode 100644 index 00000000000..bd0dbb8bc65 --- /dev/null +++ b/tests/html/viewport.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> + <head> + <title>Test innerHeight</title> + <script type="text/javascript"> + function show(){ + console.log("innerHeight: "+ window.innerHeight); + console.log("innerWidth: "+ window.innerWidth); + console.log("ScrollY: "+ window.scrollY); + console.log("ScrollX: "+ window.scrollX); + console.log("outerHeight: "+ window.outerHeight); + console.log("outerWidth: "+ window.outerWidth); + console.log("screenY: "+ window.screenY); + console.log("screenX: "+ window.screenX); + } + function test_scroll(){ + + } + </script> + </head> + <body> + <button onclick="show();">Test</button> + <button onclick="window.scroll(0,100);">Scroll</button> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <br/> + <button onclick="window.moveTo(100,10);">Move</button> + <button onclick="window.scroll(0,10);">Scroll 2</button> + <div style="background-color: #b0c4de; height:1000px; width:800px;"/> + <button onclick="show();">Test</button> + </body> +</html> diff --git a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini index 68049100081..e2a63b29756 100644 --- a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini +++ b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini @@ -377,4 +377,3 @@ [Window replaceable attribute: devicePixelRatio] expected: FAIL - |