From dce92dc44a2f548dcf2558a47cfc47d8e7f774c3 Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Wed, 23 Apr 2014 02:33:37 +0900 Subject: [PATCH 1/4] Add NodeHelpers::get_bounding_content_box(). --- src/components/script/dom/element.rs | 6 ++---- src/components/script/dom/htmlimageelement.rs | 16 +++------------- src/components/script/dom/node.rs | 16 ++++++++++++++-- src/components/script/script_task.rs | 11 ++++------- 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index c2cad3b46fa..bd0f6bb9b81 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -20,7 +20,7 @@ use dom::htmlcollection::HTMLCollection; use dom::htmlserializer::serialize; use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node}; use dom::virtualmethods::{VirtualMethods, vtable_for}; -use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery}; +use layout_interface::{ContentBoxesQuery}; use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage}; use layout_interface::MatchSelectorsDocumentDamage; use style; @@ -625,9 +625,7 @@ impl Element { let doc = self.node.owner_doc(); let win = &doc.get().window; let node: JS = NodeCast::from(abstract_self); - let (chan, port) = channel(); - let addr = node.to_trusted_node_address(); - let ContentBoxResponse(rect) = win.get().page().query_layout(ContentBoxQuery(addr, chan), port); + let rect = node.get_bounding_content_box(); ClientRect::new( win, rect.origin.y, diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index a62aea8b991..dedf78948fc 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -16,7 +16,6 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node}; use dom::virtualmethods::VirtualMethods; use servo_util::geometry::to_px; -use layout_interface::{ContentBoxQuery, ContentBoxResponse}; use servo_net::image_cache_task; use servo_util::url::parse_url; use servo_util::str::DOMString; @@ -131,11 +130,7 @@ impl HTMLImageElement { pub fn Width(&self, abstract_self: &JS) -> u32 { let node: JS = NodeCast::from(abstract_self); - let window = window_from_node(&node); - 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); + let rect = node.get_bounding_content_box(); to_px(rect.size.width) as u32 } @@ -145,13 +140,8 @@ impl HTMLImageElement { } pub fn Height(&self, abstract_self: &JS) -> u32 { - let node = &self.htmlelement.element.node; - let doc = node.owner_doc(); - let page = doc.get().window.get().page(); - let (chan, port) = channel(); - let this_node: JS = NodeCast::from(abstract_self); - let addr = this_node.to_trusted_node_address(); - let ContentBoxResponse(rect) = page.query_layout(ContentBoxQuery(addr, chan), port); + let node: JS = NodeCast::from(abstract_self); + let rect = node.get_bounding_content_box(); to_px(rect.size.height) as u32 } diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index a136e564a45..53c3776fab5 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -26,9 +26,10 @@ use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::window::Window; +use geom::rect::Rect; use html::hubbub_html_parser::build_element_from_tag; -use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress}; -use layout_interface::TrustedNodeAddress; +use layout_interface::{ContentBoxQuery, ContentBoxResponse, LayoutChan, ReapLayoutDataMsg, TrustedNodeAddress, UntrustedNodeAddress}; +use servo_util::geometry::Au; use servo_util::str::{DOMString, null_str_as_empty}; use js::jsapi::{JSContext, JSObject, JSRuntime}; @@ -283,6 +284,8 @@ pub trait NodeHelpers { fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self; fn to_trusted_node_address(&self) -> TrustedNodeAddress; + + fn get_bounding_content_box(&self) -> Rect; } impl NodeHelpers for JS { @@ -565,6 +568,15 @@ impl NodeHelpers for JS { fn to_trusted_node_address(&self) -> TrustedNodeAddress { TrustedNodeAddress(self.get() as *Node as *libc::c_void) } + + fn get_bounding_content_box(&self) -> Rect { + 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 + } } // diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index a78108c057a..f608a648518 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -22,7 +22,6 @@ use html::hubbub_html_parser::HtmlParserResult; use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript}; use html::hubbub_html_parser; use layout_interface::{AddStylesheetMsg, DocumentDamage}; -use layout_interface::{ContentBoxQuery, ContentBoxResponse}; use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery, MouseOverQuery, MouseOverResponse}; use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg}; use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg}; @@ -958,11 +957,9 @@ impl ScriptTask { chan.send(LoadCompleteMsg(page.id, url)); } - fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &Page, node: JS) { - let (chan, port) = channel(); + fn scroll_fragment_point(&self, pipeline_id: PipelineId, node: JS) { let node: JS = NodeCast::from(&node); - let ContentBoxResponse(rect) = - page.query_layout(ContentBoxQuery(node.to_trusted_node_address(), chan), port); + let rect = node.get_bounding_content_box(); let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(), to_frac_px(rect.origin.y).to_f32().unwrap()); // FIXME(#2003, pcwalton): This is pretty bogus when multiple layers are involved. @@ -1000,7 +997,7 @@ impl ScriptTask { let mut fragment_node = page.fragment_node.deref().borrow_mut(); match fragment_node.take() { - Some(node) => self.scroll_fragment_point(pipeline_id, page, node), + Some(node) => self.scroll_fragment_point(pipeline_id, node), None => {} } @@ -1159,7 +1156,7 @@ impl ScriptTask { if click_frag { 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 => {} } } else { From 7d511f4bafdfbf765e1895ceaf265bb005ab98fe Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Wed, 23 Apr 2014 02:57:16 +0900 Subject: [PATCH 2/4] Add NodeHelpers::get_content_boxes(). --- src/components/script/dom/element.rs | 7 ++----- src/components/script/dom/node.rs | 13 ++++++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index bd0f6bb9b81..156f49f67a3 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -20,8 +20,7 @@ use dom::htmlcollection::HTMLCollection; use dom::htmlserializer::serialize; use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node}; use dom::virtualmethods::{VirtualMethods, vtable_for}; -use layout_interface::{ContentBoxesQuery}; -use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage}; +use layout_interface::ContentChangedDocumentDamage; use layout_interface::MatchSelectorsDocumentDamage; use style; use servo_util::namespace; @@ -605,9 +604,7 @@ impl Element { let doc = self.node.owner_doc(); let win = &doc.get().window; let node: JS = NodeCast::from(abstract_self); - let (chan, port) = channel(); - let addr = node.to_trusted_node_address(); - let ContentBoxesResponse(rects) = win.get().page().query_layout(ContentBoxesQuery(addr, chan), port); + let rects = node.get_content_boxes(); let rects = rects.map(|r| { ClientRect::new( win, diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 53c3776fab5..35a2028478e 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -28,7 +28,8 @@ use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::window::Window; use geom::rect::Rect; use html::hubbub_html_parser::build_element_from_tag; -use layout_interface::{ContentBoxQuery, ContentBoxResponse, LayoutChan, ReapLayoutDataMsg, TrustedNodeAddress, UntrustedNodeAddress}; +use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery, ContentBoxesResponse, + LayoutChan, ReapLayoutDataMsg, TrustedNodeAddress, UntrustedNodeAddress}; use servo_util::geometry::Au; use servo_util::str::{DOMString, null_str_as_empty}; @@ -286,6 +287,7 @@ pub trait NodeHelpers { fn to_trusted_node_address(&self) -> TrustedNodeAddress; fn get_bounding_content_box(&self) -> Rect; + fn get_content_boxes(&self) -> ~[Rect]; } impl NodeHelpers for JS { @@ -577,6 +579,15 @@ impl NodeHelpers for JS { let ContentBoxResponse(rect) = page.query_layout(ContentBoxQuery(addr, chan), port); rect } + + fn get_content_boxes(&self) -> ~[Rect] { + 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 + } } // From fff94a35b3b603e50d70555712e57644a0b61d14 Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Wed, 23 Apr 2014 03:18:05 +0900 Subject: [PATCH 3/4] Add Page::hit_test(). --- src/components/script/script_task.rs | 39 ++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index f608a648518..7e8c8eca384 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -26,6 +26,7 @@ use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, Layou use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg}; use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg}; use layout_interface::ContentChangedDocumentDamage; +use layout_interface::UntrustedNodeAddress; use layout_interface; use geom::point::Point2D; @@ -435,6 +436,27 @@ impl Page { js_context: Untraceable::new(js_context), }); } + + pub fn hit_test(&self, point: &Point2D) -> Option { + 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 = 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 + } } /// Information for one frame in the browsing context. @@ -1031,17 +1053,8 @@ impl ScriptTask { ClickEvent(_button, point) => { debug!("ClickEvent: clicked at {:?}", point); - - let frame = page.frame(); - let document = frame.get_ref().document.clone(); - let root = document.get().GetDocumentElement(); - if root.is_none() { - return; - } - let (chan, port) = channel(); - let root: JS = NodeCast::from(&root.unwrap()); - match page.query_layout(HitTestQuery(root.to_trusted_node_address(), point, chan), port) { - Ok(HitTestResponse(node_address)) => { + match page.hit_test(&point) { + Some(node_address) => { debug!("node address is {:?}", node_address); let mut node: JS = NodeHelpers::from_untrusted_node_address(self.js_runtime.deref().ptr, @@ -1063,8 +1076,8 @@ impl ScriptTask { self.load_url_from_element(page, &element) } } - }, - Err(()) => debug!("layout query error"), + } + None => {} } } MouseDownEvent(..) => {} From 6c987c31b5caac83d006c1e606439a50cfaf127a Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Wed, 23 Apr 2014 14:12:55 +0900 Subject: [PATCH 4/4] Add Page::get_nodes_under_mouse(). --- src/components/script/script_task.rs | 38 +++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 7e8c8eca384..1b0da3556e7 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -457,6 +457,26 @@ impl Page { }; address } + + pub fn get_nodes_under_mouse(&self, point: &Point2D) -> 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 = 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. @@ -1077,22 +1097,15 @@ impl ScriptTask { } } } + None => {} } } MouseDownEvent(..) => {} MouseUpEvent(..) => {} MouseMoveEvent(point) => { - let frame = page.frame(); - let document = frame.get_ref().document.clone(); - let root = document.get().GetDocumentElement(); - if root.is_none() { - return; - } - let root: JS = 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)) => { + match page.get_nodes_under_mouse(&point) { + Some(node_address) => { let mut target_list: ~[JS] = ~[]; let mut target_compare = false; @@ -1150,8 +1163,9 @@ impl ScriptTask { } *mouse_over_targets = Some(target_list); } - }, - Err(()) => {}, + } + + None => {} } } }