Factor out a BluetoothChannelMac base class and a BluetoothRfcommChannelMac subclass.
[chromium-blink-merge.git] / cc / trees / layer_tree_impl_unittest.cc
blob8db2b9567c4ec679ebd77751b54fdcd326c7d3ec
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/test/fake_impl_proxy.h"
10 #include "cc/test/fake_layer_tree_host_impl.h"
11 #include "cc/test/fake_output_surface.h"
12 #include "cc/test/geometry_test_utils.h"
13 #include "cc/test/layer_tree_host_common_test.h"
14 #include "cc/test/test_shared_bitmap_manager.h"
15 #include "cc/trees/layer_tree_host_impl.h"
16 #include "ui/gfx/size_conversions.h"
18 namespace cc {
19 namespace {
21 class LayerTreeImplTest : public LayerTreeHostCommonTest {
22 public:
23 LayerTreeImplTest() {
24 LayerTreeSettings settings;
25 settings.layer_transforms_should_scale_layer_contents = true;
26 host_impl_.reset(
27 new FakeLayerTreeHostImpl(settings, &proxy_, &shared_bitmap_manager_));
28 EXPECT_TRUE(host_impl_->InitializeRenderer(
29 FakeOutputSurface::Create3d().PassAs<OutputSurface>()));
32 FakeLayerTreeHostImpl& host_impl() { return *host_impl_; }
34 LayerImpl* root_layer() { return host_impl_->active_tree()->root_layer(); }
36 const LayerImplList& RenderSurfaceLayerList() const {
37 return host_impl_->active_tree()->RenderSurfaceLayerList();
40 private:
41 TestSharedBitmapManager shared_bitmap_manager_;
42 FakeImplProxy proxy_;
43 scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
46 TEST_F(LayerTreeImplTest, HitTestingForSingleLayer) {
47 scoped_ptr<LayerImpl> root =
48 LayerImpl::Create(host_impl().active_tree(), 12345);
50 gfx::Transform identity_matrix;
51 gfx::Point3F transform_origin;
52 gfx::PointF position;
53 gfx::Size bounds(100, 100);
54 SetLayerPropertiesForTesting(root.get(),
55 identity_matrix,
56 transform_origin,
57 position,
58 bounds,
59 true,
60 false);
61 root->SetDrawsContent(true);
63 host_impl().SetViewportSize(root->bounds());
64 host_impl().active_tree()->SetRootLayer(root.Pass());
65 host_impl().active_tree()->UpdateDrawProperties();
67 // Sanity check the scenario we just created.
68 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
69 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
71 // Hit testing for a point outside the layer should return a null pointer.
72 gfx::Point test_point(101, 101);
73 LayerImpl* result_layer =
74 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
75 EXPECT_FALSE(result_layer);
77 test_point = gfx::Point(-1, -1);
78 result_layer =
79 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
80 EXPECT_FALSE(result_layer);
82 // Hit testing for a point inside should return the root layer.
83 test_point = gfx::Point(1, 1);
84 result_layer =
85 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
86 ASSERT_TRUE(result_layer);
87 EXPECT_EQ(12345, result_layer->id());
89 test_point = gfx::Point(99, 99);
90 result_layer =
91 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
92 ASSERT_TRUE(result_layer);
93 EXPECT_EQ(12345, result_layer->id());
96 TEST_F(LayerTreeImplTest, HitTestingForSingleLayerAndHud) {
97 scoped_ptr<LayerImpl> root =
98 LayerImpl::Create(host_impl().active_tree(), 12345);
99 scoped_ptr<HeadsUpDisplayLayerImpl> hud =
100 HeadsUpDisplayLayerImpl::Create(host_impl().active_tree(), 11111);
102 gfx::Transform identity_matrix;
103 gfx::Point3F transform_origin;
104 gfx::PointF position;
105 gfx::Size bounds(100, 100);
106 SetLayerPropertiesForTesting(root.get(),
107 identity_matrix,
108 transform_origin,
109 position,
110 bounds,
111 true,
112 false);
113 root->SetDrawsContent(true);
115 // Create hud and add it as a child of root.
116 gfx::Size hud_bounds(200, 200);
117 SetLayerPropertiesForTesting(hud.get(),
118 identity_matrix,
119 transform_origin,
120 position,
121 hud_bounds,
122 true,
123 false);
124 hud->SetDrawsContent(true);
126 host_impl().active_tree()->set_hud_layer(hud.get());
127 root->AddChild(hud.PassAs<LayerImpl>());
129 host_impl().SetViewportSize(hud_bounds);
130 host_impl().active_tree()->SetRootLayer(root.Pass());
131 host_impl().active_tree()->UpdateDrawProperties();
133 // Sanity check the scenario we just created.
134 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
135 ASSERT_EQ(2u, root_layer()->render_surface()->layer_list().size());
137 // Hit testing for a point inside HUD, but outside root should return null
138 gfx::Point test_point(101, 101);
139 LayerImpl* result_layer =
140 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
141 EXPECT_FALSE(result_layer);
143 test_point = gfx::Point(-1, -1);
144 result_layer =
145 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
146 EXPECT_FALSE(result_layer);
148 // Hit testing for a point inside should return the root layer, never the HUD
149 // layer.
150 test_point = gfx::Point(1, 1);
151 result_layer =
152 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
153 ASSERT_TRUE(result_layer);
154 EXPECT_EQ(12345, result_layer->id());
156 test_point = gfx::Point(99, 99);
157 result_layer =
158 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
159 ASSERT_TRUE(result_layer);
160 EXPECT_EQ(12345, result_layer->id());
163 TEST_F(LayerTreeImplTest, HitTestingForUninvertibleTransform) {
164 scoped_ptr<LayerImpl> root =
165 LayerImpl::Create(host_impl().active_tree(), 12345);
167 gfx::Transform uninvertible_transform;
168 uninvertible_transform.matrix().set(0, 0, 0.0);
169 uninvertible_transform.matrix().set(1, 1, 0.0);
170 uninvertible_transform.matrix().set(2, 2, 0.0);
171 uninvertible_transform.matrix().set(3, 3, 0.0);
172 ASSERT_FALSE(uninvertible_transform.IsInvertible());
174 gfx::Transform identity_matrix;
175 gfx::Point3F transform_origin;
176 gfx::PointF position;
177 gfx::Size bounds(100, 100);
178 SetLayerPropertiesForTesting(root.get(),
179 uninvertible_transform,
180 transform_origin,
181 position,
182 bounds,
183 true,
184 false);
185 root->SetDrawsContent(true);
187 host_impl().SetViewportSize(root->bounds());
188 host_impl().active_tree()->SetRootLayer(root.Pass());
189 host_impl().active_tree()->UpdateDrawProperties();
190 // Sanity check the scenario we just created.
191 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
192 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
193 ASSERT_FALSE(root_layer()->screen_space_transform().IsInvertible());
195 // Hit testing any point should not hit the layer. If the invertible matrix is
196 // accidentally ignored and treated like an identity, then the hit testing
197 // will incorrectly hit the layer when it shouldn't.
198 gfx::Point test_point(1, 1);
199 LayerImpl* result_layer =
200 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
201 EXPECT_FALSE(result_layer);
203 test_point = gfx::Point(10, 10);
204 result_layer =
205 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
206 EXPECT_FALSE(result_layer);
208 test_point = gfx::Point(10, 30);
209 result_layer =
210 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
211 EXPECT_FALSE(result_layer);
213 test_point = gfx::Point(50, 50);
214 result_layer =
215 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
216 EXPECT_FALSE(result_layer);
218 test_point = gfx::Point(67, 48);
219 result_layer =
220 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
221 EXPECT_FALSE(result_layer);
223 test_point = gfx::Point(99, 99);
224 result_layer =
225 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
226 EXPECT_FALSE(result_layer);
228 test_point = gfx::Point(-1, -1);
229 result_layer =
230 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
231 EXPECT_FALSE(result_layer);
234 TEST_F(LayerTreeImplTest, HitTestingForSinglePositionedLayer) {
235 scoped_ptr<LayerImpl> root =
236 LayerImpl::Create(host_impl().active_tree(), 12345);
238 gfx::Transform identity_matrix;
239 gfx::Point3F transform_origin;
240 // this layer is positioned, and hit testing should correctly know where the
241 // layer is located.
242 gfx::PointF position(50.f, 50.f);
243 gfx::Size bounds(100, 100);
244 SetLayerPropertiesForTesting(root.get(),
245 identity_matrix,
246 transform_origin,
247 position,
248 bounds,
249 true,
250 false);
251 root->SetDrawsContent(true);
253 host_impl().SetViewportSize(root->bounds());
254 host_impl().active_tree()->SetRootLayer(root.Pass());
255 host_impl().active_tree()->UpdateDrawProperties();
257 // Sanity check the scenario we just created.
258 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
259 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
261 // Hit testing for a point outside the layer should return a null pointer.
262 gfx::Point test_point(49, 49);
263 LayerImpl* result_layer =
264 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
265 EXPECT_FALSE(result_layer);
267 // Even though the layer exists at (101, 101), it should not be visible there
268 // since the root render surface would clamp it.
269 test_point = gfx::Point(101, 101);
270 result_layer =
271 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
272 EXPECT_FALSE(result_layer);
274 // Hit testing for a point inside should return the root layer.
275 test_point = gfx::Point(51, 51);
276 result_layer =
277 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
278 ASSERT_TRUE(result_layer);
279 EXPECT_EQ(12345, result_layer->id());
281 test_point = gfx::Point(99, 99);
282 result_layer =
283 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
284 ASSERT_TRUE(result_layer);
285 EXPECT_EQ(12345, result_layer->id());
288 TEST_F(LayerTreeImplTest, HitTestingForSingleRotatedLayer) {
289 scoped_ptr<LayerImpl> root =
290 LayerImpl::Create(host_impl().active_tree(), 12345);
292 gfx::Transform identity_matrix;
293 gfx::Transform rotation45_degrees_about_center;
294 rotation45_degrees_about_center.Translate(50.0, 50.0);
295 rotation45_degrees_about_center.RotateAboutZAxis(45.0);
296 rotation45_degrees_about_center.Translate(-50.0, -50.0);
297 gfx::Point3F transform_origin;
298 gfx::PointF position;
299 gfx::Size bounds(100, 100);
300 SetLayerPropertiesForTesting(root.get(),
301 rotation45_degrees_about_center,
302 transform_origin,
303 position,
304 bounds,
305 true,
306 false);
307 root->SetDrawsContent(true);
309 host_impl().SetViewportSize(root->bounds());
310 host_impl().active_tree()->SetRootLayer(root.Pass());
311 host_impl().active_tree()->UpdateDrawProperties();
313 // Sanity check the scenario we just created.
314 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
315 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
317 // Hit testing for points outside the layer.
318 // These corners would have been inside the un-transformed layer, but they
319 // should not hit the correctly transformed layer.
320 gfx::Point test_point(99, 99);
321 LayerImpl* result_layer =
322 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
323 EXPECT_FALSE(result_layer);
325 test_point = gfx::Point(1, 1);
326 result_layer =
327 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
328 EXPECT_FALSE(result_layer);
330 // Hit testing for a point inside should return the root layer.
331 test_point = gfx::Point(1, 50);
332 result_layer =
333 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
334 ASSERT_TRUE(result_layer);
335 EXPECT_EQ(12345, result_layer->id());
337 // Hit testing the corners that would overlap the unclipped layer, but are
338 // outside the clipped region.
339 test_point = gfx::Point(50, -1);
340 result_layer =
341 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
342 ASSERT_FALSE(result_layer);
344 test_point = gfx::Point(-1, 50);
345 result_layer =
346 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
347 ASSERT_FALSE(result_layer);
350 TEST_F(LayerTreeImplTest, HitTestingForSinglePerspectiveLayer) {
351 scoped_ptr<LayerImpl> root =
352 LayerImpl::Create(host_impl().active_tree(), 12345);
354 gfx::Transform identity_matrix;
356 // perspective_projection_about_center * translation_by_z is designed so that
357 // the 100 x 100 layer becomes 50 x 50, and remains centered at (50, 50).
358 gfx::Transform perspective_projection_about_center;
359 perspective_projection_about_center.Translate(50.0, 50.0);
360 perspective_projection_about_center.ApplyPerspectiveDepth(1.0);
361 perspective_projection_about_center.Translate(-50.0, -50.0);
362 gfx::Transform translation_by_z;
363 translation_by_z.Translate3d(0.0, 0.0, -1.0);
365 gfx::Point3F transform_origin;
366 gfx::PointF position;
367 gfx::Size bounds(100, 100);
368 SetLayerPropertiesForTesting(
369 root.get(),
370 perspective_projection_about_center * translation_by_z,
371 transform_origin,
372 position,
373 bounds,
374 true,
375 false);
376 root->SetDrawsContent(true);
378 host_impl().SetViewportSize(root->bounds());
379 host_impl().active_tree()->SetRootLayer(root.Pass());
380 host_impl().active_tree()->UpdateDrawProperties();
382 // Sanity check the scenario we just created.
383 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
384 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
386 // Hit testing for points outside the layer.
387 // These corners would have been inside the un-transformed layer, but they
388 // should not hit the correctly transformed layer.
389 gfx::Point test_point(24, 24);
390 LayerImpl* result_layer =
391 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
392 EXPECT_FALSE(result_layer);
394 test_point = gfx::Point(76, 76);
395 result_layer =
396 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
397 EXPECT_FALSE(result_layer);
399 // Hit testing for a point inside should return the root layer.
400 test_point = gfx::Point(26, 26);
401 result_layer =
402 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
403 ASSERT_TRUE(result_layer);
404 EXPECT_EQ(12345, result_layer->id());
406 test_point = gfx::Point(74, 74);
407 result_layer =
408 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
409 ASSERT_TRUE(result_layer);
410 EXPECT_EQ(12345, result_layer->id());
413 TEST_F(LayerTreeImplTest, HitTestingForSingleLayerWithScaledContents) {
414 // A layer's visible content rect is actually in the layer's content space.
415 // The screen space transform converts from the layer's origin space to screen
416 // space. This test makes sure that hit testing works correctly accounts for
417 // the contents scale. A contents scale that is not 1 effectively forces a
418 // non-identity transform between layer's content space and layer's origin
419 // space. The hit testing code must take this into account.
421 // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
422 // contents scale is ignored, then hit testing will mis-interpret the visible
423 // content rect as being larger than the actual bounds of the layer.
425 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
427 gfx::Transform identity_matrix;
428 gfx::Point3F transform_origin;
430 SetLayerPropertiesForTesting(root.get(),
431 identity_matrix,
432 transform_origin,
433 gfx::PointF(),
434 gfx::Size(100, 100),
435 true,
436 false);
438 gfx::PointF position(25.f, 25.f);
439 gfx::Size bounds(50, 50);
440 scoped_ptr<LayerImpl> test_layer =
441 LayerImpl::Create(host_impl().active_tree(), 12345);
442 SetLayerPropertiesForTesting(test_layer.get(),
443 identity_matrix,
444 transform_origin,
445 position,
446 bounds,
447 true,
448 false);
450 // override content bounds and contents scale
451 test_layer->SetContentBounds(gfx::Size(100, 100));
452 test_layer->SetContentsScale(2, 2);
454 test_layer->SetDrawsContent(true);
455 root->AddChild(test_layer.Pass());
458 host_impl().SetViewportSize(root->bounds());
459 host_impl().active_tree()->SetRootLayer(root.Pass());
460 host_impl().active_tree()->UpdateDrawProperties();
462 // Sanity check the scenario we just created.
463 // The visible content rect for test_layer is actually 100x100, even though
464 // its layout size is 50x50, positioned at 25x25.
465 LayerImpl* test_layer =
466 host_impl().active_tree()->root_layer()->children()[0];
467 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer->visible_content_rect());
468 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
469 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
471 // Hit testing for a point outside the layer should return a null pointer (the
472 // root layer does not draw content, so it will not be hit tested either).
473 gfx::Point test_point(101, 101);
474 LayerImpl* result_layer =
475 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
476 EXPECT_FALSE(result_layer);
478 test_point = gfx::Point(24, 24);
479 result_layer =
480 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
481 EXPECT_FALSE(result_layer);
483 test_point = gfx::Point(76, 76);
484 result_layer =
485 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
486 EXPECT_FALSE(result_layer);
488 // Hit testing for a point inside should return the test layer.
489 test_point = gfx::Point(26, 26);
490 result_layer =
491 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
492 ASSERT_TRUE(result_layer);
493 EXPECT_EQ(12345, result_layer->id());
495 test_point = gfx::Point(74, 74);
496 result_layer =
497 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
498 ASSERT_TRUE(result_layer);
499 EXPECT_EQ(12345, result_layer->id());
502 TEST_F(LayerTreeImplTest, HitTestingForSimpleClippedLayer) {
503 // Test that hit-testing will only work for the visible portion of a layer,
504 // and not the entire layer bounds. Here we just test the simple axis-aligned
505 // case.
506 gfx::Transform identity_matrix;
507 gfx::Point3F transform_origin;
509 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
510 SetLayerPropertiesForTesting(root.get(),
511 identity_matrix,
512 transform_origin,
513 gfx::PointF(),
514 gfx::Size(100, 100),
515 true,
516 false);
518 scoped_ptr<LayerImpl> clipping_layer =
519 LayerImpl::Create(host_impl().active_tree(), 123);
520 // this layer is positioned, and hit testing should correctly know where the
521 // layer is located.
522 gfx::PointF position(25.f, 25.f);
523 gfx::Size bounds(50, 50);
524 SetLayerPropertiesForTesting(clipping_layer.get(),
525 identity_matrix,
526 transform_origin,
527 position,
528 bounds,
529 true,
530 false);
531 clipping_layer->SetMasksToBounds(true);
533 scoped_ptr<LayerImpl> child =
534 LayerImpl::Create(host_impl().active_tree(), 456);
535 position = gfx::PointF(-50.f, -50.f);
536 bounds = gfx::Size(300, 300);
537 SetLayerPropertiesForTesting(child.get(),
538 identity_matrix,
539 transform_origin,
540 position,
541 bounds,
542 true,
543 false);
544 child->SetDrawsContent(true);
545 clipping_layer->AddChild(child.Pass());
546 root->AddChild(clipping_layer.Pass());
549 host_impl().SetViewportSize(root->bounds());
550 host_impl().active_tree()->SetRootLayer(root.Pass());
551 host_impl().active_tree()->UpdateDrawProperties();
553 // Sanity check the scenario we just created.
554 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
555 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
556 ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
558 // Hit testing for a point outside the layer should return a null pointer.
559 // Despite the child layer being very large, it should be clipped to the root
560 // layer's bounds.
561 gfx::Point test_point(24, 24);
562 LayerImpl* result_layer =
563 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
564 EXPECT_FALSE(result_layer);
566 // Even though the layer exists at (101, 101), it should not be visible there
567 // since the clipping_layer would clamp it.
568 test_point = gfx::Point(76, 76);
569 result_layer =
570 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
571 EXPECT_FALSE(result_layer);
573 // Hit testing for a point inside should return the child layer.
574 test_point = gfx::Point(26, 26);
575 result_layer =
576 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
577 ASSERT_TRUE(result_layer);
578 EXPECT_EQ(456, result_layer->id());
580 test_point = gfx::Point(74, 74);
581 result_layer =
582 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
583 ASSERT_TRUE(result_layer);
584 EXPECT_EQ(456, result_layer->id());
587 TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) {
588 // This test checks whether hit testing correctly avoids hit testing with
589 // multiple ancestors that clip in non axis-aligned ways. To pass this test,
590 // the hit testing algorithm needs to recognize that multiple parent layers
591 // may clip the layer, and should not actually hit those clipped areas.
593 // The child and grand_child layers are both initialized to clip the
594 // rotated_leaf. The child layer is rotated about the top-left corner, so that
595 // the root + child clips combined create a triangle. The rotated_leaf will
596 // only be visible where it overlaps this triangle.
598 scoped_ptr<LayerImpl> root =
599 LayerImpl::Create(host_impl().active_tree(), 123);
601 gfx::Transform identity_matrix;
602 gfx::Point3F transform_origin;
603 gfx::PointF position;
604 gfx::Size bounds(100, 100);
605 SetLayerPropertiesForTesting(root.get(),
606 identity_matrix,
607 transform_origin,
608 position,
609 bounds,
610 true,
611 false);
612 root->SetMasksToBounds(true);
614 scoped_ptr<LayerImpl> child =
615 LayerImpl::Create(host_impl().active_tree(), 456);
616 scoped_ptr<LayerImpl> grand_child =
617 LayerImpl::Create(host_impl().active_tree(), 789);
618 scoped_ptr<LayerImpl> rotated_leaf =
619 LayerImpl::Create(host_impl().active_tree(), 2468);
621 position = gfx::PointF(10.f, 10.f);
622 bounds = gfx::Size(80, 80);
623 SetLayerPropertiesForTesting(child.get(),
624 identity_matrix,
625 transform_origin,
626 position,
627 bounds,
628 true,
629 false);
630 child->SetMasksToBounds(true);
632 gfx::Transform rotation45_degrees_about_corner;
633 rotation45_degrees_about_corner.RotateAboutZAxis(45.0);
635 // remember, positioned with respect to its parent which is already at 10,
636 // 10
637 position = gfx::PointF();
638 bounds =
639 gfx::Size(200, 200); // to ensure it covers at least sqrt(2) * 100.
640 SetLayerPropertiesForTesting(grand_child.get(),
641 rotation45_degrees_about_corner,
642 transform_origin,
643 position,
644 bounds,
645 true,
646 false);
647 grand_child->SetMasksToBounds(true);
649 // Rotates about the center of the layer
650 gfx::Transform rotated_leaf_transform;
651 rotated_leaf_transform.Translate(
652 -10.0, -10.0); // cancel out the grand_parent's position
653 rotated_leaf_transform.RotateAboutZAxis(
654 -45.0); // cancel out the corner 45-degree rotation of the parent.
655 rotated_leaf_transform.Translate(50.0, 50.0);
656 rotated_leaf_transform.RotateAboutZAxis(45.0);
657 rotated_leaf_transform.Translate(-50.0, -50.0);
658 position = gfx::PointF();
659 bounds = gfx::Size(100, 100);
660 SetLayerPropertiesForTesting(rotated_leaf.get(),
661 rotated_leaf_transform,
662 transform_origin,
663 position,
664 bounds,
665 true,
666 false);
667 rotated_leaf->SetDrawsContent(true);
669 grand_child->AddChild(rotated_leaf.Pass());
670 child->AddChild(grand_child.Pass());
671 root->AddChild(child.Pass());
674 host_impl().SetViewportSize(root->bounds());
675 host_impl().active_tree()->SetRootLayer(root.Pass());
676 host_impl().active_tree()->UpdateDrawProperties();
678 // Sanity check the scenario we just created.
679 // The grand_child is expected to create a render surface because it
680 // MasksToBounds and is not axis aligned.
681 ASSERT_EQ(2u, RenderSurfaceLayerList().size());
682 ASSERT_EQ(
684 RenderSurfaceLayerList().at(0)->render_surface()->layer_list().size());
685 ASSERT_EQ(789,
686 RenderSurfaceLayerList()
687 .at(0)
688 ->render_surface()
689 ->layer_list()
690 .at(0)
691 ->id()); // grand_child's surface.
692 ASSERT_EQ(
694 RenderSurfaceLayerList().at(1)->render_surface()->layer_list().size());
695 ASSERT_EQ(
696 2468,
697 RenderSurfaceLayerList()[1]->render_surface()->layer_list().at(0)->id());
699 // (11, 89) is close to the the bottom left corner within the clip, but it is
700 // not inside the layer.
701 gfx::Point test_point(11, 89);
702 LayerImpl* result_layer =
703 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
704 EXPECT_FALSE(result_layer);
706 // Closer inwards from the bottom left will overlap the layer.
707 test_point = gfx::Point(25, 75);
708 result_layer =
709 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
710 ASSERT_TRUE(result_layer);
711 EXPECT_EQ(2468, result_layer->id());
713 // (4, 50) is inside the unclipped layer, but that corner of the layer should
714 // be clipped away by the grandparent and should not get hit. If hit testing
715 // blindly uses visible content rect without considering how parent may clip
716 // the layer, then hit testing would accidentally think that the point
717 // successfully hits the layer.
718 test_point = gfx::Point(4, 50);
719 result_layer =
720 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
721 EXPECT_FALSE(result_layer);
723 // (11, 50) is inside the layer and within the clipped area.
724 test_point = gfx::Point(11, 50);
725 result_layer =
726 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
727 ASSERT_TRUE(result_layer);
728 EXPECT_EQ(2468, result_layer->id());
730 // Around the middle, just to the right and up, would have hit the layer
731 // except that that area should be clipped away by the parent.
732 test_point = gfx::Point(51, 49);
733 result_layer =
734 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
735 EXPECT_FALSE(result_layer);
737 // Around the middle, just to the left and down, should successfully hit the
738 // layer.
739 test_point = gfx::Point(49, 51);
740 result_layer =
741 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
742 ASSERT_TRUE(result_layer);
743 EXPECT_EQ(2468, result_layer->id());
746 TEST_F(LayerTreeImplTest, HitTestingForNonClippingIntermediateLayer) {
747 // This test checks that hit testing code does not accidentally clip to layer
748 // bounds for a layer that actually does not clip.
749 gfx::Transform identity_matrix;
750 gfx::Point3F transform_origin;
752 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
753 SetLayerPropertiesForTesting(root.get(),
754 identity_matrix,
755 transform_origin,
756 gfx::PointF(),
757 gfx::Size(100, 100),
758 true,
759 false);
761 scoped_ptr<LayerImpl> intermediate_layer =
762 LayerImpl::Create(host_impl().active_tree(), 123);
763 // this layer is positioned, and hit testing should correctly know where the
764 // layer is located.
765 gfx::PointF position(10.f, 10.f);
766 gfx::Size bounds(50, 50);
767 SetLayerPropertiesForTesting(intermediate_layer.get(),
768 identity_matrix,
769 transform_origin,
770 position,
771 bounds,
772 true,
773 false);
774 // Sanity check the intermediate layer should not clip.
775 ASSERT_FALSE(intermediate_layer->masks_to_bounds());
776 ASSERT_FALSE(intermediate_layer->mask_layer());
778 // The child of the intermediate_layer is translated so that it does not
779 // overlap intermediate_layer at all. If child is incorrectly clipped, we
780 // would not be able to hit it successfully.
781 scoped_ptr<LayerImpl> child =
782 LayerImpl::Create(host_impl().active_tree(), 456);
783 position = gfx::PointF(60.f, 60.f); // 70, 70 in screen space
784 bounds = gfx::Size(20, 20);
785 SetLayerPropertiesForTesting(child.get(),
786 identity_matrix,
787 transform_origin,
788 position,
789 bounds,
790 true,
791 false);
792 child->SetDrawsContent(true);
793 intermediate_layer->AddChild(child.Pass());
794 root->AddChild(intermediate_layer.Pass());
797 host_impl().SetViewportSize(root->bounds());
798 host_impl().active_tree()->SetRootLayer(root.Pass());
799 host_impl().active_tree()->UpdateDrawProperties();
801 // Sanity check the scenario we just created.
802 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
803 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
804 ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
806 // Hit testing for a point outside the layer should return a null pointer.
807 gfx::Point test_point(69, 69);
808 LayerImpl* result_layer =
809 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
810 EXPECT_FALSE(result_layer);
812 test_point = gfx::Point(91, 91);
813 result_layer =
814 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
815 EXPECT_FALSE(result_layer);
817 // Hit testing for a point inside should return the child layer.
818 test_point = gfx::Point(71, 71);
819 result_layer =
820 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
821 ASSERT_TRUE(result_layer);
822 EXPECT_EQ(456, result_layer->id());
824 test_point = gfx::Point(89, 89);
825 result_layer =
826 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
827 ASSERT_TRUE(result_layer);
828 EXPECT_EQ(456, result_layer->id());
831 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) {
832 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
834 gfx::Transform identity_matrix;
835 gfx::Point3F transform_origin;
836 gfx::PointF position;
837 gfx::Size bounds(100, 100);
838 SetLayerPropertiesForTesting(root.get(),
839 identity_matrix,
840 transform_origin,
841 position,
842 bounds,
843 true,
844 false);
845 root->SetDrawsContent(true);
847 // child 1 and child2 are initialized to overlap between x=50 and x=60.
848 // grand_child is set to overlap both child1 and child2 between y=50 and
849 // y=60. The expected stacking order is: (front) child2, (second)
850 // grand_child, (third) child1, and (back) the root layer behind all other
851 // layers.
853 scoped_ptr<LayerImpl> child1 =
854 LayerImpl::Create(host_impl().active_tree(), 2);
855 scoped_ptr<LayerImpl> child2 =
856 LayerImpl::Create(host_impl().active_tree(), 3);
857 scoped_ptr<LayerImpl> grand_child1 =
858 LayerImpl::Create(host_impl().active_tree(), 4);
860 position = gfx::PointF(10.f, 10.f);
861 bounds = gfx::Size(50, 50);
862 SetLayerPropertiesForTesting(child1.get(),
863 identity_matrix,
864 transform_origin,
865 position,
866 bounds,
867 true,
868 false);
869 child1->SetDrawsContent(true);
871 position = gfx::PointF(50.f, 10.f);
872 bounds = gfx::Size(50, 50);
873 SetLayerPropertiesForTesting(child2.get(),
874 identity_matrix,
875 transform_origin,
876 position,
877 bounds,
878 true,
879 false);
880 child2->SetDrawsContent(true);
882 // Remember that grand_child is positioned with respect to its parent (i.e.
883 // child1). In screen space, the intended position is (10, 50), with size
884 // 100 x 50.
885 position = gfx::PointF(0.f, 40.f);
886 bounds = gfx::Size(100, 50);
887 SetLayerPropertiesForTesting(grand_child1.get(),
888 identity_matrix,
889 transform_origin,
890 position,
891 bounds,
892 true,
893 false);
894 grand_child1->SetDrawsContent(true);
896 child1->AddChild(grand_child1.Pass());
897 root->AddChild(child1.Pass());
898 root->AddChild(child2.Pass());
901 LayerImpl* child1 = root->children()[0];
902 LayerImpl* child2 = root->children()[1];
903 LayerImpl* grand_child1 = child1->children()[0];
905 host_impl().SetViewportSize(root->bounds());
906 host_impl().active_tree()->SetRootLayer(root.Pass());
907 host_impl().active_tree()->UpdateDrawProperties();
909 // Sanity check the scenario we just created.
910 ASSERT_TRUE(child1);
911 ASSERT_TRUE(child2);
912 ASSERT_TRUE(grand_child1);
913 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
915 RenderSurfaceImpl* root_render_surface = root_layer()->render_surface();
916 ASSERT_EQ(4u, root_render_surface->layer_list().size());
917 ASSERT_EQ(1, root_render_surface->layer_list().at(0)->id()); // root layer
918 ASSERT_EQ(2, root_render_surface->layer_list().at(1)->id()); // child1
919 ASSERT_EQ(4, root_render_surface->layer_list().at(2)->id()); // grand_child1
920 ASSERT_EQ(3, root_render_surface->layer_list().at(3)->id()); // child2
922 // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
923 // the root layer.
924 gfx::Point test_point = gfx::Point(1, 1);
925 LayerImpl* result_layer =
926 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
927 ASSERT_TRUE(result_layer);
928 EXPECT_EQ(1, result_layer->id());
930 // At (15, 15), child1 and root are the only layers. child1 is expected to be
931 // on top.
932 test_point = gfx::Point(15, 15);
933 result_layer =
934 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
935 ASSERT_TRUE(result_layer);
936 EXPECT_EQ(2, result_layer->id());
938 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
939 test_point = gfx::Point(51, 20);
940 result_layer =
941 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
942 ASSERT_TRUE(result_layer);
943 EXPECT_EQ(3, result_layer->id());
945 // At (80, 51), child2 and grand_child1 overlap. child2 is expected to be on
946 // top.
947 test_point = gfx::Point(80, 51);
948 result_layer =
949 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
950 ASSERT_TRUE(result_layer);
951 EXPECT_EQ(3, result_layer->id());
953 // At (51, 51), all layers overlap each other. child2 is expected to be on top
954 // of all other layers.
955 test_point = gfx::Point(51, 51);
956 result_layer =
957 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
958 ASSERT_TRUE(result_layer);
959 EXPECT_EQ(3, result_layer->id());
961 // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
962 // be on top.
963 test_point = gfx::Point(20, 51);
964 result_layer =
965 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
966 ASSERT_TRUE(result_layer);
967 EXPECT_EQ(4, result_layer->id());
970 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) {
971 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
973 gfx::Transform identity_matrix;
974 gfx::Point3F transform_origin;
975 gfx::PointF position;
976 gfx::Size bounds(100, 100);
977 SetLayerPropertiesForTesting(root.get(),
978 identity_matrix,
979 transform_origin,
980 position,
981 bounds,
982 true,
983 false);
984 root->SetDrawsContent(true);
985 root->SetShouldFlattenTransform(false);
986 root->SetIs3dSorted(true);
988 // child 1 and child2 are initialized to overlap between x=50 and x=60.
989 // grand_child is set to overlap both child1 and child2 between y=50 and
990 // y=60. The expected stacking order is: (front) child2, (second)
991 // grand_child, (third) child1, and (back) the root layer behind all other
992 // layers.
994 scoped_ptr<LayerImpl> child1 =
995 LayerImpl::Create(host_impl().active_tree(), 2);
996 scoped_ptr<LayerImpl> child2 =
997 LayerImpl::Create(host_impl().active_tree(), 3);
998 scoped_ptr<LayerImpl> grand_child1 =
999 LayerImpl::Create(host_impl().active_tree(), 4);
1001 position = gfx::PointF(10.f, 10.f);
1002 bounds = gfx::Size(50, 50);
1003 SetLayerPropertiesForTesting(child1.get(),
1004 identity_matrix,
1005 transform_origin,
1006 position,
1007 bounds,
1008 true,
1009 false);
1010 child1->SetDrawsContent(true);
1011 child1->SetShouldFlattenTransform(false);
1012 child1->SetIs3dSorted(true);
1014 position = gfx::PointF(50.f, 10.f);
1015 bounds = gfx::Size(50, 50);
1016 gfx::Transform translate_z;
1017 translate_z.Translate3d(0, 0, -10.f);
1018 SetLayerPropertiesForTesting(child2.get(),
1019 translate_z,
1020 transform_origin,
1021 position,
1022 bounds,
1023 true,
1024 false);
1025 child2->SetDrawsContent(true);
1026 child2->SetShouldFlattenTransform(false);
1027 child2->SetIs3dSorted(true);
1029 // Remember that grand_child is positioned with respect to its parent (i.e.
1030 // child1). In screen space, the intended position is (10, 50), with size
1031 // 100 x 50.
1032 position = gfx::PointF(0.f, 40.f);
1033 bounds = gfx::Size(100, 50);
1034 SetLayerPropertiesForTesting(grand_child1.get(),
1035 identity_matrix,
1036 transform_origin,
1037 position,
1038 bounds,
1039 true,
1040 false);
1041 grand_child1->SetDrawsContent(true);
1042 grand_child1->SetShouldFlattenTransform(false);
1044 child1->AddChild(grand_child1.Pass());
1045 root->AddChild(child1.Pass());
1046 root->AddChild(child2.Pass());
1049 LayerImpl* child1 = root->children()[0];
1050 LayerImpl* child2 = root->children()[1];
1051 LayerImpl* grand_child1 = child1->children()[0];
1053 host_impl().SetViewportSize(root->bounds());
1054 host_impl().active_tree()->SetRootLayer(root.Pass());
1055 host_impl().active_tree()->UpdateDrawProperties();
1057 // Sanity check the scenario we just created.
1058 ASSERT_TRUE(child1);
1059 ASSERT_TRUE(child2);
1060 ASSERT_TRUE(grand_child1);
1061 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1063 RenderSurfaceImpl* root_render_surface =
1064 host_impl().active_tree()->root_layer()->render_surface();
1065 ASSERT_EQ(4u, root_render_surface->layer_list().size());
1066 ASSERT_EQ(3, root_render_surface->layer_list().at(0)->id());
1067 ASSERT_EQ(1, root_render_surface->layer_list().at(1)->id());
1068 ASSERT_EQ(2, root_render_surface->layer_list().at(2)->id());
1069 ASSERT_EQ(4, root_render_surface->layer_list().at(3)->id());
1071 // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
1072 // the root layer.
1073 gfx::Point test_point = gfx::Point(1, 1);
1074 LayerImpl* result_layer =
1075 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1076 ASSERT_TRUE(result_layer);
1077 EXPECT_EQ(1, result_layer->id());
1079 // At (15, 15), child1 and root are the only layers. child1 is expected to be
1080 // on top.
1081 test_point = gfx::Point(15, 15);
1082 result_layer =
1083 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1084 ASSERT_TRUE(result_layer);
1085 EXPECT_EQ(2, result_layer->id());
1087 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
1088 // (because 3 is transformed to the back).
1089 test_point = gfx::Point(51, 20);
1090 result_layer =
1091 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1092 ASSERT_TRUE(result_layer);
1093 EXPECT_EQ(2, result_layer->id());
1095 // 3 Would have been on top if it hadn't been transformed to the background.
1096 // Make sure that it isn't hit.
1097 test_point = gfx::Point(80, 51);
1098 result_layer =
1099 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1100 ASSERT_TRUE(result_layer);
1101 EXPECT_EQ(4, result_layer->id());
1103 // 3 Would have been on top if it hadn't been transformed to the background.
1104 // Make sure that it isn't hit.
1105 test_point = gfx::Point(51, 51);
1106 result_layer =
1107 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1108 ASSERT_TRUE(result_layer);
1109 EXPECT_EQ(4, result_layer->id());
1111 // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
1112 // be on top.
1113 test_point = gfx::Point(20, 51);
1114 result_layer =
1115 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1116 ASSERT_TRUE(result_layer);
1117 EXPECT_EQ(4, result_layer->id());
1120 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) {
1122 // The geometry is set up similarly to the previous case, but
1123 // all layers are forced to be render surfaces now.
1125 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1127 gfx::Transform identity_matrix;
1128 gfx::Point3F transform_origin;
1129 gfx::PointF position;
1130 gfx::Size bounds(100, 100);
1131 SetLayerPropertiesForTesting(root.get(),
1132 identity_matrix,
1133 transform_origin,
1134 position,
1135 bounds,
1136 true,
1137 false);
1138 root->SetDrawsContent(true);
1140 // child 1 and child2 are initialized to overlap between x=50 and x=60.
1141 // grand_child is set to overlap both child1 and child2 between y=50 and
1142 // y=60. The expected stacking order is: (front) child2, (second)
1143 // grand_child, (third) child1, and (back) the root layer behind all other
1144 // layers.
1146 scoped_ptr<LayerImpl> child1 =
1147 LayerImpl::Create(host_impl().active_tree(), 2);
1148 scoped_ptr<LayerImpl> child2 =
1149 LayerImpl::Create(host_impl().active_tree(), 3);
1150 scoped_ptr<LayerImpl> grand_child1 =
1151 LayerImpl::Create(host_impl().active_tree(), 4);
1153 position = gfx::PointF(10.f, 10.f);
1154 bounds = gfx::Size(50, 50);
1155 SetLayerPropertiesForTesting(child1.get(),
1156 identity_matrix,
1157 transform_origin,
1158 position,
1159 bounds,
1160 true,
1161 false);
1162 child1->SetDrawsContent(true);
1163 child1->SetForceRenderSurface(true);
1165 position = gfx::PointF(50.f, 10.f);
1166 bounds = gfx::Size(50, 50);
1167 SetLayerPropertiesForTesting(child2.get(),
1168 identity_matrix,
1169 transform_origin,
1170 position,
1171 bounds,
1172 true,
1173 false);
1174 child2->SetDrawsContent(true);
1175 child2->SetForceRenderSurface(true);
1177 // Remember that grand_child is positioned with respect to its parent (i.e.
1178 // child1). In screen space, the intended position is (10, 50), with size
1179 // 100 x 50.
1180 position = gfx::PointF(0.f, 40.f);
1181 bounds = gfx::Size(100, 50);
1182 SetLayerPropertiesForTesting(grand_child1.get(),
1183 identity_matrix,
1184 transform_origin,
1185 position,
1186 bounds,
1187 true,
1188 false);
1189 grand_child1->SetDrawsContent(true);
1190 grand_child1->SetForceRenderSurface(true);
1192 child1->AddChild(grand_child1.Pass());
1193 root->AddChild(child1.Pass());
1194 root->AddChild(child2.Pass());
1197 LayerImpl* child1 = root->children()[0];
1198 LayerImpl* child2 = root->children()[1];
1199 LayerImpl* grand_child1 = child1->children()[0];
1201 host_impl().SetViewportSize(root->bounds());
1202 host_impl().active_tree()->SetRootLayer(root.Pass());
1203 host_impl().active_tree()->UpdateDrawProperties();
1205 // Sanity check the scenario we just created.
1206 ASSERT_TRUE(child1);
1207 ASSERT_TRUE(child2);
1208 ASSERT_TRUE(grand_child1);
1209 ASSERT_TRUE(child1->render_surface());
1210 ASSERT_TRUE(child2->render_surface());
1211 ASSERT_TRUE(grand_child1->render_surface());
1212 ASSERT_EQ(4u, RenderSurfaceLayerList().size());
1213 // The root surface has the root layer, and child1's and child2's render
1214 // surfaces.
1215 ASSERT_EQ(3u, root_layer()->render_surface()->layer_list().size());
1216 // The child1 surface has the child1 layer and grand_child1's render surface.
1217 ASSERT_EQ(2u, child1->render_surface()->layer_list().size());
1218 ASSERT_EQ(1u, child2->render_surface()->layer_list().size());
1219 ASSERT_EQ(1u, grand_child1->render_surface()->layer_list().size());
1220 ASSERT_EQ(1, RenderSurfaceLayerList().at(0)->id()); // root layer
1221 ASSERT_EQ(2, RenderSurfaceLayerList()[1]->id()); // child1
1222 ASSERT_EQ(4, RenderSurfaceLayerList().at(2)->id()); // grand_child1
1223 ASSERT_EQ(3, RenderSurfaceLayerList()[3]->id()); // child2
1225 // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
1226 // the root layer.
1227 gfx::Point test_point = gfx::Point(1, 1);
1228 LayerImpl* result_layer =
1229 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1230 ASSERT_TRUE(result_layer);
1231 EXPECT_EQ(1, result_layer->id());
1233 // At (15, 15), child1 and root are the only layers. child1 is expected to be
1234 // on top.
1235 test_point = gfx::Point(15, 15);
1236 result_layer =
1237 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1238 ASSERT_TRUE(result_layer);
1239 EXPECT_EQ(2, result_layer->id());
1241 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
1242 test_point = gfx::Point(51, 20);
1243 result_layer =
1244 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1245 ASSERT_TRUE(result_layer);
1246 EXPECT_EQ(3, result_layer->id());
1248 // At (80, 51), child2 and grand_child1 overlap. child2 is expected to be on
1249 // top.
1250 test_point = gfx::Point(80, 51);
1251 result_layer =
1252 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1253 ASSERT_TRUE(result_layer);
1254 EXPECT_EQ(3, result_layer->id());
1256 // At (51, 51), all layers overlap each other. child2 is expected to be on top
1257 // of all other layers.
1258 test_point = gfx::Point(51, 51);
1259 result_layer =
1260 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1261 ASSERT_TRUE(result_layer);
1262 EXPECT_EQ(3, result_layer->id());
1264 // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
1265 // be on top.
1266 test_point = gfx::Point(20, 51);
1267 result_layer =
1268 host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1269 ASSERT_TRUE(result_layer);
1270 EXPECT_EQ(4, result_layer->id());
1273 TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSingleLayer) {
1274 scoped_ptr<LayerImpl> root =
1275 LayerImpl::Create(host_impl().active_tree(), 12345);
1277 gfx::Transform identity_matrix;
1278 Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1279 gfx::Point3F transform_origin;
1280 gfx::PointF position;
1281 gfx::Size bounds(100, 100);
1282 SetLayerPropertiesForTesting(root.get(),
1283 identity_matrix,
1284 transform_origin,
1285 position,
1286 bounds,
1287 true,
1288 false);
1289 root->SetDrawsContent(true);
1291 host_impl().SetViewportSize(root->bounds());
1292 host_impl().active_tree()->SetRootLayer(root.Pass());
1293 host_impl().active_tree()->UpdateDrawProperties();
1295 // Sanity check the scenario we just created.
1296 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1297 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1299 // Hit checking for any point should return a null pointer for a layer without
1300 // any touch event handler regions.
1301 gfx::Point test_point(11, 11);
1302 LayerImpl* result_layer =
1303 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1304 test_point);
1305 EXPECT_FALSE(result_layer);
1307 host_impl().active_tree()->root_layer()->SetTouchEventHandlerRegion(
1308 touch_handler_region);
1309 // Hit checking for a point outside the layer should return a null pointer.
1310 test_point = gfx::Point(101, 101);
1311 result_layer =
1312 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1313 test_point);
1314 EXPECT_FALSE(result_layer);
1316 test_point = gfx::Point(-1, -1);
1317 result_layer =
1318 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1319 test_point);
1320 EXPECT_FALSE(result_layer);
1322 // Hit checking for a point inside the layer, but outside the touch handler
1323 // region should return a null pointer.
1324 test_point = gfx::Point(1, 1);
1325 result_layer =
1326 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1327 test_point);
1328 EXPECT_FALSE(result_layer);
1330 test_point = gfx::Point(99, 99);
1331 result_layer =
1332 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1333 test_point);
1334 EXPECT_FALSE(result_layer);
1336 // Hit checking for a point inside the touch event handler region should
1337 // return the root layer.
1338 test_point = gfx::Point(11, 11);
1339 result_layer =
1340 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1341 test_point);
1342 ASSERT_TRUE(result_layer);
1343 EXPECT_EQ(12345, result_layer->id());
1345 test_point = gfx::Point(59, 59);
1346 result_layer =
1347 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1348 test_point);
1349 ASSERT_TRUE(result_layer);
1350 EXPECT_EQ(12345, result_layer->id());
1353 TEST_F(LayerTreeImplTest,
1354 HitCheckingTouchHandlerRegionsForUninvertibleTransform) {
1355 scoped_ptr<LayerImpl> root =
1356 LayerImpl::Create(host_impl().active_tree(), 12345);
1358 gfx::Transform uninvertible_transform;
1359 uninvertible_transform.matrix().set(0, 0, 0.0);
1360 uninvertible_transform.matrix().set(1, 1, 0.0);
1361 uninvertible_transform.matrix().set(2, 2, 0.0);
1362 uninvertible_transform.matrix().set(3, 3, 0.0);
1363 ASSERT_FALSE(uninvertible_transform.IsInvertible());
1365 gfx::Transform identity_matrix;
1366 Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1367 gfx::Point3F transform_origin;
1368 gfx::PointF position;
1369 gfx::Size bounds(100, 100);
1370 SetLayerPropertiesForTesting(root.get(),
1371 uninvertible_transform,
1372 transform_origin,
1373 position,
1374 bounds,
1375 true,
1376 false);
1377 root->SetDrawsContent(true);
1378 root->SetTouchEventHandlerRegion(touch_handler_region);
1380 host_impl().SetViewportSize(root->bounds());
1381 host_impl().active_tree()->SetRootLayer(root.Pass());
1382 host_impl().active_tree()->UpdateDrawProperties();
1384 // Sanity check the scenario we just created.
1385 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1386 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1387 ASSERT_FALSE(root_layer()->screen_space_transform().IsInvertible());
1389 // Hit checking any point should not hit the touch handler region on the
1390 // layer. If the invertible matrix is accidentally ignored and treated like an
1391 // identity, then the hit testing will incorrectly hit the layer when it
1392 // shouldn't.
1393 gfx::Point test_point(1, 1);
1394 LayerImpl* result_layer =
1395 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1396 test_point);
1397 EXPECT_FALSE(result_layer);
1399 test_point = gfx::Point(10, 10);
1400 result_layer =
1401 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1402 test_point);
1403 EXPECT_FALSE(result_layer);
1405 test_point = gfx::Point(10, 30);
1406 result_layer =
1407 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1408 test_point);
1409 EXPECT_FALSE(result_layer);
1411 test_point = gfx::Point(50, 50);
1412 result_layer =
1413 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1414 test_point);
1415 EXPECT_FALSE(result_layer);
1417 test_point = gfx::Point(67, 48);
1418 result_layer =
1419 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1420 test_point);
1421 EXPECT_FALSE(result_layer);
1423 test_point = gfx::Point(99, 99);
1424 result_layer =
1425 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1426 test_point);
1427 EXPECT_FALSE(result_layer);
1429 test_point = gfx::Point(-1, -1);
1430 result_layer =
1431 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1432 test_point);
1433 EXPECT_FALSE(result_layer);
1436 TEST_F(LayerTreeImplTest,
1437 HitCheckingTouchHandlerRegionsForSinglePositionedLayer) {
1438 scoped_ptr<LayerImpl> root =
1439 LayerImpl::Create(host_impl().active_tree(), 12345);
1441 gfx::Transform identity_matrix;
1442 Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1443 gfx::Point3F transform_origin;
1444 // this layer is positioned, and hit testing should correctly know where the
1445 // layer is located.
1446 gfx::PointF position(50.f, 50.f);
1447 gfx::Size bounds(100, 100);
1448 SetLayerPropertiesForTesting(root.get(),
1449 identity_matrix,
1450 transform_origin,
1451 position,
1452 bounds,
1453 true,
1454 false);
1455 root->SetDrawsContent(true);
1456 root->SetTouchEventHandlerRegion(touch_handler_region);
1458 host_impl().SetViewportSize(root->bounds());
1459 host_impl().active_tree()->SetRootLayer(root.Pass());
1460 host_impl().active_tree()->UpdateDrawProperties();
1462 // Sanity check the scenario we just created.
1463 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1464 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1466 // Hit checking for a point outside the layer should return a null pointer.
1467 gfx::Point test_point(49, 49);
1468 LayerImpl* result_layer =
1469 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1470 test_point);
1471 EXPECT_FALSE(result_layer);
1473 // Even though the layer has a touch handler region containing (101, 101), it
1474 // should not be visible there since the root render surface would clamp it.
1475 test_point = gfx::Point(101, 101);
1476 result_layer =
1477 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1478 test_point);
1479 EXPECT_FALSE(result_layer);
1481 // Hit checking for a point inside the layer, but outside the touch handler
1482 // region should return a null pointer.
1483 test_point = gfx::Point(51, 51);
1484 result_layer =
1485 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1486 test_point);
1487 EXPECT_FALSE(result_layer);
1489 // Hit checking for a point inside the touch event handler region should
1490 // return the root layer.
1491 test_point = gfx::Point(61, 61);
1492 result_layer =
1493 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1494 test_point);
1495 ASSERT_TRUE(result_layer);
1496 EXPECT_EQ(12345, result_layer->id());
1498 test_point = gfx::Point(99, 99);
1499 result_layer =
1500 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1501 test_point);
1502 ASSERT_TRUE(result_layer);
1503 EXPECT_EQ(12345, result_layer->id());
1506 TEST_F(LayerTreeImplTest,
1507 HitCheckingTouchHandlerRegionsForSingleLayerWithScaledContents) {
1508 // A layer's visible content rect is actually in the layer's content space.
1509 // The screen space transform converts from the layer's origin space to screen
1510 // space. This test makes sure that hit testing works correctly accounts for
1511 // the contents scale. A contents scale that is not 1 effectively forces a
1512 // non-identity transform between layer's content space and layer's origin
1513 // space. The hit testing code must take this into account.
1515 // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
1516 // contents scale is ignored, then hit checking will mis-interpret the visible
1517 // content rect as being larger than the actual bounds of the layer.
1519 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1521 gfx::Transform identity_matrix;
1522 gfx::Point3F transform_origin;
1524 SetLayerPropertiesForTesting(root.get(),
1525 identity_matrix,
1526 transform_origin,
1527 gfx::PointF(),
1528 gfx::Size(100, 100),
1529 true,
1530 false);
1532 Region touch_handler_region(gfx::Rect(10, 10, 30, 30));
1533 gfx::PointF position(25.f, 25.f);
1534 gfx::Size bounds(50, 50);
1535 scoped_ptr<LayerImpl> test_layer =
1536 LayerImpl::Create(host_impl().active_tree(), 12345);
1537 SetLayerPropertiesForTesting(test_layer.get(),
1538 identity_matrix,
1539 transform_origin,
1540 position,
1541 bounds,
1542 true,
1543 false);
1545 // override content bounds and contents scale
1546 test_layer->SetContentBounds(gfx::Size(100, 100));
1547 test_layer->SetContentsScale(2, 2);
1549 test_layer->SetDrawsContent(true);
1550 test_layer->SetTouchEventHandlerRegion(touch_handler_region);
1551 root->AddChild(test_layer.Pass());
1554 host_impl().SetViewportSize(root->bounds());
1555 host_impl().active_tree()->SetRootLayer(root.Pass());
1556 host_impl().active_tree()->UpdateDrawProperties();
1558 // Sanity check the scenario we just created.
1559 // The visible content rect for test_layer is actually 100x100, even though
1560 // its layout size is 50x50, positioned at 25x25.
1561 LayerImpl* test_layer =
1562 host_impl().active_tree()->root_layer()->children()[0];
1563 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer->visible_content_rect());
1564 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1565 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1567 // Hit checking for a point outside the layer should return a null pointer
1568 // (the root layer does not draw content, so it will not be tested either).
1569 gfx::Point test_point(76, 76);
1570 LayerImpl* result_layer =
1571 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1572 test_point);
1573 EXPECT_FALSE(result_layer);
1575 // Hit checking for a point inside the layer, but outside the touch handler
1576 // region should return a null pointer.
1577 test_point = gfx::Point(26, 26);
1578 result_layer =
1579 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1580 test_point);
1581 EXPECT_FALSE(result_layer);
1583 test_point = gfx::Point(34, 34);
1584 result_layer =
1585 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1586 test_point);
1587 EXPECT_FALSE(result_layer);
1589 test_point = gfx::Point(65, 65);
1590 result_layer =
1591 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1592 test_point);
1593 EXPECT_FALSE(result_layer);
1595 test_point = gfx::Point(74, 74);
1596 result_layer =
1597 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1598 test_point);
1599 EXPECT_FALSE(result_layer);
1601 // Hit checking for a point inside the touch event handler region should
1602 // return the root layer.
1603 test_point = gfx::Point(35, 35);
1604 result_layer =
1605 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1606 test_point);
1607 ASSERT_TRUE(result_layer);
1608 EXPECT_EQ(12345, result_layer->id());
1610 test_point = gfx::Point(64, 64);
1611 result_layer =
1612 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1613 test_point);
1614 ASSERT_TRUE(result_layer);
1615 EXPECT_EQ(12345, result_layer->id());
1618 TEST_F(LayerTreeImplTest,
1619 HitCheckingTouchHandlerRegionsForSingleLayerWithDeviceScale) {
1620 // The layer's device_scale_factor and page_scale_factor should scale the
1621 // content rect and we should be able to hit the touch handler region by
1622 // scaling the points accordingly.
1623 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1625 gfx::Transform identity_matrix;
1626 gfx::Point3F transform_origin;
1627 // Set the bounds of the root layer big enough to fit the child when scaled.
1628 SetLayerPropertiesForTesting(root.get(),
1629 identity_matrix,
1630 transform_origin,
1631 gfx::PointF(),
1632 gfx::Size(100, 100),
1633 true,
1634 false);
1636 Region touch_handler_region(gfx::Rect(10, 10, 30, 30));
1637 gfx::PointF position(25.f, 25.f);
1638 gfx::Size bounds(50, 50);
1639 scoped_ptr<LayerImpl> test_layer =
1640 LayerImpl::Create(host_impl().active_tree(), 12345);
1641 SetLayerPropertiesForTesting(test_layer.get(),
1642 identity_matrix,
1643 transform_origin,
1644 position,
1645 bounds,
1646 true,
1647 false);
1649 test_layer->SetDrawsContent(true);
1650 test_layer->SetTouchEventHandlerRegion(touch_handler_region);
1651 root->AddChild(test_layer.Pass());
1654 float device_scale_factor = 3.f;
1655 float page_scale_factor = 5.f;
1656 gfx::Size scaled_bounds_for_root = gfx::ToCeiledSize(
1657 gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor));
1658 host_impl().SetViewportSize(scaled_bounds_for_root);
1660 host_impl().SetDeviceScaleFactor(device_scale_factor);
1661 host_impl().active_tree()->SetPageScaleFactorAndLimits(
1662 page_scale_factor, page_scale_factor, page_scale_factor);
1663 host_impl().active_tree()->SetRootLayer(root.Pass());
1664 host_impl().active_tree()->SetViewportLayersFromIds(1, 1, Layer::INVALID_ID);
1665 host_impl().active_tree()->UpdateDrawProperties();
1667 // Sanity check the scenario we just created.
1668 // The visible content rect for test_layer is actually 100x100, even though
1669 // its layout size is 50x50, positioned at 25x25.
1670 LayerImpl* test_layer =
1671 host_impl().active_tree()->root_layer()->children()[0];
1672 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1673 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1675 // Check whether the child layer fits into the root after scaled.
1676 EXPECT_RECT_EQ(gfx::Rect(test_layer->content_bounds()),
1677 test_layer->visible_content_rect());
1679 // Hit checking for a point outside the layer should return a null pointer
1680 // (the root layer does not draw content, so it will not be tested either).
1681 gfx::PointF test_point(76.f, 76.f);
1682 test_point =
1683 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1684 LayerImpl* result_layer =
1685 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1686 test_point);
1687 EXPECT_FALSE(result_layer);
1689 // Hit checking for a point inside the layer, but outside the touch handler
1690 // region should return a null pointer.
1691 test_point = gfx::Point(26, 26);
1692 test_point =
1693 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1694 result_layer =
1695 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1696 test_point);
1697 EXPECT_FALSE(result_layer);
1699 test_point = gfx::Point(34, 34);
1700 test_point =
1701 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1702 result_layer =
1703 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1704 test_point);
1705 EXPECT_FALSE(result_layer);
1707 test_point = gfx::Point(65, 65);
1708 test_point =
1709 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1710 result_layer =
1711 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1712 test_point);
1713 EXPECT_FALSE(result_layer);
1715 test_point = gfx::Point(74, 74);
1716 test_point =
1717 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1718 result_layer =
1719 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1720 test_point);
1721 EXPECT_FALSE(result_layer);
1723 // Hit checking for a point inside the touch event handler region should
1724 // return the root layer.
1725 test_point = gfx::Point(35, 35);
1726 test_point =
1727 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1728 result_layer =
1729 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1730 test_point);
1731 ASSERT_TRUE(result_layer);
1732 EXPECT_EQ(12345, result_layer->id());
1734 test_point = gfx::Point(64, 64);
1735 test_point =
1736 gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1737 result_layer =
1738 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1739 test_point);
1740 ASSERT_TRUE(result_layer);
1741 EXPECT_EQ(12345, result_layer->id());
1744 TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSimpleClippedLayer) {
1745 // Test that hit-checking will only work for the visible portion of a layer,
1746 // and not the entire layer bounds. Here we just test the simple axis-aligned
1747 // case.
1748 gfx::Transform identity_matrix;
1749 gfx::Point3F transform_origin;
1751 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1752 SetLayerPropertiesForTesting(root.get(),
1753 identity_matrix,
1754 transform_origin,
1755 gfx::PointF(),
1756 gfx::Size(100, 100),
1757 true,
1758 false);
1760 scoped_ptr<LayerImpl> clipping_layer =
1761 LayerImpl::Create(host_impl().active_tree(), 123);
1762 // this layer is positioned, and hit testing should correctly know where the
1763 // layer is located.
1764 gfx::PointF position(25.f, 25.f);
1765 gfx::Size bounds(50, 50);
1766 SetLayerPropertiesForTesting(clipping_layer.get(),
1767 identity_matrix,
1768 transform_origin,
1769 position,
1770 bounds,
1771 true,
1772 false);
1773 clipping_layer->SetMasksToBounds(true);
1775 scoped_ptr<LayerImpl> child =
1776 LayerImpl::Create(host_impl().active_tree(), 456);
1777 Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1778 position = gfx::PointF(-50.f, -50.f);
1779 bounds = gfx::Size(300, 300);
1780 SetLayerPropertiesForTesting(child.get(),
1781 identity_matrix,
1782 transform_origin,
1783 position,
1784 bounds,
1785 true,
1786 false);
1787 child->SetDrawsContent(true);
1788 child->SetTouchEventHandlerRegion(touch_handler_region);
1789 clipping_layer->AddChild(child.Pass());
1790 root->AddChild(clipping_layer.Pass());
1793 host_impl().SetViewportSize(root->bounds());
1794 host_impl().active_tree()->SetRootLayer(root.Pass());
1795 host_impl().active_tree()->UpdateDrawProperties();
1797 // Sanity check the scenario we just created.
1798 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1799 ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1800 ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
1802 // Hit checking for a point outside the layer should return a null pointer.
1803 // Despite the child layer being very large, it should be clipped to the root
1804 // layer's bounds.
1805 gfx::Point test_point(24, 24);
1806 LayerImpl* result_layer =
1807 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1808 test_point);
1809 EXPECT_FALSE(result_layer);
1811 // Hit checking for a point inside the layer, but outside the touch handler
1812 // region should return a null pointer.
1813 test_point = gfx::Point(35, 35);
1814 result_layer =
1815 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1816 test_point);
1817 EXPECT_FALSE(result_layer);
1819 test_point = gfx::Point(74, 74);
1820 result_layer =
1821 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1822 test_point);
1823 EXPECT_FALSE(result_layer);
1825 // Hit checking for a point inside the touch event handler region should
1826 // return the root layer.
1827 test_point = gfx::Point(25, 25);
1828 result_layer =
1829 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1830 test_point);
1831 ASSERT_TRUE(result_layer);
1832 EXPECT_EQ(456, result_layer->id());
1834 test_point = gfx::Point(34, 34);
1835 result_layer =
1836 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1837 test_point);
1838 ASSERT_TRUE(result_layer);
1839 EXPECT_EQ(456, result_layer->id());
1842 TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) {
1843 gfx::Transform identity_matrix;
1844 gfx::Point3F transform_origin;
1846 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1847 SetLayerPropertiesForTesting(root.get(),
1848 identity_matrix,
1849 transform_origin,
1850 gfx::PointF(),
1851 gfx::Size(100, 100),
1852 true,
1853 false);
1855 scoped_ptr<LayerImpl> touch_layer =
1856 LayerImpl::Create(host_impl().active_tree(), 123);
1857 // this layer is positioned, and hit testing should correctly know where the
1858 // layer is located.
1859 gfx::PointF position;
1860 gfx::Size bounds(50, 50);
1861 SetLayerPropertiesForTesting(touch_layer.get(),
1862 identity_matrix,
1863 transform_origin,
1864 position,
1865 bounds,
1866 true,
1867 false);
1868 touch_layer->SetDrawsContent(true);
1869 touch_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50));
1870 root->AddChild(touch_layer.Pass());
1874 scoped_ptr<LayerImpl> notouch_layer =
1875 LayerImpl::Create(host_impl().active_tree(), 1234);
1876 // this layer is positioned, and hit testing should correctly know where the
1877 // layer is located.
1878 gfx::PointF position(0, 25);
1879 gfx::Size bounds(50, 50);
1880 SetLayerPropertiesForTesting(notouch_layer.get(),
1881 identity_matrix,
1882 transform_origin,
1883 position,
1884 bounds,
1885 true,
1886 false);
1887 notouch_layer->SetDrawsContent(true);
1888 root->AddChild(notouch_layer.Pass());
1891 host_impl().SetViewportSize(root->bounds());
1892 host_impl().active_tree()->SetRootLayer(root.Pass());
1893 host_impl().active_tree()->UpdateDrawProperties();
1895 // Sanity check the scenario we just created.
1896 ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1897 ASSERT_EQ(2u, root_layer()->render_surface()->layer_list().size());
1898 ASSERT_EQ(123, root_layer()->render_surface()->layer_list().at(0)->id());
1899 ASSERT_EQ(1234, root_layer()->render_surface()->layer_list().at(1)->id());
1901 gfx::Point test_point(35, 35);
1902 LayerImpl* result_layer =
1903 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1904 test_point);
1906 // We should have passed through the no-touch layer and found the layer
1907 // behind it.
1908 EXPECT_TRUE(result_layer);
1910 host_impl().active_tree()->LayerById(1234)->SetContentsOpaque(true);
1911 result_layer =
1912 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1913 test_point);
1915 // Even with an opaque layer in the middle, we should still find the layer
1916 // with
1917 // the touch handler behind it (since we can't assume that opaque layers are
1918 // opaque to hit testing).
1919 EXPECT_TRUE(result_layer);
1921 test_point = gfx::Point(35, 15);
1922 result_layer =
1923 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1924 test_point);
1925 ASSERT_TRUE(result_layer);
1926 EXPECT_EQ(123, result_layer->id());
1928 test_point = gfx::Point(35, 65);
1929 result_layer =
1930 host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1931 test_point);
1932 EXPECT_FALSE(result_layer);
1935 } // namespace
1936 } // namespace cc