aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/layout_thread.rs21
-rw-r--r--components/layout/query.rs46
2 files changed, 39 insertions, 28 deletions
diff --git a/components/layout/layout_thread.rs b/components/layout/layout_thread.rs
index a361e42fb15..1a8bdfb4a19 100644
--- a/components/layout/layout_thread.rs
+++ b/components/layout/layout_thread.rs
@@ -22,7 +22,7 @@ use euclid::size::Size2D;
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::{self, FlowRef};
use fnv::FnvHasher;
-use gfx::display_list::{ClippingRegion, DisplayList, LayerInfo};
+use gfx::display_list::{ClippingRegion, DisplayItemMetadata, DisplayList, LayerInfo};
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId, StackingContextType};
use gfx::font;
use gfx::font_cache_thread::FontCacheThread;
@@ -114,6 +114,9 @@ pub struct LayoutThreadData {
/// A queued response for the client {top, left, width, height} of a node in pixels.
pub client_rect_response: Rect<i32>,
+ /// A queued response for the node at a given point
+ pub hit_test_response: (Option<DisplayItemMetadata>, bool),
+
/// A queued response for the resolved style property of an element.
pub resolved_style_response: Option<String>,
@@ -458,6 +461,7 @@ impl LayoutThread {
content_box_response: Rect::zero(),
content_boxes_response: Vec::new(),
client_rect_response: Rect::zero(),
+ hit_test_response: (None, false),
resolved_style_response: None,
offset_parent_response: OffsetParentResponse::empty(),
margin_style_response: MarginStyleResponse::empty(),
@@ -977,6 +981,9 @@ impl LayoutThread {
ReflowQueryType::ContentBoxesQuery(_) => {
rw_data.content_boxes_response = Vec::new();
},
+ ReflowQueryType::HitTestQuery(_, _) => {
+ rw_data.hit_test_response = (None, false);
+ },
ReflowQueryType::NodeGeometryQuery(_) => {
rw_data.client_rect_response = Rect::zero();
},
@@ -1119,6 +1126,18 @@ impl LayoutThread {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.content_boxes_response = process_content_boxes_request(node, &mut root_flow);
},
+ ReflowQueryType::HitTestQuery(point, update_cursor) => {
+ let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
+ let result = match rw_data.display_list {
+ None => panic!("Tried to hit test with no display list"),
+ Some(ref dl) => dl.hit_test(point),
+ };
+ rw_data.hit_test_response = if result.len() > 0 {
+ (Some(result[0]), update_cursor)
+ } else {
+ (None, update_cursor)
+ };
+ },
ReflowQueryType::NodeGeometryQuery(node) => {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.client_rect_response = process_node_geometry_request(node, &mut root_flow);
diff --git a/components/layout/query.rs b/components/layout/query.rs
index df45301106a..039de56f5c4 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -51,6 +51,25 @@ impl LayoutRPC for LayoutRPCImpl {
ContentBoxesResponse(rw_data.content_boxes_response.clone())
}
+ /// Requests the node containing the point of interest.
+ fn hit_test(&self) -> HitTestResponse {
+ let &LayoutRPCImpl(ref rw_data) = self;
+ let rw_data = rw_data.lock().unwrap();
+ let &(ref result, update_cursor) = &rw_data.hit_test_response;
+ if update_cursor {
+ // Compute the new cursor.
+ let cursor = match *result {
+ None => Cursor::DefaultCursor,
+ Some(dim) => dim.pointing.unwrap(),
+ };
+ let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan;
+ constellation_chan.send(ConstellationMsg::SetCursor(cursor)).unwrap();
+ }
+ HitTestResponse {
+ node_address: result.map(|dim| dim.node.to_untrusted_node_address()),
+ }
+ }
+
fn node_geometry(&self) -> NodeGeometryResponse {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
@@ -66,33 +85,6 @@ impl LayoutRPC for LayoutRPCImpl {
ResolvedStyleResponse(rw_data.resolved_style_response.clone())
}
- /// Requests the node containing the point of interest.
- fn hit_test(&self, point: Point2D<f32>, update_cursor: bool) -> Result<HitTestResponse, ()> {
- let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
- let &LayoutRPCImpl(ref rw_data) = self;
- let rw_data = rw_data.lock().unwrap();
- let display_list = rw_data.display_list.as_ref().expect("Tried to hit test without a DisplayList!");
-
- let result = display_list.hit_test(point);
-
- if update_cursor {
- let cursor = if !result.is_empty() {
- result[0].pointing.unwrap()
- } else {
- Cursor::DefaultCursor
- };
-
- let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan;
- constellation_chan.send(ConstellationMsg::SetCursor(cursor)).unwrap();
- };
-
- if !result.is_empty() {
- Ok(HitTestResponse(result[0].node.to_untrusted_node_address()))
- } else {
- Err(())
- }
- }
-
fn offset_parent(&self) -> OffsetParentResponse {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();