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