From 66f6c3a213476ea237eaa70feb46a1a5ebca8fe2 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 11 Dec 2014 12:29:31 +0100 Subject: [PATCH 1/2] All root layers should mask their content Root layers that define the extent of iframes should always mask their child content. This fixes a bug where root layers without an assigned size and location do not spill over the entire scene. --- components/compositing/compositor.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index c5a11fa1605..6c39c3b1c7a 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -1178,10 +1178,11 @@ fn create_root_layer_for_pipeline_and_rect(pipeline: &CompositionPipeline, WantsScrollEvents, opts::get().tile_size); + // All root layers mask to bounds. + *root_layer.masks_to_bounds.borrow_mut() = true; + match frame_rect { Some(ref frame_rect) => { - *root_layer.masks_to_bounds.borrow_mut() = true; - let frame_rect = frame_rect.to_untyped(); *root_layer.bounds.borrow_mut() = Rect::from_untyped(&frame_rect); } From 14bfa451058b3bc6d6925137240de5e172045213 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 11 Dec 2014 13:18:21 +0100 Subject: [PATCH 2/2] 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, } }