aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/compositor.rs40
-rw-r--r--components/compositing/compositor_layer.rs2
-rw-r--r--components/script/dom/document.rs65
3 files changed, 61 insertions, 46 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index e91bc951086..0ce000d1b9d 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -242,7 +242,9 @@ enum ShutdownState {
}
struct HitTestResult {
+ /// The topmost layer containing the requested point
layer: Rc<Layer<CompositorData>>,
+ /// The point in client coordinates of the innermost window or frame containing `layer`
point: TypedPoint2D<LayerPixel, f32>,
}
@@ -1934,45 +1936,53 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn find_topmost_layer_at_point_for_layer(&self,
layer: Rc<Layer<CompositorData>>,
- point: TypedPoint2D<LayerPixel, f32>,
- clip_rect: &TypedRect<LayerPixel, f32>)
+ point_in_parent_layer: TypedPoint2D<LayerPixel, f32>,
+ clip_rect_in_parent_layer: &TypedRect<LayerPixel, f32>)
-> Option<HitTestResult> {
let layer_bounds = *layer.bounds.borrow();
let masks_to_bounds = *layer.masks_to_bounds.borrow();
if layer_bounds.is_empty() && masks_to_bounds {
return None;
}
+ let scroll_offset = layer.extra_data.borrow().scroll_offset;
- let clipped_layer_bounds = match clip_rect.intersection(&layer_bounds) {
+ // Total offset from parent coordinates to this layer's coordinates.
+ // FIXME: This offset is incorrect for fixed-position layers.
+ let layer_offset = scroll_offset + layer_bounds.origin;
+
+ let clipped_layer_bounds = match clip_rect_in_parent_layer.intersection(&layer_bounds) {
Some(rect) => rect,
None => return None,
};
let clip_rect_for_children = if masks_to_bounds {
- Rect::new(Point2D::zero(), clipped_layer_bounds.size)
+ &clipped_layer_bounds
} else {
- clipped_layer_bounds.translate(&clip_rect.origin)
- };
+ clip_rect_in_parent_layer
+ }.translate(&-layer_offset);
- let child_point = point - layer_bounds.origin;
+ let child_point = point_in_parent_layer - layer_offset;
for child in layer.children().iter().rev() {
// Translate the clip rect into the child's coordinate system.
- let clip_rect_for_child =
- clip_rect_for_children.translate(&-*child.content_offset.borrow());
let result = self.find_topmost_layer_at_point_for_layer(child.clone(),
child_point,
- &clip_rect_for_child);
- if result.is_some() {
- return result;
+ &clip_rect_for_children);
+ if let Some(mut result) = result {
+ // Return the point in layer coordinates of the topmost frame containing the point.
+ let pipeline_id = layer.extra_data.borrow().pipeline_id;
+ let child_pipeline_id = result.layer.extra_data.borrow().pipeline_id;
+ if pipeline_id == child_pipeline_id {
+ result.point = result.point + layer_offset;
+ }
+ return Some(result);
}
}
- let point = point - *layer.content_offset.borrow();
- if !clipped_layer_bounds.contains(&point) {
+ if !clipped_layer_bounds.contains(&point_in_parent_layer) {
return None;
}
- return Some(HitTestResult { layer: layer, point: point });
+ return Some(HitTestResult { layer: layer, point: point_in_parent_layer });
}
fn find_topmost_layer_at_point(&self,
diff --git a/components/compositing/compositor_layer.rs b/components/compositing/compositor_layer.rs
index b47cff1ccca..ceb034c83bd 100644
--- a/components/compositing/compositor_layer.rs
+++ b/components/compositing/compositor_layer.rs
@@ -121,7 +121,7 @@ pub trait CompositorLayer {
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
// sends the event off to the appropriate pipeline. NB: the cursor position is in
- // page coordinates.
+ // client coordinates.
fn send_mouse_event<Window>(&self,
compositor: &IOCompositor<Window>,
event: MouseWindowEvent,
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index b8ca6723e2c..19adfbd490d 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -492,9 +492,9 @@ impl Document {
})
}
- pub fn hit_test(&self, point: &Point2D<f32>) -> Option<UntrustedNodeAddress> {
+ pub fn hit_test(&self, page_point: &Point2D<f32>) -> Option<UntrustedNodeAddress> {
assert!(self.GetDocumentElement().is_some());
- match self.window.layout().hit_test(*point) {
+ match self.window.layout().hit_test(*page_point) {
Ok(HitTestResponse(node_address)) => Some(node_address),
Err(()) => {
debug!("layout query error");
@@ -503,9 +503,9 @@ impl Document {
}
}
- pub fn get_nodes_under_mouse(&self, point: &Point2D<f32>) -> Vec<UntrustedNodeAddress> {
+ pub fn get_nodes_under_mouse(&self, page_point: &Point2D<f32>) -> Vec<UntrustedNodeAddress> {
assert!(self.GetDocumentElement().is_some());
- match self.window.layout().mouse_over(*point) {
+ match self.window.layout().mouse_over(*page_point) {
Ok(MouseOverResponse(node_address)) => node_address,
Err(()) => vec![],
}
@@ -604,15 +604,18 @@ impl Document {
pub fn handle_mouse_event(&self,
js_runtime: *mut JSRuntime,
_button: MouseButton,
- point: Point2D<f32>,
+ client_point: Point2D<f32>,
mouse_event_type: MouseEventType) {
let mouse_event_type_string = match mouse_event_type {
MouseEventType::Click => "click".to_owned(),
MouseEventType::MouseUp => "mouseup".to_owned(),
MouseEventType::MouseDown => "mousedown".to_owned(),
};
- debug!("{}: at {:?}", mouse_event_type_string, point);
- let node = match self.hit_test(&point) {
+ debug!("{}: at {:?}", mouse_event_type_string, client_point);
+
+ let page_point = Point2D::new(client_point.x + self.window.PageXOffset() as f32,
+ client_point.y + self.window.PageYOffset() as f32);
+ let node = match self.hit_test(&page_point) {
Some(node_address) => {
debug!("node address is {:?}", node_address);
node::from_untrusted_node_address(js_runtime, node_address)
@@ -643,8 +646,8 @@ impl Document {
}
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-click
- let x = point.x as i32;
- let y = point.y as i32;
+ let client_x = client_point.x as i32;
+ let client_y = client_point.y as i32;
let clickCount = 1;
let event = MouseEvent::new(&self.window,
DOMString::from(mouse_event_type_string),
@@ -652,10 +655,10 @@ impl Document {
EventCancelable::Cancelable,
Some(&self.window),
clickCount,
- x,
- y,
- x,
- y, // TODO: Get real screen coordinates?
+ client_x,
+ client_y,
+ client_x,
+ client_y, // TODO: Get real screen coordinates?
false,
false,
false,
@@ -683,9 +686,9 @@ impl Document {
ReflowReason::MouseEvent);
}
- pub fn fire_mouse_event(&self, point: Point2D<f32>, target: &EventTarget, event_name: String) {
- let x = point.x.to_i32().unwrap_or(0);
- let y = point.y.to_i32().unwrap_or(0);
+ pub fn fire_mouse_event(&self, client_point: Point2D<f32>, target: &EventTarget, event_name: String) {
+ let client_x = client_point.x.to_i32().unwrap_or(0);
+ let client_y = client_point.y.to_i32().unwrap_or(0);
let mouse_event = MouseEvent::new(&self.window,
DOMString::from(event_name),
@@ -693,10 +696,10 @@ impl Document {
EventCancelable::Cancelable,
Some(&self.window),
0i32,
- x,
- y,
- x,
- y,
+ client_x,
+ client_y,
+ client_x,
+ client_y,
false,
false,
false,
@@ -709,12 +712,14 @@ impl Document {
pub fn handle_mouse_move_event(&self,
js_runtime: *mut JSRuntime,
- point: Option<Point2D<f32>>,
+ client_point: Option<Point2D<f32>>,
prev_mouse_over_targets: &mut RootedVec<JS<Element>>) {
// Build a list of elements that are currently under the mouse.
- let mouse_over_addresses = point.as_ref()
- .map(|point| self.get_nodes_under_mouse(point))
- .unwrap_or(vec![]);
+ let mouse_over_addresses = 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()
@@ -735,8 +740,8 @@ impl Document {
// FIXME: we should be dispatching this event but we lack an actual
// point to pass to it.
- if let Some(point) = point {
- self.fire_mouse_event(point, &target, "mouseout".to_owned());
+ if let Some(client_point) = client_point {
+ self.fire_mouse_event(client_point, &target, "mouseout".to_owned());
}
}
}
@@ -751,8 +756,8 @@ impl Document {
let target = target.upcast();
- if let Some(point) = point {
- self.fire_mouse_event(point, target, "mouseover".to_owned());
+ if let Some(client_point) = client_point {
+ self.fire_mouse_event(client_point, target, "mouseover".to_owned());
}
}
}
@@ -763,8 +768,8 @@ impl Document {
mouse_over_addresses[0]);
let target = top_most_node.upcast();
- if let Some(point) = point {
- self.fire_mouse_event(point, target, "mousemove".to_owned());
+ if let Some(client_point) = client_point {
+ self.fire_mouse_event(client_point, target, "mousemove".to_owned());
}
}