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

Unified Diff: cc/trees/layer_tree_host_common.cc

Issue 26112002: cc: Fix hit-testing in zero-opacity layers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 2 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 d483cc697bd76d44e0b7d9353dbb0974c6fdfc5d..b496ee5da9c1a65049bd8d9bb0807bd07de57cdc 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -63,6 +63,12 @@ static gfx::Vector2dF GetEffectiveTotalScrollOffset(LayerType* layer) {
return offset;
}
+template <typename LayerType>
+static inline bool LayerCanAcceptInput(LayerType* layer) {
+ return !layer->touch_event_handler_region().IsEmpty() ||
+ layer->have_wheel_event_handlers();
+}
+
inline gfx::Rect CalculateVisibleRectWithCachedLayerRect(
gfx::Rect target_surface_rect,
gfx::Rect layer_bound_rect,
@@ -415,7 +421,16 @@ static inline bool TransformToScreenIsKnown(Layer* layer) {
template <typename LayerType>
static bool LayerShouldBeSkipped(LayerType* layer,
- bool layer_is_visible) {
+ bool layer_is_visible,
+ bool visit_for_event_handler_only) {
danakj 2013/10/08 18:32:32 how about bool "layer_has_zero_opacity"? only is a
+ // If an ancestor node was going to be skipped, but wasn't only because it had
+ // event handlers in the subtree, and there are not event handlers in the
+ // subtree rooted at |layer|, then skip this layer.
+ if (visit_for_event_handler_only &&
danakj 2013/10/08 18:32:32 Move this down below the big intro comment, and up
+ !layer->draw_properties().layer_or_descendant_has_event_handler) {
+ return true;
+ }
+
// Layers can be skipped if any of these conditions are met.
// - is not visible due to it or one of its ancestors being hidden.
// - has empty bounds
@@ -452,18 +467,27 @@ static bool LayerShouldBeSkipped(LayerType* layer,
IsLayerBackFaceVisible(backface_test_layer))
return true;
- // The layer is visible to events. If it's subject to hit testing, then
- // we can't skip it.
- bool can_accept_input = !layer->touch_event_handler_region().IsEmpty() ||
- layer->have_wheel_event_handlers();
- if (!layer->DrawsContent() && !can_accept_input)
+ // A layer cannot be skipped if it is subject to hit-testing.
+ if (LayerCanAcceptInput(layer))
+ return false;
+
+ if (!layer->DrawsContent())
+ return true;
+
+ if (!layer->draw_opacity() && !layer->draw_opacity_is_animating())
danakj 2013/10/08 18:32:32 Animating only matters on the main thread. On the
return true;
return false;
}
static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
- bool layer_is_visible) {
+ bool layer_is_visible,
+ bool *visit_for_event_handler_only) {
+ if (*visit_for_event_handler_only &&
+ !layer->draw_properties().layer_or_descendant_has_event_handler) {
+ return true;
+ }
+
// When we need to do a readback/copy of a layer's output, we can not skip
// it or any of its ancestors.
if (layer->draw_properties().layer_or_descendant_has_copy_request)
@@ -479,15 +503,30 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating())
return false;
+ bool skip_if_no_event_handler = !layer->opacity();
+
+ // If the layer (or any of its descendant) is subject to hit-testing, then the
+ // subtree cannot be skipped.
+ if (layer->draw_properties().layer_or_descendant_has_event_handler) {
+ if (skip_if_no_event_handler)
+ *visit_for_event_handler_only = true;
+ return false;
+ }
+
// The opacity of a layer always applies to its children (either implicitly
// via a render surface or explicitly if the parent preserves 3D), so the
// entire subtree can be skipped if this layer is fully transparent.
- // TODO(sad): Don't skip layers used for hit testing crbug.com/295295.
- return !layer->opacity();
+ return skip_if_no_event_handler;
}
static inline bool SubtreeShouldBeSkipped(Layer* layer,
- bool layer_is_visible) {
+ bool layer_is_visible,
+ bool* visit_for_event_handler_only) {
+ if (*visit_for_event_handler_only &&
+ !layer->draw_properties().layer_or_descendant_has_event_handler) {
+ return true;
+ }
+
// When we need to do a readback/copy of a layer's output, we can not skip
// it or any of its ancestors.
if (layer->draw_properties().layer_or_descendant_has_copy_request)
@@ -503,9 +542,19 @@ static inline bool SubtreeShouldBeSkipped(Layer* layer,
// In particular, it should not cause the subtree to be skipped.
// Similarly, for layers that might animate opacity using an impl-only
// animation, their subtree should also not be skipped.
- // TODO(sad): Don't skip layers used for hit testing crbug.com/295295.
- return !layer->opacity() && !layer->OpacityIsAnimating() &&
- !layer->OpacityCanAnimateOnImplThread();
+ bool skip_if_no_event_handler =
+ !layer->opacity() && !layer->OpacityIsAnimating() &&
+ !layer->OpacityCanAnimateOnImplThread();
+
+ // If the layer (or any of its descendant) is subject to hit-testing, then the
+ // subtree cannot be skipped.
+ if (layer->draw_properties().layer_or_descendant_has_event_handler) {
+ if (skip_if_no_event_handler)
+ *visit_for_event_handler_only = true;
+ return false;
+ }
+
+ return skip_if_no_event_handler;
}
// Called on each layer that could be drawn after all information from
@@ -1014,15 +1063,19 @@ static inline void RemoveSurfaceForEarlyExit(
struct PreCalculateMetaInformationRecursiveData {
bool layer_or_descendant_has_copy_request;
+ bool layer_or_descendant_has_event_handler;
int num_unclipped_descendants;
PreCalculateMetaInformationRecursiveData()
: layer_or_descendant_has_copy_request(false),
+ layer_or_descendant_has_event_handler(false),
num_unclipped_descendants(0) {}
void Merge(const PreCalculateMetaInformationRecursiveData& data) {
layer_or_descendant_has_copy_request |=
data.layer_or_descendant_has_copy_request;
+ layer_or_descendant_has_event_handler |=
+ data.layer_or_descendant_has_event_handler;
num_unclipped_descendants +=
data.num_unclipped_descendants;
}
@@ -1084,6 +1137,9 @@ static void PreCalculateMetaInformation(
if (layer->HasCopyRequest())
recursive_data->layer_or_descendant_has_copy_request = true;
+ if (LayerCanAcceptInput(layer))
+ recursive_data->layer_or_descendant_has_event_handler = true;
+
layer->draw_properties().num_descendants_that_draw_content =
num_descendants_that_draw_content;
layer->draw_properties().num_unclipped_descendants =
@@ -1092,6 +1148,8 @@ static void PreCalculateMetaInformation(
descendants_can_clip_selves;
layer->draw_properties().layer_or_descendant_has_copy_request =
recursive_data->layer_or_descendant_has_copy_request;
+ layer->draw_properties().layer_or_descendant_has_event_handler =
+ recursive_data->layer_or_descendant_has_event_handler;
}
static void RoundTranslationComponents(gfx::Transform* transform) {
@@ -1147,6 +1205,8 @@ struct DataForRecursion {
bool in_subtree_of_page_scale_application_layer;
bool subtree_can_use_lcd_text;
bool subtree_is_visible_from_ancestor;
+
+ bool visit_for_event_handler_only;
};
// Recursively walks the layer tree starting at the given node and computes all
@@ -1306,12 +1366,17 @@ static void CalculateDrawPropertiesInternal(
if (layer->HasCopyRequest())
layer_is_visible = true;
+ bool visit_for_event_handler_only =
+ data_from_ancestor.visit_for_event_handler_only;
// The root layer cannot skip CalcDrawProperties.
- if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_visible)) {
+ if (!IsRootLayer(layer) &&
+ SubtreeShouldBeSkipped(layer, layer_is_visible,
+ &visit_for_event_handler_only)) {
if (layer->render_surface())
layer->ClearRenderSurface();
return;
}
+ data_for_children.visit_for_event_handler_only = visit_for_event_handler_only;
// We need to circumvent the normal recursive flow of information for clip
// children (they don't inherit their direct ancestor's clip information).
@@ -1729,7 +1794,8 @@ static void CalculateDrawPropertiesInternal(
// and should be included in the sorting process.
size_t sorting_start_index = descendants.size();
- if (!LayerShouldBeSkipped(layer, layer_is_visible))
+ if (!LayerShouldBeSkipped(layer, layer_is_visible,
+ data_from_ancestor.visit_for_event_handler_only))
descendants.push_back(layer);
if (!layer->children().empty()) {
@@ -1826,7 +1892,8 @@ static void CalculateDrawPropertiesInternal(
}
// Compute the layer's visible content rect (the rect is in content space).
- layer_draw_properties.visible_content_rect = CalculateVisibleContentRect(
+ layer_draw_properties.visible_content_rect =
danakj 2013/10/08 18:32:32 Leave this rect alone. If the layer has 0 opacity
+ visit_for_event_handler_only ? gfx::Rect() : CalculateVisibleContentRect(
layer, clip_rect_of_target_surface_in_target_space, rect_in_target_space);
// Compute the remaining properties for the render surface, if the layer has
@@ -1982,6 +2049,7 @@ void LayerTreeHostCommon::CalculateDrawProperties(
data_for_recursion.in_subtree_of_page_scale_application_layer = false;
data_for_recursion.subtree_can_use_lcd_text = inputs->can_use_lcd_text;
data_for_recursion.subtree_is_visible_from_ancestor = true;
+ data_for_recursion.visit_for_event_handler_only = false;
PreCalculateMetaInformationRecursiveData recursive_data;
PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
@@ -2041,6 +2109,7 @@ void LayerTreeHostCommon::CalculateDrawProperties(
data_for_recursion.in_subtree_of_page_scale_application_layer = false;
data_for_recursion.subtree_can_use_lcd_text = inputs->can_use_lcd_text;
data_for_recursion.subtree_is_visible_from_ancestor = true;
+ data_for_recursion.visit_for_event_handler_only = false;
PreCalculateMetaInformationRecursiveData recursive_data;
PreCalculateMetaInformation(inputs->root_layer, &recursive_data);

Powered by Google App Engine
This is Rietveld 408576698