aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorZhen Zhang <izgzhen@gmail.com>2016-04-03 15:41:37 +0800
committerZhen Zhang <izgzhen@gmail.com>2016-04-19 12:27:35 +0800
commitfefdaf76ded7675c0c67fd33f5abfbb5f74ac30f (patch)
tree90131ccb368cc04b279f82b085052ae4236495e2 /components/script/dom
parentf73c6143d5375db80fd2e0b7de96a99c78b5866b (diff)
downloadservo-fefdaf76ded7675c0c67fd33f5abfbb5f74ac30f.tar.gz
servo-fefdaf76ded7675c0c67fd33f5abfbb5f74ac30f.zip
Implement ScrollTop and ScrollLeft getters:
Add new compositor message to get scroll_offset; Add new layout query for computed value of overflow-x/y; Implement layer_id method for ThreadSafeLayoutNode; Add new layout query for layer_id; Implement script interface for getting scrollTop and scrollLeft, as well as relavant helper functions.
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/element.rs95
-rw-r--r--components/script/dom/node.rs6
-rw-r--r--components/script/dom/webidls/Element.webidl2
-rw-r--r--components/script/dom/window.rs22
4 files changed, 124 insertions, 1 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index e14e1af0d97..8fa454c0e73 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -19,6 +19,7 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
@@ -39,6 +40,7 @@ use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementLayoutHelpers};
use dom::htmlbuttonelement::HTMLButtonElement;
use dom::htmlcollection::HTMLCollection;
+use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlfontelement::{HTMLFontElement, HTMLFontElementLayoutHelpers};
use dom::htmlhrelement::{HTMLHRElement, HTMLHRLayoutHelpers};
@@ -86,7 +88,7 @@ use string_cache::{Atom, Namespace, QualName};
use style::element_state::*;
use style::error_reporting::ParseErrorReporter;
use style::properties::DeclaredValue;
-use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size};
+use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::values::CSSFloat;
@@ -164,6 +166,35 @@ impl Element {
document,
ElementBinding::Wrap)
}
+
+ // https://drafts.csswg.org/cssom-view/#css-layout-box
+ // Elements that have a computed value of the display property
+ // that is table-column or table-column-group
+ // FIXME: Currently, it is assumed to be true always
+ fn has_css_layout_box(&self) -> bool {
+ true
+ }
+
+ // https://drafts.csswg.org/cssom-view/#potentially-scrollable
+ fn potentially_scrollable(&self) -> bool {
+ self.has_css_layout_box() &&
+ !self.overflow_x_is_visible() &&
+ !self.overflow_y_is_visible()
+ }
+
+ // used value of overflow-x is "visible"
+ fn overflow_x_is_visible(&self) -> bool {
+ let window = window_from_node(self);
+ let overflow_pair = window.overflow_query(self.upcast::<Node>().to_trusted_node_address());
+ overflow_pair.x == overflow_x::computed_value::T::visible
+ }
+
+ // used value of overflow-y is "visible"
+ fn overflow_y_is_visible(&self) -> bool {
+ let window = window_from_node(self);
+ let overflow_pair = window.overflow_query(self.upcast::<Node>().to_trusted_node_address());
+ overflow_pair.y != overflow_x::computed_value::T::visible
+ }
}
#[allow(unsafe_code)]
@@ -1452,6 +1483,68 @@ impl ElementMethods for Element {
rect.size.height.to_f64_px())
}
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
+ fn ScrollTop(&self) -> f64 {
+ let node = self.upcast::<Node>();
+
+ // 1. Let document be the element’s node document.
+ let doc = node.owner_doc();
+
+ // 2. If the document is not the active document, return zero and terminate these steps.
+ if !doc.is_fully_active() {
+ return 0.0;
+ } else {
+ // 3. Let window be the value of document’s defaultView attribute.
+ let win = doc.DefaultView();
+
+ // 5. If the element is the root element and document is in quirks mode,
+ // return zero and terminate these steps.
+ if *self.root_element() == *self {
+ if doc.quirks_mode() == Quirks {
+ return 0.0;
+ }
+
+ // 6. If the element is the root element return the value of scrollY on window.
+ return (*win).ScrollY() as f64;
+ }
+
+ // 7. If the element is the HTML body element, document is in quirks mode,
+ // and the element is not potentially scrollable, return the value of scrollY on window.
+ if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
+ doc.quirks_mode() == Quirks &&
+ !self.potentially_scrollable() {
+ return (*win).ScrollY() as f64;
+ }
+
+
+ // 8. If the element does not have any associated CSS layout box, return zero and terminate these steps.
+ if !self.has_css_layout_box() {
+ return 0.0;
+ }
+
+ // 9. Return the y-coordinate of the scrolling area at the alignment point
+ // with the top of the padding edge of the element.
+ let point = node.scroll_offset();
+ return -point.y as f64;
+ }
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
+ fn SetScrollTop(&self, _scroll_top: f64) {
+ unimplemented!()
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrollleft
+ fn ScrollLeft(&self) -> f64 {
+ let point = self.upcast::<Node>().scroll_offset();
+ return -point.x as f64;
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrollleft
+ fn SetScrollLeft(&self, _scroll_left: f64) {
+ unimplemented!()
+ }
+
// https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth
fn ScrollWidth(&self) -> i32 {
self.upcast::<Node>().scroll_area().size.width
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 1e71966e4e7..d8c23b559d9 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -614,6 +614,12 @@ impl Node {
}
}
+ pub fn scroll_offset(&self) -> Point2D<f32> {
+ let document = self.owner_doc();
+ let window = document.window();
+ window.scroll_offset_query(self.to_trusted_node_address())
+ }
+
// https://dom.spec.whatwg.org/#dom-childnode-before
pub fn before(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
// Step 1.
diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl
index 9bc5ff64597..b161a782a55 100644
--- a/components/script/dom/webidls/Element.webidl
+++ b/components/script/dom/webidls/Element.webidl
@@ -81,6 +81,8 @@ partial interface Element {
DOMRectList getClientRects();
DOMRect getBoundingClientRect();
+ attribute unrestricted double scrollTop;
+ attribute unrestricted double scrollLeft;
readonly attribute long scrollWidth;
readonly attribute long scrollHeight;
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 8a3affefe06..75c7089fac3 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -74,6 +74,7 @@ use std::sync::{Arc, Mutex};
use string_cache::Atom;
use style::context::ReflowGoal;
use style::error_reporting::ParseErrorReporter;
+use style::properties::longhands::{overflow_x};
use style::selector_impl::PseudoElement;
use task_source::TaskSource;
use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask};
@@ -1122,6 +1123,25 @@ impl Window {
self.layout_rpc.node_scroll_area().client_rect
}
+ pub fn overflow_query(&self, node: TrustedNodeAddress) -> Point2D<overflow_x::computed_value::T> {
+ self.reflow(ReflowGoal::ForScriptQuery,
+ ReflowQueryType::NodeOverflowQuery(node),
+ ReflowReason::Query);
+ self.layout_rpc.node_overflow().0.unwrap()
+ }
+
+ pub fn scroll_offset_query(&self, node: TrustedNodeAddress) -> Point2D<f32> {
+ self.reflow(ReflowGoal::ForScriptQuery,
+ ReflowQueryType::NodeLayerIdQuery(node),
+ ReflowReason::Query);
+ let layer_id = self.layout_rpc.node_layer_id().layer_id;
+ let pipeline_id = self.id;
+
+ let (send, recv) = ipc::channel::<Point2D<f32>>().unwrap();
+ self.compositor.send(ScriptToCompositorMsg::GetScrollOffset(pipeline_id, layer_id, send)).unwrap();
+ recv.recv().unwrap_or(Point2D::zero())
+ }
+
pub fn resolved_style_query(&self,
element: TrustedNodeAddress,
pseudo: Option<PseudoElement>,
@@ -1476,6 +1496,8 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
ReflowQueryType::HitTestQuery(_n, _o) => "\tHitTestQuery",
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
+ ReflowQueryType::NodeLayerIdQuery(_n) => "\tNodeLayerIdQuery",
+ ReflowQueryType::NodeOverflowQuery(_n) => "\tNodeOverFlowQuery",
ReflowQueryType::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",