Index: cc/layer_tree_host_common.cc |
diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc |
index a119b89979cb8aea377c4e92aa57fcfce2fb375f..4c8779f7319437a2d2fe330a4eb04a3bb28c7894 100644 |
--- a/cc/layer_tree_host_common.cc |
+++ b/cc/layer_tree_host_common.cc |
@@ -13,6 +13,7 @@ |
#include "cc/math_util.h" |
#include "cc/render_surface.h" |
#include "cc/render_surface_impl.h" |
+#include "ui/gfx/point_conversions.h" |
#include "ui/gfx/rect_conversions.h" |
#include <algorithm> |
#include <public/WebTransformationMatrix.h> |
@@ -876,6 +877,24 @@ static bool pointHitsRect(const gfx::PointF& screenSpacePoint, const WebTransfor |
return localSpaceRect.Contains(hitTestPointInLocalSpace); |
} |
+static bool pointHitsRegion(const gfx::PointF& screenSpacePoint, const WebTransformationMatrix& screenSpaceTransform, Region layerSpaceRegion, float layerContentScaleX, float layerContentScaleY) |
danakj
2012/11/08 02:18:48
You can pass the PointF by value (2 floats), but p
|
+{ |
+ // If the transform is not invertible, then assume that this point doesn't hit this rect. |
+ if (!screenSpaceTransform.isInvertible()) |
+ return false; |
+ |
+ // Transform the hit test point from screen space to the local space of the given rect. |
+ bool clipped = false; |
+ gfx::PointF hitTestPointInContentSpace = MathUtil::projectPoint(screenSpaceTransform.inverse(), screenSpacePoint, clipped); |
+ gfx::PointF hitTestPointInLayerSpace = hitTestPointInContentSpace.Scale(1 / layerContentScaleX, 1 / layerContentScaleY); |
+ |
+ // If projectPoint could not project to a valid value, then we assume that this point doesn't hit this rect. |
+ if (clipped) |
+ return false; |
+ |
+ return layerSpaceRegion.Contains(gfx::ToRoundedPoint(hitTestPointInLayerSpace)); |
+} |
+ |
static bool pointIsClippedBySurfaceOrClipRect(const gfx::PointF& screenSpacePoint, LayerImpl* layer) |
{ |
LayerImpl* currentLayer = layer; |
@@ -930,4 +949,38 @@ LayerImpl* LayerTreeHostCommon::findLayerThatIsHitByPoint(const gfx::PointF& scr |
return foundLayer; |
} |
+LayerImpl* LayerTreeHostCommon::findLayerThatIsHitByPointInTouchHandlerRegion(const gfx::PointF& screenSpacePoint, std::vector<LayerImpl*>& renderSurfaceLayerList) |
+{ |
+ LayerImpl* foundLayer = 0; |
+ |
+ typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType; |
+ LayerIteratorType end = LayerIteratorType::end(&renderSurfaceLayerList); |
+ |
+ for (LayerIteratorType it = LayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { |
+ // We don't want to consider renderSurfaces for hit testing. |
+ if (!it.representsItself()) |
+ continue; |
+ |
+ LayerImpl* currentLayer = (*it); |
+ |
+ if (currentLayer->touchEventHandlerRegion().IsEmpty()) |
+ continue; |
+ |
+ if (!pointHitsRegion(screenSpacePoint, currentLayer->screenSpaceTransform(), currentLayer->touchEventHandlerRegion(), currentLayer->contentsScaleX(), currentLayer->contentsScaleY())) |
+ continue; |
+ |
+ // At this point, we think the point does hit the touch event handler region on the layer, but we need to walk up |
+ // the parents to ensure that the layer was not clipped in such a way that the |
+ // hit point actually should not hit the layer. |
+ if (pointIsClippedBySurfaceOrClipRect(screenSpacePoint, currentLayer)) |
+ continue; |
+ |
+ foundLayer = currentLayer; |
+ break; |
+ } |
+ |
+ // This can potentially return 0, which means the screenSpacePoint did not successfully hit test any layers, not even the root layer. |
+ return foundLayer; |
+} |
+ |
} // namespace cc |