diff --git a/components/layout/query.rs b/components/layout/query.rs index 348a3ad556d..54acfe92e90 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -107,11 +107,8 @@ impl LayoutRPC for LayoutRPCImpl { if mouse_over_list.is_empty() { Err(()) } else { - let response_list = - mouse_over_list.iter() - .map(|metadata| metadata.node.to_untrusted_node_address()) - .collect(); - Ok(MouseOverResponse(response_list)) + let response = mouse_over_list[0].node.to_untrusted_node_address(); + Ok(MouseOverResponse(response)) } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 501ad242305..4062fb7415f 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -574,11 +574,11 @@ impl Document { } } - pub fn get_nodes_under_mouse(&self, page_point: &Point2D) -> Vec { + pub fn get_node_under_mouse(&self, page_point: &Point2D) -> Option { assert!(self.GetDocumentElement().is_some()); match self.window.layout().mouse_over(*page_point) { - Ok(MouseOverResponse(node_address)) => node_address, - Err(()) => vec![], + Ok(MouseOverResponse(node_address)) => Some(node_address), + Err(()) => None, } } @@ -808,18 +808,21 @@ impl Document { client_point: Option>, prev_mouse_over_targets: &mut RootedVec>) { // Build a list of elements that are currently under the mouse. - let mouse_over_addresses = client_point.as_ref().map(|client_point| { + let mouse_over_address = client_point.as_ref().map(|client_point| { let page_point = Point2D::new(client_point.x + self.window.PageXOffset() as f32, client_point.y + self.window.PageYOffset() as f32); - self.get_nodes_under_mouse(&page_point) - }).unwrap_or(vec![]); - let mut mouse_over_targets = mouse_over_addresses.iter().map(|node_address| { - node::from_untrusted_node_address(js_runtime, *node_address) - .inclusive_ancestors() - .filter_map(Root::downcast::) - .next() - .unwrap() - }).collect::>>(); + self.get_node_under_mouse(&page_point) + }).unwrap_or(None); + + let mut mouse_over_targets = RootedVec::>::new(); + + if let Some(address) = mouse_over_address { + let node = node::from_untrusted_node_address(js_runtime, address); + for node in node.inclusive_ancestors() + .filter_map(Root::downcast::) { + mouse_over_targets.push(JS::from_rooted(&node)); + } + } // Remove hover from any elements in the previous list that are no longer // under the mouse. @@ -856,9 +859,9 @@ impl Document { } // Send mousemove event to topmost target - if mouse_over_addresses.len() > 0 { + if let Some(address) = mouse_over_address { let top_most_node = node::from_untrusted_node_address(js_runtime, - mouse_over_addresses[0]); + address); let client_point = client_point.unwrap(); // Must succeed because hit test succeeded. // If the target is an iframe, forward the event to the child document. diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index 17f553d43e8..4ad7c241f14 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -106,6 +106,7 @@ pub trait LayoutRPC { fn node_geometry(&self) -> NodeGeometryResponse; /// Requests the node containing the point of interest fn hit_test(&self, point: Point2D) -> Result; + /// Query layout for the topmost node under the mouse. fn mouse_over(&self, point: Point2D) -> Result; /// Query layout for the resolved value of a given CSS property fn resolved_style(&self) -> ResolvedStyleResponse; @@ -139,7 +140,7 @@ pub struct NodeGeometryResponse { pub client_rect: Rect, } pub struct HitTestResponse(pub UntrustedNodeAddress); -pub struct MouseOverResponse(pub Vec); +pub struct MouseOverResponse(pub UntrustedNodeAddress); pub struct ResolvedStyleResponse(pub Option); #[derive(Clone)]