1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_impl.h"
7 #include "cc/layers/heads_up_display_layer_impl.h"
8 #include "cc/layers/layer.h"
9 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
10 #include "cc/test/fake_impl_proxy.h"
11 #include "cc/test/fake_layer_tree_host_impl.h"
12 #include "cc/test/fake_output_surface.h"
13 #include "cc/test/geometry_test_utils.h"
14 #include "cc/test/layer_tree_host_common_test.h"
15 #include "cc/test/test_shared_bitmap_manager.h"
16 #include "cc/trees/layer_tree_host_impl.h"
17 #include "ui/gfx/geometry/size_conversions.h"
22 class LayerTreeImplTest
: public LayerTreeHostCommonTest
{
25 LayerTreeSettings settings
;
26 settings
.layer_transforms_should_scale_layer_contents
= true;
27 settings
.scrollbar_show_scale_threshold
= 1.1f
;
29 new FakeLayerTreeHostImpl(settings
, &proxy_
, &shared_bitmap_manager_
));
30 EXPECT_TRUE(host_impl_
->InitializeRenderer(FakeOutputSurface::Create3d()));
33 FakeLayerTreeHostImpl
& host_impl() { return *host_impl_
; }
35 LayerImpl
* root_layer() { return host_impl_
->active_tree()->root_layer(); }
37 const LayerImplList
& RenderSurfaceLayerList() const {
38 return host_impl_
->active_tree()->RenderSurfaceLayerList();
42 TestSharedBitmapManager shared_bitmap_manager_
;
44 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
47 TEST_F(LayerTreeImplTest
, HitTestingForSingleLayer
) {
48 scoped_ptr
<LayerImpl
> root
=
49 LayerImpl::Create(host_impl().active_tree(), 12345);
51 gfx::Transform identity_matrix
;
52 gfx::Point3F transform_origin
;
54 gfx::Size
bounds(100, 100);
55 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
56 position
, bounds
, true, false, true);
57 root
->SetDrawsContent(true);
59 host_impl().SetViewportSize(root
->bounds());
60 host_impl().active_tree()->SetRootLayer(root
.Pass());
61 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
63 // Sanity check the scenario we just created.
64 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
65 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
67 // Hit testing for a point outside the layer should return a null pointer.
68 gfx::Point
test_point(101, 101);
69 LayerImpl
* result_layer
=
70 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
71 EXPECT_FALSE(result_layer
);
73 test_point
= gfx::Point(-1, -1);
75 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
76 EXPECT_FALSE(result_layer
);
78 // Hit testing for a point inside should return the root layer.
79 test_point
= gfx::Point(1, 1);
81 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
82 ASSERT_TRUE(result_layer
);
83 EXPECT_EQ(12345, result_layer
->id());
85 test_point
= gfx::Point(99, 99);
87 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
88 ASSERT_TRUE(result_layer
);
89 EXPECT_EQ(12345, result_layer
->id());
92 TEST_F(LayerTreeImplTest
, HitTestingForSingleLayerAndHud
) {
93 scoped_ptr
<LayerImpl
> root
=
94 LayerImpl::Create(host_impl().active_tree(), 12345);
95 scoped_ptr
<HeadsUpDisplayLayerImpl
> hud
=
96 HeadsUpDisplayLayerImpl::Create(host_impl().active_tree(), 11111);
98 gfx::Transform identity_matrix
;
99 gfx::Point3F transform_origin
;
100 gfx::PointF position
;
101 gfx::Size
bounds(100, 100);
102 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
103 position
, bounds
, true, false, true);
104 root
->SetDrawsContent(true);
106 // Create hud and add it as a child of root.
107 gfx::Size
hud_bounds(200, 200);
108 SetLayerPropertiesForTesting(hud
.get(), identity_matrix
, transform_origin
,
109 position
, hud_bounds
, true, false, false);
110 hud
->SetDrawsContent(true);
112 host_impl().active_tree()->set_hud_layer(hud
.get());
113 root
->AddChild(hud
.Pass());
115 host_impl().SetViewportSize(hud_bounds
);
116 host_impl().active_tree()->SetRootLayer(root
.Pass());
117 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
119 // Sanity check the scenario we just created.
120 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
121 ASSERT_EQ(2u, root_layer()->render_surface()->layer_list().size());
123 // Hit testing for a point inside HUD, but outside root should return null
124 gfx::Point
test_point(101, 101);
125 LayerImpl
* result_layer
=
126 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
127 EXPECT_FALSE(result_layer
);
129 test_point
= gfx::Point(-1, -1);
131 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
132 EXPECT_FALSE(result_layer
);
134 // Hit testing for a point inside should return the root layer, never the HUD
136 test_point
= gfx::Point(1, 1);
138 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
139 ASSERT_TRUE(result_layer
);
140 EXPECT_EQ(12345, result_layer
->id());
142 test_point
= gfx::Point(99, 99);
144 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
145 ASSERT_TRUE(result_layer
);
146 EXPECT_EQ(12345, result_layer
->id());
149 TEST_F(LayerTreeImplTest
, HitTestingForUninvertibleTransform
) {
150 scoped_ptr
<LayerImpl
> root
=
151 LayerImpl::Create(host_impl().active_tree(), 12345);
153 gfx::Transform uninvertible_transform
;
154 uninvertible_transform
.matrix().set(0, 0, 0.0);
155 uninvertible_transform
.matrix().set(1, 1, 0.0);
156 uninvertible_transform
.matrix().set(2, 2, 0.0);
157 uninvertible_transform
.matrix().set(3, 3, 0.0);
158 ASSERT_FALSE(uninvertible_transform
.IsInvertible());
160 gfx::Transform identity_matrix
;
161 gfx::Point3F transform_origin
;
162 gfx::PointF position
;
163 gfx::Size
bounds(100, 100);
164 SetLayerPropertiesForTesting(root
.get(), uninvertible_transform
,
165 transform_origin
, position
, bounds
, true, false,
167 root
->SetDrawsContent(true);
169 host_impl().SetViewportSize(root
->bounds());
170 host_impl().active_tree()->SetRootLayer(root
.Pass());
171 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
172 // Sanity check the scenario we just created.
173 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
174 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
175 ASSERT_FALSE(root_layer()->screen_space_transform().IsInvertible());
177 // Hit testing any point should not hit the layer. If the invertible matrix is
178 // accidentally ignored and treated like an identity, then the hit testing
179 // will incorrectly hit the layer when it shouldn't.
180 gfx::Point
test_point(1, 1);
181 LayerImpl
* result_layer
=
182 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
183 EXPECT_FALSE(result_layer
);
185 test_point
= gfx::Point(10, 10);
187 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
188 EXPECT_FALSE(result_layer
);
190 test_point
= gfx::Point(10, 30);
192 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
193 EXPECT_FALSE(result_layer
);
195 test_point
= gfx::Point(50, 50);
197 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
198 EXPECT_FALSE(result_layer
);
200 test_point
= gfx::Point(67, 48);
202 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
203 EXPECT_FALSE(result_layer
);
205 test_point
= gfx::Point(99, 99);
207 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
208 EXPECT_FALSE(result_layer
);
210 test_point
= gfx::Point(-1, -1);
212 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
213 EXPECT_FALSE(result_layer
);
216 TEST_F(LayerTreeImplTest
, HitTestingForSinglePositionedLayer
) {
217 scoped_ptr
<LayerImpl
> root
=
218 LayerImpl::Create(host_impl().active_tree(), 12345);
220 gfx::Transform identity_matrix
;
221 gfx::Point3F transform_origin
;
222 // this layer is positioned, and hit testing should correctly know where the
224 gfx::PointF
position(50.f
, 50.f
);
225 gfx::Size
bounds(100, 100);
226 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
227 position
, bounds
, true, false, true);
228 root
->SetDrawsContent(true);
230 host_impl().SetViewportSize(root
->bounds());
231 host_impl().active_tree()->SetRootLayer(root
.Pass());
232 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
234 // Sanity check the scenario we just created.
235 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
236 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
238 // Hit testing for a point outside the layer should return a null pointer.
239 gfx::Point
test_point(49, 49);
240 LayerImpl
* result_layer
=
241 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
242 EXPECT_FALSE(result_layer
);
244 // Even though the layer exists at (101, 101), it should not be visible there
245 // since the root render surface would clamp it.
246 test_point
= gfx::Point(101, 101);
248 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
249 EXPECT_FALSE(result_layer
);
251 // Hit testing for a point inside should return the root layer.
252 test_point
= gfx::Point(51, 51);
254 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
255 ASSERT_TRUE(result_layer
);
256 EXPECT_EQ(12345, result_layer
->id());
258 test_point
= gfx::Point(99, 99);
260 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
261 ASSERT_TRUE(result_layer
);
262 EXPECT_EQ(12345, result_layer
->id());
265 TEST_F(LayerTreeImplTest
, HitTestingForSingleRotatedLayer
) {
266 scoped_ptr
<LayerImpl
> root
=
267 LayerImpl::Create(host_impl().active_tree(), 12345);
269 gfx::Transform identity_matrix
;
270 gfx::Transform rotation45_degrees_about_center
;
271 rotation45_degrees_about_center
.Translate(50.0, 50.0);
272 rotation45_degrees_about_center
.RotateAboutZAxis(45.0);
273 rotation45_degrees_about_center
.Translate(-50.0, -50.0);
274 gfx::Point3F transform_origin
;
275 gfx::PointF position
;
276 gfx::Size
bounds(100, 100);
277 SetLayerPropertiesForTesting(root
.get(), rotation45_degrees_about_center
,
278 transform_origin
, position
, bounds
, true, false,
280 root
->SetDrawsContent(true);
282 host_impl().SetViewportSize(root
->bounds());
283 host_impl().active_tree()->SetRootLayer(root
.Pass());
284 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
286 // Sanity check the scenario we just created.
287 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
288 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
290 // Hit testing for points outside the layer.
291 // These corners would have been inside the un-transformed layer, but they
292 // should not hit the correctly transformed layer.
293 gfx::Point
test_point(99, 99);
294 LayerImpl
* result_layer
=
295 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
296 EXPECT_FALSE(result_layer
);
298 test_point
= gfx::Point(1, 1);
300 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
301 EXPECT_FALSE(result_layer
);
303 // Hit testing for a point inside should return the root layer.
304 test_point
= gfx::Point(1, 50);
306 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
307 ASSERT_TRUE(result_layer
);
308 EXPECT_EQ(12345, result_layer
->id());
310 // Hit testing the corners that would overlap the unclipped layer, but are
311 // outside the clipped region.
312 test_point
= gfx::Point(50, -1);
314 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
315 ASSERT_FALSE(result_layer
);
317 test_point
= gfx::Point(-1, 50);
319 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
320 ASSERT_FALSE(result_layer
);
323 TEST_F(LayerTreeImplTest
, HitTestingForSinglePerspectiveLayer
) {
324 scoped_ptr
<LayerImpl
> root
=
325 LayerImpl::Create(host_impl().active_tree(), 12345);
327 gfx::Transform identity_matrix
;
329 // perspective_projection_about_center * translation_by_z is designed so that
330 // the 100 x 100 layer becomes 50 x 50, and remains centered at (50, 50).
331 gfx::Transform perspective_projection_about_center
;
332 perspective_projection_about_center
.Translate(50.0, 50.0);
333 perspective_projection_about_center
.ApplyPerspectiveDepth(1.0);
334 perspective_projection_about_center
.Translate(-50.0, -50.0);
335 gfx::Transform translation_by_z
;
336 translation_by_z
.Translate3d(0.0, 0.0, -1.0);
338 gfx::Point3F transform_origin
;
339 gfx::PointF position
;
340 gfx::Size
bounds(100, 100);
341 SetLayerPropertiesForTesting(
342 root
.get(), perspective_projection_about_center
* translation_by_z
,
343 transform_origin
, position
, bounds
, true, false, true);
344 root
->SetDrawsContent(true);
346 host_impl().SetViewportSize(root
->bounds());
347 host_impl().active_tree()->SetRootLayer(root
.Pass());
348 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
350 // Sanity check the scenario we just created.
351 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
352 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
354 // Hit testing for points outside the layer.
355 // These corners would have been inside the un-transformed layer, but they
356 // should not hit the correctly transformed layer.
357 gfx::Point
test_point(24, 24);
358 LayerImpl
* result_layer
=
359 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
360 EXPECT_FALSE(result_layer
);
362 test_point
= gfx::Point(76, 76);
364 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
365 EXPECT_FALSE(result_layer
);
367 // Hit testing for a point inside should return the root layer.
368 test_point
= gfx::Point(26, 26);
370 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
371 ASSERT_TRUE(result_layer
);
372 EXPECT_EQ(12345, result_layer
->id());
374 test_point
= gfx::Point(74, 74);
376 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
377 ASSERT_TRUE(result_layer
);
378 EXPECT_EQ(12345, result_layer
->id());
381 TEST_F(LayerTreeImplTest
, HitTestingForSingleLayerWithScaledContents
) {
382 // A layer's visible content rect is actually in the layer's content space.
383 // The screen space transform converts from the layer's origin space to screen
384 // space. This test makes sure that hit testing works correctly accounts for
385 // the contents scale. A contents scale that is not 1 effectively forces a
386 // non-identity transform between layer's content space and layer's origin
387 // space. The hit testing code must take this into account.
389 // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
390 // contents scale is ignored, then hit testing will mis-interpret the visible
391 // content rect as being larger than the actual bounds of the layer.
393 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
395 gfx::Transform identity_matrix
;
396 gfx::Point3F transform_origin
;
398 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
399 gfx::PointF(), gfx::Size(100, 100), true, false,
402 gfx::PointF
position(25.f
, 25.f
);
403 gfx::Size
bounds(50, 50);
404 scoped_ptr
<LayerImpl
> test_layer
=
405 LayerImpl::Create(host_impl().active_tree(), 12345);
406 SetLayerPropertiesForTesting(test_layer
.get(), identity_matrix
,
407 transform_origin
, position
, bounds
, true,
410 // override content bounds and contents scale
411 test_layer
->SetContentBounds(gfx::Size(100, 100));
412 test_layer
->SetContentsScale(2, 2);
414 test_layer
->SetDrawsContent(true);
415 root
->AddChild(test_layer
.Pass());
418 host_impl().SetViewportSize(root
->bounds());
419 host_impl().active_tree()->SetRootLayer(root
.Pass());
420 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
422 // Sanity check the scenario we just created.
423 // The visible content rect for test_layer is actually 100x100, even though
424 // its layout size is 50x50, positioned at 25x25.
425 LayerImpl
* test_layer
=
426 host_impl().active_tree()->root_layer()->children()[0];
427 EXPECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer
->visible_content_rect());
428 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
429 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
431 // Hit testing for a point outside the layer should return a null pointer (the
432 // root layer does not draw content, so it will not be hit tested either).
433 gfx::Point
test_point(101, 101);
434 LayerImpl
* result_layer
=
435 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
436 EXPECT_FALSE(result_layer
);
438 test_point
= gfx::Point(24, 24);
440 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
441 EXPECT_FALSE(result_layer
);
443 test_point
= gfx::Point(76, 76);
445 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
446 EXPECT_FALSE(result_layer
);
448 // Hit testing for a point inside should return the test layer.
449 test_point
= gfx::Point(26, 26);
451 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
452 ASSERT_TRUE(result_layer
);
453 EXPECT_EQ(12345, result_layer
->id());
455 test_point
= gfx::Point(74, 74);
457 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
458 ASSERT_TRUE(result_layer
);
459 EXPECT_EQ(12345, result_layer
->id());
462 TEST_F(LayerTreeImplTest
, HitTestingForSimpleClippedLayer
) {
463 // Test that hit-testing will only work for the visible portion of a layer,
464 // and not the entire layer bounds. Here we just test the simple axis-aligned
466 gfx::Transform identity_matrix
;
467 gfx::Point3F transform_origin
;
469 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
470 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
471 gfx::PointF(), gfx::Size(100, 100), true, false,
474 scoped_ptr
<LayerImpl
> clipping_layer
=
475 LayerImpl::Create(host_impl().active_tree(), 123);
476 // this layer is positioned, and hit testing should correctly know where the
478 gfx::PointF
position(25.f
, 25.f
);
479 gfx::Size
bounds(50, 50);
480 SetLayerPropertiesForTesting(clipping_layer
.get(), identity_matrix
,
481 transform_origin
, position
, bounds
, true,
483 clipping_layer
->SetMasksToBounds(true);
485 scoped_ptr
<LayerImpl
> child
=
486 LayerImpl::Create(host_impl().active_tree(), 456);
487 position
= gfx::PointF(-50.f
, -50.f
);
488 bounds
= gfx::Size(300, 300);
489 SetLayerPropertiesForTesting(child
.get(), identity_matrix
, transform_origin
,
490 position
, bounds
, true, false, false);
491 child
->SetDrawsContent(true);
492 clipping_layer
->AddChild(child
.Pass());
493 root
->AddChild(clipping_layer
.Pass());
496 host_impl().SetViewportSize(root
->bounds());
497 host_impl().active_tree()->SetRootLayer(root
.Pass());
498 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
500 // Sanity check the scenario we just created.
501 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
502 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
503 ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
505 // Hit testing for a point outside the layer should return a null pointer.
506 // Despite the child layer being very large, it should be clipped to the root
508 gfx::Point
test_point(24, 24);
509 LayerImpl
* result_layer
=
510 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
511 EXPECT_FALSE(result_layer
);
513 // Even though the layer exists at (101, 101), it should not be visible there
514 // since the clipping_layer would clamp it.
515 test_point
= gfx::Point(76, 76);
517 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
518 EXPECT_FALSE(result_layer
);
520 // Hit testing for a point inside should return the child layer.
521 test_point
= gfx::Point(26, 26);
523 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
524 ASSERT_TRUE(result_layer
);
525 EXPECT_EQ(456, result_layer
->id());
527 test_point
= gfx::Point(74, 74);
529 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
530 ASSERT_TRUE(result_layer
);
531 EXPECT_EQ(456, result_layer
->id());
534 TEST_F(LayerTreeImplTest
, HitTestingForMultiClippedRotatedLayer
) {
535 // This test checks whether hit testing correctly avoids hit testing with
536 // multiple ancestors that clip in non axis-aligned ways. To pass this test,
537 // the hit testing algorithm needs to recognize that multiple parent layers
538 // may clip the layer, and should not actually hit those clipped areas.
540 // The child and grand_child layers are both initialized to clip the
541 // rotated_leaf. The child layer is rotated about the top-left corner, so that
542 // the root + child clips combined create a triangle. The rotated_leaf will
543 // only be visible where it overlaps this triangle.
545 scoped_ptr
<LayerImpl
> root
=
546 LayerImpl::Create(host_impl().active_tree(), 123);
548 gfx::Transform identity_matrix
;
549 gfx::Point3F transform_origin
;
550 gfx::PointF position
;
551 gfx::Size
bounds(100, 100);
552 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
553 position
, bounds
, true, false, true);
554 root
->SetMasksToBounds(true);
556 scoped_ptr
<LayerImpl
> child
=
557 LayerImpl::Create(host_impl().active_tree(), 456);
558 scoped_ptr
<LayerImpl
> grand_child
=
559 LayerImpl::Create(host_impl().active_tree(), 789);
560 scoped_ptr
<LayerImpl
> rotated_leaf
=
561 LayerImpl::Create(host_impl().active_tree(), 2468);
563 position
= gfx::PointF(10.f
, 10.f
);
564 bounds
= gfx::Size(80, 80);
565 SetLayerPropertiesForTesting(child
.get(), identity_matrix
, transform_origin
,
566 position
, bounds
, true, false, false);
567 child
->SetMasksToBounds(true);
569 gfx::Transform rotation45_degrees_about_corner
;
570 rotation45_degrees_about_corner
.RotateAboutZAxis(45.0);
572 // remember, positioned with respect to its parent which is already at 10,
574 position
= gfx::PointF();
576 gfx::Size(200, 200); // to ensure it covers at least sqrt(2) * 100.
577 SetLayerPropertiesForTesting(
578 grand_child
.get(), rotation45_degrees_about_corner
, transform_origin
,
579 position
, bounds
, true, false, false);
580 grand_child
->SetMasksToBounds(true);
582 // Rotates about the center of the layer
583 gfx::Transform rotated_leaf_transform
;
584 rotated_leaf_transform
.Translate(
585 -10.0, -10.0); // cancel out the grand_parent's position
586 rotated_leaf_transform
.RotateAboutZAxis(
587 -45.0); // cancel out the corner 45-degree rotation of the parent.
588 rotated_leaf_transform
.Translate(50.0, 50.0);
589 rotated_leaf_transform
.RotateAboutZAxis(45.0);
590 rotated_leaf_transform
.Translate(-50.0, -50.0);
591 position
= gfx::PointF();
592 bounds
= gfx::Size(100, 100);
593 SetLayerPropertiesForTesting(rotated_leaf
.get(), rotated_leaf_transform
,
594 transform_origin
, position
, bounds
, true,
596 rotated_leaf
->SetDrawsContent(true);
598 grand_child
->AddChild(rotated_leaf
.Pass());
599 child
->AddChild(grand_child
.Pass());
600 root
->AddChild(child
.Pass());
603 host_impl().SetViewportSize(root
->bounds());
604 host_impl().active_tree()->SetRootLayer(root
.Pass());
605 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
607 // (11, 89) is close to the the bottom left corner within the clip, but it is
608 // not inside the layer.
609 gfx::Point
test_point(11, 89);
610 LayerImpl
* result_layer
=
611 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
612 EXPECT_FALSE(result_layer
);
614 // Closer inwards from the bottom left will overlap the layer.
615 test_point
= gfx::Point(25, 75);
617 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
618 ASSERT_TRUE(result_layer
);
619 EXPECT_EQ(2468, result_layer
->id());
621 // (4, 50) is inside the unclipped layer, but that corner of the layer should
622 // be clipped away by the grandparent and should not get hit. If hit testing
623 // blindly uses visible content rect without considering how parent may clip
624 // the layer, then hit testing would accidentally think that the point
625 // successfully hits the layer.
626 test_point
= gfx::Point(4, 50);
628 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
629 EXPECT_FALSE(result_layer
);
631 // (11, 50) is inside the layer and within the clipped area.
632 test_point
= gfx::Point(11, 50);
634 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
635 ASSERT_TRUE(result_layer
);
636 EXPECT_EQ(2468, result_layer
->id());
638 // Around the middle, just to the right and up, would have hit the layer
639 // except that that area should be clipped away by the parent.
640 test_point
= gfx::Point(51, 49);
642 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
643 EXPECT_FALSE(result_layer
);
645 // Around the middle, just to the left and down, should successfully hit the
647 test_point
= gfx::Point(49, 51);
649 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
650 ASSERT_TRUE(result_layer
);
651 EXPECT_EQ(2468, result_layer
->id());
654 TEST_F(LayerTreeImplTest
, HitTestingForNonClippingIntermediateLayer
) {
655 // This test checks that hit testing code does not accidentally clip to layer
656 // bounds for a layer that actually does not clip.
657 gfx::Transform identity_matrix
;
658 gfx::Point3F transform_origin
;
660 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
661 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
662 gfx::PointF(), gfx::Size(100, 100), true, false,
665 scoped_ptr
<LayerImpl
> intermediate_layer
=
666 LayerImpl::Create(host_impl().active_tree(), 123);
667 // this layer is positioned, and hit testing should correctly know where the
669 gfx::PointF
position(10.f
, 10.f
);
670 gfx::Size
bounds(50, 50);
671 SetLayerPropertiesForTesting(intermediate_layer
.get(), identity_matrix
,
672 transform_origin
, position
, bounds
, true,
674 // Sanity check the intermediate layer should not clip.
675 ASSERT_FALSE(intermediate_layer
->masks_to_bounds());
676 ASSERT_FALSE(intermediate_layer
->mask_layer());
678 // The child of the intermediate_layer is translated so that it does not
679 // overlap intermediate_layer at all. If child is incorrectly clipped, we
680 // would not be able to hit it successfully.
681 scoped_ptr
<LayerImpl
> child
=
682 LayerImpl::Create(host_impl().active_tree(), 456);
683 position
= gfx::PointF(60.f
, 60.f
); // 70, 70 in screen space
684 bounds
= gfx::Size(20, 20);
685 SetLayerPropertiesForTesting(child
.get(), identity_matrix
, transform_origin
,
686 position
, bounds
, true, false, false);
687 child
->SetDrawsContent(true);
688 intermediate_layer
->AddChild(child
.Pass());
689 root
->AddChild(intermediate_layer
.Pass());
692 host_impl().SetViewportSize(root
->bounds());
693 host_impl().active_tree()->SetRootLayer(root
.Pass());
694 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
696 // Sanity check the scenario we just created.
697 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
698 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
699 ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
701 // Hit testing for a point outside the layer should return a null pointer.
702 gfx::Point
test_point(69, 69);
703 LayerImpl
* result_layer
=
704 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
705 EXPECT_FALSE(result_layer
);
707 test_point
= gfx::Point(91, 91);
709 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
710 EXPECT_FALSE(result_layer
);
712 // Hit testing for a point inside should return the child layer.
713 test_point
= gfx::Point(71, 71);
715 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
716 ASSERT_TRUE(result_layer
);
717 EXPECT_EQ(456, result_layer
->id());
719 test_point
= gfx::Point(89, 89);
721 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
722 ASSERT_TRUE(result_layer
);
723 EXPECT_EQ(456, result_layer
->id());
726 TEST_F(LayerTreeImplTest
, HitTestingForMultipleLayers
) {
727 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
729 gfx::Transform identity_matrix
;
730 gfx::Point3F transform_origin
;
731 gfx::PointF position
;
732 gfx::Size
bounds(100, 100);
733 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
734 position
, bounds
, true, false, true);
735 root
->SetDrawsContent(true);
737 // child 1 and child2 are initialized to overlap between x=50 and x=60.
738 // grand_child is set to overlap both child1 and child2 between y=50 and
739 // y=60. The expected stacking order is: (front) child2, (second)
740 // grand_child, (third) child1, and (back) the root layer behind all other
743 scoped_ptr
<LayerImpl
> child1
=
744 LayerImpl::Create(host_impl().active_tree(), 2);
745 scoped_ptr
<LayerImpl
> child2
=
746 LayerImpl::Create(host_impl().active_tree(), 3);
747 scoped_ptr
<LayerImpl
> grand_child1
=
748 LayerImpl::Create(host_impl().active_tree(), 4);
750 position
= gfx::PointF(10.f
, 10.f
);
751 bounds
= gfx::Size(50, 50);
752 SetLayerPropertiesForTesting(child1
.get(), identity_matrix
,
753 transform_origin
, position
, bounds
, true,
755 child1
->SetDrawsContent(true);
757 position
= gfx::PointF(50.f
, 10.f
);
758 bounds
= gfx::Size(50, 50);
759 SetLayerPropertiesForTesting(child2
.get(), identity_matrix
,
760 transform_origin
, position
, bounds
, true,
762 child2
->SetDrawsContent(true);
764 // Remember that grand_child is positioned with respect to its parent (i.e.
765 // child1). In screen space, the intended position is (10, 50), with size
767 position
= gfx::PointF(0.f
, 40.f
);
768 bounds
= gfx::Size(100, 50);
769 SetLayerPropertiesForTesting(grand_child1
.get(), identity_matrix
,
770 transform_origin
, position
, bounds
, true,
772 grand_child1
->SetDrawsContent(true);
774 child1
->AddChild(grand_child1
.Pass());
775 root
->AddChild(child1
.Pass());
776 root
->AddChild(child2
.Pass());
779 LayerImpl
* child1
= root
->children()[0];
780 LayerImpl
* child2
= root
->children()[1];
781 LayerImpl
* grand_child1
= child1
->children()[0];
783 host_impl().SetViewportSize(root
->bounds());
784 host_impl().active_tree()->SetRootLayer(root
.Pass());
785 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
787 // Sanity check the scenario we just created.
790 ASSERT_TRUE(grand_child1
);
791 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
793 RenderSurfaceImpl
* root_render_surface
= root_layer()->render_surface();
794 ASSERT_EQ(4u, root_render_surface
->layer_list().size());
795 ASSERT_EQ(1, root_render_surface
->layer_list().at(0)->id()); // root layer
796 ASSERT_EQ(2, root_render_surface
->layer_list().at(1)->id()); // child1
797 ASSERT_EQ(4, root_render_surface
->layer_list().at(2)->id()); // grand_child1
798 ASSERT_EQ(3, root_render_surface
->layer_list().at(3)->id()); // child2
800 // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
802 gfx::Point test_point
= gfx::Point(1, 1);
803 LayerImpl
* result_layer
=
804 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
805 ASSERT_TRUE(result_layer
);
806 EXPECT_EQ(1, result_layer
->id());
808 // At (15, 15), child1 and root are the only layers. child1 is expected to be
810 test_point
= gfx::Point(15, 15);
812 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
813 ASSERT_TRUE(result_layer
);
814 EXPECT_EQ(2, result_layer
->id());
816 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
817 test_point
= gfx::Point(51, 20);
819 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
820 ASSERT_TRUE(result_layer
);
821 EXPECT_EQ(3, result_layer
->id());
823 // At (80, 51), child2 and grand_child1 overlap. child2 is expected to be on
825 test_point
= gfx::Point(80, 51);
827 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
828 ASSERT_TRUE(result_layer
);
829 EXPECT_EQ(3, result_layer
->id());
831 // At (51, 51), all layers overlap each other. child2 is expected to be on top
832 // of all other layers.
833 test_point
= gfx::Point(51, 51);
835 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
836 ASSERT_TRUE(result_layer
);
837 EXPECT_EQ(3, result_layer
->id());
839 // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
841 test_point
= gfx::Point(20, 51);
843 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
844 ASSERT_TRUE(result_layer
);
845 EXPECT_EQ(4, result_layer
->id());
848 TEST_F(LayerTreeImplTest
, HitTestingForMultipleLayersAtVaryingDepths
) {
849 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
851 gfx::Transform identity_matrix
;
852 gfx::Point3F transform_origin
;
853 gfx::PointF position
;
854 gfx::Size
bounds(100, 100);
855 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
856 position
, bounds
, true, false, true);
857 root
->SetDrawsContent(true);
858 root
->SetShouldFlattenTransform(false);
859 root
->Set3dSortingContextId(1);
861 // child 1 and child2 are initialized to overlap between x=50 and x=60.
862 // grand_child is set to overlap both child1 and child2 between y=50 and
863 // y=60. The expected stacking order is: (front) child2, (second)
864 // grand_child, (third) child1, and (back) the root layer behind all other
867 scoped_ptr
<LayerImpl
> child1
=
868 LayerImpl::Create(host_impl().active_tree(), 2);
869 scoped_ptr
<LayerImpl
> child2
=
870 LayerImpl::Create(host_impl().active_tree(), 3);
871 scoped_ptr
<LayerImpl
> grand_child1
=
872 LayerImpl::Create(host_impl().active_tree(), 4);
874 position
= gfx::PointF(10.f
, 10.f
);
875 bounds
= gfx::Size(50, 50);
876 SetLayerPropertiesForTesting(child1
.get(), identity_matrix
,
877 transform_origin
, position
, bounds
, true,
879 child1
->SetDrawsContent(true);
880 child1
->SetShouldFlattenTransform(false);
881 child1
->Set3dSortingContextId(1);
883 position
= gfx::PointF(50.f
, 10.f
);
884 bounds
= gfx::Size(50, 50);
885 gfx::Transform translate_z
;
886 translate_z
.Translate3d(0, 0, -10.f
);
887 SetLayerPropertiesForTesting(child2
.get(), translate_z
, transform_origin
,
888 position
, bounds
, true, false, false);
889 child2
->SetDrawsContent(true);
890 child2
->SetShouldFlattenTransform(false);
891 child2
->Set3dSortingContextId(1);
893 // Remember that grand_child is positioned with respect to its parent (i.e.
894 // child1). In screen space, the intended position is (10, 50), with size
896 position
= gfx::PointF(0.f
, 40.f
);
897 bounds
= gfx::Size(100, 50);
898 SetLayerPropertiesForTesting(grand_child1
.get(), identity_matrix
,
899 transform_origin
, position
, bounds
, true,
901 grand_child1
->SetDrawsContent(true);
902 grand_child1
->SetShouldFlattenTransform(false);
904 child1
->AddChild(grand_child1
.Pass());
905 root
->AddChild(child1
.Pass());
906 root
->AddChild(child2
.Pass());
909 LayerImpl
* child1
= root
->children()[0];
910 LayerImpl
* child2
= root
->children()[1];
911 LayerImpl
* grand_child1
= child1
->children()[0];
913 host_impl().SetViewportSize(root
->bounds());
914 host_impl().active_tree()->SetRootLayer(root
.Pass());
915 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
917 // Sanity check the scenario we just created.
920 ASSERT_TRUE(grand_child1
);
921 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
923 RenderSurfaceImpl
* root_render_surface
=
924 host_impl().active_tree()->root_layer()->render_surface();
925 ASSERT_EQ(4u, root_render_surface
->layer_list().size());
926 ASSERT_EQ(3, root_render_surface
->layer_list().at(0)->id());
927 ASSERT_EQ(1, root_render_surface
->layer_list().at(1)->id());
928 ASSERT_EQ(2, root_render_surface
->layer_list().at(2)->id());
929 ASSERT_EQ(4, root_render_surface
->layer_list().at(3)->id());
931 // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
933 gfx::Point test_point
= gfx::Point(1, 1);
934 LayerImpl
* result_layer
=
935 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
936 ASSERT_TRUE(result_layer
);
937 EXPECT_EQ(1, result_layer
->id());
939 // At (15, 15), child1 and root are the only layers. child1 is expected to be
941 test_point
= gfx::Point(15, 15);
943 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
944 ASSERT_TRUE(result_layer
);
945 EXPECT_EQ(2, result_layer
->id());
947 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
948 // (because 3 is transformed to the back).
949 test_point
= gfx::Point(51, 20);
951 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
952 ASSERT_TRUE(result_layer
);
953 EXPECT_EQ(2, result_layer
->id());
955 // 3 Would have been on top if it hadn't been transformed to the background.
956 // Make sure that it isn't hit.
957 test_point
= gfx::Point(80, 51);
959 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
960 ASSERT_TRUE(result_layer
);
961 EXPECT_EQ(4, result_layer
->id());
963 // 3 Would have been on top if it hadn't been transformed to the background.
964 // Make sure that it isn't hit.
965 test_point
= gfx::Point(51, 51);
967 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
968 ASSERT_TRUE(result_layer
);
969 EXPECT_EQ(4, result_layer
->id());
971 // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
973 test_point
= gfx::Point(20, 51);
975 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
976 ASSERT_TRUE(result_layer
);
977 EXPECT_EQ(4, result_layer
->id());
980 TEST_F(LayerTreeImplTest
, HitTestingRespectsClipParents
) {
981 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
982 gfx::Transform identity_matrix
;
983 gfx::Point3F transform_origin
;
984 gfx::PointF position
;
985 gfx::Size
bounds(100, 100);
986 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
987 position
, bounds
, true, false, true);
988 root
->SetDrawsContent(true);
990 scoped_ptr
<LayerImpl
> child
=
991 LayerImpl::Create(host_impl().active_tree(), 2);
992 scoped_ptr
<LayerImpl
> grand_child
=
993 LayerImpl::Create(host_impl().active_tree(), 4);
995 position
= gfx::PointF(10.f
, 10.f
);
996 bounds
= gfx::Size(1, 1);
997 SetLayerPropertiesForTesting(child
.get(), identity_matrix
, transform_origin
,
998 position
, bounds
, true, false, false);
999 child
->SetDrawsContent(true);
1000 child
->SetMasksToBounds(true);
1002 position
= gfx::PointF(0.f
, 40.f
);
1003 bounds
= gfx::Size(100, 50);
1004 SetLayerPropertiesForTesting(grand_child
.get(), identity_matrix
,
1005 transform_origin
, position
, bounds
, true,
1007 grand_child
->SetDrawsContent(true);
1008 grand_child
->SetHasRenderSurface(true);
1010 // This should let |grand_child| "escape" |child|'s clip.
1011 grand_child
->SetClipParent(root
.get());
1013 child
->AddChild(grand_child
.Pass());
1014 root
->AddChild(child
.Pass());
1017 host_impl().SetViewportSize(root
->bounds());
1018 host_impl().active_tree()->SetRootLayer(root
.Pass());
1019 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1021 gfx::Point test_point
= gfx::Point(12, 52);
1022 LayerImpl
* result_layer
=
1023 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1024 ASSERT_TRUE(result_layer
);
1025 EXPECT_EQ(4, result_layer
->id());
1028 TEST_F(LayerTreeImplTest
, HitTestingRespectsScrollParents
) {
1029 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
1030 gfx::Transform identity_matrix
;
1031 gfx::Point3F transform_origin
;
1032 gfx::PointF position
;
1033 gfx::Size
bounds(100, 100);
1034 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1035 position
, bounds
, true, false, true);
1036 root
->SetDrawsContent(true);
1038 scoped_ptr
<LayerImpl
> child
=
1039 LayerImpl::Create(host_impl().active_tree(), 2);
1040 scoped_ptr
<LayerImpl
> scroll_child
=
1041 LayerImpl::Create(host_impl().active_tree(), 3);
1042 scoped_ptr
<LayerImpl
> grand_child
=
1043 LayerImpl::Create(host_impl().active_tree(), 4);
1045 position
= gfx::PointF(10.f
, 10.f
);
1046 bounds
= gfx::Size(1, 1);
1047 SetLayerPropertiesForTesting(child
.get(), identity_matrix
, transform_origin
,
1048 position
, bounds
, true, false, false);
1049 child
->SetDrawsContent(true);
1050 child
->SetMasksToBounds(true);
1052 position
= gfx::PointF();
1053 bounds
= gfx::Size(200, 200);
1054 SetLayerPropertiesForTesting(scroll_child
.get(), identity_matrix
,
1055 transform_origin
, position
, bounds
, true,
1057 scroll_child
->SetDrawsContent(true);
1059 // This should cause scroll child and its descendants to be affected by
1061 scroll_child
->SetScrollParent(child
.get());
1063 SetLayerPropertiesForTesting(grand_child
.get(), identity_matrix
,
1064 transform_origin
, position
, bounds
, true,
1066 grand_child
->SetDrawsContent(true);
1067 grand_child
->SetHasRenderSurface(true);
1069 scroll_child
->AddChild(grand_child
.Pass());
1070 root
->AddChild(scroll_child
.Pass());
1071 root
->AddChild(child
.Pass());
1074 host_impl().SetViewportSize(root
->bounds());
1075 host_impl().active_tree()->SetRootLayer(root
.Pass());
1076 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1078 gfx::Point test_point
= gfx::Point(12, 52);
1079 LayerImpl
* result_layer
=
1080 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1081 // The |test_point| should have been clipped away by |child|, the scroll
1082 // parent, so the only thing that should be hit is |root|.
1083 ASSERT_TRUE(result_layer
);
1084 ASSERT_EQ(1, result_layer
->id());
1086 TEST_F(LayerTreeImplTest
, HitTestingForMultipleLayerLists
) {
1088 // The geometry is set up similarly to the previous case, but
1089 // all layers are forced to be render surfaces now.
1091 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
1093 gfx::Transform identity_matrix
;
1094 gfx::Point3F transform_origin
;
1095 gfx::PointF position
;
1096 gfx::Size
bounds(100, 100);
1097 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1098 position
, bounds
, true, false, true);
1099 root
->SetDrawsContent(true);
1101 // child 1 and child2 are initialized to overlap between x=50 and x=60.
1102 // grand_child is set to overlap both child1 and child2 between y=50 and
1103 // y=60. The expected stacking order is: (front) child2, (second)
1104 // grand_child, (third) child1, and (back) the root layer behind all other
1107 scoped_ptr
<LayerImpl
> child1
=
1108 LayerImpl::Create(host_impl().active_tree(), 2);
1109 scoped_ptr
<LayerImpl
> child2
=
1110 LayerImpl::Create(host_impl().active_tree(), 3);
1111 scoped_ptr
<LayerImpl
> grand_child1
=
1112 LayerImpl::Create(host_impl().active_tree(), 4);
1114 position
= gfx::PointF(10.f
, 10.f
);
1115 bounds
= gfx::Size(50, 50);
1116 SetLayerPropertiesForTesting(child1
.get(), identity_matrix
,
1117 transform_origin
, position
, bounds
, true,
1119 child1
->SetDrawsContent(true);
1120 child1
->SetHasRenderSurface(true);
1122 position
= gfx::PointF(50.f
, 10.f
);
1123 bounds
= gfx::Size(50, 50);
1124 SetLayerPropertiesForTesting(child2
.get(), identity_matrix
,
1125 transform_origin
, position
, bounds
, true,
1127 child2
->SetDrawsContent(true);
1128 child2
->SetHasRenderSurface(true);
1130 // Remember that grand_child is positioned with respect to its parent (i.e.
1131 // child1). In screen space, the intended position is (10, 50), with size
1133 position
= gfx::PointF(0.f
, 40.f
);
1134 bounds
= gfx::Size(100, 50);
1135 SetLayerPropertiesForTesting(grand_child1
.get(), identity_matrix
,
1136 transform_origin
, position
, bounds
, true,
1138 grand_child1
->SetDrawsContent(true);
1139 grand_child1
->SetHasRenderSurface(true);
1141 child1
->AddChild(grand_child1
.Pass());
1142 root
->AddChild(child1
.Pass());
1143 root
->AddChild(child2
.Pass());
1146 LayerImpl
* child1
= root
->children()[0];
1147 LayerImpl
* child2
= root
->children()[1];
1148 LayerImpl
* grand_child1
= child1
->children()[0];
1150 host_impl().SetViewportSize(root
->bounds());
1151 host_impl().active_tree()->SetRootLayer(root
.Pass());
1152 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1154 // Sanity check the scenario we just created.
1155 ASSERT_TRUE(child1
);
1156 ASSERT_TRUE(child2
);
1157 ASSERT_TRUE(grand_child1
);
1158 ASSERT_TRUE(child1
->render_surface());
1159 ASSERT_TRUE(child2
->render_surface());
1160 ASSERT_TRUE(grand_child1
->render_surface());
1161 ASSERT_EQ(4u, RenderSurfaceLayerList().size());
1162 // The root surface has the root layer, and child1's and child2's render
1164 ASSERT_EQ(3u, root_layer()->render_surface()->layer_list().size());
1165 // The child1 surface has the child1 layer and grand_child1's render surface.
1166 ASSERT_EQ(2u, child1
->render_surface()->layer_list().size());
1167 ASSERT_EQ(1u, child2
->render_surface()->layer_list().size());
1168 ASSERT_EQ(1u, grand_child1
->render_surface()->layer_list().size());
1169 ASSERT_EQ(1, RenderSurfaceLayerList().at(0)->id()); // root layer
1170 ASSERT_EQ(2, RenderSurfaceLayerList()[1]->id()); // child1
1171 ASSERT_EQ(4, RenderSurfaceLayerList().at(2)->id()); // grand_child1
1172 ASSERT_EQ(3, RenderSurfaceLayerList()[3]->id()); // child2
1174 // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
1176 gfx::Point test_point
= gfx::Point(1, 1);
1177 LayerImpl
* result_layer
=
1178 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1179 ASSERT_TRUE(result_layer
);
1180 EXPECT_EQ(1, result_layer
->id());
1182 // At (15, 15), child1 and root are the only layers. child1 is expected to be
1184 test_point
= gfx::Point(15, 15);
1186 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1187 ASSERT_TRUE(result_layer
);
1188 EXPECT_EQ(2, result_layer
->id());
1190 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
1191 test_point
= gfx::Point(51, 20);
1193 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1194 ASSERT_TRUE(result_layer
);
1195 EXPECT_EQ(3, result_layer
->id());
1197 // At (80, 51), child2 and grand_child1 overlap. child2 is expected to be on
1199 test_point
= gfx::Point(80, 51);
1201 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1202 ASSERT_TRUE(result_layer
);
1203 EXPECT_EQ(3, result_layer
->id());
1205 // At (51, 51), all layers overlap each other. child2 is expected to be on top
1206 // of all other layers.
1207 test_point
= gfx::Point(51, 51);
1209 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1210 ASSERT_TRUE(result_layer
);
1211 EXPECT_EQ(3, result_layer
->id());
1213 // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
1215 test_point
= gfx::Point(20, 51);
1217 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point
);
1218 ASSERT_TRUE(result_layer
);
1219 EXPECT_EQ(4, result_layer
->id());
1222 TEST_F(LayerTreeImplTest
, HitCheckingTouchHandlerRegionsForSingleLayer
) {
1223 scoped_ptr
<LayerImpl
> root
=
1224 LayerImpl::Create(host_impl().active_tree(), 12345);
1226 gfx::Transform identity_matrix
;
1227 Region
touch_handler_region(gfx::Rect(10, 10, 50, 50));
1228 gfx::Point3F transform_origin
;
1229 gfx::PointF position
;
1230 gfx::Size
bounds(100, 100);
1231 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1232 position
, bounds
, true, false, true);
1233 root
->SetDrawsContent(true);
1235 host_impl().SetViewportSize(root
->bounds());
1236 host_impl().active_tree()->SetRootLayer(root
.Pass());
1237 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1239 // Sanity check the scenario we just created.
1240 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1241 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1243 // Hit checking for any point should return a null pointer for a layer without
1244 // any touch event handler regions.
1245 gfx::Point
test_point(11, 11);
1246 LayerImpl
* result_layer
=
1247 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1249 EXPECT_FALSE(result_layer
);
1251 host_impl().active_tree()->root_layer()->SetTouchEventHandlerRegion(
1252 touch_handler_region
);
1253 // Hit checking for a point outside the layer should return a null pointer.
1254 test_point
= gfx::Point(101, 101);
1256 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1258 EXPECT_FALSE(result_layer
);
1260 test_point
= gfx::Point(-1, -1);
1262 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1264 EXPECT_FALSE(result_layer
);
1266 // Hit checking for a point inside the layer, but outside the touch handler
1267 // region should return a null pointer.
1268 test_point
= gfx::Point(1, 1);
1270 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1272 EXPECT_FALSE(result_layer
);
1274 test_point
= gfx::Point(99, 99);
1276 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1278 EXPECT_FALSE(result_layer
);
1280 // Hit checking for a point inside the touch event handler region should
1281 // return the root layer.
1282 test_point
= gfx::Point(11, 11);
1284 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1286 ASSERT_TRUE(result_layer
);
1287 EXPECT_EQ(12345, result_layer
->id());
1289 test_point
= gfx::Point(59, 59);
1291 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1293 ASSERT_TRUE(result_layer
);
1294 EXPECT_EQ(12345, result_layer
->id());
1297 TEST_F(LayerTreeImplTest
,
1298 HitCheckingTouchHandlerRegionsForUninvertibleTransform
) {
1299 scoped_ptr
<LayerImpl
> root
=
1300 LayerImpl::Create(host_impl().active_tree(), 12345);
1302 gfx::Transform uninvertible_transform
;
1303 uninvertible_transform
.matrix().set(0, 0, 0.0);
1304 uninvertible_transform
.matrix().set(1, 1, 0.0);
1305 uninvertible_transform
.matrix().set(2, 2, 0.0);
1306 uninvertible_transform
.matrix().set(3, 3, 0.0);
1307 ASSERT_FALSE(uninvertible_transform
.IsInvertible());
1309 gfx::Transform identity_matrix
;
1310 Region
touch_handler_region(gfx::Rect(10, 10, 50, 50));
1311 gfx::Point3F transform_origin
;
1312 gfx::PointF position
;
1313 gfx::Size
bounds(100, 100);
1314 SetLayerPropertiesForTesting(root
.get(), uninvertible_transform
,
1315 transform_origin
, position
, bounds
, true, false,
1317 root
->SetDrawsContent(true);
1318 root
->SetTouchEventHandlerRegion(touch_handler_region
);
1320 host_impl().SetViewportSize(root
->bounds());
1321 host_impl().active_tree()->SetRootLayer(root
.Pass());
1322 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1324 // Sanity check the scenario we just created.
1325 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1326 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1327 ASSERT_FALSE(root_layer()->screen_space_transform().IsInvertible());
1329 // Hit checking any point should not hit the touch handler region on the
1330 // layer. If the invertible matrix is accidentally ignored and treated like an
1331 // identity, then the hit testing will incorrectly hit the layer when it
1333 gfx::Point
test_point(1, 1);
1334 LayerImpl
* result_layer
=
1335 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1337 EXPECT_FALSE(result_layer
);
1339 test_point
= gfx::Point(10, 10);
1341 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1343 EXPECT_FALSE(result_layer
);
1345 test_point
= gfx::Point(10, 30);
1347 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1349 EXPECT_FALSE(result_layer
);
1351 test_point
= gfx::Point(50, 50);
1353 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1355 EXPECT_FALSE(result_layer
);
1357 test_point
= gfx::Point(67, 48);
1359 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1361 EXPECT_FALSE(result_layer
);
1363 test_point
= gfx::Point(99, 99);
1365 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1367 EXPECT_FALSE(result_layer
);
1369 test_point
= gfx::Point(-1, -1);
1371 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1373 EXPECT_FALSE(result_layer
);
1376 TEST_F(LayerTreeImplTest
, MakeScrollbarsInvisibleNearMinPageScale
) {
1377 const int kThumbThickness
= 10;
1378 const int kTrackStart
= 0;
1379 const bool kIsLeftSideVerticalScrollbar
= false;
1380 const bool kIsOverlayScrollbar
= true;
1382 LayerTreeImpl
* active_tree
= host_impl().active_tree();
1384 scoped_ptr
<LayerImpl
> scroll_layer
= LayerImpl::Create(active_tree
, 1);
1385 scoped_ptr
<SolidColorScrollbarLayerImpl
> vertical_scrollbar_layer
=
1386 SolidColorScrollbarLayerImpl::Create(active_tree
,
1391 kIsLeftSideVerticalScrollbar
,
1392 kIsOverlayScrollbar
);
1393 scoped_ptr
<SolidColorScrollbarLayerImpl
> horizontal_scrollbar_layer
=
1394 SolidColorScrollbarLayerImpl::Create(active_tree
,
1399 kIsLeftSideVerticalScrollbar
,
1400 kIsOverlayScrollbar
);
1402 scoped_ptr
<LayerImpl
> clip_layer
= LayerImpl::Create(active_tree
, 4);
1403 scoped_ptr
<LayerImpl
> page_scale_layer
= LayerImpl::Create(active_tree
, 5);
1405 scroll_layer
->SetScrollClipLayer(clip_layer
->id());
1407 LayerImpl
* scroll_layer_ptr
= scroll_layer
.get();
1408 LayerImpl
* page_scale_layer_ptr
= page_scale_layer
.get();
1410 clip_layer
->AddChild(page_scale_layer
.Pass());
1411 page_scale_layer_ptr
->AddChild(scroll_layer
.Pass());
1413 vertical_scrollbar_layer
->SetScrollLayerAndClipLayerByIds(
1414 scroll_layer_ptr
->id(),
1416 horizontal_scrollbar_layer
->SetScrollLayerAndClipLayerByIds(
1417 scroll_layer_ptr
->id(),
1420 active_tree
->PushPageScaleFromMainThread(1.0f
, 1.0f
, 4.0f
);
1421 active_tree
->SetViewportLayersFromIds(
1422 Layer::INVALID_ID
, // Overscroll
1423 page_scale_layer_ptr
->id(),
1424 scroll_layer_ptr
->id(),
1425 Layer::INVALID_ID
); // Outer Scroll
1427 EXPECT_TRUE(vertical_scrollbar_layer
->hide_layer_and_subtree());
1428 EXPECT_TRUE(horizontal_scrollbar_layer
->hide_layer_and_subtree());
1430 active_tree
->PushPageScaleFromMainThread(1.05f
, 1.0f
, 4.0f
);
1431 EXPECT_TRUE(vertical_scrollbar_layer
->hide_layer_and_subtree());
1432 EXPECT_TRUE(horizontal_scrollbar_layer
->hide_layer_and_subtree());
1434 active_tree
->PushPageScaleFromMainThread(1.1f
, 1.0f
, 4.0f
);
1435 EXPECT_FALSE(vertical_scrollbar_layer
->hide_layer_and_subtree());
1436 EXPECT_FALSE(horizontal_scrollbar_layer
->hide_layer_and_subtree());
1438 active_tree
->PushPageScaleFromMainThread(1.5f
, 1.0f
, 4.0f
);
1439 EXPECT_FALSE(vertical_scrollbar_layer
->hide_layer_and_subtree());
1440 EXPECT_FALSE(horizontal_scrollbar_layer
->hide_layer_and_subtree());
1443 TEST_F(LayerTreeImplTest
,
1444 HitCheckingTouchHandlerRegionsForSinglePositionedLayer
) {
1445 scoped_ptr
<LayerImpl
> root
=
1446 LayerImpl::Create(host_impl().active_tree(), 12345);
1448 gfx::Transform identity_matrix
;
1449 Region
touch_handler_region(gfx::Rect(10, 10, 50, 50));
1450 gfx::Point3F transform_origin
;
1451 // this layer is positioned, and hit testing should correctly know where the
1452 // layer is located.
1453 gfx::PointF
position(50.f
, 50.f
);
1454 gfx::Size
bounds(100, 100);
1455 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1456 position
, bounds
, true, false, true);
1457 root
->SetDrawsContent(true);
1458 root
->SetTouchEventHandlerRegion(touch_handler_region
);
1460 host_impl().SetViewportSize(root
->bounds());
1461 host_impl().active_tree()->SetRootLayer(root
.Pass());
1462 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1464 // Sanity check the scenario we just created.
1465 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1466 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1468 // Hit checking for a point outside the layer should return a null pointer.
1469 gfx::Point
test_point(49, 49);
1470 LayerImpl
* result_layer
=
1471 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1473 EXPECT_FALSE(result_layer
);
1475 // Even though the layer has a touch handler region containing (101, 101), it
1476 // should not be visible there since the root render surface would clamp it.
1477 test_point
= gfx::Point(101, 101);
1479 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1481 EXPECT_FALSE(result_layer
);
1483 // Hit checking for a point inside the layer, but outside the touch handler
1484 // region should return a null pointer.
1485 test_point
= gfx::Point(51, 51);
1487 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1489 EXPECT_FALSE(result_layer
);
1491 // Hit checking for a point inside the touch event handler region should
1492 // return the root layer.
1493 test_point
= gfx::Point(61, 61);
1495 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1497 ASSERT_TRUE(result_layer
);
1498 EXPECT_EQ(12345, result_layer
->id());
1500 test_point
= gfx::Point(99, 99);
1502 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1504 ASSERT_TRUE(result_layer
);
1505 EXPECT_EQ(12345, result_layer
->id());
1508 TEST_F(LayerTreeImplTest
,
1509 HitCheckingTouchHandlerRegionsForSingleLayerWithScaledContents
) {
1510 // A layer's visible content rect is actually in the layer's content space.
1511 // The screen space transform converts from the layer's origin space to screen
1512 // space. This test makes sure that hit testing works correctly accounts for
1513 // the contents scale. A contents scale that is not 1 effectively forces a
1514 // non-identity transform between layer's content space and layer's origin
1515 // space. The hit testing code must take this into account.
1517 // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
1518 // contents scale is ignored, then hit checking will mis-interpret the visible
1519 // content rect as being larger than the actual bounds of the layer.
1521 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
1523 gfx::Transform identity_matrix
;
1524 gfx::Point3F transform_origin
;
1526 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1527 gfx::PointF(), gfx::Size(100, 100), true, false,
1530 Region
touch_handler_region(gfx::Rect(10, 10, 30, 30));
1531 gfx::PointF
position(25.f
, 25.f
);
1532 gfx::Size
bounds(50, 50);
1533 scoped_ptr
<LayerImpl
> test_layer
=
1534 LayerImpl::Create(host_impl().active_tree(), 12345);
1535 SetLayerPropertiesForTesting(test_layer
.get(), identity_matrix
,
1536 transform_origin
, position
, bounds
, true,
1539 // override content bounds and contents scale
1540 test_layer
->SetContentBounds(gfx::Size(100, 100));
1541 test_layer
->SetContentsScale(2, 2);
1543 test_layer
->SetDrawsContent(true);
1544 test_layer
->SetTouchEventHandlerRegion(touch_handler_region
);
1545 root
->AddChild(test_layer
.Pass());
1548 host_impl().SetViewportSize(root
->bounds());
1549 host_impl().active_tree()->SetRootLayer(root
.Pass());
1550 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1552 // Sanity check the scenario we just created.
1553 // The visible content rect for test_layer is actually 100x100, even though
1554 // its layout size is 50x50, positioned at 25x25.
1555 LayerImpl
* test_layer
=
1556 host_impl().active_tree()->root_layer()->children()[0];
1557 EXPECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer
->visible_content_rect());
1558 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1559 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1561 // Hit checking for a point outside the layer should return a null pointer
1562 // (the root layer does not draw content, so it will not be tested either).
1563 gfx::Point
test_point(76, 76);
1564 LayerImpl
* result_layer
=
1565 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1567 EXPECT_FALSE(result_layer
);
1569 // Hit checking for a point inside the layer, but outside the touch handler
1570 // region should return a null pointer.
1571 test_point
= gfx::Point(26, 26);
1573 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1575 EXPECT_FALSE(result_layer
);
1577 test_point
= gfx::Point(34, 34);
1579 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1581 EXPECT_FALSE(result_layer
);
1583 test_point
= gfx::Point(65, 65);
1585 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1587 EXPECT_FALSE(result_layer
);
1589 test_point
= gfx::Point(74, 74);
1591 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1593 EXPECT_FALSE(result_layer
);
1595 // Hit checking for a point inside the touch event handler region should
1596 // return the root layer.
1597 test_point
= gfx::Point(35, 35);
1599 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1601 ASSERT_TRUE(result_layer
);
1602 EXPECT_EQ(12345, result_layer
->id());
1604 test_point
= gfx::Point(64, 64);
1606 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1608 ASSERT_TRUE(result_layer
);
1609 EXPECT_EQ(12345, result_layer
->id());
1612 TEST_F(LayerTreeImplTest
,
1613 HitCheckingTouchHandlerRegionsForSingleLayerWithDeviceScale
) {
1614 // The layer's device_scale_factor and page_scale_factor should scale the
1615 // content rect and we should be able to hit the touch handler region by
1616 // scaling the points accordingly.
1617 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
1619 gfx::Transform identity_matrix
;
1620 gfx::Point3F transform_origin
;
1621 // Set the bounds of the root layer big enough to fit the child when scaled.
1622 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1623 gfx::PointF(), gfx::Size(100, 100), true, false,
1626 Region
touch_handler_region(gfx::Rect(10, 10, 30, 30));
1627 gfx::PointF
position(25.f
, 25.f
);
1628 gfx::Size
bounds(50, 50);
1629 scoped_ptr
<LayerImpl
> test_layer
=
1630 LayerImpl::Create(host_impl().active_tree(), 12345);
1631 SetLayerPropertiesForTesting(test_layer
.get(), identity_matrix
,
1632 transform_origin
, position
, bounds
, true,
1635 test_layer
->SetDrawsContent(true);
1636 test_layer
->SetTouchEventHandlerRegion(touch_handler_region
);
1637 root
->AddChild(test_layer
.Pass());
1640 float device_scale_factor
= 3.f
;
1641 float page_scale_factor
= 5.f
;
1642 gfx::Size scaled_bounds_for_root
= gfx::ToCeiledSize(
1643 gfx::ScaleSize(root
->bounds(), device_scale_factor
* page_scale_factor
));
1644 host_impl().SetViewportSize(scaled_bounds_for_root
);
1646 host_impl().SetDeviceScaleFactor(device_scale_factor
);
1647 host_impl().active_tree()->PushPageScaleFromMainThread(
1648 page_scale_factor
, page_scale_factor
, page_scale_factor
);
1649 host_impl().SetPageScaleOnActiveTree(page_scale_factor
);
1650 host_impl().active_tree()->SetRootLayer(root
.Pass());
1651 host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 1,
1653 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1655 // Sanity check the scenario we just created.
1656 // The visible content rect for test_layer is actually 100x100, even though
1657 // its layout size is 50x50, positioned at 25x25.
1658 LayerImpl
* test_layer
=
1659 host_impl().active_tree()->root_layer()->children()[0];
1660 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1661 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1663 // Check whether the child layer fits into the root after scaled.
1664 EXPECT_EQ(gfx::Rect(test_layer
->content_bounds()),
1665 test_layer
->visible_content_rect());
1667 // Hit checking for a point outside the layer should return a null pointer
1668 // (the root layer does not draw content, so it will not be tested either).
1669 gfx::PointF
test_point(76.f
, 76.f
);
1671 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1672 LayerImpl
* result_layer
=
1673 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1675 EXPECT_FALSE(result_layer
);
1677 // Hit checking for a point inside the layer, but outside the touch handler
1678 // region should return a null pointer.
1679 test_point
= gfx::Point(26, 26);
1681 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1683 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1685 EXPECT_FALSE(result_layer
);
1687 test_point
= gfx::Point(34, 34);
1689 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1691 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1693 EXPECT_FALSE(result_layer
);
1695 test_point
= gfx::Point(65, 65);
1697 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1699 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1701 EXPECT_FALSE(result_layer
);
1703 test_point
= gfx::Point(74, 74);
1705 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1707 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1709 EXPECT_FALSE(result_layer
);
1711 // Hit checking for a point inside the touch event handler region should
1712 // return the root layer.
1713 test_point
= gfx::Point(35, 35);
1715 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1717 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1719 ASSERT_TRUE(result_layer
);
1720 EXPECT_EQ(12345, result_layer
->id());
1722 test_point
= gfx::Point(64, 64);
1724 gfx::ScalePoint(test_point
, device_scale_factor
* page_scale_factor
);
1726 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1728 ASSERT_TRUE(result_layer
);
1729 EXPECT_EQ(12345, result_layer
->id());
1732 TEST_F(LayerTreeImplTest
, HitCheckingTouchHandlerRegionsForSimpleClippedLayer
) {
1733 // Test that hit-checking will only work for the visible portion of a layer,
1734 // and not the entire layer bounds. Here we just test the simple axis-aligned
1736 gfx::Transform identity_matrix
;
1737 gfx::Point3F transform_origin
;
1739 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
1740 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1741 gfx::PointF(), gfx::Size(100, 100), true, false,
1744 scoped_ptr
<LayerImpl
> clipping_layer
=
1745 LayerImpl::Create(host_impl().active_tree(), 123);
1746 // this layer is positioned, and hit testing should correctly know where the
1747 // layer is located.
1748 gfx::PointF
position(25.f
, 25.f
);
1749 gfx::Size
bounds(50, 50);
1750 SetLayerPropertiesForTesting(clipping_layer
.get(), identity_matrix
,
1751 transform_origin
, position
, bounds
, true,
1753 clipping_layer
->SetMasksToBounds(true);
1755 scoped_ptr
<LayerImpl
> child
=
1756 LayerImpl::Create(host_impl().active_tree(), 456);
1757 Region
touch_handler_region(gfx::Rect(10, 10, 50, 50));
1758 position
= gfx::PointF(-50.f
, -50.f
);
1759 bounds
= gfx::Size(300, 300);
1760 SetLayerPropertiesForTesting(child
.get(), identity_matrix
, transform_origin
,
1761 position
, bounds
, true, false, false);
1762 child
->SetDrawsContent(true);
1763 child
->SetTouchEventHandlerRegion(touch_handler_region
);
1764 clipping_layer
->AddChild(child
.Pass());
1765 root
->AddChild(clipping_layer
.Pass());
1768 host_impl().SetViewportSize(root
->bounds());
1769 host_impl().active_tree()->SetRootLayer(root
.Pass());
1770 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1772 // Sanity check the scenario we just created.
1773 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1774 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1775 ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
1777 // Hit checking for a point outside the layer should return a null pointer.
1778 // Despite the child layer being very large, it should be clipped to the root
1780 gfx::Point
test_point(24, 24);
1781 LayerImpl
* result_layer
=
1782 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1784 EXPECT_FALSE(result_layer
);
1786 // Hit checking for a point inside the layer, but outside the touch handler
1787 // region should return a null pointer.
1788 test_point
= gfx::Point(35, 35);
1790 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1792 EXPECT_FALSE(result_layer
);
1794 test_point
= gfx::Point(74, 74);
1796 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1798 EXPECT_FALSE(result_layer
);
1800 // Hit checking for a point inside the touch event handler region should
1801 // return the root layer.
1802 test_point
= gfx::Point(25, 25);
1804 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1806 ASSERT_TRUE(result_layer
);
1807 EXPECT_EQ(456, result_layer
->id());
1809 test_point
= gfx::Point(34, 34);
1811 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1813 ASSERT_TRUE(result_layer
);
1814 EXPECT_EQ(456, result_layer
->id());
1817 TEST_F(LayerTreeImplTest
, HitCheckingTouchHandlerOverlappingRegions
) {
1818 gfx::Transform identity_matrix
;
1819 gfx::Point3F transform_origin
;
1821 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
1822 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1823 gfx::PointF(), gfx::Size(100, 100), true, false,
1826 scoped_ptr
<LayerImpl
> touch_layer
=
1827 LayerImpl::Create(host_impl().active_tree(), 123);
1828 // this layer is positioned, and hit testing should correctly know where the
1829 // layer is located.
1830 gfx::PointF position
;
1831 gfx::Size
bounds(50, 50);
1832 SetLayerPropertiesForTesting(touch_layer
.get(), identity_matrix
,
1833 transform_origin
, position
, bounds
, true,
1835 touch_layer
->SetDrawsContent(true);
1836 touch_layer
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50));
1837 root
->AddChild(touch_layer
.Pass());
1841 scoped_ptr
<LayerImpl
> notouch_layer
=
1842 LayerImpl::Create(host_impl().active_tree(), 1234);
1843 // this layer is positioned, and hit testing should correctly know where the
1844 // layer is located.
1845 gfx::PointF
position(0, 25);
1846 gfx::Size
bounds(50, 50);
1847 SetLayerPropertiesForTesting(notouch_layer
.get(), identity_matrix
,
1848 transform_origin
, position
, bounds
, true,
1850 notouch_layer
->SetDrawsContent(true);
1851 root
->AddChild(notouch_layer
.Pass());
1854 host_impl().SetViewportSize(root
->bounds());
1855 host_impl().active_tree()->SetRootLayer(root
.Pass());
1856 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1858 // Sanity check the scenario we just created.
1859 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1860 ASSERT_EQ(2u, root_layer()->render_surface()->layer_list().size());
1861 ASSERT_EQ(123, root_layer()->render_surface()->layer_list().at(0)->id());
1862 ASSERT_EQ(1234, root_layer()->render_surface()->layer_list().at(1)->id());
1864 gfx::Point
test_point(35, 35);
1865 LayerImpl
* result_layer
=
1866 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1869 // We should have passed through the no-touch layer and found the layer
1871 EXPECT_TRUE(result_layer
);
1873 host_impl().active_tree()->LayerById(1234)->SetContentsOpaque(true);
1875 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1878 // Even with an opaque layer in the middle, we should still find the layer
1880 // the touch handler behind it (since we can't assume that opaque layers are
1881 // opaque to hit testing).
1882 EXPECT_TRUE(result_layer
);
1884 test_point
= gfx::Point(35, 15);
1886 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1888 ASSERT_TRUE(result_layer
);
1889 EXPECT_EQ(123, result_layer
->id());
1891 test_point
= gfx::Point(35, 65);
1893 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1895 EXPECT_FALSE(result_layer
);
1898 TEST_F(LayerTreeImplTest
, SelectionBoundsForSingleLayer
) {
1899 int root_layer_id
= 12345;
1900 scoped_ptr
<LayerImpl
> root
=
1901 LayerImpl::Create(host_impl().active_tree(), root_layer_id
);
1903 gfx::Transform identity_matrix
;
1904 gfx::Point3F transform_origin
;
1905 gfx::PointF position
;
1906 gfx::Size
bounds(100, 100);
1907 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1908 position
, bounds
, true, false, true);
1909 root
->SetDrawsContent(true);
1911 host_impl().SetViewportSize(root
->bounds());
1912 host_impl().active_tree()->SetRootLayer(root
.Pass());
1913 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1915 // Sanity check the scenario we just created.
1916 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1917 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1919 LayerSelectionBound left_input
;
1920 left_input
.type
= SELECTION_BOUND_LEFT
;
1921 left_input
.edge_top
= gfx::PointF(10, 10);
1922 left_input
.edge_bottom
= gfx::PointF(10, 20);
1923 left_input
.layer_id
= root_layer_id
;
1925 LayerSelectionBound right_input
;
1926 right_input
.type
= SELECTION_BOUND_RIGHT
;
1927 right_input
.edge_top
= gfx::PointF(50, 10);
1928 right_input
.edge_bottom
= gfx::PointF(50, 30);
1929 right_input
.layer_id
= root_layer_id
;
1931 ViewportSelectionBound left_output
, right_output
;
1933 // Empty input bounds should produce empty output bounds.
1934 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
1935 EXPECT_EQ(ViewportSelectionBound(), left_output
);
1936 EXPECT_EQ(ViewportSelectionBound(), right_output
);
1938 // Selection bounds should produce distinct left and right bounds.
1939 host_impl().active_tree()->RegisterSelection(left_input
, right_input
);
1940 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
1941 EXPECT_EQ(left_input
.type
, left_output
.type
);
1942 EXPECT_EQ(left_input
.edge_bottom
, left_output
.edge_bottom
);
1943 EXPECT_EQ(left_input
.edge_top
, left_output
.edge_top
);
1944 EXPECT_TRUE(left_output
.visible
);
1945 EXPECT_EQ(right_input
.type
, right_output
.type
);
1946 EXPECT_EQ(right_input
.edge_bottom
, right_output
.edge_bottom
);
1947 EXPECT_EQ(right_input
.edge_top
, right_output
.edge_top
);
1948 EXPECT_TRUE(right_output
.visible
);
1950 // Insertion bounds should produce identical left and right bounds.
1951 LayerSelectionBound insertion_input
;
1952 insertion_input
.type
= SELECTION_BOUND_CENTER
;
1953 insertion_input
.edge_top
= gfx::PointF(15, 10);
1954 insertion_input
.edge_bottom
= gfx::PointF(15, 30);
1955 insertion_input
.layer_id
= root_layer_id
;
1956 host_impl().active_tree()->RegisterSelection(insertion_input
,
1957 LayerSelectionBound());
1958 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
1959 EXPECT_EQ(insertion_input
.type
, left_output
.type
);
1960 EXPECT_EQ(insertion_input
.edge_bottom
, left_output
.edge_bottom
);
1961 EXPECT_EQ(insertion_input
.edge_top
, left_output
.edge_top
);
1962 EXPECT_TRUE(left_output
.visible
);
1963 EXPECT_EQ(left_output
, right_output
);
1966 TEST_F(LayerTreeImplTest
, SelectionBoundsForPartialOccludedLayers
) {
1967 int root_layer_id
= 12345;
1968 int clip_layer_id
= 1234;
1969 int clipped_layer_id
= 123;
1970 scoped_ptr
<LayerImpl
> root
=
1971 LayerImpl::Create(host_impl().active_tree(), root_layer_id
);
1972 root
->SetDrawsContent(true);
1974 gfx::Transform identity_matrix
;
1975 gfx::Point3F transform_origin
;
1976 gfx::PointF position
;
1977 gfx::Size
bounds(100, 100);
1978 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
1979 position
, bounds
, true, false, true);
1981 gfx::Vector2dF
clipping_offset(10, 10);
1983 scoped_ptr
<LayerImpl
> clipping_layer
=
1984 LayerImpl::Create(host_impl().active_tree(), clip_layer_id
);
1985 // The clipping layer should occlude the right selection bound.
1986 gfx::PointF position
= gfx::PointF() + clipping_offset
;
1987 gfx::Size
bounds(50, 50);
1988 SetLayerPropertiesForTesting(clipping_layer
.get(), identity_matrix
,
1989 transform_origin
, position
, bounds
, true,
1991 clipping_layer
->SetMasksToBounds(true);
1993 scoped_ptr
<LayerImpl
> clipped_layer
=
1994 LayerImpl::Create(host_impl().active_tree(), clipped_layer_id
);
1995 position
= gfx::PointF();
1996 bounds
= gfx::Size(100, 100);
1997 SetLayerPropertiesForTesting(clipped_layer
.get(), identity_matrix
,
1998 transform_origin
, position
, bounds
, true,
2000 clipped_layer
->SetDrawsContent(true);
2001 clipping_layer
->AddChild(clipped_layer
.Pass());
2002 root
->AddChild(clipping_layer
.Pass());
2005 host_impl().SetViewportSize(root
->bounds());
2006 host_impl().active_tree()->SetRootLayer(root
.Pass());
2007 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
2009 // Sanity check the scenario we just created.
2010 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
2012 LayerSelectionBound left_input
;
2013 left_input
.type
= SELECTION_BOUND_LEFT
;
2014 left_input
.edge_top
= gfx::PointF(25, 10);
2015 left_input
.edge_bottom
= gfx::PointF(25, 30);
2016 left_input
.layer_id
= clipped_layer_id
;
2018 LayerSelectionBound right_input
;
2019 right_input
.type
= SELECTION_BOUND_RIGHT
;
2020 right_input
.edge_top
= gfx::PointF(75, 10);
2021 right_input
.edge_bottom
= gfx::PointF(75, 30);
2022 right_input
.layer_id
= clipped_layer_id
;
2023 host_impl().active_tree()->RegisterSelection(left_input
, right_input
);
2025 // The left bound should be occluded by the clip layer.
2026 ViewportSelectionBound left_output
, right_output
;
2027 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
2028 EXPECT_EQ(left_input
.type
, left_output
.type
);
2029 gfx::PointF expected_left_output_top
= left_input
.edge_top
;
2030 gfx::PointF expected_left_output_bottom
= left_input
.edge_bottom
;
2031 expected_left_output_top
.Offset(clipping_offset
.x(), clipping_offset
.y());
2032 expected_left_output_bottom
.Offset(clipping_offset
.x(), clipping_offset
.y());
2033 EXPECT_EQ(expected_left_output_top
, left_output
.edge_top
);
2034 EXPECT_EQ(expected_left_output_bottom
, left_output
.edge_bottom
);
2035 EXPECT_TRUE(left_output
.visible
);
2036 EXPECT_EQ(right_input
.type
, right_output
.type
);
2037 gfx::PointF expected_right_output_top
= right_input
.edge_top
;
2038 gfx::PointF expected_right_output_bottom
= right_input
.edge_bottom
;
2039 expected_right_output_bottom
.Offset(clipping_offset
.x(), clipping_offset
.y());
2040 expected_right_output_top
.Offset(clipping_offset
.x(), clipping_offset
.y());
2041 EXPECT_EQ(expected_right_output_top
, right_output
.edge_top
);
2042 EXPECT_EQ(expected_right_output_bottom
, right_output
.edge_bottom
);
2043 EXPECT_FALSE(right_output
.visible
);
2045 // Handles outside the viewport bounds should be marked invisible.
2046 left_input
.edge_top
= gfx::PointF(-25, 0);
2047 left_input
.edge_bottom
= gfx::PointF(-25, 20);
2048 host_impl().active_tree()->RegisterSelection(left_input
, right_input
);
2049 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
2050 EXPECT_FALSE(left_output
.visible
);
2052 left_input
.edge_top
= gfx::PointF(0, -25);
2053 left_input
.edge_bottom
= gfx::PointF(0, -5);
2054 host_impl().active_tree()->RegisterSelection(left_input
, right_input
);
2055 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
2056 EXPECT_FALSE(left_output
.visible
);
2058 // If the handle bottom is partially visible, the handle is marked visible.
2059 left_input
.edge_top
= gfx::PointF(0, -20);
2060 left_input
.edge_bottom
= gfx::PointF(0, 1);
2061 host_impl().active_tree()->RegisterSelection(left_input
, right_input
);
2062 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
2063 EXPECT_TRUE(left_output
.visible
);
2066 TEST_F(LayerTreeImplTest
, SelectionBoundsForScaledLayers
) {
2067 int root_layer_id
= 1;
2068 int sub_layer_id
= 2;
2069 scoped_ptr
<LayerImpl
> root
=
2070 LayerImpl::Create(host_impl().active_tree(), root_layer_id
);
2071 root
->SetDrawsContent(true);
2073 gfx::Transform identity_matrix
;
2074 gfx::Point3F transform_origin
;
2075 gfx::PointF position
;
2076 gfx::Size
bounds(100, 100);
2077 SetLayerPropertiesForTesting(root
.get(), identity_matrix
, transform_origin
,
2078 position
, bounds
, true, false, true);
2080 gfx::Vector2dF
sub_layer_offset(10, 0);
2082 scoped_ptr
<LayerImpl
> sub_layer
=
2083 LayerImpl::Create(host_impl().active_tree(), sub_layer_id
);
2084 gfx::PointF position
= gfx::PointF() + sub_layer_offset
;
2085 gfx::Size
bounds(50, 50);
2086 SetLayerPropertiesForTesting(sub_layer
.get(), identity_matrix
,
2087 transform_origin
, position
, bounds
, true,
2089 sub_layer
->SetDrawsContent(true);
2090 root
->AddChild(sub_layer
.Pass());
2093 float device_scale_factor
= 3.f
;
2094 float page_scale_factor
= 5.f
;
2095 gfx::Size scaled_bounds_for_root
= gfx::ToCeiledSize(
2096 gfx::ScaleSize(root
->bounds(), device_scale_factor
* page_scale_factor
));
2097 host_impl().SetViewportSize(scaled_bounds_for_root
);
2099 host_impl().SetDeviceScaleFactor(device_scale_factor
);
2100 host_impl().active_tree()->PushPageScaleFromMainThread(
2101 page_scale_factor
, page_scale_factor
, page_scale_factor
);
2102 host_impl().SetPageScaleOnActiveTree(page_scale_factor
);
2103 host_impl().active_tree()->SetRootLayer(root
.Pass());
2104 host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 1,
2106 host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
2108 // Sanity check the scenario we just created.
2109 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
2111 LayerSelectionBound left_input
;
2112 left_input
.type
= SELECTION_BOUND_LEFT
;
2113 left_input
.edge_top
= gfx::PointF(10, 10);
2114 left_input
.edge_bottom
= gfx::PointF(10, 30);
2115 left_input
.layer_id
= root_layer_id
;
2117 LayerSelectionBound right_input
;
2118 right_input
.type
= SELECTION_BOUND_RIGHT
;
2119 right_input
.edge_top
= gfx::PointF(0, 0);
2120 right_input
.edge_bottom
= gfx::PointF(0, 20);
2121 right_input
.layer_id
= sub_layer_id
;
2122 host_impl().active_tree()->RegisterSelection(left_input
, right_input
);
2124 // The viewport bounds should be properly scaled by the page scale, but should
2125 // remain in DIP coordinates.
2126 ViewportSelectionBound left_output
, right_output
;
2127 host_impl().active_tree()->GetViewportSelection(&left_output
, &right_output
);
2128 EXPECT_EQ(left_input
.type
, left_output
.type
);
2129 gfx::PointF expected_left_output_top
= left_input
.edge_top
;
2130 gfx::PointF expected_left_output_bottom
= left_input
.edge_bottom
;
2131 expected_left_output_top
.Scale(page_scale_factor
);
2132 expected_left_output_bottom
.Scale(page_scale_factor
);
2133 EXPECT_EQ(left_input
.edge_top
, left_output
.edge_top
);
2134 EXPECT_EQ(left_input
.edge_bottom
, left_output
.edge_bottom
);
2135 EXPECT_TRUE(left_output
.visible
);
2136 EXPECT_EQ(right_input
.type
, right_output
.type
);
2138 gfx::PointF expected_right_output_top
= right_input
.edge_top
;
2139 gfx::PointF expected_right_output_bottom
= right_input
.edge_bottom
;
2140 expected_right_output_top
.Offset(sub_layer_offset
.x(), sub_layer_offset
.y());
2141 expected_right_output_bottom
.Offset(sub_layer_offset
.x(),
2142 sub_layer_offset
.y());
2143 expected_right_output_top
.Scale(page_scale_factor
);
2144 expected_right_output_bottom
.Scale(page_scale_factor
);
2145 EXPECT_EQ(expected_right_output_top
, right_output
.edge_top
);
2146 EXPECT_EQ(expected_right_output_bottom
, right_output
.edge_bottom
);
2147 EXPECT_TRUE(right_output
.visible
);
2150 TEST_F(LayerTreeImplTest
, NumLayersTestOne
) {
2151 EXPECT_EQ(0u, host_impl().active_tree()->NumLayers());
2152 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
2153 EXPECT_EQ(1u, host_impl().active_tree()->NumLayers());
2156 TEST_F(LayerTreeImplTest
, NumLayersSmallTree
) {
2157 EXPECT_EQ(0u, host_impl().active_tree()->NumLayers());
2158 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl().active_tree(), 1);
2159 root
->AddChild(LayerImpl::Create(host_impl().active_tree(), 2));
2160 root
->AddChild(LayerImpl::Create(host_impl().active_tree(), 3));
2161 root
->child_at(1)->AddChild(LayerImpl::Create(host_impl().active_tree(), 4));
2162 EXPECT_EQ(4u, host_impl().active_tree()->NumLayers());