aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-04-04 12:48:39 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2016-04-04 12:48:39 +0530
commit241518a7d2c26da421d0273f101550215576c5a7 (patch)
treeeed9c5cb5f33941a25835e1841db76608a2288ec
parentd35ae3beb73158ec4c9ab20b3361e948379a4c90 (diff)
parent07584b9f29bf99362b74c75ea4291e3438768291 (diff)
downloadservo-241518a7d2c26da421d0273f101550215576c5a7.tar.gz
servo-241518a7d2c26da421d0273f101550215576c5a7.zip
Auto merge of #10034 - rilut:implement-elementsfrompoint, r=emilio
Implement Document#elementsFromPoint Fixes #9859. I'm trying to implement Document#elementsFromPoint, which I need to reuse the `get_nodes_under_mouse` and `mouse_over` function which have been removed a days ago in #9715. So I added it back while I'm not sure if my implementation is correct. Any advice will be greatly appreciated. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10034) <!-- Reviewable:end -->
-rw-r--r--components/layout/query.rs19
-rw-r--r--components/script/dom/document.rs42
-rw-r--r--components/script/dom/webidls/Document.webidl1
-rw-r--r--components/script/layout_interface.rs2
-rw-r--r--tests/wpt/include.ini2
-rw-r--r--tests/wpt/metadata/cssom-view/elementsFromPoint.html.ini17
-rw-r--r--tests/wpt/metadata/cssom-view/scrollingElement.html.ini5
7 files changed, 88 insertions, 0 deletions
diff --git a/components/layout/query.rs b/components/layout/query.rs
index 65296bc1b4e..2d914ece89a 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -20,6 +20,7 @@ use script::layout_interface::{ContentBoxResponse, ContentBoxesResponse, NodeGeo
use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse};
use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, MarginStyleResponse};
use script_traits::LayoutMsg as ConstellationMsg;
+use script_traits::UntrustedNodeAddress;
use sequential;
use std::cmp::{min, max};
use std::ops::Deref;
@@ -85,6 +86,24 @@ impl LayoutRPC for LayoutRPCImpl {
}
}
+ fn nodes_from_point(&self, point: Point2D<f32>) -> Vec<UntrustedNodeAddress> {
+ let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
+ let nodes_from_point_list = {
+ let &LayoutRPCImpl(ref rw_data) = self;
+ let rw_data = rw_data.lock().unwrap();
+ let result = match rw_data.display_list {
+ None => panic!("Tried to hit test without a DisplayList"),
+ Some(ref display_list) => display_list.hit_test(point),
+ };
+
+ result
+ };
+
+ nodes_from_point_list.iter()
+ .map(|metadata| metadata.node.to_untrusted_node_address())
+ .collect()
+ }
+
fn node_geometry(&self) -> NodeGeometryResponse {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index eb7e0da8a1b..a708e9b6cc6 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -94,6 +94,7 @@ use net_traits::response::HttpsState;
use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
use num::ToPrimitive;
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan};
+use script_traits::UntrustedNodeAddress;
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg};
use script_traits::{TouchEventType, TouchId};
@@ -1480,6 +1481,12 @@ impl Document {
self.browsing_context.is_none() || !url_has_network_scheme(&self.url)
}
+
+ pub fn nodes_from_point(&self, page_point: &Point2D<f32>) -> Vec<UntrustedNodeAddress> {
+ assert!(self.GetDocumentElement().is_some());
+
+ self.window.layout().nodes_from_point(*page_point)
+ }
}
#[derive(PartialEq, HeapSizeOf)]
@@ -2601,6 +2608,40 @@ impl DocumentMethods for Document {
None => self.GetDocumentElement()
}
}
+
+ #[allow(unsafe_code)]
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementsfrompoint
+ fn ElementsFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Vec<Root<Element>> {
+ let x = *x as f32;
+ let y = *y as f32;
+ let point = &Point2D { x: x, y: y };
+ let window = window_from_node(self);
+ let viewport = window.window_size().unwrap().visible_viewport;
+
+ // Step 2
+ if x < 0.0 || y < 0.0 || x > viewport.width.get() || y > viewport.height.get() {
+ return vec!();
+ }
+
+ let js_runtime = unsafe { JS_GetRuntime(window.get_cx()) };
+
+ // Step 1 and Step 3
+ let mut elements: Vec<Root<Element>> = self.nodes_from_point(point).iter()
+ .flat_map(|&untrusted_node_address| {
+ let node = node::from_untrusted_node_address(js_runtime, untrusted_node_address);
+ Root::downcast::<Element>(node)
+ }).collect();
+
+ // Step 4
+ if let Some(root_element) = self.GetDocumentElement() {
+ if elements.last() != Some(&root_element) {
+ elements.push(root_element);
+ }
+ }
+
+ // Step 5
+ elements
+ }
}
fn is_scheme_host_port_tuple(url: &Url) -> bool {
@@ -2672,3 +2713,4 @@ pub enum FocusEventType {
Focus, // Element gained focus. Doesn't bubble.
Blur, // Element lost focus. Doesn't bubble.
}
+
diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl
index 845037e430c..7ca1dec527f 100644
--- a/components/script/dom/webidls/Document.webidl
+++ b/components/script/dom/webidls/Document.webidl
@@ -184,6 +184,7 @@ partial interface Document {
// https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
partial interface Document {
Element? elementFromPoint(double x, double y);
+ sequence<Element> elementsFromPoint(double x, double y);
};
// https://drafts.csswg.org/cssom/#extensions-to-the-document-interface
diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs
index 0d063f47bc1..07d8ac47edc 100644
--- a/components/script/layout_interface.rs
+++ b/components/script/layout_interface.rs
@@ -113,6 +113,8 @@ pub trait LayoutRPC {
fn offset_parent(&self) -> OffsetParentResponse;
/// Query layout for the resolve values of the margin properties for an element.
fn margin_style(&self) -> MarginStyleResponse;
+
+ fn nodes_from_point(&self, point: Point2D<f32>) -> Vec<UntrustedNodeAddress>;
}
#[derive(Clone)]
diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini
index 77436641c36..75243947ba9 100644
--- a/tests/wpt/include.ini
+++ b/tests/wpt/include.ini
@@ -55,3 +55,5 @@ skip: true
skip: false
[WebIDL]
skip: false
+[cssom-view]
+ skip: false
diff --git a/tests/wpt/metadata/cssom-view/elementsFromPoint.html.ini b/tests/wpt/metadata/cssom-view/elementsFromPoint.html.ini
new file mode 100644
index 00000000000..ceb62f43b0b
--- /dev/null
+++ b/tests/wpt/metadata/cssom-view/elementsFromPoint.html.ini
@@ -0,0 +1,17 @@
+[elementsFromPoint.html]
+ type: testharness
+ [co-ordinates larger than the viewport from in iframe]
+ expected: FAIL
+
+ [SVG element at x,y]
+ expected: FAIL
+
+ [transformed element at x,y]
+ expected: FAIL
+
+ [no hit target at x,y]
+ expected: FAIL
+
+ [No viewport available]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/cssom-view/scrollingElement.html.ini b/tests/wpt/metadata/cssom-view/scrollingElement.html.ini
new file mode 100644
index 00000000000..8719b06550b
--- /dev/null
+++ b/tests/wpt/metadata/cssom-view/scrollingElement.html.ini
@@ -0,0 +1,5 @@
+[scrollingElement.html]
+ type: testharness
+ [Tests for scrollingElement]
+ expected: FAIL
+