Commit 0da498c0 authored by jaydasika's avatar jaydasika Committed by Commit bot

cc: Fix sublayer scale bug in hit testing

In hit testing, we should use the render surface screen space
transform (which doesn't have sublayer scale) instead of the
screen_space_transform stored on the transform node (which
has the sublayer scale baked in) as the clips stored in clip
tree already account for the scale.

BUG=604731
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1917043002

Cr-Commit-Position: refs/heads/master@{#389873}
parent 26ef2644
......@@ -1639,9 +1639,17 @@ static bool PointIsClippedByAncestorClipNode(
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))
const LayerImpl* target_layer =
layer->layer_tree_impl()->LayerById(transform_node->owner_id);
DCHECK(transform_node->id == 0 || target_layer->render_surface());
gfx::Transform surface_screen_space_transform =
transform_node->id == 0
? gfx::Transform()
: SurfaceScreenSpaceTransform(target_layer, transform_tree);
if (!PointHitsRect(screen_space_point, surface_screen_space_transform,
combined_clip_in_target_space, NULL)) {
return true;
}
}
const LayerImpl* clip_node_owner =
layer->layer_tree_impl()->LayerById(clip_node->owner_id);
......@@ -1674,8 +1682,9 @@ static bool PointHitsLayer(const LayerImpl* layer,
const ClipTree& clip_tree) {
gfx::Rect content_rect(layer->bounds());
if (!PointHitsRect(screen_space_point, layer->ScreenSpaceTransform(),
content_rect, distance_to_intersection))
content_rect, distance_to_intersection)) {
return false;
}
// At this point, we think the point does hit the layer, but we need to walk
// up the parents to ensure that the layer was not clipped in such a way
......
......@@ -1895,6 +1895,94 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSimpleClippedLayer) {
EXPECT_EQ(456, result_layer->id());
}
TEST_F(LayerTreeImplTest,
HitCheckingTouchHandlerRegionsForClippedLayerWithDeviceScale) {
// The layer's device_scale_factor and page_scale_factor should scale the
// content rect and we should be able to hit the touch handler region by
// scaling the points accordingly.
std::unique_ptr<LayerImpl> root =
LayerImpl::Create(host_impl().active_tree(), 1);
gfx::Transform identity_matrix;
gfx::Point3F transform_origin;
// Set the bounds of the root layer big enough to fit the child when scaled.
SetLayerPropertiesForTesting(root.get(), identity_matrix, transform_origin,
gfx::PointF(), gfx::Size(100, 100), true, false,
true);
std::unique_ptr<LayerImpl> surface =
LayerImpl::Create(host_impl().active_tree(), 2);
SetLayerPropertiesForTesting(surface.get(), identity_matrix, transform_origin,
gfx::PointF(), gfx::Size(100, 100), true, false,
true);
{
std::unique_ptr<LayerImpl> clipping_layer =
LayerImpl::Create(host_impl().active_tree(), 123);
// This layer is positioned, and hit testing should correctly know where the
// layer is located.
gfx::PointF position(25.f, 20.f);
gfx::Size bounds(50, 50);
SetLayerPropertiesForTesting(clipping_layer.get(), identity_matrix,
transform_origin, position, bounds, true,
false, false);
clipping_layer->SetMasksToBounds(true);
std::unique_ptr<LayerImpl> child =
LayerImpl::Create(host_impl().active_tree(), 456);
Region touch_handler_region(gfx::Rect(0, 0, 300, 300));
position = gfx::PointF(-50.f, -50.f);
bounds = gfx::Size(300, 300);
SetLayerPropertiesForTesting(child.get(), identity_matrix, transform_origin,
position, bounds, true, false, false);
child->SetDrawsContent(true);
child->SetTouchEventHandlerRegion(touch_handler_region);
clipping_layer->AddChild(std::move(child));
surface->AddChild(std::move(clipping_layer));
root->AddChild(std::move(surface));
}
float device_scale_factor = 3.f;
float page_scale_factor = 1.f;
float max_page_scale_factor = 1.f;
gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
root->bounds(), device_scale_factor * page_scale_factor);
host_impl().SetViewportSize(scaled_bounds_for_root);
host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor);
host_impl().active_tree()->SetRootLayer(std::move(root));
host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 1,
Layer::INVALID_ID);
host_impl().active_tree()->BuildPropertyTreesForTesting();
host_impl().active_tree()->PushPageScaleFromMainThread(
page_scale_factor, page_scale_factor, max_page_scale_factor);
host_impl().active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
// Sanity check the scenario we just created.
ASSERT_EQ(2u, RenderSurfaceLayerList().size());
// Hit checking for a point outside the layer should return a null pointer.
// Despite the child layer being very large, it should be clipped to the root
// layer's bounds.
gfx::PointF test_point(24.f, 24.f);
test_point =
gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
LayerImpl* result_layer =
host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
test_point);
EXPECT_FALSE(result_layer);
// Hit checking for a point inside the touch event handler region should
// return the child layer.
test_point = gfx::PointF(25.f, 25.f);
test_point =
gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
result_layer =
host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
test_point);
ASSERT_TRUE(result_layer);
EXPECT_EQ(456, result_layer->id());
}
TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) {
gfx::Transform identity_matrix;
gfx::Point3F transform_origin;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment