Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / cc / trees / layer_tree_impl_unittest.cc
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.
4
5 #include "cc/trees/layer_tree_impl.h"
6
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/geometry/size_conversions.h"
17
18 namespace cc {
19 namespace {
20
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(FakeOutputSurface::Create3d()));
29   }
30
31   FakeLayerTreeHostImpl& host_impl() { return *host_impl_; }
32
33   LayerImpl* root_layer() { return host_impl_->active_tree()->root_layer(); }
34
35   const LayerImplList& RenderSurfaceLayerList() const {
36     return host_impl_->active_tree()->RenderSurfaceLayerList();
37   }
38
39  private:
40   TestSharedBitmapManager shared_bitmap_manager_;
41   FakeImplProxy proxy_;
42   scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
43 };
44
45 TEST_F(LayerTreeImplTest, HitTestingForSingleLayer) {
46   scoped_ptr<LayerImpl> root =
47       LayerImpl::Create(host_impl().active_tree(), 12345);
48
49   gfx::Transform identity_matrix;
50   gfx::Point3F transform_origin;
51   gfx::PointF position;
52   gfx::Size bounds(100, 100);
53   SetLayerPropertiesForTesting(root.get(),
54                                identity_matrix,
55                                transform_origin,
56                                position,
57                                bounds,
58                                true,
59                                false);
60   root->SetDrawsContent(true);
61
62   host_impl().SetViewportSize(root->bounds());
63   host_impl().active_tree()->SetRootLayer(root.Pass());
64   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
65
66   // Sanity check the scenario we just created.
67   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
68   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
69
70   // Hit testing for a point outside the layer should return a null pointer.
71   gfx::Point test_point(101, 101);
72   LayerImpl* result_layer =
73       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
74   EXPECT_FALSE(result_layer);
75
76   test_point = gfx::Point(-1, -1);
77   result_layer =
78       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
79   EXPECT_FALSE(result_layer);
80
81   // Hit testing for a point inside should return the root layer.
82   test_point = gfx::Point(1, 1);
83   result_layer =
84       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
85   ASSERT_TRUE(result_layer);
86   EXPECT_EQ(12345, result_layer->id());
87
88   test_point = gfx::Point(99, 99);
89   result_layer =
90       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
91   ASSERT_TRUE(result_layer);
92   EXPECT_EQ(12345, result_layer->id());
93 }
94
95 TEST_F(LayerTreeImplTest, HitTestingForSingleLayerAndHud) {
96   scoped_ptr<LayerImpl> root =
97       LayerImpl::Create(host_impl().active_tree(), 12345);
98   scoped_ptr<HeadsUpDisplayLayerImpl> hud =
99       HeadsUpDisplayLayerImpl::Create(host_impl().active_tree(), 11111);
100
101   gfx::Transform identity_matrix;
102   gfx::Point3F transform_origin;
103   gfx::PointF position;
104   gfx::Size bounds(100, 100);
105   SetLayerPropertiesForTesting(root.get(),
106                                identity_matrix,
107                                transform_origin,
108                                position,
109                                bounds,
110                                true,
111                                false);
112   root->SetDrawsContent(true);
113
114   // Create hud and add it as a child of root.
115   gfx::Size hud_bounds(200, 200);
116   SetLayerPropertiesForTesting(hud.get(),
117                                identity_matrix,
118                                transform_origin,
119                                position,
120                                hud_bounds,
121                                true,
122                                false);
123   hud->SetDrawsContent(true);
124
125   host_impl().active_tree()->set_hud_layer(hud.get());
126   root->AddChild(hud.Pass());
127
128   host_impl().SetViewportSize(hud_bounds);
129   host_impl().active_tree()->SetRootLayer(root.Pass());
130   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
131
132   // Sanity check the scenario we just created.
133   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
134   ASSERT_EQ(2u, root_layer()->render_surface()->layer_list().size());
135
136   // Hit testing for a point inside HUD, but outside root should return null
137   gfx::Point test_point(101, 101);
138   LayerImpl* result_layer =
139       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
140   EXPECT_FALSE(result_layer);
141
142   test_point = gfx::Point(-1, -1);
143   result_layer =
144       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
145   EXPECT_FALSE(result_layer);
146
147   // Hit testing for a point inside should return the root layer, never the HUD
148   // layer.
149   test_point = gfx::Point(1, 1);
150   result_layer =
151       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
152   ASSERT_TRUE(result_layer);
153   EXPECT_EQ(12345, result_layer->id());
154
155   test_point = gfx::Point(99, 99);
156   result_layer =
157       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
158   ASSERT_TRUE(result_layer);
159   EXPECT_EQ(12345, result_layer->id());
160 }
161
162 TEST_F(LayerTreeImplTest, HitTestingForUninvertibleTransform) {
163   scoped_ptr<LayerImpl> root =
164       LayerImpl::Create(host_impl().active_tree(), 12345);
165
166   gfx::Transform uninvertible_transform;
167   uninvertible_transform.matrix().set(0, 0, 0.0);
168   uninvertible_transform.matrix().set(1, 1, 0.0);
169   uninvertible_transform.matrix().set(2, 2, 0.0);
170   uninvertible_transform.matrix().set(3, 3, 0.0);
171   ASSERT_FALSE(uninvertible_transform.IsInvertible());
172
173   gfx::Transform identity_matrix;
174   gfx::Point3F transform_origin;
175   gfx::PointF position;
176   gfx::Size bounds(100, 100);
177   SetLayerPropertiesForTesting(root.get(),
178                                uninvertible_transform,
179                                transform_origin,
180                                position,
181                                bounds,
182                                true,
183                                false);
184   root->SetDrawsContent(true);
185
186   host_impl().SetViewportSize(root->bounds());
187   host_impl().active_tree()->SetRootLayer(root.Pass());
188   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
189   // Sanity check the scenario we just created.
190   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
191   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
192   ASSERT_FALSE(root_layer()->screen_space_transform().IsInvertible());
193
194   // Hit testing any point should not hit the layer. If the invertible matrix is
195   // accidentally ignored and treated like an identity, then the hit testing
196   // will incorrectly hit the layer when it shouldn't.
197   gfx::Point test_point(1, 1);
198   LayerImpl* result_layer =
199       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
200   EXPECT_FALSE(result_layer);
201
202   test_point = gfx::Point(10, 10);
203   result_layer =
204       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
205   EXPECT_FALSE(result_layer);
206
207   test_point = gfx::Point(10, 30);
208   result_layer =
209       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
210   EXPECT_FALSE(result_layer);
211
212   test_point = gfx::Point(50, 50);
213   result_layer =
214       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
215   EXPECT_FALSE(result_layer);
216
217   test_point = gfx::Point(67, 48);
218   result_layer =
219       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
220   EXPECT_FALSE(result_layer);
221
222   test_point = gfx::Point(99, 99);
223   result_layer =
224       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
225   EXPECT_FALSE(result_layer);
226
227   test_point = gfx::Point(-1, -1);
228   result_layer =
229       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
230   EXPECT_FALSE(result_layer);
231 }
232
233 TEST_F(LayerTreeImplTest, HitTestingForSinglePositionedLayer) {
234   scoped_ptr<LayerImpl> root =
235       LayerImpl::Create(host_impl().active_tree(), 12345);
236
237   gfx::Transform identity_matrix;
238   gfx::Point3F transform_origin;
239   // this layer is positioned, and hit testing should correctly know where the
240   // layer is located.
241   gfx::PointF position(50.f, 50.f);
242   gfx::Size bounds(100, 100);
243   SetLayerPropertiesForTesting(root.get(),
244                                identity_matrix,
245                                transform_origin,
246                                position,
247                                bounds,
248                                true,
249                                false);
250   root->SetDrawsContent(true);
251
252   host_impl().SetViewportSize(root->bounds());
253   host_impl().active_tree()->SetRootLayer(root.Pass());
254   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
255
256   // Sanity check the scenario we just created.
257   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
258   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
259
260   // Hit testing for a point outside the layer should return a null pointer.
261   gfx::Point test_point(49, 49);
262   LayerImpl* result_layer =
263       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
264   EXPECT_FALSE(result_layer);
265
266   // Even though the layer exists at (101, 101), it should not be visible there
267   // since the root render surface would clamp it.
268   test_point = gfx::Point(101, 101);
269   result_layer =
270       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
271   EXPECT_FALSE(result_layer);
272
273   // Hit testing for a point inside should return the root layer.
274   test_point = gfx::Point(51, 51);
275   result_layer =
276       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
277   ASSERT_TRUE(result_layer);
278   EXPECT_EQ(12345, result_layer->id());
279
280   test_point = gfx::Point(99, 99);
281   result_layer =
282       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
283   ASSERT_TRUE(result_layer);
284   EXPECT_EQ(12345, result_layer->id());
285 }
286
287 TEST_F(LayerTreeImplTest, HitTestingForSingleRotatedLayer) {
288   scoped_ptr<LayerImpl> root =
289       LayerImpl::Create(host_impl().active_tree(), 12345);
290
291   gfx::Transform identity_matrix;
292   gfx::Transform rotation45_degrees_about_center;
293   rotation45_degrees_about_center.Translate(50.0, 50.0);
294   rotation45_degrees_about_center.RotateAboutZAxis(45.0);
295   rotation45_degrees_about_center.Translate(-50.0, -50.0);
296   gfx::Point3F transform_origin;
297   gfx::PointF position;
298   gfx::Size bounds(100, 100);
299   SetLayerPropertiesForTesting(root.get(),
300                                rotation45_degrees_about_center,
301                                transform_origin,
302                                position,
303                                bounds,
304                                true,
305                                false);
306   root->SetDrawsContent(true);
307
308   host_impl().SetViewportSize(root->bounds());
309   host_impl().active_tree()->SetRootLayer(root.Pass());
310   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
311
312   // Sanity check the scenario we just created.
313   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
314   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
315
316   // Hit testing for points outside the layer.
317   // These corners would have been inside the un-transformed layer, but they
318   // should not hit the correctly transformed layer.
319   gfx::Point test_point(99, 99);
320   LayerImpl* result_layer =
321       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
322   EXPECT_FALSE(result_layer);
323
324   test_point = gfx::Point(1, 1);
325   result_layer =
326       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
327   EXPECT_FALSE(result_layer);
328
329   // Hit testing for a point inside should return the root layer.
330   test_point = gfx::Point(1, 50);
331   result_layer =
332       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
333   ASSERT_TRUE(result_layer);
334   EXPECT_EQ(12345, result_layer->id());
335
336   // Hit testing the corners that would overlap the unclipped layer, but are
337   // outside the clipped region.
338   test_point = gfx::Point(50, -1);
339   result_layer =
340       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
341   ASSERT_FALSE(result_layer);
342
343   test_point = gfx::Point(-1, 50);
344   result_layer =
345       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
346   ASSERT_FALSE(result_layer);
347 }
348
349 TEST_F(LayerTreeImplTest, HitTestingForSinglePerspectiveLayer) {
350   scoped_ptr<LayerImpl> root =
351       LayerImpl::Create(host_impl().active_tree(), 12345);
352
353   gfx::Transform identity_matrix;
354
355   // perspective_projection_about_center * translation_by_z is designed so that
356   // the 100 x 100 layer becomes 50 x 50, and remains centered at (50, 50).
357   gfx::Transform perspective_projection_about_center;
358   perspective_projection_about_center.Translate(50.0, 50.0);
359   perspective_projection_about_center.ApplyPerspectiveDepth(1.0);
360   perspective_projection_about_center.Translate(-50.0, -50.0);
361   gfx::Transform translation_by_z;
362   translation_by_z.Translate3d(0.0, 0.0, -1.0);
363
364   gfx::Point3F transform_origin;
365   gfx::PointF position;
366   gfx::Size bounds(100, 100);
367   SetLayerPropertiesForTesting(
368       root.get(),
369       perspective_projection_about_center * translation_by_z,
370       transform_origin,
371       position,
372       bounds,
373       true,
374       false);
375   root->SetDrawsContent(true);
376
377   host_impl().SetViewportSize(root->bounds());
378   host_impl().active_tree()->SetRootLayer(root.Pass());
379   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
380
381   // Sanity check the scenario we just created.
382   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
383   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
384
385   // Hit testing for points outside the layer.
386   // These corners would have been inside the un-transformed layer, but they
387   // should not hit the correctly transformed layer.
388   gfx::Point test_point(24, 24);
389   LayerImpl* result_layer =
390       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
391   EXPECT_FALSE(result_layer);
392
393   test_point = gfx::Point(76, 76);
394   result_layer =
395       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
396   EXPECT_FALSE(result_layer);
397
398   // Hit testing for a point inside should return the root layer.
399   test_point = gfx::Point(26, 26);
400   result_layer =
401       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
402   ASSERT_TRUE(result_layer);
403   EXPECT_EQ(12345, result_layer->id());
404
405   test_point = gfx::Point(74, 74);
406   result_layer =
407       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
408   ASSERT_TRUE(result_layer);
409   EXPECT_EQ(12345, result_layer->id());
410 }
411
412 TEST_F(LayerTreeImplTest, HitTestingForSingleLayerWithScaledContents) {
413   // A layer's visible content rect is actually in the layer's content space.
414   // The screen space transform converts from the layer's origin space to screen
415   // space. This test makes sure that hit testing works correctly accounts for
416   // the contents scale.  A contents scale that is not 1 effectively forces a
417   // non-identity transform between layer's content space and layer's origin
418   // space. The hit testing code must take this into account.
419   //
420   // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
421   // contents scale is ignored, then hit testing will mis-interpret the visible
422   // content rect as being larger than the actual bounds of the layer.
423   //
424   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
425
426   gfx::Transform identity_matrix;
427   gfx::Point3F transform_origin;
428
429   SetLayerPropertiesForTesting(root.get(),
430                                identity_matrix,
431                                transform_origin,
432                                gfx::PointF(),
433                                gfx::Size(100, 100),
434                                true,
435                                false);
436   {
437     gfx::PointF position(25.f, 25.f);
438     gfx::Size bounds(50, 50);
439     scoped_ptr<LayerImpl> test_layer =
440         LayerImpl::Create(host_impl().active_tree(), 12345);
441     SetLayerPropertiesForTesting(test_layer.get(),
442                                  identity_matrix,
443                                  transform_origin,
444                                  position,
445                                  bounds,
446                                  true,
447                                  false);
448
449     // override content bounds and contents scale
450     test_layer->SetContentBounds(gfx::Size(100, 100));
451     test_layer->SetContentsScale(2, 2);
452
453     test_layer->SetDrawsContent(true);
454     root->AddChild(test_layer.Pass());
455   }
456
457   host_impl().SetViewportSize(root->bounds());
458   host_impl().active_tree()->SetRootLayer(root.Pass());
459   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
460
461   // Sanity check the scenario we just created.
462   // The visible content rect for test_layer is actually 100x100, even though
463   // its layout size is 50x50, positioned at 25x25.
464   LayerImpl* test_layer =
465       host_impl().active_tree()->root_layer()->children()[0];
466   EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer->visible_content_rect());
467   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
468   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
469
470   // Hit testing for a point outside the layer should return a null pointer (the
471   // root layer does not draw content, so it will not be hit tested either).
472   gfx::Point test_point(101, 101);
473   LayerImpl* result_layer =
474       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
475   EXPECT_FALSE(result_layer);
476
477   test_point = gfx::Point(24, 24);
478   result_layer =
479       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
480   EXPECT_FALSE(result_layer);
481
482   test_point = gfx::Point(76, 76);
483   result_layer =
484       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
485   EXPECT_FALSE(result_layer);
486
487   // Hit testing for a point inside should return the test layer.
488   test_point = gfx::Point(26, 26);
489   result_layer =
490       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
491   ASSERT_TRUE(result_layer);
492   EXPECT_EQ(12345, result_layer->id());
493
494   test_point = gfx::Point(74, 74);
495   result_layer =
496       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
497   ASSERT_TRUE(result_layer);
498   EXPECT_EQ(12345, result_layer->id());
499 }
500
501 TEST_F(LayerTreeImplTest, HitTestingForSimpleClippedLayer) {
502   // Test that hit-testing will only work for the visible portion of a layer,
503   // and not the entire layer bounds. Here we just test the simple axis-aligned
504   // case.
505   gfx::Transform identity_matrix;
506   gfx::Point3F transform_origin;
507
508   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
509   SetLayerPropertiesForTesting(root.get(),
510                                identity_matrix,
511                                transform_origin,
512                                gfx::PointF(),
513                                gfx::Size(100, 100),
514                                true,
515                                false);
516   {
517     scoped_ptr<LayerImpl> clipping_layer =
518         LayerImpl::Create(host_impl().active_tree(), 123);
519     // this layer is positioned, and hit testing should correctly know where the
520     // layer is located.
521     gfx::PointF position(25.f, 25.f);
522     gfx::Size bounds(50, 50);
523     SetLayerPropertiesForTesting(clipping_layer.get(),
524                                  identity_matrix,
525                                  transform_origin,
526                                  position,
527                                  bounds,
528                                  true,
529                                  false);
530     clipping_layer->SetMasksToBounds(true);
531
532     scoped_ptr<LayerImpl> child =
533         LayerImpl::Create(host_impl().active_tree(), 456);
534     position = gfx::PointF(-50.f, -50.f);
535     bounds = gfx::Size(300, 300);
536     SetLayerPropertiesForTesting(child.get(),
537                                  identity_matrix,
538                                  transform_origin,
539                                  position,
540                                  bounds,
541                                  true,
542                                  false);
543     child->SetDrawsContent(true);
544     clipping_layer->AddChild(child.Pass());
545     root->AddChild(clipping_layer.Pass());
546   }
547
548   host_impl().SetViewportSize(root->bounds());
549   host_impl().active_tree()->SetRootLayer(root.Pass());
550   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
551
552   // Sanity check the scenario we just created.
553   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
554   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
555   ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
556
557   // Hit testing for a point outside the layer should return a null pointer.
558   // Despite the child layer being very large, it should be clipped to the root
559   // layer's bounds.
560   gfx::Point test_point(24, 24);
561   LayerImpl* result_layer =
562       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
563   EXPECT_FALSE(result_layer);
564
565   // Even though the layer exists at (101, 101), it should not be visible there
566   // since the clipping_layer would clamp it.
567   test_point = gfx::Point(76, 76);
568   result_layer =
569       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
570   EXPECT_FALSE(result_layer);
571
572   // Hit testing for a point inside should return the child layer.
573   test_point = gfx::Point(26, 26);
574   result_layer =
575       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
576   ASSERT_TRUE(result_layer);
577   EXPECT_EQ(456, result_layer->id());
578
579   test_point = gfx::Point(74, 74);
580   result_layer =
581       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
582   ASSERT_TRUE(result_layer);
583   EXPECT_EQ(456, result_layer->id());
584 }
585
586 TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) {
587   // This test checks whether hit testing correctly avoids hit testing with
588   // multiple ancestors that clip in non axis-aligned ways. To pass this test,
589   // the hit testing algorithm needs to recognize that multiple parent layers
590   // may clip the layer, and should not actually hit those clipped areas.
591   //
592   // The child and grand_child layers are both initialized to clip the
593   // rotated_leaf. The child layer is rotated about the top-left corner, so that
594   // the root + child clips combined create a triangle. The rotated_leaf will
595   // only be visible where it overlaps this triangle.
596   //
597   scoped_ptr<LayerImpl> root =
598       LayerImpl::Create(host_impl().active_tree(), 123);
599
600   gfx::Transform identity_matrix;
601   gfx::Point3F transform_origin;
602   gfx::PointF position;
603   gfx::Size bounds(100, 100);
604   SetLayerPropertiesForTesting(root.get(),
605                                identity_matrix,
606                                transform_origin,
607                                position,
608                                bounds,
609                                true,
610                                false);
611   root->SetMasksToBounds(true);
612   {
613     scoped_ptr<LayerImpl> child =
614         LayerImpl::Create(host_impl().active_tree(), 456);
615     scoped_ptr<LayerImpl> grand_child =
616         LayerImpl::Create(host_impl().active_tree(), 789);
617     scoped_ptr<LayerImpl> rotated_leaf =
618         LayerImpl::Create(host_impl().active_tree(), 2468);
619
620     position = gfx::PointF(10.f, 10.f);
621     bounds = gfx::Size(80, 80);
622     SetLayerPropertiesForTesting(child.get(),
623                                  identity_matrix,
624                                  transform_origin,
625                                  position,
626                                  bounds,
627                                  true,
628                                  false);
629     child->SetMasksToBounds(true);
630
631     gfx::Transform rotation45_degrees_about_corner;
632     rotation45_degrees_about_corner.RotateAboutZAxis(45.0);
633
634     // remember, positioned with respect to its parent which is already at 10,
635     // 10
636     position = gfx::PointF();
637     bounds =
638         gfx::Size(200, 200);  // to ensure it covers at least sqrt(2) * 100.
639     SetLayerPropertiesForTesting(grand_child.get(),
640                                  rotation45_degrees_about_corner,
641                                  transform_origin,
642                                  position,
643                                  bounds,
644                                  true,
645                                  false);
646     grand_child->SetMasksToBounds(true);
647
648     // Rotates about the center of the layer
649     gfx::Transform rotated_leaf_transform;
650     rotated_leaf_transform.Translate(
651         -10.0, -10.0);  // cancel out the grand_parent's position
652     rotated_leaf_transform.RotateAboutZAxis(
653         -45.0);  // cancel out the corner 45-degree rotation of the parent.
654     rotated_leaf_transform.Translate(50.0, 50.0);
655     rotated_leaf_transform.RotateAboutZAxis(45.0);
656     rotated_leaf_transform.Translate(-50.0, -50.0);
657     position = gfx::PointF();
658     bounds = gfx::Size(100, 100);
659     SetLayerPropertiesForTesting(rotated_leaf.get(),
660                                  rotated_leaf_transform,
661                                  transform_origin,
662                                  position,
663                                  bounds,
664                                  true,
665                                  false);
666     rotated_leaf->SetDrawsContent(true);
667
668     grand_child->AddChild(rotated_leaf.Pass());
669     child->AddChild(grand_child.Pass());
670     root->AddChild(child.Pass());
671   }
672
673   host_impl().SetViewportSize(root->bounds());
674   host_impl().active_tree()->SetRootLayer(root.Pass());
675   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
676
677   // Sanity check the scenario we just created.
678   // The grand_child is expected to create a render surface because it
679   // MasksToBounds and is not axis aligned.
680   ASSERT_EQ(2u, RenderSurfaceLayerList().size());
681   ASSERT_EQ(
682       1u,
683       RenderSurfaceLayerList().at(0)->render_surface()->layer_list().size());
684   ASSERT_EQ(789,
685             RenderSurfaceLayerList()
686                 .at(0)
687                 ->render_surface()
688                 ->layer_list()
689                 .at(0)
690                 ->id());  // grand_child's surface.
691   ASSERT_EQ(
692       1u,
693       RenderSurfaceLayerList().at(1)->render_surface()->layer_list().size());
694   ASSERT_EQ(
695       2468,
696       RenderSurfaceLayerList()[1]->render_surface()->layer_list().at(0)->id());
697
698   // (11, 89) is close to the the bottom left corner within the clip, but it is
699   // not inside the layer.
700   gfx::Point test_point(11, 89);
701   LayerImpl* result_layer =
702       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
703   EXPECT_FALSE(result_layer);
704
705   // Closer inwards from the bottom left will overlap the layer.
706   test_point = gfx::Point(25, 75);
707   result_layer =
708       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
709   ASSERT_TRUE(result_layer);
710   EXPECT_EQ(2468, result_layer->id());
711
712   // (4, 50) is inside the unclipped layer, but that corner of the layer should
713   // be clipped away by the grandparent and should not get hit. If hit testing
714   // blindly uses visible content rect without considering how parent may clip
715   // the layer, then hit testing would accidentally think that the point
716   // successfully hits the layer.
717   test_point = gfx::Point(4, 50);
718   result_layer =
719       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
720   EXPECT_FALSE(result_layer);
721
722   // (11, 50) is inside the layer and within the clipped area.
723   test_point = gfx::Point(11, 50);
724   result_layer =
725       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
726   ASSERT_TRUE(result_layer);
727   EXPECT_EQ(2468, result_layer->id());
728
729   // Around the middle, just to the right and up, would have hit the layer
730   // except that that area should be clipped away by the parent.
731   test_point = gfx::Point(51, 49);
732   result_layer =
733       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
734   EXPECT_FALSE(result_layer);
735
736   // Around the middle, just to the left and down, should successfully hit the
737   // layer.
738   test_point = gfx::Point(49, 51);
739   result_layer =
740       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
741   ASSERT_TRUE(result_layer);
742   EXPECT_EQ(2468, result_layer->id());
743 }
744
745 TEST_F(LayerTreeImplTest, HitTestingForNonClippingIntermediateLayer) {
746   // This test checks that hit testing code does not accidentally clip to layer
747   // bounds for a layer that actually does not clip.
748   gfx::Transform identity_matrix;
749   gfx::Point3F transform_origin;
750
751   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
752   SetLayerPropertiesForTesting(root.get(),
753                                identity_matrix,
754                                transform_origin,
755                                gfx::PointF(),
756                                gfx::Size(100, 100),
757                                true,
758                                false);
759   {
760     scoped_ptr<LayerImpl> intermediate_layer =
761         LayerImpl::Create(host_impl().active_tree(), 123);
762     // this layer is positioned, and hit testing should correctly know where the
763     // layer is located.
764     gfx::PointF position(10.f, 10.f);
765     gfx::Size bounds(50, 50);
766     SetLayerPropertiesForTesting(intermediate_layer.get(),
767                                  identity_matrix,
768                                  transform_origin,
769                                  position,
770                                  bounds,
771                                  true,
772                                  false);
773     // Sanity check the intermediate layer should not clip.
774     ASSERT_FALSE(intermediate_layer->masks_to_bounds());
775     ASSERT_FALSE(intermediate_layer->mask_layer());
776
777     // The child of the intermediate_layer is translated so that it does not
778     // overlap intermediate_layer at all.  If child is incorrectly clipped, we
779     // would not be able to hit it successfully.
780     scoped_ptr<LayerImpl> child =
781         LayerImpl::Create(host_impl().active_tree(), 456);
782     position = gfx::PointF(60.f, 60.f);  // 70, 70 in screen space
783     bounds = gfx::Size(20, 20);
784     SetLayerPropertiesForTesting(child.get(),
785                                  identity_matrix,
786                                  transform_origin,
787                                  position,
788                                  bounds,
789                                  true,
790                                  false);
791     child->SetDrawsContent(true);
792     intermediate_layer->AddChild(child.Pass());
793     root->AddChild(intermediate_layer.Pass());
794   }
795
796   host_impl().SetViewportSize(root->bounds());
797   host_impl().active_tree()->SetRootLayer(root.Pass());
798   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
799
800   // Sanity check the scenario we just created.
801   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
802   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
803   ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
804
805   // Hit testing for a point outside the layer should return a null pointer.
806   gfx::Point test_point(69, 69);
807   LayerImpl* result_layer =
808       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
809   EXPECT_FALSE(result_layer);
810
811   test_point = gfx::Point(91, 91);
812   result_layer =
813       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
814   EXPECT_FALSE(result_layer);
815
816   // Hit testing for a point inside should return the child layer.
817   test_point = gfx::Point(71, 71);
818   result_layer =
819       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
820   ASSERT_TRUE(result_layer);
821   EXPECT_EQ(456, result_layer->id());
822
823   test_point = gfx::Point(89, 89);
824   result_layer =
825       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
826   ASSERT_TRUE(result_layer);
827   EXPECT_EQ(456, result_layer->id());
828 }
829
830 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) {
831   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
832
833   gfx::Transform identity_matrix;
834   gfx::Point3F transform_origin;
835   gfx::PointF position;
836   gfx::Size bounds(100, 100);
837   SetLayerPropertiesForTesting(root.get(),
838                                identity_matrix,
839                                transform_origin,
840                                position,
841                                bounds,
842                                true,
843                                false);
844   root->SetDrawsContent(true);
845   {
846     // child 1 and child2 are initialized to overlap between x=50 and x=60.
847     // grand_child is set to overlap both child1 and child2 between y=50 and
848     // y=60.  The expected stacking order is: (front) child2, (second)
849     // grand_child, (third) child1, and (back) the root layer behind all other
850     // layers.
851
852     scoped_ptr<LayerImpl> child1 =
853         LayerImpl::Create(host_impl().active_tree(), 2);
854     scoped_ptr<LayerImpl> child2 =
855         LayerImpl::Create(host_impl().active_tree(), 3);
856     scoped_ptr<LayerImpl> grand_child1 =
857         LayerImpl::Create(host_impl().active_tree(), 4);
858
859     position = gfx::PointF(10.f, 10.f);
860     bounds = gfx::Size(50, 50);
861     SetLayerPropertiesForTesting(child1.get(),
862                                  identity_matrix,
863                                  transform_origin,
864                                  position,
865                                  bounds,
866                                  true,
867                                  false);
868     child1->SetDrawsContent(true);
869
870     position = gfx::PointF(50.f, 10.f);
871     bounds = gfx::Size(50, 50);
872     SetLayerPropertiesForTesting(child2.get(),
873                                  identity_matrix,
874                                  transform_origin,
875                                  position,
876                                  bounds,
877                                  true,
878                                  false);
879     child2->SetDrawsContent(true);
880
881     // Remember that grand_child is positioned with respect to its parent (i.e.
882     // child1).  In screen space, the intended position is (10, 50), with size
883     // 100 x 50.
884     position = gfx::PointF(0.f, 40.f);
885     bounds = gfx::Size(100, 50);
886     SetLayerPropertiesForTesting(grand_child1.get(),
887                                  identity_matrix,
888                                  transform_origin,
889                                  position,
890                                  bounds,
891                                  true,
892                                  false);
893     grand_child1->SetDrawsContent(true);
894
895     child1->AddChild(grand_child1.Pass());
896     root->AddChild(child1.Pass());
897     root->AddChild(child2.Pass());
898   }
899
900   LayerImpl* child1 = root->children()[0];
901   LayerImpl* child2 = root->children()[1];
902   LayerImpl* grand_child1 = child1->children()[0];
903
904   host_impl().SetViewportSize(root->bounds());
905   host_impl().active_tree()->SetRootLayer(root.Pass());
906   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
907
908   // Sanity check the scenario we just created.
909   ASSERT_TRUE(child1);
910   ASSERT_TRUE(child2);
911   ASSERT_TRUE(grand_child1);
912   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
913
914   RenderSurfaceImpl* root_render_surface = root_layer()->render_surface();
915   ASSERT_EQ(4u, root_render_surface->layer_list().size());
916   ASSERT_EQ(1, root_render_surface->layer_list().at(0)->id());  // root layer
917   ASSERT_EQ(2, root_render_surface->layer_list().at(1)->id());  // child1
918   ASSERT_EQ(4, root_render_surface->layer_list().at(2)->id());  // grand_child1
919   ASSERT_EQ(3, root_render_surface->layer_list().at(3)->id());  // child2
920
921   // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
922   // the root layer.
923   gfx::Point test_point = gfx::Point(1, 1);
924   LayerImpl* result_layer =
925       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
926   ASSERT_TRUE(result_layer);
927   EXPECT_EQ(1, result_layer->id());
928
929   // At (15, 15), child1 and root are the only layers. child1 is expected to be
930   // on top.
931   test_point = gfx::Point(15, 15);
932   result_layer =
933       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
934   ASSERT_TRUE(result_layer);
935   EXPECT_EQ(2, result_layer->id());
936
937   // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
938   test_point = gfx::Point(51, 20);
939   result_layer =
940       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
941   ASSERT_TRUE(result_layer);
942   EXPECT_EQ(3, result_layer->id());
943
944   // At (80, 51), child2 and grand_child1 overlap. child2 is expected to be on
945   // top.
946   test_point = gfx::Point(80, 51);
947   result_layer =
948       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
949   ASSERT_TRUE(result_layer);
950   EXPECT_EQ(3, result_layer->id());
951
952   // At (51, 51), all layers overlap each other. child2 is expected to be on top
953   // of all other layers.
954   test_point = gfx::Point(51, 51);
955   result_layer =
956       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
957   ASSERT_TRUE(result_layer);
958   EXPECT_EQ(3, result_layer->id());
959
960   // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
961   // be on top.
962   test_point = gfx::Point(20, 51);
963   result_layer =
964       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
965   ASSERT_TRUE(result_layer);
966   EXPECT_EQ(4, result_layer->id());
967 }
968
969 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) {
970   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
971
972   gfx::Transform identity_matrix;
973   gfx::Point3F transform_origin;
974   gfx::PointF position;
975   gfx::Size bounds(100, 100);
976   SetLayerPropertiesForTesting(root.get(),
977                                identity_matrix,
978                                transform_origin,
979                                position,
980                                bounds,
981                                true,
982                                false);
983   root->SetDrawsContent(true);
984   root->SetShouldFlattenTransform(false);
985   root->Set3dSortingContextId(1);
986   {
987     // child 1 and child2 are initialized to overlap between x=50 and x=60.
988     // grand_child is set to overlap both child1 and child2 between y=50 and
989     // y=60.  The expected stacking order is: (front) child2, (second)
990     // grand_child, (third) child1, and (back) the root layer behind all other
991     // layers.
992
993     scoped_ptr<LayerImpl> child1 =
994         LayerImpl::Create(host_impl().active_tree(), 2);
995     scoped_ptr<LayerImpl> child2 =
996         LayerImpl::Create(host_impl().active_tree(), 3);
997     scoped_ptr<LayerImpl> grand_child1 =
998         LayerImpl::Create(host_impl().active_tree(), 4);
999
1000     position = gfx::PointF(10.f, 10.f);
1001     bounds = gfx::Size(50, 50);
1002     SetLayerPropertiesForTesting(child1.get(),
1003                                  identity_matrix,
1004                                  transform_origin,
1005                                  position,
1006                                  bounds,
1007                                  true,
1008                                  false);
1009     child1->SetDrawsContent(true);
1010     child1->SetShouldFlattenTransform(false);
1011     child1->Set3dSortingContextId(1);
1012
1013     position = gfx::PointF(50.f, 10.f);
1014     bounds = gfx::Size(50, 50);
1015     gfx::Transform translate_z;
1016     translate_z.Translate3d(0, 0, -10.f);
1017     SetLayerPropertiesForTesting(child2.get(),
1018                                  translate_z,
1019                                  transform_origin,
1020                                  position,
1021                                  bounds,
1022                                  true,
1023                                  false);
1024     child2->SetDrawsContent(true);
1025     child2->SetShouldFlattenTransform(false);
1026     child2->Set3dSortingContextId(1);
1027
1028     // Remember that grand_child is positioned with respect to its parent (i.e.
1029     // child1).  In screen space, the intended position is (10, 50), with size
1030     // 100 x 50.
1031     position = gfx::PointF(0.f, 40.f);
1032     bounds = gfx::Size(100, 50);
1033     SetLayerPropertiesForTesting(grand_child1.get(),
1034                                  identity_matrix,
1035                                  transform_origin,
1036                                  position,
1037                                  bounds,
1038                                  true,
1039                                  false);
1040     grand_child1->SetDrawsContent(true);
1041     grand_child1->SetShouldFlattenTransform(false);
1042
1043     child1->AddChild(grand_child1.Pass());
1044     root->AddChild(child1.Pass());
1045     root->AddChild(child2.Pass());
1046   }
1047
1048   LayerImpl* child1 = root->children()[0];
1049   LayerImpl* child2 = root->children()[1];
1050   LayerImpl* grand_child1 = child1->children()[0];
1051
1052   host_impl().SetViewportSize(root->bounds());
1053   host_impl().active_tree()->SetRootLayer(root.Pass());
1054   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1055
1056   // Sanity check the scenario we just created.
1057   ASSERT_TRUE(child1);
1058   ASSERT_TRUE(child2);
1059   ASSERT_TRUE(grand_child1);
1060   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1061
1062   RenderSurfaceImpl* root_render_surface =
1063       host_impl().active_tree()->root_layer()->render_surface();
1064   ASSERT_EQ(4u, root_render_surface->layer_list().size());
1065   ASSERT_EQ(3, root_render_surface->layer_list().at(0)->id());
1066   ASSERT_EQ(1, root_render_surface->layer_list().at(1)->id());
1067   ASSERT_EQ(2, root_render_surface->layer_list().at(2)->id());
1068   ASSERT_EQ(4, root_render_surface->layer_list().at(3)->id());
1069
1070   // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
1071   // the root layer.
1072   gfx::Point test_point = gfx::Point(1, 1);
1073   LayerImpl* result_layer =
1074       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1075   ASSERT_TRUE(result_layer);
1076   EXPECT_EQ(1, result_layer->id());
1077
1078   // At (15, 15), child1 and root are the only layers. child1 is expected to be
1079   // on top.
1080   test_point = gfx::Point(15, 15);
1081   result_layer =
1082       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1083   ASSERT_TRUE(result_layer);
1084   EXPECT_EQ(2, result_layer->id());
1085
1086   // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
1087   // (because 3 is transformed to the back).
1088   test_point = gfx::Point(51, 20);
1089   result_layer =
1090       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1091   ASSERT_TRUE(result_layer);
1092   EXPECT_EQ(2, result_layer->id());
1093
1094   // 3 Would have been on top if it hadn't been transformed to the background.
1095   // Make sure that it isn't hit.
1096   test_point = gfx::Point(80, 51);
1097   result_layer =
1098       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1099   ASSERT_TRUE(result_layer);
1100   EXPECT_EQ(4, result_layer->id());
1101
1102   // 3 Would have been on top if it hadn't been transformed to the background.
1103   // Make sure that it isn't hit.
1104   test_point = gfx::Point(51, 51);
1105   result_layer =
1106       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1107   ASSERT_TRUE(result_layer);
1108   EXPECT_EQ(4, result_layer->id());
1109
1110   // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
1111   // be on top.
1112   test_point = gfx::Point(20, 51);
1113   result_layer =
1114       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1115   ASSERT_TRUE(result_layer);
1116   EXPECT_EQ(4, result_layer->id());
1117 }
1118
1119 TEST_F(LayerTreeImplTest, HitTestingRespectsClipParents) {
1120   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1121   gfx::Transform identity_matrix;
1122   gfx::Point3F transform_origin;
1123   gfx::PointF position;
1124   gfx::Size bounds(100, 100);
1125   SetLayerPropertiesForTesting(root.get(),
1126                                identity_matrix,
1127                                transform_origin,
1128                                position,
1129                                bounds,
1130                                true,
1131                                false);
1132   root->SetDrawsContent(true);
1133   {
1134     scoped_ptr<LayerImpl> child =
1135         LayerImpl::Create(host_impl().active_tree(), 2);
1136     scoped_ptr<LayerImpl> grand_child =
1137         LayerImpl::Create(host_impl().active_tree(), 4);
1138
1139     position = gfx::PointF(10.f, 10.f);
1140     bounds = gfx::Size(1, 1);
1141     SetLayerPropertiesForTesting(child.get(),
1142                                  identity_matrix,
1143                                  transform_origin,
1144                                  position,
1145                                  bounds,
1146                                  true,
1147                                  false);
1148     child->SetDrawsContent(true);
1149     child->SetMasksToBounds(true);
1150
1151     position = gfx::PointF(0.f, 40.f);
1152     bounds = gfx::Size(100, 50);
1153     SetLayerPropertiesForTesting(grand_child.get(),
1154                                  identity_matrix,
1155                                  transform_origin,
1156                                  position,
1157                                  bounds,
1158                                  true,
1159                                  false);
1160     grand_child->SetDrawsContent(true);
1161     grand_child->SetForceRenderSurface(true);
1162
1163     // This should let |grand_child| "escape" |child|'s clip.
1164     grand_child->SetClipParent(root.get());
1165
1166     child->AddChild(grand_child.Pass());
1167     root->AddChild(child.Pass());
1168   }
1169
1170   host_impl().SetViewportSize(root->bounds());
1171   host_impl().active_tree()->SetRootLayer(root.Pass());
1172   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1173
1174   gfx::Point test_point = gfx::Point(12, 52);
1175   LayerImpl* result_layer =
1176       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1177   ASSERT_TRUE(result_layer);
1178   EXPECT_EQ(4, result_layer->id());
1179 }
1180
1181 TEST_F(LayerTreeImplTest, HitTestingRespectsScrollParents) {
1182   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1183   gfx::Transform identity_matrix;
1184   gfx::Point3F transform_origin;
1185   gfx::PointF position;
1186   gfx::Size bounds(100, 100);
1187   SetLayerPropertiesForTesting(root.get(),
1188                                identity_matrix,
1189                                transform_origin,
1190                                position,
1191                                bounds,
1192                                true,
1193                                false);
1194   root->SetDrawsContent(true);
1195   {
1196     scoped_ptr<LayerImpl> child =
1197         LayerImpl::Create(host_impl().active_tree(), 2);
1198     scoped_ptr<LayerImpl> scroll_child =
1199         LayerImpl::Create(host_impl().active_tree(), 3);
1200     scoped_ptr<LayerImpl> grand_child =
1201         LayerImpl::Create(host_impl().active_tree(), 4);
1202
1203     position = gfx::PointF(10.f, 10.f);
1204     bounds = gfx::Size(1, 1);
1205     SetLayerPropertiesForTesting(child.get(),
1206                                  identity_matrix,
1207                                  transform_origin,
1208                                  position,
1209                                  bounds,
1210                                  true,
1211                                  false);
1212     child->SetDrawsContent(true);
1213     child->SetMasksToBounds(true);
1214
1215     position = gfx::PointF();
1216     bounds = gfx::Size(200, 200);
1217     SetLayerPropertiesForTesting(scroll_child.get(),
1218                                  identity_matrix,
1219                                  transform_origin,
1220                                  position,
1221                                  bounds,
1222                                  true,
1223                                  false);
1224     scroll_child->SetDrawsContent(true);
1225
1226     // This should cause scroll child and its descendants to be affected by
1227     // |child|'s clip.
1228     scroll_child->SetScrollParent(child.get());
1229
1230     SetLayerPropertiesForTesting(grand_child.get(),
1231                                  identity_matrix,
1232                                  transform_origin,
1233                                  position,
1234                                  bounds,
1235                                  true,
1236                                  false);
1237     grand_child->SetDrawsContent(true);
1238     grand_child->SetForceRenderSurface(true);
1239
1240     scroll_child->AddChild(grand_child.Pass());
1241     root->AddChild(scroll_child.Pass());
1242     root->AddChild(child.Pass());
1243   }
1244
1245   host_impl().SetViewportSize(root->bounds());
1246   host_impl().active_tree()->SetRootLayer(root.Pass());
1247   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1248
1249   gfx::Point test_point = gfx::Point(12, 52);
1250   LayerImpl* result_layer =
1251       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1252   // The |test_point| should have been clipped away by |child|, the scroll
1253   // parent, so the only thing that should be hit is |root|.
1254   ASSERT_TRUE(result_layer);
1255   ASSERT_EQ(1, result_layer->id());
1256 }
1257 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) {
1258   //
1259   // The geometry is set up similarly to the previous case, but
1260   // all layers are forced to be render surfaces now.
1261   //
1262   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1263
1264   gfx::Transform identity_matrix;
1265   gfx::Point3F transform_origin;
1266   gfx::PointF position;
1267   gfx::Size bounds(100, 100);
1268   SetLayerPropertiesForTesting(root.get(),
1269                                identity_matrix,
1270                                transform_origin,
1271                                position,
1272                                bounds,
1273                                true,
1274                                false);
1275   root->SetDrawsContent(true);
1276   {
1277     // child 1 and child2 are initialized to overlap between x=50 and x=60.
1278     // grand_child is set to overlap both child1 and child2 between y=50 and
1279     // y=60.  The expected stacking order is: (front) child2, (second)
1280     // grand_child, (third) child1, and (back) the root layer behind all other
1281     // layers.
1282
1283     scoped_ptr<LayerImpl> child1 =
1284         LayerImpl::Create(host_impl().active_tree(), 2);
1285     scoped_ptr<LayerImpl> child2 =
1286         LayerImpl::Create(host_impl().active_tree(), 3);
1287     scoped_ptr<LayerImpl> grand_child1 =
1288         LayerImpl::Create(host_impl().active_tree(), 4);
1289
1290     position = gfx::PointF(10.f, 10.f);
1291     bounds = gfx::Size(50, 50);
1292     SetLayerPropertiesForTesting(child1.get(),
1293                                  identity_matrix,
1294                                  transform_origin,
1295                                  position,
1296                                  bounds,
1297                                  true,
1298                                  false);
1299     child1->SetDrawsContent(true);
1300     child1->SetForceRenderSurface(true);
1301
1302     position = gfx::PointF(50.f, 10.f);
1303     bounds = gfx::Size(50, 50);
1304     SetLayerPropertiesForTesting(child2.get(),
1305                                  identity_matrix,
1306                                  transform_origin,
1307                                  position,
1308                                  bounds,
1309                                  true,
1310                                  false);
1311     child2->SetDrawsContent(true);
1312     child2->SetForceRenderSurface(true);
1313
1314     // Remember that grand_child is positioned with respect to its parent (i.e.
1315     // child1).  In screen space, the intended position is (10, 50), with size
1316     // 100 x 50.
1317     position = gfx::PointF(0.f, 40.f);
1318     bounds = gfx::Size(100, 50);
1319     SetLayerPropertiesForTesting(grand_child1.get(),
1320                                  identity_matrix,
1321                                  transform_origin,
1322                                  position,
1323                                  bounds,
1324                                  true,
1325                                  false);
1326     grand_child1->SetDrawsContent(true);
1327     grand_child1->SetForceRenderSurface(true);
1328
1329     child1->AddChild(grand_child1.Pass());
1330     root->AddChild(child1.Pass());
1331     root->AddChild(child2.Pass());
1332   }
1333
1334   LayerImpl* child1 = root->children()[0];
1335   LayerImpl* child2 = root->children()[1];
1336   LayerImpl* grand_child1 = child1->children()[0];
1337
1338   host_impl().SetViewportSize(root->bounds());
1339   host_impl().active_tree()->SetRootLayer(root.Pass());
1340   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1341
1342   // Sanity check the scenario we just created.
1343   ASSERT_TRUE(child1);
1344   ASSERT_TRUE(child2);
1345   ASSERT_TRUE(grand_child1);
1346   ASSERT_TRUE(child1->render_surface());
1347   ASSERT_TRUE(child2->render_surface());
1348   ASSERT_TRUE(grand_child1->render_surface());
1349   ASSERT_EQ(4u, RenderSurfaceLayerList().size());
1350   // The root surface has the root layer, and child1's and child2's render
1351   // surfaces.
1352   ASSERT_EQ(3u, root_layer()->render_surface()->layer_list().size());
1353   // The child1 surface has the child1 layer and grand_child1's render surface.
1354   ASSERT_EQ(2u, child1->render_surface()->layer_list().size());
1355   ASSERT_EQ(1u, child2->render_surface()->layer_list().size());
1356   ASSERT_EQ(1u, grand_child1->render_surface()->layer_list().size());
1357   ASSERT_EQ(1, RenderSurfaceLayerList().at(0)->id());  // root layer
1358   ASSERT_EQ(2, RenderSurfaceLayerList()[1]->id());     // child1
1359   ASSERT_EQ(4, RenderSurfaceLayerList().at(2)->id());  // grand_child1
1360   ASSERT_EQ(3, RenderSurfaceLayerList()[3]->id());     // child2
1361
1362   // Nothing overlaps the root_layer at (1, 1), so hit testing there should find
1363   // the root layer.
1364   gfx::Point test_point = gfx::Point(1, 1);
1365   LayerImpl* result_layer =
1366       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1367   ASSERT_TRUE(result_layer);
1368   EXPECT_EQ(1, result_layer->id());
1369
1370   // At (15, 15), child1 and root are the only layers. child1 is expected to be
1371   // on top.
1372   test_point = gfx::Point(15, 15);
1373   result_layer =
1374       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1375   ASSERT_TRUE(result_layer);
1376   EXPECT_EQ(2, result_layer->id());
1377
1378   // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
1379   test_point = gfx::Point(51, 20);
1380   result_layer =
1381       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1382   ASSERT_TRUE(result_layer);
1383   EXPECT_EQ(3, result_layer->id());
1384
1385   // At (80, 51), child2 and grand_child1 overlap. child2 is expected to be on
1386   // top.
1387   test_point = gfx::Point(80, 51);
1388   result_layer =
1389       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1390   ASSERT_TRUE(result_layer);
1391   EXPECT_EQ(3, result_layer->id());
1392
1393   // At (51, 51), all layers overlap each other. child2 is expected to be on top
1394   // of all other layers.
1395   test_point = gfx::Point(51, 51);
1396   result_layer =
1397       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1398   ASSERT_TRUE(result_layer);
1399   EXPECT_EQ(3, result_layer->id());
1400
1401   // At (20, 51), child1 and grand_child1 overlap. grand_child1 is expected to
1402   // be on top.
1403   test_point = gfx::Point(20, 51);
1404   result_layer =
1405       host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point);
1406   ASSERT_TRUE(result_layer);
1407   EXPECT_EQ(4, result_layer->id());
1408 }
1409
1410 TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSingleLayer) {
1411   scoped_ptr<LayerImpl> root =
1412       LayerImpl::Create(host_impl().active_tree(), 12345);
1413
1414   gfx::Transform identity_matrix;
1415   Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1416   gfx::Point3F transform_origin;
1417   gfx::PointF position;
1418   gfx::Size bounds(100, 100);
1419   SetLayerPropertiesForTesting(root.get(),
1420                                identity_matrix,
1421                                transform_origin,
1422                                position,
1423                                bounds,
1424                                true,
1425                                false);
1426   root->SetDrawsContent(true);
1427
1428   host_impl().SetViewportSize(root->bounds());
1429   host_impl().active_tree()->SetRootLayer(root.Pass());
1430   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1431
1432   // Sanity check the scenario we just created.
1433   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1434   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1435
1436   // Hit checking for any point should return a null pointer for a layer without
1437   // any touch event handler regions.
1438   gfx::Point test_point(11, 11);
1439   LayerImpl* result_layer =
1440       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1441           test_point);
1442   EXPECT_FALSE(result_layer);
1443
1444   host_impl().active_tree()->root_layer()->SetTouchEventHandlerRegion(
1445       touch_handler_region);
1446   // Hit checking for a point outside the layer should return a null pointer.
1447   test_point = gfx::Point(101, 101);
1448   result_layer =
1449       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1450           test_point);
1451   EXPECT_FALSE(result_layer);
1452
1453   test_point = gfx::Point(-1, -1);
1454   result_layer =
1455       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1456           test_point);
1457   EXPECT_FALSE(result_layer);
1458
1459   // Hit checking for a point inside the layer, but outside the touch handler
1460   // region should return a null pointer.
1461   test_point = gfx::Point(1, 1);
1462   result_layer =
1463       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1464           test_point);
1465   EXPECT_FALSE(result_layer);
1466
1467   test_point = gfx::Point(99, 99);
1468   result_layer =
1469       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1470           test_point);
1471   EXPECT_FALSE(result_layer);
1472
1473   // Hit checking for a point inside the touch event handler region should
1474   // return the root layer.
1475   test_point = gfx::Point(11, 11);
1476   result_layer =
1477       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1478           test_point);
1479   ASSERT_TRUE(result_layer);
1480   EXPECT_EQ(12345, result_layer->id());
1481
1482   test_point = gfx::Point(59, 59);
1483   result_layer =
1484       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1485           test_point);
1486   ASSERT_TRUE(result_layer);
1487   EXPECT_EQ(12345, result_layer->id());
1488 }
1489
1490 TEST_F(LayerTreeImplTest,
1491        HitCheckingTouchHandlerRegionsForUninvertibleTransform) {
1492   scoped_ptr<LayerImpl> root =
1493       LayerImpl::Create(host_impl().active_tree(), 12345);
1494
1495   gfx::Transform uninvertible_transform;
1496   uninvertible_transform.matrix().set(0, 0, 0.0);
1497   uninvertible_transform.matrix().set(1, 1, 0.0);
1498   uninvertible_transform.matrix().set(2, 2, 0.0);
1499   uninvertible_transform.matrix().set(3, 3, 0.0);
1500   ASSERT_FALSE(uninvertible_transform.IsInvertible());
1501
1502   gfx::Transform identity_matrix;
1503   Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1504   gfx::Point3F transform_origin;
1505   gfx::PointF position;
1506   gfx::Size bounds(100, 100);
1507   SetLayerPropertiesForTesting(root.get(),
1508                                uninvertible_transform,
1509                                transform_origin,
1510                                position,
1511                                bounds,
1512                                true,
1513                                false);
1514   root->SetDrawsContent(true);
1515   root->SetTouchEventHandlerRegion(touch_handler_region);
1516
1517   host_impl().SetViewportSize(root->bounds());
1518   host_impl().active_tree()->SetRootLayer(root.Pass());
1519   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1520
1521   // Sanity check the scenario we just created.
1522   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1523   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1524   ASSERT_FALSE(root_layer()->screen_space_transform().IsInvertible());
1525
1526   // Hit checking any point should not hit the touch handler region on the
1527   // layer. If the invertible matrix is accidentally ignored and treated like an
1528   // identity, then the hit testing will incorrectly hit the layer when it
1529   // shouldn't.
1530   gfx::Point test_point(1, 1);
1531   LayerImpl* result_layer =
1532       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1533           test_point);
1534   EXPECT_FALSE(result_layer);
1535
1536   test_point = gfx::Point(10, 10);
1537   result_layer =
1538       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1539           test_point);
1540   EXPECT_FALSE(result_layer);
1541
1542   test_point = gfx::Point(10, 30);
1543   result_layer =
1544       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1545           test_point);
1546   EXPECT_FALSE(result_layer);
1547
1548   test_point = gfx::Point(50, 50);
1549   result_layer =
1550       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1551           test_point);
1552   EXPECT_FALSE(result_layer);
1553
1554   test_point = gfx::Point(67, 48);
1555   result_layer =
1556       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1557           test_point);
1558   EXPECT_FALSE(result_layer);
1559
1560   test_point = gfx::Point(99, 99);
1561   result_layer =
1562       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1563           test_point);
1564   EXPECT_FALSE(result_layer);
1565
1566   test_point = gfx::Point(-1, -1);
1567   result_layer =
1568       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1569           test_point);
1570   EXPECT_FALSE(result_layer);
1571 }
1572
1573 TEST_F(LayerTreeImplTest,
1574        HitCheckingTouchHandlerRegionsForSinglePositionedLayer) {
1575   scoped_ptr<LayerImpl> root =
1576       LayerImpl::Create(host_impl().active_tree(), 12345);
1577
1578   gfx::Transform identity_matrix;
1579   Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1580   gfx::Point3F transform_origin;
1581   // this layer is positioned, and hit testing should correctly know where the
1582   // layer is located.
1583   gfx::PointF position(50.f, 50.f);
1584   gfx::Size bounds(100, 100);
1585   SetLayerPropertiesForTesting(root.get(),
1586                                identity_matrix,
1587                                transform_origin,
1588                                position,
1589                                bounds,
1590                                true,
1591                                false);
1592   root->SetDrawsContent(true);
1593   root->SetTouchEventHandlerRegion(touch_handler_region);
1594
1595   host_impl().SetViewportSize(root->bounds());
1596   host_impl().active_tree()->SetRootLayer(root.Pass());
1597   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1598
1599   // Sanity check the scenario we just created.
1600   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1601   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1602
1603   // Hit checking for a point outside the layer should return a null pointer.
1604   gfx::Point test_point(49, 49);
1605   LayerImpl* result_layer =
1606       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1607           test_point);
1608   EXPECT_FALSE(result_layer);
1609
1610   // Even though the layer has a touch handler region containing (101, 101), it
1611   // should not be visible there since the root render surface would clamp it.
1612   test_point = gfx::Point(101, 101);
1613   result_layer =
1614       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1615           test_point);
1616   EXPECT_FALSE(result_layer);
1617
1618   // Hit checking for a point inside the layer, but outside the touch handler
1619   // region should return a null pointer.
1620   test_point = gfx::Point(51, 51);
1621   result_layer =
1622       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1623           test_point);
1624   EXPECT_FALSE(result_layer);
1625
1626   // Hit checking for a point inside the touch event handler region should
1627   // return the root layer.
1628   test_point = gfx::Point(61, 61);
1629   result_layer =
1630       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1631           test_point);
1632   ASSERT_TRUE(result_layer);
1633   EXPECT_EQ(12345, result_layer->id());
1634
1635   test_point = gfx::Point(99, 99);
1636   result_layer =
1637       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1638           test_point);
1639   ASSERT_TRUE(result_layer);
1640   EXPECT_EQ(12345, result_layer->id());
1641 }
1642
1643 TEST_F(LayerTreeImplTest,
1644        HitCheckingTouchHandlerRegionsForSingleLayerWithScaledContents) {
1645   // A layer's visible content rect is actually in the layer's content space.
1646   // The screen space transform converts from the layer's origin space to screen
1647   // space. This test makes sure that hit testing works correctly accounts for
1648   // the contents scale.  A contents scale that is not 1 effectively forces a
1649   // non-identity transform between layer's content space and layer's origin
1650   // space. The hit testing code must take this into account.
1651   //
1652   // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
1653   // contents scale is ignored, then hit checking will mis-interpret the visible
1654   // content rect as being larger than the actual bounds of the layer.
1655   //
1656   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1657
1658   gfx::Transform identity_matrix;
1659   gfx::Point3F transform_origin;
1660
1661   SetLayerPropertiesForTesting(root.get(),
1662                                identity_matrix,
1663                                transform_origin,
1664                                gfx::PointF(),
1665                                gfx::Size(100, 100),
1666                                true,
1667                                false);
1668   {
1669     Region touch_handler_region(gfx::Rect(10, 10, 30, 30));
1670     gfx::PointF position(25.f, 25.f);
1671     gfx::Size bounds(50, 50);
1672     scoped_ptr<LayerImpl> test_layer =
1673         LayerImpl::Create(host_impl().active_tree(), 12345);
1674     SetLayerPropertiesForTesting(test_layer.get(),
1675                                  identity_matrix,
1676                                  transform_origin,
1677                                  position,
1678                                  bounds,
1679                                  true,
1680                                  false);
1681
1682     // override content bounds and contents scale
1683     test_layer->SetContentBounds(gfx::Size(100, 100));
1684     test_layer->SetContentsScale(2, 2);
1685
1686     test_layer->SetDrawsContent(true);
1687     test_layer->SetTouchEventHandlerRegion(touch_handler_region);
1688     root->AddChild(test_layer.Pass());
1689   }
1690
1691   host_impl().SetViewportSize(root->bounds());
1692   host_impl().active_tree()->SetRootLayer(root.Pass());
1693   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1694
1695   // Sanity check the scenario we just created.
1696   // The visible content rect for test_layer is actually 100x100, even though
1697   // its layout size is 50x50, positioned at 25x25.
1698   LayerImpl* test_layer =
1699       host_impl().active_tree()->root_layer()->children()[0];
1700   EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), test_layer->visible_content_rect());
1701   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1702   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1703
1704   // Hit checking for a point outside the layer should return a null pointer
1705   // (the root layer does not draw content, so it will not be tested either).
1706   gfx::Point test_point(76, 76);
1707   LayerImpl* result_layer =
1708       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1709           test_point);
1710   EXPECT_FALSE(result_layer);
1711
1712   // Hit checking for a point inside the layer, but outside the touch handler
1713   // region should return a null pointer.
1714   test_point = gfx::Point(26, 26);
1715   result_layer =
1716       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1717           test_point);
1718   EXPECT_FALSE(result_layer);
1719
1720   test_point = gfx::Point(34, 34);
1721   result_layer =
1722       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1723           test_point);
1724   EXPECT_FALSE(result_layer);
1725
1726   test_point = gfx::Point(65, 65);
1727   result_layer =
1728       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1729           test_point);
1730   EXPECT_FALSE(result_layer);
1731
1732   test_point = gfx::Point(74, 74);
1733   result_layer =
1734       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1735           test_point);
1736   EXPECT_FALSE(result_layer);
1737
1738   // Hit checking for a point inside the touch event handler region should
1739   // return the root layer.
1740   test_point = gfx::Point(35, 35);
1741   result_layer =
1742       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1743           test_point);
1744   ASSERT_TRUE(result_layer);
1745   EXPECT_EQ(12345, result_layer->id());
1746
1747   test_point = gfx::Point(64, 64);
1748   result_layer =
1749       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1750           test_point);
1751   ASSERT_TRUE(result_layer);
1752   EXPECT_EQ(12345, result_layer->id());
1753 }
1754
1755 TEST_F(LayerTreeImplTest,
1756        HitCheckingTouchHandlerRegionsForSingleLayerWithDeviceScale) {
1757   // The layer's device_scale_factor and page_scale_factor should scale the
1758   // content rect and we should be able to hit the touch handler region by
1759   // scaling the points accordingly.
1760   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1761
1762   gfx::Transform identity_matrix;
1763   gfx::Point3F transform_origin;
1764   // Set the bounds of the root layer big enough to fit the child when scaled.
1765   SetLayerPropertiesForTesting(root.get(),
1766                                identity_matrix,
1767                                transform_origin,
1768                                gfx::PointF(),
1769                                gfx::Size(100, 100),
1770                                true,
1771                                false);
1772   {
1773     Region touch_handler_region(gfx::Rect(10, 10, 30, 30));
1774     gfx::PointF position(25.f, 25.f);
1775     gfx::Size bounds(50, 50);
1776     scoped_ptr<LayerImpl> test_layer =
1777         LayerImpl::Create(host_impl().active_tree(), 12345);
1778     SetLayerPropertiesForTesting(test_layer.get(),
1779                                  identity_matrix,
1780                                  transform_origin,
1781                                  position,
1782                                  bounds,
1783                                  true,
1784                                  false);
1785
1786     test_layer->SetDrawsContent(true);
1787     test_layer->SetTouchEventHandlerRegion(touch_handler_region);
1788     root->AddChild(test_layer.Pass());
1789   }
1790
1791   float device_scale_factor = 3.f;
1792   float page_scale_factor = 5.f;
1793   gfx::Size scaled_bounds_for_root = gfx::ToCeiledSize(
1794       gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor));
1795   host_impl().SetViewportSize(scaled_bounds_for_root);
1796
1797   host_impl().SetDeviceScaleFactor(device_scale_factor);
1798   host_impl().active_tree()->SetPageScaleFactorAndLimits(
1799       page_scale_factor, page_scale_factor, page_scale_factor);
1800   host_impl().active_tree()->SetRootLayer(root.Pass());
1801   host_impl().active_tree()->SetViewportLayersFromIds(1, 1, Layer::INVALID_ID);
1802   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1803
1804   // Sanity check the scenario we just created.
1805   // The visible content rect for test_layer is actually 100x100, even though
1806   // its layout size is 50x50, positioned at 25x25.
1807   LayerImpl* test_layer =
1808       host_impl().active_tree()->root_layer()->children()[0];
1809   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1810   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1811
1812   // Check whether the child layer fits into the root after scaled.
1813   EXPECT_RECT_EQ(gfx::Rect(test_layer->content_bounds()),
1814                  test_layer->visible_content_rect());
1815
1816   // Hit checking for a point outside the layer should return a null pointer
1817   // (the root layer does not draw content, so it will not be tested either).
1818   gfx::PointF test_point(76.f, 76.f);
1819   test_point =
1820       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1821   LayerImpl* result_layer =
1822       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1823           test_point);
1824   EXPECT_FALSE(result_layer);
1825
1826   // Hit checking for a point inside the layer, but outside the touch handler
1827   // region should return a null pointer.
1828   test_point = gfx::Point(26, 26);
1829   test_point =
1830       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1831   result_layer =
1832       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1833           test_point);
1834   EXPECT_FALSE(result_layer);
1835
1836   test_point = gfx::Point(34, 34);
1837   test_point =
1838       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1839   result_layer =
1840       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1841           test_point);
1842   EXPECT_FALSE(result_layer);
1843
1844   test_point = gfx::Point(65, 65);
1845   test_point =
1846       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1847   result_layer =
1848       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1849           test_point);
1850   EXPECT_FALSE(result_layer);
1851
1852   test_point = gfx::Point(74, 74);
1853   test_point =
1854       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1855   result_layer =
1856       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1857           test_point);
1858   EXPECT_FALSE(result_layer);
1859
1860   // Hit checking for a point inside the touch event handler region should
1861   // return the root layer.
1862   test_point = gfx::Point(35, 35);
1863   test_point =
1864       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1865   result_layer =
1866       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1867           test_point);
1868   ASSERT_TRUE(result_layer);
1869   EXPECT_EQ(12345, result_layer->id());
1870
1871   test_point = gfx::Point(64, 64);
1872   test_point =
1873       gfx::ScalePoint(test_point, device_scale_factor * page_scale_factor);
1874   result_layer =
1875       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1876           test_point);
1877   ASSERT_TRUE(result_layer);
1878   EXPECT_EQ(12345, result_layer->id());
1879 }
1880
1881 TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSimpleClippedLayer) {
1882   // Test that hit-checking will only work for the visible portion of a layer,
1883   // and not the entire layer bounds. Here we just test the simple axis-aligned
1884   // case.
1885   gfx::Transform identity_matrix;
1886   gfx::Point3F transform_origin;
1887
1888   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1889   SetLayerPropertiesForTesting(root.get(),
1890                                identity_matrix,
1891                                transform_origin,
1892                                gfx::PointF(),
1893                                gfx::Size(100, 100),
1894                                true,
1895                                false);
1896   {
1897     scoped_ptr<LayerImpl> clipping_layer =
1898         LayerImpl::Create(host_impl().active_tree(), 123);
1899     // this layer is positioned, and hit testing should correctly know where the
1900     // layer is located.
1901     gfx::PointF position(25.f, 25.f);
1902     gfx::Size bounds(50, 50);
1903     SetLayerPropertiesForTesting(clipping_layer.get(),
1904                                  identity_matrix,
1905                                  transform_origin,
1906                                  position,
1907                                  bounds,
1908                                  true,
1909                                  false);
1910     clipping_layer->SetMasksToBounds(true);
1911
1912     scoped_ptr<LayerImpl> child =
1913         LayerImpl::Create(host_impl().active_tree(), 456);
1914     Region touch_handler_region(gfx::Rect(10, 10, 50, 50));
1915     position = gfx::PointF(-50.f, -50.f);
1916     bounds = gfx::Size(300, 300);
1917     SetLayerPropertiesForTesting(child.get(),
1918                                  identity_matrix,
1919                                  transform_origin,
1920                                  position,
1921                                  bounds,
1922                                  true,
1923                                  false);
1924     child->SetDrawsContent(true);
1925     child->SetTouchEventHandlerRegion(touch_handler_region);
1926     clipping_layer->AddChild(child.Pass());
1927     root->AddChild(clipping_layer.Pass());
1928   }
1929
1930   host_impl().SetViewportSize(root->bounds());
1931   host_impl().active_tree()->SetRootLayer(root.Pass());
1932   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
1933
1934   // Sanity check the scenario we just created.
1935   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
1936   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
1937   ASSERT_EQ(456, root_layer()->render_surface()->layer_list().at(0)->id());
1938
1939   // Hit checking for a point outside the layer should return a null pointer.
1940   // Despite the child layer being very large, it should be clipped to the root
1941   // layer's bounds.
1942   gfx::Point test_point(24, 24);
1943   LayerImpl* result_layer =
1944       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1945           test_point);
1946   EXPECT_FALSE(result_layer);
1947
1948   // Hit checking for a point inside the layer, but outside the touch handler
1949   // region should return a null pointer.
1950   test_point = gfx::Point(35, 35);
1951   result_layer =
1952       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1953           test_point);
1954   EXPECT_FALSE(result_layer);
1955
1956   test_point = gfx::Point(74, 74);
1957   result_layer =
1958       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1959           test_point);
1960   EXPECT_FALSE(result_layer);
1961
1962   // Hit checking for a point inside the touch event handler region should
1963   // return the root layer.
1964   test_point = gfx::Point(25, 25);
1965   result_layer =
1966       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1967           test_point);
1968   ASSERT_TRUE(result_layer);
1969   EXPECT_EQ(456, result_layer->id());
1970
1971   test_point = gfx::Point(34, 34);
1972   result_layer =
1973       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
1974           test_point);
1975   ASSERT_TRUE(result_layer);
1976   EXPECT_EQ(456, result_layer->id());
1977 }
1978
1979 TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) {
1980   gfx::Transform identity_matrix;
1981   gfx::Point3F transform_origin;
1982
1983   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
1984   SetLayerPropertiesForTesting(root.get(),
1985                                identity_matrix,
1986                                transform_origin,
1987                                gfx::PointF(),
1988                                gfx::Size(100, 100),
1989                                true,
1990                                false);
1991   {
1992     scoped_ptr<LayerImpl> touch_layer =
1993         LayerImpl::Create(host_impl().active_tree(), 123);
1994     // this layer is positioned, and hit testing should correctly know where the
1995     // layer is located.
1996     gfx::PointF position;
1997     gfx::Size bounds(50, 50);
1998     SetLayerPropertiesForTesting(touch_layer.get(),
1999                                  identity_matrix,
2000                                  transform_origin,
2001                                  position,
2002                                  bounds,
2003                                  true,
2004                                  false);
2005     touch_layer->SetDrawsContent(true);
2006     touch_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50));
2007     root->AddChild(touch_layer.Pass());
2008   }
2009
2010   {
2011     scoped_ptr<LayerImpl> notouch_layer =
2012         LayerImpl::Create(host_impl().active_tree(), 1234);
2013     // this layer is positioned, and hit testing should correctly know where the
2014     // layer is located.
2015     gfx::PointF position(0, 25);
2016     gfx::Size bounds(50, 50);
2017     SetLayerPropertiesForTesting(notouch_layer.get(),
2018                                  identity_matrix,
2019                                  transform_origin,
2020                                  position,
2021                                  bounds,
2022                                  true,
2023                                  false);
2024     notouch_layer->SetDrawsContent(true);
2025     root->AddChild(notouch_layer.Pass());
2026   }
2027
2028   host_impl().SetViewportSize(root->bounds());
2029   host_impl().active_tree()->SetRootLayer(root.Pass());
2030   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
2031
2032   // Sanity check the scenario we just created.
2033   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
2034   ASSERT_EQ(2u, root_layer()->render_surface()->layer_list().size());
2035   ASSERT_EQ(123, root_layer()->render_surface()->layer_list().at(0)->id());
2036   ASSERT_EQ(1234, root_layer()->render_surface()->layer_list().at(1)->id());
2037
2038   gfx::Point test_point(35, 35);
2039   LayerImpl* result_layer =
2040       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
2041           test_point);
2042
2043   // We should have passed through the no-touch layer and found the layer
2044   // behind it.
2045   EXPECT_TRUE(result_layer);
2046
2047   host_impl().active_tree()->LayerById(1234)->SetContentsOpaque(true);
2048   result_layer =
2049       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
2050           test_point);
2051
2052   // Even with an opaque layer in the middle, we should still find the layer
2053   // with
2054   // the touch handler behind it (since we can't assume that opaque layers are
2055   // opaque to hit testing).
2056   EXPECT_TRUE(result_layer);
2057
2058   test_point = gfx::Point(35, 15);
2059   result_layer =
2060       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
2061           test_point);
2062   ASSERT_TRUE(result_layer);
2063   EXPECT_EQ(123, result_layer->id());
2064
2065   test_point = gfx::Point(35, 65);
2066   result_layer =
2067       host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion(
2068           test_point);
2069   EXPECT_FALSE(result_layer);
2070 }
2071
2072 TEST_F(LayerTreeImplTest, SelectionBoundsForSingleLayer) {
2073   int root_layer_id = 12345;
2074   scoped_ptr<LayerImpl> root =
2075       LayerImpl::Create(host_impl().active_tree(), root_layer_id);
2076
2077   gfx::Transform identity_matrix;
2078   gfx::Point3F transform_origin;
2079   gfx::PointF position;
2080   gfx::Size bounds(100, 100);
2081   SetLayerPropertiesForTesting(root.get(),
2082                                identity_matrix,
2083                                transform_origin,
2084                                position,
2085                                bounds,
2086                                true,
2087                                false);
2088   root->SetDrawsContent(true);
2089
2090   host_impl().SetViewportSize(root->bounds());
2091   host_impl().active_tree()->SetRootLayer(root.Pass());
2092   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
2093
2094   // Sanity check the scenario we just created.
2095   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
2096   ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size());
2097
2098   LayerSelectionBound left_input;
2099   left_input.type = SELECTION_BOUND_LEFT;
2100   left_input.edge_top = gfx::PointF(10, 10);
2101   left_input.edge_bottom = gfx::PointF(10, 20);
2102   left_input.layer_id = root_layer_id;
2103
2104   LayerSelectionBound right_input;
2105   right_input.type = SELECTION_BOUND_RIGHT;
2106   right_input.edge_top = gfx::PointF(50, 10);
2107   right_input.edge_bottom = gfx::PointF(50, 30);
2108   right_input.layer_id = root_layer_id;
2109
2110   ViewportSelectionBound left_output, right_output;
2111
2112   // Empty input bounds should produce empty output bounds.
2113   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2114   EXPECT_EQ(ViewportSelectionBound(), left_output);
2115   EXPECT_EQ(ViewportSelectionBound(), right_output);
2116
2117   // Selection bounds should produce distinct left and right bounds.
2118   host_impl().active_tree()->RegisterSelection(left_input, right_input);
2119   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2120   EXPECT_EQ(left_input.type, left_output.type);
2121   EXPECT_EQ(left_input.edge_bottom, left_output.edge_bottom);
2122   EXPECT_EQ(left_input.edge_top, left_output.edge_top);
2123   EXPECT_TRUE(left_output.visible);
2124   EXPECT_EQ(right_input.type, right_output.type);
2125   EXPECT_EQ(right_input.edge_bottom, right_output.edge_bottom);
2126   EXPECT_EQ(right_input.edge_top, right_output.edge_top);
2127   EXPECT_TRUE(right_output.visible);
2128
2129   // Insertion bounds should produce identical left and right bounds.
2130   LayerSelectionBound insertion_input;
2131   insertion_input.type = SELECTION_BOUND_CENTER;
2132   insertion_input.edge_top = gfx::PointF(15, 10);
2133   insertion_input.edge_bottom = gfx::PointF(15, 30);
2134   insertion_input.layer_id = root_layer_id;
2135   host_impl().active_tree()->RegisterSelection(insertion_input,
2136                                                LayerSelectionBound());
2137   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2138   EXPECT_EQ(insertion_input.type, left_output.type);
2139   EXPECT_EQ(insertion_input.edge_bottom, left_output.edge_bottom);
2140   EXPECT_EQ(insertion_input.edge_top, left_output.edge_top);
2141   EXPECT_TRUE(left_output.visible);
2142   EXPECT_EQ(left_output, right_output);
2143 }
2144
2145 TEST_F(LayerTreeImplTest, SelectionBoundsForPartialOccludedLayers) {
2146   int root_layer_id = 12345;
2147   int clip_layer_id = 1234;
2148   int clipped_layer_id = 123;
2149   scoped_ptr<LayerImpl> root =
2150       LayerImpl::Create(host_impl().active_tree(), root_layer_id);
2151   root->SetDrawsContent(true);
2152
2153   gfx::Transform identity_matrix;
2154   gfx::Point3F transform_origin;
2155   gfx::PointF position;
2156   gfx::Size bounds(100, 100);
2157   SetLayerPropertiesForTesting(root.get(),
2158                                identity_matrix,
2159                                transform_origin,
2160                                position,
2161                                bounds,
2162                                true,
2163                                false);
2164
2165   gfx::Vector2dF clipping_offset(10, 10);
2166   {
2167     scoped_ptr<LayerImpl> clipping_layer =
2168         LayerImpl::Create(host_impl().active_tree(), clip_layer_id);
2169     // The clipping layer should occlude the right selection bound.
2170     gfx::PointF position = gfx::PointF() + clipping_offset;
2171     gfx::Size bounds(50, 50);
2172     SetLayerPropertiesForTesting(clipping_layer.get(),
2173                                  identity_matrix,
2174                                  transform_origin,
2175                                  position,
2176                                  bounds,
2177                                  true,
2178                                  false);
2179     clipping_layer->SetMasksToBounds(true);
2180
2181     scoped_ptr<LayerImpl> clipped_layer =
2182         LayerImpl::Create(host_impl().active_tree(), clipped_layer_id);
2183     position = gfx::PointF();
2184     bounds = gfx::Size(100, 100);
2185     SetLayerPropertiesForTesting(clipped_layer.get(),
2186                                  identity_matrix,
2187                                  transform_origin,
2188                                  position,
2189                                  bounds,
2190                                  true,
2191                                  false);
2192     clipped_layer->SetDrawsContent(true);
2193     clipping_layer->AddChild(clipped_layer.Pass());
2194     root->AddChild(clipping_layer.Pass());
2195   }
2196
2197   host_impl().SetViewportSize(root->bounds());
2198   host_impl().active_tree()->SetRootLayer(root.Pass());
2199   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
2200
2201   // Sanity check the scenario we just created.
2202   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
2203
2204   LayerSelectionBound left_input;
2205   left_input.type = SELECTION_BOUND_LEFT;
2206   left_input.edge_top = gfx::PointF(25, 10);
2207   left_input.edge_bottom = gfx::PointF(25, 30);
2208   left_input.layer_id = clipped_layer_id;
2209
2210   LayerSelectionBound right_input;
2211   right_input.type = SELECTION_BOUND_RIGHT;
2212   right_input.edge_top = gfx::PointF(75, 10);
2213   right_input.edge_bottom = gfx::PointF(75, 30);
2214   right_input.layer_id = clipped_layer_id;
2215   host_impl().active_tree()->RegisterSelection(left_input, right_input);
2216
2217   // The left bound should be occluded by the clip layer.
2218   ViewportSelectionBound left_output, right_output;
2219   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2220   EXPECT_EQ(left_input.type, left_output.type);
2221   gfx::PointF expected_left_output_top = left_input.edge_top;
2222   gfx::PointF expected_left_output_bottom = left_input.edge_bottom;
2223   expected_left_output_top.Offset(clipping_offset.x(), clipping_offset.y());
2224   expected_left_output_bottom.Offset(clipping_offset.x(), clipping_offset.y());
2225   EXPECT_EQ(expected_left_output_top, left_output.edge_top);
2226   EXPECT_EQ(expected_left_output_bottom, left_output.edge_bottom);
2227   EXPECT_TRUE(left_output.visible);
2228   EXPECT_EQ(right_input.type, right_output.type);
2229   gfx::PointF expected_right_output_top = right_input.edge_top;
2230   gfx::PointF expected_right_output_bottom = right_input.edge_bottom;
2231   expected_right_output_bottom.Offset(clipping_offset.x(), clipping_offset.y());
2232   expected_right_output_top.Offset(clipping_offset.x(), clipping_offset.y());
2233   EXPECT_EQ(expected_right_output_top, right_output.edge_top);
2234   EXPECT_EQ(expected_right_output_bottom, right_output.edge_bottom);
2235   EXPECT_FALSE(right_output.visible);
2236
2237   // Handles outside the viewport bounds should be marked invisible.
2238   left_input.edge_top = gfx::PointF(-25, 0);
2239   left_input.edge_bottom = gfx::PointF(-25, 20);
2240   host_impl().active_tree()->RegisterSelection(left_input, right_input);
2241   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2242   EXPECT_FALSE(left_output.visible);
2243
2244   left_input.edge_top = gfx::PointF(0, -25);
2245   left_input.edge_bottom = gfx::PointF(0, -5);
2246   host_impl().active_tree()->RegisterSelection(left_input, right_input);
2247   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2248   EXPECT_FALSE(left_output.visible);
2249
2250   // If the handle bottom is partially visible, the handle is marked visible.
2251   left_input.edge_top = gfx::PointF(0, -20);
2252   left_input.edge_bottom = gfx::PointF(0, 1);
2253   host_impl().active_tree()->RegisterSelection(left_input, right_input);
2254   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2255   EXPECT_TRUE(left_output.visible);
2256 }
2257
2258 TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) {
2259   int root_layer_id = 1;
2260   int sub_layer_id = 2;
2261   scoped_ptr<LayerImpl> root =
2262       LayerImpl::Create(host_impl().active_tree(), root_layer_id);
2263   root->SetDrawsContent(true);
2264
2265   gfx::Transform identity_matrix;
2266   gfx::Point3F transform_origin;
2267   gfx::PointF position;
2268   gfx::Size bounds(100, 100);
2269   SetLayerPropertiesForTesting(root.get(),
2270                                identity_matrix,
2271                                transform_origin,
2272                                position,
2273                                bounds,
2274                                true,
2275                                false);
2276
2277   gfx::Vector2dF sub_layer_offset(10, 0);
2278   {
2279     scoped_ptr<LayerImpl> sub_layer =
2280         LayerImpl::Create(host_impl().active_tree(), sub_layer_id);
2281     gfx::PointF position = gfx::PointF() + sub_layer_offset;
2282     gfx::Size bounds(50, 50);
2283     SetLayerPropertiesForTesting(sub_layer.get(),
2284                                  identity_matrix,
2285                                  transform_origin,
2286                                  position,
2287                                  bounds,
2288                                  true,
2289                                  false);
2290     sub_layer->SetDrawsContent(true);
2291     root->AddChild(sub_layer.Pass());
2292   }
2293
2294   float device_scale_factor = 3.f;
2295   float page_scale_factor = 5.f;
2296   gfx::Size scaled_bounds_for_root = gfx::ToCeiledSize(
2297       gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor));
2298   host_impl().SetViewportSize(scaled_bounds_for_root);
2299
2300   host_impl().SetDeviceScaleFactor(device_scale_factor);
2301   host_impl().active_tree()->SetPageScaleFactorAndLimits(
2302       page_scale_factor, page_scale_factor, page_scale_factor);
2303   host_impl().active_tree()->SetRootLayer(root.Pass());
2304   host_impl().active_tree()->SetViewportLayersFromIds(1, 1, Layer::INVALID_ID);
2305   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
2306
2307   // Sanity check the scenario we just created.
2308   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
2309
2310   LayerSelectionBound left_input;
2311   left_input.type = SELECTION_BOUND_LEFT;
2312   left_input.edge_top = gfx::PointF(10, 10);
2313   left_input.edge_bottom = gfx::PointF(10, 30);
2314   left_input.layer_id = root_layer_id;
2315
2316   LayerSelectionBound right_input;
2317   right_input.type = SELECTION_BOUND_RIGHT;
2318   right_input.edge_top = gfx::PointF(0, 0);
2319   right_input.edge_bottom = gfx::PointF(0, 20);
2320   right_input.layer_id = sub_layer_id;
2321   host_impl().active_tree()->RegisterSelection(left_input, right_input);
2322
2323   // The viewport bounds should be properly scaled by the page scale, but should
2324   // remain in DIP coordinates.
2325   ViewportSelectionBound left_output, right_output;
2326   host_impl().active_tree()->GetViewportSelection(&left_output, &right_output);
2327   EXPECT_EQ(left_input.type, left_output.type);
2328   gfx::PointF expected_left_output_top = left_input.edge_top;
2329   gfx::PointF expected_left_output_bottom = left_input.edge_bottom;
2330   expected_left_output_top.Scale(page_scale_factor);
2331   expected_left_output_bottom.Scale(page_scale_factor);
2332   EXPECT_EQ(left_input.edge_top, left_output.edge_top);
2333   EXPECT_EQ(left_input.edge_bottom, left_output.edge_bottom);
2334   EXPECT_TRUE(left_output.visible);
2335   EXPECT_EQ(right_input.type, right_output.type);
2336
2337   gfx::PointF expected_right_output_top = right_input.edge_top;
2338   gfx::PointF expected_right_output_bottom = right_input.edge_bottom;
2339   expected_right_output_top.Offset(sub_layer_offset.x(), sub_layer_offset.y());
2340   expected_right_output_bottom.Offset(sub_layer_offset.x(),
2341                                       sub_layer_offset.y());
2342   expected_right_output_top.Scale(page_scale_factor);
2343   expected_right_output_bottom.Scale(page_scale_factor);
2344   EXPECT_EQ(expected_right_output_top, right_output.edge_top);
2345   EXPECT_EQ(expected_right_output_bottom, right_output.edge_bottom);
2346   EXPECT_TRUE(right_output.visible);
2347 }
2348
2349 TEST_F(LayerTreeImplTest, NumLayersTestOne) {
2350   EXPECT_EQ(0u, host_impl().active_tree()->NumLayers());
2351   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
2352   EXPECT_EQ(1u, host_impl().active_tree()->NumLayers());
2353 }
2354
2355 TEST_F(LayerTreeImplTest, NumLayersSmallTree) {
2356   EXPECT_EQ(0u, host_impl().active_tree()->NumLayers());
2357   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
2358   root->AddChild(LayerImpl::Create(host_impl().active_tree(), 2));
2359   root->AddChild(LayerImpl::Create(host_impl().active_tree(), 3));
2360   root->child_at(1)->AddChild(LayerImpl::Create(host_impl().active_tree(), 4));
2361   EXPECT_EQ(4u, host_impl().active_tree()->NumLayers());
2362 }
2363
2364 }  // namespace
2365 }  // namespace cc