aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/compositor.rs29
-rw-r--r--components/compositing/compositor_task.rs30
-rw-r--r--components/compositing/headless.rs9
-rw-r--r--components/compositing/windowing.rs8
-rw-r--r--components/msg/compositor_msg.rs10
-rw-r--r--components/msg/constellation_msg.rs3
-rw-r--r--components/script/dom/webidls/Window.webidl53
-rw-r--r--components/script/dom/window.rs267
-rw-r--r--components/script/script_task.rs2
-rw-r--r--ports/cef/window.rs24
-rw-r--r--ports/glutin/window.rs35
-rw-r--r--ports/gonk/src/window.rs16
-rw-r--r--tests/html/viewport.html42
-rw-r--r--tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini1
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
-