From 14bfa451058b3bc6d6925137240de5e172045213 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 11 Dec 2014 13:18:21 +0100 Subject: [PATCH] Hit test against clipped layer boundaries When finding the layer under a point, take into account clipping rectangles defined by layers that mask to bounds. This prevents clicks from being hijacked by masked layers. --- components/compositing/compositor.rs | 33 +++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 6c39c3b1c7a..0466b05540d 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -1098,18 +1098,38 @@ impl IOCompositor { fn find_topmost_layer_at_point_for_layer(&self, layer: Rc>, - point: TypedPoint2D) + point: TypedPoint2D, + clip_rect: &TypedRect) -> Option { - let child_point = point - layer.bounds.borrow().origin; + 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 clipped_layer_bounds = match clip_rect.intersection(&layer_bounds) { + Some(rect) => rect, + None => return None, + }; + + let clip_rect_for_children = if masks_to_bounds { + Rect(Zero::zero(), clipped_layer_bounds.size) + } else { + clipped_layer_bounds.translate(&clip_rect.origin) + }; + + let child_point = point - layer_bounds.origin; for child in layer.children().iter().rev() { - let result = self.find_topmost_layer_at_point_for_layer(child.clone(), child_point); + let result = self.find_topmost_layer_at_point_for_layer(child.clone(), + child_point, + &clip_rect_for_children); if result.is_some() { return result; } } let point = point - *layer.content_offset.borrow(); - if !layer.bounds.borrow().contains(&point) { + if !clipped_layer_bounds.contains(&point) { return None; } @@ -1120,7 +1140,10 @@ impl IOCompositor { point: TypedPoint2D) -> Option { match self.scene.root { - Some(ref layer) => self.find_topmost_layer_at_point_for_layer(layer.clone(), point), + Some(ref layer) => self.find_topmost_layer_at_point_for_layer(layer.clone(), + point, + &*layer.bounds.borrow()), + None => None, } }