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

Unified Diff: cc/trees/layer_tree_host_common.cc

Issue 266913021: Hit test on the layer tree rather than the RSLL (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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
Index: cc/trees/layer_tree_host_common.cc
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index ba92d8d546b1f18879f45cafd2f67e21b4769858..4fdc6a4543f97764174a82c77faebe2038a9c570 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -1174,6 +1174,7 @@ static void PreCalculateMetaInformation(
bool has_delegated_content = layer->HasDelegatedContent();
int num_descendants_that_draw_content = 0;
+ layer->draw_properties().is_in_layer_list = false;
layer->draw_properties().sorted_for_recursion = false;
layer->draw_properties().has_child_with_a_scroll_parent = false;
@@ -2011,8 +2012,10 @@ static void CalculateDrawPropertiesInternal(
// and should be included in the sorting process.
size_t sorting_start_index = descendants.size();
- if (!LayerShouldBeSkipped(layer, layer_is_drawn))
+ if (!LayerShouldBeSkipped(layer, layer_is_drawn)) {
+ layer_draw_properties.is_in_layer_list = true;
descendants.push_back(layer);
+ }
// Any layers that are appended after this point may need to be sorted if we
// visit the children out of order.
@@ -2373,7 +2376,8 @@ void LayerTreeHostCommon::CalculateDrawProperties(
static bool PointHitsRect(
const gfx::PointF& screen_space_point,
const gfx::Transform& local_space_to_screen_space_transform,
- const gfx::RectF& local_space_rect) {
+ const gfx::RectF& local_space_rect,
+ float* distance_to_camera) {
// If the transform is not invertible, then assume that this point doesn't hit
// this rect.
gfx::Transform inverse_local_space_to_screen_space(
@@ -2385,15 +2389,29 @@ static bool PointHitsRect(
// Transform the hit test point from screen space to the local space of the
// given rect.
bool clipped = false;
- gfx::PointF hit_test_point_in_local_space = MathUtil::ProjectPoint(
+ gfx::Point3F planar_point = MathUtil::ProjectPoint3D(
inverse_local_space_to_screen_space, screen_space_point, &clipped);
+ gfx::PointF hit_test_point_in_local_space =
+ gfx::PointF(planar_point.x(), planar_point.y());
// 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 local_space_rect.Contains(hit_test_point_in_local_space);
+ if (!local_space_rect.Contains(hit_test_point_in_local_space))
+ return false;
+
+ if (distance_to_camera) {
+ // To compute the distance to the camera, we have to take the planar point
+ // and pull it back to world space and compute the displacement along the
+ // z-axis.
+ gfx::Point3F planar_point_in_screen_space(planar_point);
+ local_space_to_screen_space_transform.TransformPoint(&planar_point);
+ *distance_to_camera = planar_point_in_screen_space.z();
+ }
+
+ return true;
}
static bool PointHitsRegion(const gfx::PointF& screen_space_point,
@@ -2439,7 +2457,8 @@ static bool PointIsClippedBySurfaceOrClipRect(
!PointHitsRect(
screen_space_point,
current_layer->render_surface()->screen_space_transform(),
- current_layer->render_surface()->content_rect()))
+ current_layer->render_surface()->content_rect(),
+ NULL))
return true;
// Note that drawable content rects are actually in target surface space, so
@@ -2450,7 +2469,8 @@ static bool PointIsClippedBySurfaceOrClipRect(
!PointHitsRect(
screen_space_point,
render_target->render_surface()->screen_space_transform(),
- current_layer->drawable_content_rect()))
+ current_layer->drawable_content_rect(),
+ NULL))
return true;
current_layer = current_layer->parent();
@@ -2462,10 +2482,13 @@ static bool PointIsClippedBySurfaceOrClipRect(
}
static bool PointHitsLayer(LayerImpl* layer,
- const gfx::PointF& screen_space_point) {
+ const gfx::PointF& screen_space_point,
+ float* distance_to_intersection) {
gfx::RectF content_rect(layer->content_bounds());
- if (!PointHitsRect(
- screen_space_point, layer->screen_space_transform(), content_rect))
+ if (!PointHitsRect(screen_space_point,
+ layer->screen_space_transform(),
+ content_rect,
+ distance_to_intersection))
return false;
// At this point, we think the point does hit the layer, but we need to walk
@@ -2481,87 +2504,83 @@ static bool PointHitsLayer(LayerImpl* layer,
return true;
}
-LayerImpl* LayerTreeHostCommon::FindFirstScrollingLayerThatIsHitByPoint(
- const gfx::PointF& screen_space_point,
- const LayerImplList& render_surface_layer_list) {
- typedef LayerIterator<LayerImpl> LayerIteratorType;
- LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
- for (LayerIteratorType it =
- LayerIteratorType::Begin(&render_surface_layer_list);
- it != end;
- ++it) {
- // We don't want to consider render_surfaces for hit testing.
- if (!it.represents_itself())
- continue;
-
- LayerImpl* current_layer = (*it);
- if (!PointHitsLayer(current_layer, screen_space_point))
- continue;
+struct FindClosestMatchingLayerDataForRecursion {
+ FindClosestMatchingLayerDataForRecursion()
+ : closest_match(NULL), closest_distance(0.f), found_match(false) {}
+ LayerImpl* closest_match;
+ float closest_distance;
+ bool found_match;
+};
- if (current_layer->scrollable())
- return current_layer;
+template <typename Functor>
+static void FindClosestMatchingLayer(
+ const gfx::PointF& screen_space_point,
+ LayerImpl* layer,
+ const Functor& func,
+ FindClosestMatchingLayerDataForRecursion* data_for_recursion) {
+ for (int i = layer->children().size() - 1; i >= 0; --i) {
+ FindClosestMatchingLayer(
+ screen_space_point, layer->children()[i], func, data_for_recursion);
+ }
+
+ float distance_to_intersection = 0.f;
+ if (func(layer) &&
+ PointHitsLayer(layer, screen_space_point, &distance_to_intersection) &&
+ ((!data_for_recursion->found_match ||
+ distance_to_intersection < data_for_recursion->closest_distance))) {
+ data_for_recursion->found_match = true;
+ data_for_recursion->closest_distance = distance_to_intersection;
+ data_for_recursion->closest_match = layer;
}
-
- return NULL;
}
-LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPoint(
- const gfx::PointF& screen_space_point,
- const LayerImplList& render_surface_layer_list) {
- LayerImpl* found_layer = NULL;
-
- typedef LayerIterator<LayerImpl> LayerIteratorType;
- LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
- for (LayerIteratorType
- it = LayerIteratorType::Begin(&render_surface_layer_list);
- it != end;
- ++it) {
- // We don't want to consider render_surfaces for hit testing.
- if (!it.represents_itself())
- continue;
+struct FindScrollingLayerFunctor {
+ bool operator()(LayerImpl* layer) const { return layer->scrollable(); }
+};
- LayerImpl* current_layer = (*it);
- if (!PointHitsLayer(current_layer, screen_space_point))
- continue;
+LayerImpl* LayerTreeHostCommon::FindFirstScrollingLayerThatIsHitByPoint(
+ const gfx::PointF& screen_space_point,
+ LayerImpl* root) {
+ FindClosestMatchingLayerDataForRecursion data_for_recursion;
+ FindClosestMatchingLayer(screen_space_point,
+ root,
+ FindScrollingLayerFunctor(),
+ &data_for_recursion);
+ return data_for_recursion.closest_match;
+}
- found_layer = current_layer;
- break;
+struct HitTestVisibleFunctor {
+ bool operator()(LayerImpl* layer) const {
+ return layer->draw_properties().is_in_layer_list ||
enne (OOO) 2014/05/06 20:30:58 What is the "is_in_layer_list" function standing i
+ !layer->touch_event_handler_region().IsEmpty() ||
+ layer->have_wheel_event_handlers();
}
+};
- // This can potentially return NULL, which means the screen_space_point did
- // not successfully hit test any layers, not even the root layer.
- return found_layer;
+LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ const gfx::PointF& screen_space_point,
+ LayerImpl* root) {
+ FindClosestMatchingLayerDataForRecursion data_for_recursion;
+ FindClosestMatchingLayer(
+ screen_space_point, root, HitTestVisibleFunctor(), &data_for_recursion);
+ return data_for_recursion.closest_match;
}
+struct FindTouchEventLayerFunctor {
+ bool operator()(LayerImpl* layer) const {
+ return LayerTreeHostCommon::LayerHasTouchEventHandlersAt(screen_space_point,
+ layer);
+ }
+ const gfx::PointF screen_space_point;
+};
+
LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
const gfx::PointF& screen_space_point,
- const LayerImplList& render_surface_layer_list) {
- typedef LayerIterator<LayerImpl> LayerIteratorType;
- LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
- for (LayerIteratorType it =
- LayerIteratorType::Begin(&render_surface_layer_list);
- it != end;
- ++it) {
- // We don't want to consider render_surfaces for hit testing.
- if (!it.represents_itself())
- continue;
-
- LayerImpl* current_layer = (*it);
- if (!PointHitsLayer(current_layer, screen_space_point))
- continue;
-
- if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(screen_space_point,
- current_layer))
- return current_layer;
-
- // Note that we could stop searching if we hit a layer we know to be
- // opaque to hit-testing, but knowing that reliably is tricky (eg. due to
- // CSS pointer-events: none). Also blink has an optimization for the
- // common case of an entire document having handlers where it doesn't
- // report any rects for child layers (since it knows they can't exceed
- // the document bounds).
- }
- return NULL;
+ LayerImpl* root) {
+ FindTouchEventLayerFunctor func = {screen_space_point};
+ FindClosestMatchingLayerDataForRecursion data_for_recursion;
+ FindClosestMatchingLayer(screen_space_point, root, func, &data_for_recursion);
+ return data_for_recursion.closest_match;
}
bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt(
@@ -2586,4 +2605,5 @@ bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt(
return true;
}
+
} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698