diff options
author | Matt Brubeck <mbrubeck@limpet.net> | 2015-11-16 16:46:47 -0800 |
---|---|---|
committer | Paul Rouget <me@paulrouget.com> | 2015-11-25 05:28:47 +0100 |
commit | a61989e82b3a58b8ae868264a996459ca9bc6e7d (patch) | |
tree | b07c9bb7838243b810803262b019ef0f6de3dfbd | |
parent | 4f625d3ab67bc14b1563f90c48cf97ca59dc1a28 (diff) | |
download | servo-a61989e82b3a58b8ae868264a996459ca9bc6e7d.tar.gz servo-a61989e82b3a58b8ae868264a996459ca9bc6e7d.zip |
Fix clip rect for iframes in hit testing code
Fixes #8080
-rw-r--r-- | components/compositing/compositor.rs | 40 | ||||
-rw-r--r-- | components/compositing/compositor_layer.rs | 2 |
2 files changed, 26 insertions, 16 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, |