Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4297)

Unified Diff: cc/trees/layer_tree_impl.cc

Issue 1551333003: cc:: Use clip tree instead of layer tree during hit testing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | cc/trees/layer_tree_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
}
« no previous file with comments | « no previous file | cc/trees/layer_tree_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698