| Index: cc/trees/layer_tree_impl.cc
|
| diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
|
| index 6c0ff5a74f9afec86ed38e8a0b3235ae0537cfbc..86be523f5ff2e678b2b0696ff9584f4bf267394a 100644
|
| --- a/cc/trees/layer_tree_impl.cc
|
| +++ b/cc/trees/layer_tree_impl.cc
|
| @@ -40,6 +40,7 @@
|
| #include "cc/trees/property_tree_builder.h"
|
| #include "ui/gfx/geometry/box_f.h"
|
| #include "ui/gfx/geometry/point_conversions.h"
|
| +#include "ui/gfx/geometry/rect_conversions.h"
|
| #include "ui/gfx/geometry/size_conversions.h"
|
| #include "ui/gfx/geometry/vector2d_conversions.h"
|
|
|
| @@ -1430,25 +1431,79 @@ static const gfx::Transform SurfaceScreenSpaceTransform(
|
| layer->render_surface(), transform_tree);
|
| }
|
|
|
| +static bool PointIsClippedByAncestorClipNode(
|
| + const gfx::PointF& screen_space_point,
|
| + const LayerImpl* layer,
|
| + const ClipTree& clip_tree,
|
| + const TransformTree& transform_tree) {
|
| + // We need to visit all ancestor clip nodes to check this. Checking with just
|
| + // the combined clip stored at a clip node is not enough because parent
|
| + // combined clip can sometimes be smaller than current combined clip. This can
|
| + // happen when we have transforms like rotation that inflate the combined
|
| + // clip's bounds. Also, the point can be clipped by the content rect of an
|
| + // ancestor render surface.
|
| +
|
| + // We first check if the point is clipped by viewport.
|
| + const ClipNode* clip_node = clip_tree.Node(1);
|
| + gfx::Rect combined_clip_in_target_space =
|
| + gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
|
| + if (!PointHitsRect(screen_space_point, gfx::Transform(),
|
| + combined_clip_in_target_space, NULL))
|
| + return true;
|
| +
|
| + for (const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
|
| + clip_node->id > 1; clip_node = clip_tree.parent(clip_node)) {
|
| + if (clip_node->data.applies_local_clip) {
|
| + const TransformNode* transform_node =
|
| + transform_tree.Node(clip_node->data.target_id);
|
| + gfx::Rect combined_clip_in_target_space =
|
| + gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
|
| +
|
| + if (!PointHitsRect(screen_space_point, transform_node->data.to_screen,
|
| + combined_clip_in_target_space, NULL))
|
| + return true;
|
| + }
|
| + const LayerImpl* clip_node_owner =
|
| + layer->layer_tree_impl()->LayerById(clip_node->owner_id);
|
| + if (clip_node_owner->render_surface() &&
|
| + !PointHitsRect(
|
| + screen_space_point,
|
| + SurfaceScreenSpaceTransform(clip_node_owner, transform_tree,
|
| + true /*use_property_trees*/),
|
| + clip_node_owner->render_surface()->content_rect(), NULL)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| static bool PointIsClippedBySurfaceOrClipRect(
|
| const gfx::PointF& screen_space_point,
|
| const LayerImpl* layer,
|
| const TransformTree& transform_tree,
|
| + const ClipTree& clip_tree,
|
| const bool use_property_trees) {
|
| // Walk up the layer tree and hit-test any render_surfaces and any layer
|
| // clip rects that are active.
|
| + if (use_property_trees) {
|
| + return PointIsClippedByAncestorClipNode(screen_space_point, layer,
|
| + clip_tree, transform_tree);
|
| + }
|
| +
|
| for (; layer; layer = GetNextClippingLayer(layer)) {
|
| if (layer->render_surface() &&
|
| !PointHitsRect(screen_space_point,
|
| SurfaceScreenSpaceTransform(layer, transform_tree,
|
| use_property_trees),
|
| - layer->render_surface()->content_rect(), NULL))
|
| + layer->render_surface()->content_rect(), NULL)) {
|
| return true;
|
| + }
|
|
|
| if (LayerClipsSubtree(layer) &&
|
| !PointHitsRect(screen_space_point, layer->ScreenSpaceTransform(),
|
| - gfx::Rect(layer->bounds()), NULL))
|
| + gfx::Rect(layer->bounds()), NULL)) {
|
| return true;
|
| + }
|
| }
|
|
|
| // If we have finished walking all ancestors without having already exited,
|
| @@ -1460,6 +1515,7 @@ static bool PointHitsLayer(const LayerImpl* layer,
|
| const gfx::PointF& screen_space_point,
|
| float* distance_to_intersection,
|
| const TransformTree& transform_tree,
|
| + const ClipTree& clip_tree,
|
| const bool use_property_trees) {
|
| gfx::Rect content_rect(layer->bounds());
|
| if (!PointHitsRect(screen_space_point, layer->ScreenSpaceTransform(),
|
| @@ -1470,7 +1526,8 @@ static bool PointHitsLayer(const LayerImpl* layer,
|
| // 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(screen_space_point, layer,
|
| - transform_tree, use_property_trees))
|
| + transform_tree, clip_tree,
|
| + use_property_trees))
|
| return false;
|
|
|
| // Skip the HUD layer.
|
| @@ -1496,14 +1553,15 @@ static void FindClosestMatchingLayer(
|
| LayerImpl* layer,
|
| const Functor& func,
|
| const TransformTree& transform_tree,
|
| + const ClipTree& clip_tree,
|
| const bool use_property_trees,
|
| FindClosestMatchingLayerDataForRecursion* data_for_recursion) {
|
| size_t children_size = layer->children().size();
|
| for (size_t i = 0; i < children_size; ++i) {
|
| size_t index = children_size - 1 - i;
|
| FindClosestMatchingLayer(screen_space_point, layer->children()[index].get(),
|
| - func, transform_tree, use_property_trees,
|
| - data_for_recursion);
|
| + func, transform_tree, clip_tree,
|
| + use_property_trees, data_for_recursion);
|
| }
|
|
|
| if (!func(layer))
|
| @@ -1513,10 +1571,10 @@ static void FindClosestMatchingLayer(
|
| bool hit = false;
|
| if (layer->Is3dSorted())
|
| hit = PointHitsLayer(layer, screen_space_point, &distance_to_intersection,
|
| - transform_tree, use_property_trees);
|
| + transform_tree, clip_tree, use_property_trees);
|
| else
|
| hit = PointHitsLayer(layer, screen_space_point, nullptr, transform_tree,
|
| - use_property_trees);
|
| + clip_tree, use_property_trees);
|
|
|
| if (!hit)
|
| return;
|
| @@ -1565,7 +1623,8 @@ LayerImpl* LayerTreeImpl::FindFirstScrollingLayerThatIsHitByPoint(
|
| settings().use_property_trees || settings().verify_property_trees;
|
| FindClosestMatchingLayer(
|
| screen_space_point, root_layer(), FindScrollingLayerFunctor(),
|
| - property_trees_.transform_tree, use_property_trees, &data_for_recursion);
|
| + property_trees_.transform_tree, property_trees_.clip_tree,
|
| + use_property_trees, &data_for_recursion);
|
| return data_for_recursion.closest_match;
|
| }
|
|
|
| @@ -1590,7 +1649,8 @@ LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint(
|
| FindClosestMatchingLayerDataForRecursion data_for_recursion;
|
| FindClosestMatchingLayer(screen_space_point, root_layer(),
|
| HitTestVisibleScrollableOrTouchableFunctor(),
|
| - property_trees_.transform_tree, use_property_trees,
|
| + property_trees_.transform_tree,
|
| + property_trees_.clip_tree, use_property_trees,
|
| &data_for_recursion);
|
| return data_for_recursion.closest_match;
|
| }
|
| @@ -1598,6 +1658,7 @@ LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint(
|
| static bool LayerHasTouchEventHandlersAt(const gfx::PointF& screen_space_point,
|
| LayerImpl* layer_impl,
|
| const TransformTree& transform_tree,
|
| + const ClipTree& clip_tree,
|
| const bool use_property_trees) {
|
| if (layer_impl->touch_event_handler_region().IsEmpty())
|
| return false;
|
| @@ -1611,7 +1672,8 @@ static bool LayerHasTouchEventHandlersAt(const gfx::PointF& screen_space_point,
|
| // was not clipped in such a way that the hit point actually should not hit
|
| // the layer.
|
| if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer_impl,
|
| - transform_tree, use_property_trees))
|
| + transform_tree, clip_tree,
|
| + use_property_trees))
|
| return false;
|
|
|
| return true;
|
| @@ -1634,19 +1696,21 @@ LayerImpl* LayerTreeImpl::FindLayerWithWheelHandlerThatIsHitByPoint(
|
| settings().use_property_trees || settings().verify_property_trees;
|
| FindWheelEventLayerFunctor func;
|
| FindClosestMatchingLayerDataForRecursion data_for_recursion;
|
| - FindClosestMatchingLayer(screen_space_point, root_layer(), func,
|
| - property_trees_.transform_tree, use_property_trees,
|
| - &data_for_recursion);
|
| + FindClosestMatchingLayer(
|
| + screen_space_point, root_layer(), func, property_trees_.transform_tree,
|
| + property_trees_.clip_tree, use_property_trees, &data_for_recursion);
|
| return data_for_recursion.closest_match;
|
| }
|
|
|
| struct FindTouchEventLayerFunctor {
|
| bool operator()(LayerImpl* layer) const {
|
| return LayerHasTouchEventHandlersAt(screen_space_point, layer,
|
| - transform_tree, use_property_trees);
|
| + transform_tree, clip_tree,
|
| + use_property_trees);
|
| }
|
| const gfx::PointF screen_space_point;
|
| const TransformTree& transform_tree;
|
| + const ClipTree& clip_tree;
|
| const bool use_property_trees;
|
| };
|
|
|
| @@ -1660,11 +1724,12 @@ LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInTouchHandlerRegion(
|
| bool use_property_trees =
|
| settings().use_property_trees || settings().verify_property_trees;
|
| FindTouchEventLayerFunctor func = {
|
| - screen_space_point, property_trees_.transform_tree, use_property_trees};
|
| + screen_space_point, property_trees_.transform_tree,
|
| + property_trees_.clip_tree, use_property_trees};
|
| FindClosestMatchingLayerDataForRecursion data_for_recursion;
|
| - FindClosestMatchingLayer(screen_space_point, root_layer(), func,
|
| - property_trees_.transform_tree, use_property_trees,
|
| - &data_for_recursion);
|
| + FindClosestMatchingLayer(
|
| + screen_space_point, root_layer(), func, property_trees_.transform_tree,
|
| + property_trees_.clip_tree, use_property_trees, &data_for_recursion);
|
| return data_for_recursion.closest_match;
|
| }
|
|
|
| @@ -1677,6 +1742,7 @@ static ViewportSelectionBound ComputeViewportSelectionBound(
|
| LayerImpl* layer,
|
| float device_scale_factor,
|
| const TransformTree& transform_tree,
|
| + const ClipTree& clip_tree,
|
| const bool use_property_trees) {
|
| ViewportSelectionBound viewport_bound;
|
| viewport_bound.type = layer_bound.type;
|
| @@ -1722,7 +1788,7 @@ static ViewportSelectionBound ComputeViewportSelectionBound(
|
| float intersect_distance = 0.f;
|
| viewport_bound.visible =
|
| PointHitsLayer(layer, visibility_point, &intersect_distance,
|
| - transform_tree, use_property_trees);
|
| + transform_tree, clip_tree, use_property_trees);
|
|
|
| return viewport_bound;
|
| }
|
| @@ -1736,7 +1802,7 @@ void LayerTreeImpl::GetViewportSelection(ViewportSelection* selection) {
|
| selection_.start,
|
| selection_.start.layer_id ? LayerById(selection_.start.layer_id) : NULL,
|
| device_scale_factor(), property_trees_.transform_tree,
|
| - use_property_trees);
|
| + property_trees_.clip_tree, use_property_trees);
|
| selection->is_editable = selection_.is_editable;
|
| selection->is_empty_text_form_control = selection_.is_empty_text_form_control;
|
| if (selection->start.type == SELECTION_BOUND_CENTER ||
|
| @@ -1747,7 +1813,7 @@ void LayerTreeImpl::GetViewportSelection(ViewportSelection* selection) {
|
| selection_.end,
|
| selection_.end.layer_id ? LayerById(selection_.end.layer_id) : NULL,
|
| device_scale_factor(), property_trees_.transform_tree,
|
| - use_property_trees);
|
| + property_trees_.clip_tree, use_property_trees);
|
| }
|
| }
|
|
|
|
|