mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Implement Document#elementsFromPoint
This commit is contained in:
parent
88d29e537c
commit
07584b9f29
7 changed files with 88 additions and 0 deletions
|
@ -20,6 +20,7 @@ use script::layout_interface::{ContentBoxResponse, ContentBoxesResponse, NodeGeo
|
||||||
use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse};
|
use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse};
|
||||||
use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, MarginStyleResponse};
|
use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, MarginStyleResponse};
|
||||||
use script_traits::LayoutMsg as ConstellationMsg;
|
use script_traits::LayoutMsg as ConstellationMsg;
|
||||||
|
use script_traits::UntrustedNodeAddress;
|
||||||
use sequential;
|
use sequential;
|
||||||
use std::cmp::{min, max};
|
use std::cmp::{min, max};
|
||||||
use std::ops::Deref;
|
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 {
|
fn node_geometry(&self) -> NodeGeometryResponse {
|
||||||
let &LayoutRPCImpl(ref rw_data) = self;
|
let &LayoutRPCImpl(ref rw_data) = self;
|
||||||
let rw_data = rw_data.lock().unwrap();
|
let rw_data = rw_data.lock().unwrap();
|
||||||
|
|
|
@ -94,6 +94,7 @@ use net_traits::response::HttpsState;
|
||||||
use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
|
use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
|
||||||
use num::ToPrimitive;
|
use num::ToPrimitive;
|
||||||
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan};
|
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan};
|
||||||
|
use script_traits::UntrustedNodeAddress;
|
||||||
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
|
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
|
||||||
use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg};
|
use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg};
|
||||||
use script_traits::{TouchEventType, TouchId};
|
use script_traits::{TouchEventType, TouchId};
|
||||||
|
@ -1480,6 +1481,12 @@ impl Document {
|
||||||
|
|
||||||
self.browsing_context.is_none() || !url_has_network_scheme(&self.url)
|
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)]
|
#[derive(PartialEq, HeapSizeOf)]
|
||||||
|
@ -2601,6 +2608,40 @@ impl DocumentMethods for Document {
|
||||||
None => self.GetDocumentElement()
|
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 {
|
fn is_scheme_host_port_tuple(url: &Url) -> bool {
|
||||||
|
@ -2672,3 +2713,4 @@ pub enum FocusEventType {
|
||||||
Focus, // Element gained focus. Doesn't bubble.
|
Focus, // Element gained focus. Doesn't bubble.
|
||||||
Blur, // Element lost focus. Doesn't bubble.
|
Blur, // Element lost focus. Doesn't bubble.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,7 @@ partial interface Document {
|
||||||
// https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
|
// https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
|
||||||
partial interface Document {
|
partial interface Document {
|
||||||
Element? elementFromPoint(double x, double y);
|
Element? elementFromPoint(double x, double y);
|
||||||
|
sequence<Element> elementsFromPoint(double x, double y);
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom/#extensions-to-the-document-interface
|
// https://drafts.csswg.org/cssom/#extensions-to-the-document-interface
|
||||||
|
|
|
@ -113,6 +113,8 @@ pub trait LayoutRPC {
|
||||||
fn offset_parent(&self) -> OffsetParentResponse;
|
fn offset_parent(&self) -> OffsetParentResponse;
|
||||||
/// Query layout for the resolve values of the margin properties for an element.
|
/// Query layout for the resolve values of the margin properties for an element.
|
||||||
fn margin_style(&self) -> MarginStyleResponse;
|
fn margin_style(&self) -> MarginStyleResponse;
|
||||||
|
|
||||||
|
fn nodes_from_point(&self, point: Point2D<f32>) -> Vec<UntrustedNodeAddress>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -55,3 +55,5 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[WebIDL]
|
[WebIDL]
|
||||||
skip: false
|
skip: false
|
||||||
|
[cssom-view]
|
||||||
|
skip: false
|
||||||
|
|
17
tests/wpt/metadata/cssom-view/elementsFromPoint.html.ini
Normal file
17
tests/wpt/metadata/cssom-view/elementsFromPoint.html.ini
Normal file
|
@ -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
|
||||||
|
|
5
tests/wpt/metadata/cssom-view/scrollingElement.html.ini
Normal file
5
tests/wpt/metadata/cssom-view/scrollingElement.html.ini
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[scrollingElement.html]
|
||||||
|
type: testharness
|
||||||
|
[Tests for scrollingElement]
|
||||||
|
expected: FAIL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue