mirror of
https://github.com/servo/servo.git
synced 2025-06-25 09:34:32 +01:00
auto merge of #2210 : saneyuki/servo/query, r=jdm
- see #356 - To decrease the conversion code, `JS<Node>` -> `Node`, I added API methods to `NodeHelpers`. - I added APIs to `Page` not `Document` because I had thought that their APIs returns the hitted nodes address in the "page".
This commit is contained in:
commit
6d89e67194
4 changed files with 87 additions and 55 deletions
|
@ -20,8 +20,7 @@ use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::htmlserializer::serialize;
|
use dom::htmlserializer::serialize;
|
||||||
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
||||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||||
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
|
use layout_interface::ContentChangedDocumentDamage;
|
||||||
use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
|
|
||||||
use layout_interface::MatchSelectorsDocumentDamage;
|
use layout_interface::MatchSelectorsDocumentDamage;
|
||||||
use style;
|
use style;
|
||||||
use servo_util::namespace;
|
use servo_util::namespace;
|
||||||
|
@ -605,9 +604,7 @@ impl Element {
|
||||||
let doc = self.node.owner_doc();
|
let doc = self.node.owner_doc();
|
||||||
let win = &doc.get().window;
|
let win = &doc.get().window;
|
||||||
let node: JS<Node> = NodeCast::from(abstract_self);
|
let node: JS<Node> = NodeCast::from(abstract_self);
|
||||||
let (chan, port) = channel();
|
let rects = node.get_content_boxes();
|
||||||
let addr = node.to_trusted_node_address();
|
|
||||||
let ContentBoxesResponse(rects) = win.get().page().query_layout(ContentBoxesQuery(addr, chan), port);
|
|
||||||
let rects = rects.map(|r| {
|
let rects = rects.map(|r| {
|
||||||
ClientRect::new(
|
ClientRect::new(
|
||||||
win,
|
win,
|
||||||
|
@ -625,9 +622,7 @@ impl Element {
|
||||||
let doc = self.node.owner_doc();
|
let doc = self.node.owner_doc();
|
||||||
let win = &doc.get().window;
|
let win = &doc.get().window;
|
||||||
let node: JS<Node> = NodeCast::from(abstract_self);
|
let node: JS<Node> = NodeCast::from(abstract_self);
|
||||||
let (chan, port) = channel();
|
let rect = node.get_bounding_content_box();
|
||||||
let addr = node.to_trusted_node_address();
|
|
||||||
let ContentBoxResponse(rect) = win.get().page().query_layout(ContentBoxQuery(addr, chan), port);
|
|
||||||
ClientRect::new(
|
ClientRect::new(
|
||||||
win,
|
win,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
|
|
|
@ -16,7 +16,6 @@ use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
|
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use servo_util::geometry::to_px;
|
use servo_util::geometry::to_px;
|
||||||
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
|
|
||||||
use servo_net::image_cache_task;
|
use servo_net::image_cache_task;
|
||||||
use servo_util::url::parse_url;
|
use servo_util::url::parse_url;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
@ -131,11 +130,7 @@ impl HTMLImageElement {
|
||||||
|
|
||||||
pub fn Width(&self, abstract_self: &JS<HTMLImageElement>) -> u32 {
|
pub fn Width(&self, abstract_self: &JS<HTMLImageElement>) -> u32 {
|
||||||
let node: JS<Node> = NodeCast::from(abstract_self);
|
let node: JS<Node> = NodeCast::from(abstract_self);
|
||||||
let window = window_from_node(&node);
|
let rect = node.get_bounding_content_box();
|
||||||
let page = window.get().page();
|
|
||||||
let (chan, port) = channel();
|
|
||||||
let addr = node.to_trusted_node_address();
|
|
||||||
let ContentBoxResponse(rect) = page.query_layout(ContentBoxQuery(addr, chan), port);
|
|
||||||
to_px(rect.size.width) as u32
|
to_px(rect.size.width) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,13 +140,8 @@ impl HTMLImageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Height(&self, abstract_self: &JS<HTMLImageElement>) -> u32 {
|
pub fn Height(&self, abstract_self: &JS<HTMLImageElement>) -> u32 {
|
||||||
let node = &self.htmlelement.element.node;
|
let node: JS<Node> = NodeCast::from(abstract_self);
|
||||||
let doc = node.owner_doc();
|
let rect = node.get_bounding_content_box();
|
||||||
let page = doc.get().window.get().page();
|
|
||||||
let (chan, port) = channel();
|
|
||||||
let this_node: JS<Node> = NodeCast::from(abstract_self);
|
|
||||||
let addr = this_node.to_trusted_node_address();
|
|
||||||
let ContentBoxResponse(rect) = page.query_layout(ContentBoxQuery(addr, chan), port);
|
|
||||||
to_px(rect.size.height) as u32
|
to_px(rect.size.height) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,11 @@ use dom::processinginstruction::ProcessingInstruction;
|
||||||
use dom::text::Text;
|
use dom::text::Text;
|
||||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
|
use geom::rect::Rect;
|
||||||
use html::hubbub_html_parser::build_element_from_tag;
|
use html::hubbub_html_parser::build_element_from_tag;
|
||||||
use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress};
|
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery, ContentBoxesResponse,
|
||||||
use layout_interface::TrustedNodeAddress;
|
LayoutChan, ReapLayoutDataMsg, TrustedNodeAddress, UntrustedNodeAddress};
|
||||||
|
use servo_util::geometry::Au;
|
||||||
use servo_util::str::{DOMString, null_str_as_empty};
|
use servo_util::str::{DOMString, null_str_as_empty};
|
||||||
|
|
||||||
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
||||||
|
@ -283,6 +285,9 @@ pub trait NodeHelpers {
|
||||||
|
|
||||||
fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self;
|
fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self;
|
||||||
fn to_trusted_node_address(&self) -> TrustedNodeAddress;
|
fn to_trusted_node_address(&self) -> TrustedNodeAddress;
|
||||||
|
|
||||||
|
fn get_bounding_content_box(&self) -> Rect<Au>;
|
||||||
|
fn get_content_boxes(&self) -> ~[Rect<Au>];
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeHelpers for JS<Node> {
|
impl NodeHelpers for JS<Node> {
|
||||||
|
@ -565,6 +570,24 @@ impl NodeHelpers for JS<Node> {
|
||||||
fn to_trusted_node_address(&self) -> TrustedNodeAddress {
|
fn to_trusted_node_address(&self) -> TrustedNodeAddress {
|
||||||
TrustedNodeAddress(self.get() as *Node as *libc::c_void)
|
TrustedNodeAddress(self.get() as *Node as *libc::c_void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_bounding_content_box(&self) -> Rect<Au> {
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let page = window.get().page();
|
||||||
|
let (chan, port) = channel();
|
||||||
|
let addr = self.to_trusted_node_address();
|
||||||
|
let ContentBoxResponse(rect) = page.query_layout(ContentBoxQuery(addr, chan), port);
|
||||||
|
rect
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_content_boxes(&self) -> ~[Rect<Au>] {
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let page = window.get().page();
|
||||||
|
let (chan, port) = channel();
|
||||||
|
let addr = self.to_trusted_node_address();
|
||||||
|
let ContentBoxesResponse(rects) = page.query_layout(ContentBoxesQuery(addr, chan), port);
|
||||||
|
rects
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -22,11 +22,11 @@ use html::hubbub_html_parser::HtmlParserResult;
|
||||||
use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript};
|
use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript};
|
||||||
use html::hubbub_html_parser;
|
use html::hubbub_html_parser;
|
||||||
use layout_interface::{AddStylesheetMsg, DocumentDamage};
|
use layout_interface::{AddStylesheetMsg, DocumentDamage};
|
||||||
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
|
|
||||||
use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery, MouseOverQuery, MouseOverResponse};
|
use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery, MouseOverQuery, MouseOverResponse};
|
||||||
use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg};
|
use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg};
|
||||||
use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg};
|
use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg};
|
||||||
use layout_interface::ContentChangedDocumentDamage;
|
use layout_interface::ContentChangedDocumentDamage;
|
||||||
|
use layout_interface::UntrustedNodeAddress;
|
||||||
use layout_interface;
|
use layout_interface;
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
@ -436,6 +436,47 @@ impl Page {
|
||||||
js_context: Untraceable::new(js_context),
|
js_context: Untraceable::new(js_context),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hit_test(&self, point: &Point2D<f32>) -> Option<UntrustedNodeAddress> {
|
||||||
|
let frame = self.frame();
|
||||||
|
let document = frame.get_ref().document.clone();
|
||||||
|
let root = document.get().GetDocumentElement();
|
||||||
|
if root.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let root: JS<Node> = NodeCast::from(&root.unwrap());
|
||||||
|
let (chan, port) = channel();
|
||||||
|
let address = match self.query_layout(HitTestQuery(root.to_trusted_node_address(), *point, chan), port) {
|
||||||
|
Ok(HitTestResponse(node_address)) => {
|
||||||
|
Some(node_address)
|
||||||
|
}
|
||||||
|
Err(()) => {
|
||||||
|
debug!("layout query error");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
address
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_nodes_under_mouse(&self, point: &Point2D<f32>) -> Option<~[UntrustedNodeAddress]> {
|
||||||
|
let frame = self.frame();
|
||||||
|
let document = frame.get_ref().document.clone();
|
||||||
|
let root = document.get().GetDocumentElement();
|
||||||
|
if root.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let root: JS<Node> = NodeCast::from(&root.unwrap());
|
||||||
|
let (chan, port) = channel();
|
||||||
|
let address = match self.query_layout(MouseOverQuery(root.to_trusted_node_address(), *point, chan), port) {
|
||||||
|
Ok(MouseOverResponse(node_address)) => {
|
||||||
|
Some(node_address)
|
||||||
|
}
|
||||||
|
Err(()) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
address
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information for one frame in the browsing context.
|
/// Information for one frame in the browsing context.
|
||||||
|
@ -955,11 +996,9 @@ impl ScriptTask {
|
||||||
chan.send(LoadCompleteMsg(page.id, url));
|
chan.send(LoadCompleteMsg(page.id, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &Page, node: JS<Element>) {
|
fn scroll_fragment_point(&self, pipeline_id: PipelineId, node: JS<Element>) {
|
||||||
let (chan, port) = channel();
|
|
||||||
let node: JS<Node> = NodeCast::from(&node);
|
let node: JS<Node> = NodeCast::from(&node);
|
||||||
let ContentBoxResponse(rect) =
|
let rect = node.get_bounding_content_box();
|
||||||
page.query_layout(ContentBoxQuery(node.to_trusted_node_address(), chan), port);
|
|
||||||
let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(),
|
let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(),
|
||||||
to_frac_px(rect.origin.y).to_f32().unwrap());
|
to_frac_px(rect.origin.y).to_f32().unwrap());
|
||||||
// FIXME(#2003, pcwalton): This is pretty bogus when multiple layers are involved.
|
// FIXME(#2003, pcwalton): This is pretty bogus when multiple layers are involved.
|
||||||
|
@ -997,7 +1036,7 @@ impl ScriptTask {
|
||||||
|
|
||||||
let mut fragment_node = page.fragment_node.deref().borrow_mut();
|
let mut fragment_node = page.fragment_node.deref().borrow_mut();
|
||||||
match fragment_node.take() {
|
match fragment_node.take() {
|
||||||
Some(node) => self.scroll_fragment_point(pipeline_id, page, node),
|
Some(node) => self.scroll_fragment_point(pipeline_id, node),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,17 +1070,8 @@ impl ScriptTask {
|
||||||
|
|
||||||
ClickEvent(_button, point) => {
|
ClickEvent(_button, point) => {
|
||||||
debug!("ClickEvent: clicked at {:?}", point);
|
debug!("ClickEvent: clicked at {:?}", point);
|
||||||
|
match page.hit_test(&point) {
|
||||||
let frame = page.frame();
|
Some(node_address) => {
|
||||||
let document = frame.get_ref().document.clone();
|
|
||||||
let root = document.get().GetDocumentElement();
|
|
||||||
if root.is_none() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (chan, port) = channel();
|
|
||||||
let root: JS<Node> = NodeCast::from(&root.unwrap());
|
|
||||||
match page.query_layout(HitTestQuery(root.to_trusted_node_address(), point, chan), port) {
|
|
||||||
Ok(HitTestResponse(node_address)) => {
|
|
||||||
debug!("node address is {:?}", node_address);
|
debug!("node address is {:?}", node_address);
|
||||||
let mut node: JS<Node> =
|
let mut node: JS<Node> =
|
||||||
NodeHelpers::from_untrusted_node_address(self.js_runtime.deref().ptr,
|
NodeHelpers::from_untrusted_node_address(self.js_runtime.deref().ptr,
|
||||||
|
@ -1063,23 +1093,16 @@ impl ScriptTask {
|
||||||
self.load_url_from_element(page, &element)
|
self.load_url_from_element(page, &element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(()) => debug!("layout query error"),
|
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseDownEvent(..) => {}
|
MouseDownEvent(..) => {}
|
||||||
MouseUpEvent(..) => {}
|
MouseUpEvent(..) => {}
|
||||||
MouseMoveEvent(point) => {
|
MouseMoveEvent(point) => {
|
||||||
let frame = page.frame();
|
match page.get_nodes_under_mouse(&point) {
|
||||||
let document = frame.get_ref().document.clone();
|
Some(node_address) => {
|
||||||
let root = document.get().GetDocumentElement();
|
|
||||||
if root.is_none() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let root: JS<Node> = NodeCast::from(&root.unwrap());
|
|
||||||
let (chan, port) = channel();
|
|
||||||
match page.query_layout(MouseOverQuery(root.to_trusted_node_address(), point, chan), port) {
|
|
||||||
Ok(MouseOverResponse(node_address)) => {
|
|
||||||
|
|
||||||
let mut target_list: ~[JS<Node>] = ~[];
|
let mut target_list: ~[JS<Node>] = ~[];
|
||||||
let mut target_compare = false;
|
let mut target_compare = false;
|
||||||
|
@ -1137,8 +1160,9 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
*mouse_over_targets = Some(target_list);
|
*mouse_over_targets = Some(target_list);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(()) => {},
|
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1180,7 @@ impl ScriptTask {
|
||||||
|
|
||||||
if click_frag {
|
if click_frag {
|
||||||
match page.find_fragment_node(url.fragment.unwrap()) {
|
match page.find_fragment_node(url.fragment.unwrap()) {
|
||||||
Some(node) => self.scroll_fragment_point(page.id, page, node),
|
Some(node) => self.scroll_fragment_point(page.id, node),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue