1 // Copyright 2013 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/layers/layer_position_constraint.h"
9 #include "cc/layers/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/geometry_test_utils.h"
13 #include "cc/trees/layer_tree_host_common.h"
14 #include "testing/gtest/include/gtest/gtest.h"
19 void SetLayerPropertiesForTesting(LayerImpl
* layer
,
20 const gfx::Transform
& transform
,
21 const gfx::Transform
& sublayer_transform
,
26 layer
->SetTransform(transform
);
27 layer
->SetSublayerTransform(sublayer_transform
);
28 layer
->SetAnchorPoint(anchor
);
29 layer
->SetPosition(position
);
30 layer
->SetBounds(bounds
);
31 layer
->SetPreserves3d(preserves3d
);
32 layer
->SetContentBounds(bounds
);
35 void ExecuteCalculateDrawProperties(LayerImpl
* root_layer
,
36 float device_scale_factor
,
37 float page_scale_factor
,
38 LayerImpl
* page_scale_application_layer
,
39 bool can_use_lcd_text
) {
40 gfx::Transform identity_matrix
;
41 std::vector
<LayerImpl
*> dummy_render_surface_layer_list
;
42 gfx::Size device_viewport_size
=
43 gfx::Size(root_layer
->bounds().width() * device_scale_factor
,
44 root_layer
->bounds().height() * device_scale_factor
);
46 // We are probably not testing what is intended if the root_layer bounds are
48 DCHECK(!root_layer
->bounds().IsEmpty());
49 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting
inputs(
50 root_layer
, device_viewport_size
, &dummy_render_surface_layer_list
);
51 inputs
.device_scale_factor
= device_scale_factor
;
52 inputs
.page_scale_factor
= page_scale_factor
;
53 inputs
.page_scale_application_layer
= page_scale_application_layer
;
54 inputs
.can_use_lcd_text
= can_use_lcd_text
;
55 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
58 void ExecuteCalculateDrawProperties(LayerImpl
* root_layer
) {
59 LayerImpl
* page_scale_application_layer
= NULL
;
60 ExecuteCalculateDrawProperties(
61 root_layer
, 1.f
, 1.f
, page_scale_application_layer
, false);
64 class LayerPositionConstraintTest
: public testing::Test
{
66 LayerPositionConstraintTest()
67 : host_impl_(&proxy_
) {
68 root_
= CreateTreeForTest();
69 fixed_to_top_left_
.set_is_fixed_position(true);
70 fixed_to_bottom_right_
.set_is_fixed_position(true);
71 fixed_to_bottom_right_
.set_is_fixed_to_right_edge(true);
72 fixed_to_bottom_right_
.set_is_fixed_to_bottom_edge(true);
75 scoped_ptr
<LayerImpl
> CreateTreeForTest() {
76 scoped_ptr
<LayerImpl
> root
=
77 LayerImpl::Create(host_impl_
.active_tree(), 1);
78 scoped_ptr
<LayerImpl
> child
=
79 LayerImpl::Create(host_impl_
.active_tree(), 2);
80 scoped_ptr
<LayerImpl
> grand_child
=
81 LayerImpl::Create(host_impl_
.active_tree(), 3);
82 scoped_ptr
<LayerImpl
> great_grand_child
=
83 LayerImpl::Create(host_impl_
.active_tree(), 4);
85 gfx::Transform IdentityMatrix
;
88 gfx::Size
bounds(100, 100);
89 SetLayerPropertiesForTesting(root
.get(),
96 SetLayerPropertiesForTesting(child
.get(),
103 SetLayerPropertiesForTesting(grand_child
.get(),
110 SetLayerPropertiesForTesting(great_grand_child
.get(),
118 root
->SetMaxScrollOffset(gfx::Vector2d(100, 100));
119 root
->SetScrollable(true);
120 child
->SetMaxScrollOffset(gfx::Vector2d(100, 100));
121 child
->SetScrollable(true);
122 grand_child
->SetMaxScrollOffset(gfx::Vector2d(100, 100));
123 grand_child
->SetScrollable(true);
125 grand_child
->AddChild(great_grand_child
.Pass());
126 child
->AddChild(grand_child
.Pass());
127 root
->AddChild(child
.Pass());
133 FakeImplProxy proxy_
;
134 FakeLayerTreeHostImpl host_impl_
;
135 scoped_ptr
<LayerImpl
> root_
;
137 LayerPositionConstraint fixed_to_top_left_
;
138 LayerPositionConstraint fixed_to_bottom_right_
;
141 TEST_F(LayerPositionConstraintTest
,
142 ScrollCompensationForFixedPositionLayerWithDirectContainer
) {
143 // This test checks for correct scroll compensation when the fixed-position
144 // container is the direct parent of the fixed-position layer.
145 LayerImpl
* child
= root_
->children()[0];
146 LayerImpl
* grand_child
= child
->children()[0];
148 child
->SetIsContainerForFixedPositionLayers(true);
149 grand_child
->SetPositionConstraint(fixed_to_top_left_
);
151 // Case 1: scroll delta of 0, 0
152 child
->SetScrollDelta(gfx::Vector2d(0, 0));
153 ExecuteCalculateDrawProperties(root_
.get());
155 gfx::Transform expected_child_transform
;
156 gfx::Transform expected_grand_child_transform
= expected_child_transform
;
158 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
159 child
->draw_transform());
160 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
161 grand_child
->draw_transform());
163 // Case 2: scroll delta of 10, 10
164 child
->SetScrollDelta(gfx::Vector2d(10, 10));
165 ExecuteCalculateDrawProperties(root_
.get());
167 // Here the child is affected by scroll delta, but the fixed position
168 // grand_child should not be affected.
169 expected_child_transform
.MakeIdentity();
170 expected_child_transform
.Translate(-10.0, -10.0);
172 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
173 child
->draw_transform());
174 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
175 grand_child
->draw_transform());
177 // Case 3: fixed-container size delta of 20, 20
178 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
179 ExecuteCalculateDrawProperties(root_
.get());
181 // Top-left fixed-position layer should not be affected by container size.
182 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
183 child
->draw_transform());
184 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
185 grand_child
->draw_transform());
187 // Case 4: Bottom-right fixed-position layer.
188 grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
189 ExecuteCalculateDrawProperties(root_
.get());
191 // Bottom-right fixed-position layer moves as container resizes.
192 expected_grand_child_transform
.MakeIdentity();
193 // Apply size delta from the child(container) layer.
194 expected_grand_child_transform
.Translate(20.0, 20.0);
196 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
197 child
->draw_transform());
198 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
199 grand_child
->draw_transform());
202 TEST_F(LayerPositionConstraintTest
,
203 ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer
) {
204 // This test checks for correct scroll compensation when the fixed-position
205 // container is the direct parent of the fixed-position layer, but that
206 // container is transformed. In this case, the fixed position element
207 // inherits the container's transform, but the scroll delta that has to be
208 // undone should not be affected by that transform.
210 // Transforms are in general non-commutative; using something like a
211 // non-uniform scale helps to verify that translations and non-uniform scales
212 // are applied in the correct order.
213 LayerImpl
* child
= root_
->children()[0];
214 LayerImpl
* grand_child
= child
->children()[0];
216 // This scale will cause child and grand_child to be effectively 200 x 800
217 // with respect to the render target.
218 gfx::Transform non_uniform_scale
;
219 non_uniform_scale
.Scale(2.0, 8.0);
220 child
->SetTransform(non_uniform_scale
);
222 child
->SetIsContainerForFixedPositionLayers(true);
223 grand_child
->SetPositionConstraint(fixed_to_top_left_
);
225 // Case 1: scroll delta of 0, 0
226 child
->SetScrollDelta(gfx::Vector2d(0, 0));
227 ExecuteCalculateDrawProperties(root_
.get());
229 gfx::Transform expected_child_transform
;
230 expected_child_transform
.PreconcatTransform(non_uniform_scale
);
232 gfx::Transform expected_grand_child_transform
= expected_child_transform
;
234 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
235 child
->draw_transform());
236 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
237 grand_child
->draw_transform());
239 // Case 2: scroll delta of 10, 20
240 child
->SetScrollDelta(gfx::Vector2d(10, 20));
241 ExecuteCalculateDrawProperties(root_
.get());
243 // The child should be affected by scroll delta, but the fixed position
244 // grand_child should not be affected.
245 expected_child_transform
.MakeIdentity();
246 expected_child_transform
.Translate(-10.0, -20.0); // scroll delta
247 expected_child_transform
.PreconcatTransform(non_uniform_scale
);
249 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
250 child
->draw_transform());
251 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
252 grand_child
->draw_transform());
254 // Case 3: fixed-container size delta of 20, 20
255 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
256 ExecuteCalculateDrawProperties(root_
.get());
258 // Top-left fixed-position layer should not be affected by container size.
259 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
260 child
->draw_transform());
261 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
262 grand_child
->draw_transform());
264 // Case 4: Bottom-right fixed-position layer.
265 grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
266 ExecuteCalculateDrawProperties(root_
.get());
268 // Bottom-right fixed-position layer moves as container resizes.
269 expected_grand_child_transform
.MakeIdentity();
270 // Apply child layer transform.
271 expected_grand_child_transform
.PreconcatTransform(non_uniform_scale
);
272 // Apply size delta from the child(container) layer.
273 expected_grand_child_transform
.Translate(20.0, 20.0);
275 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
276 child
->draw_transform());
277 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
278 grand_child
->draw_transform());
281 TEST_F(LayerPositionConstraintTest
,
282 ScrollCompensationForFixedPositionLayerWithDistantContainer
) {
283 // This test checks for correct scroll compensation when the fixed-position
284 // container is NOT the direct parent of the fixed-position layer.
285 LayerImpl
* child
= root_
->children()[0];
286 LayerImpl
* grand_child
= child
->children()[0];
287 LayerImpl
* great_grand_child
= grand_child
->children()[0];
289 child
->SetIsContainerForFixedPositionLayers(true);
290 grand_child
->SetPosition(gfx::PointF(8.f
, 6.f
));
291 great_grand_child
->SetPositionConstraint(fixed_to_top_left_
);
293 // Case 1: scroll delta of 0, 0
294 child
->SetScrollDelta(gfx::Vector2d(0, 0));
295 ExecuteCalculateDrawProperties(root_
.get());
297 gfx::Transform expected_child_transform
;
298 gfx::Transform expected_grand_child_transform
;
299 expected_grand_child_transform
.Translate(8.0, 6.0);
301 gfx::Transform expected_great_grand_child_transform
=
302 expected_grand_child_transform
;
304 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
305 child
->draw_transform());
306 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
307 grand_child
->draw_transform());
308 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
309 great_grand_child
->draw_transform());
311 // Case 2: scroll delta of 10, 10
312 child
->SetScrollDelta(gfx::Vector2d(10, 10));
313 ExecuteCalculateDrawProperties(root_
.get());
315 // Here the child and grand_child are affected by scroll delta, but the fixed
316 // position great_grand_child should not be affected.
317 expected_child_transform
.MakeIdentity();
318 expected_child_transform
.Translate(-10.0, -10.0);
319 expected_grand_child_transform
.MakeIdentity();
320 expected_grand_child_transform
.Translate(-2.0, -4.0);
321 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
322 child
->draw_transform());
323 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
324 grand_child
->draw_transform());
325 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
326 great_grand_child
->draw_transform());
328 // Case 3: fixed-container size delta of 20, 20
329 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
330 ExecuteCalculateDrawProperties(root_
.get());
332 // Top-left fixed-position layer should not be affected by container size.
333 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
334 child
->draw_transform());
335 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
336 grand_child
->draw_transform());
337 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
338 great_grand_child
->draw_transform());
340 // Case 4: Bottom-right fixed-position layer.
341 great_grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
342 ExecuteCalculateDrawProperties(root_
.get());
344 // Bottom-right fixed-position layer moves as container resizes.
345 expected_great_grand_child_transform
.MakeIdentity();
346 // Apply size delta from the child(container) layer.
347 expected_great_grand_child_transform
.Translate(20.0, 20.0);
348 // Apply layer position from the grand child layer.
349 expected_great_grand_child_transform
.Translate(8.0, 6.0);
351 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
352 child
->draw_transform());
353 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
354 grand_child
->draw_transform());
355 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
356 great_grand_child
->draw_transform());
359 TEST_F(LayerPositionConstraintTest
,
360 ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms
) {
361 // This test checks for correct scroll compensation when the fixed-position
362 // container is NOT the direct parent of the fixed-position layer, and the
363 // hierarchy has various transforms that have to be processed in the correct
365 LayerImpl
* child
= root_
->children()[0];
366 LayerImpl
* grand_child
= child
->children()[0];
367 LayerImpl
* great_grand_child
= grand_child
->children()[0];
369 gfx::Transform rotation_about_z
;
370 rotation_about_z
.RotateAboutZAxis(90.0);
372 child
->SetIsContainerForFixedPositionLayers(true);
373 child
->SetTransform(rotation_about_z
);
374 grand_child
->SetPosition(gfx::PointF(8.f
, 6.f
));
375 grand_child
->SetTransform(rotation_about_z
);
376 // great_grand_child is positioned upside-down with respect to the render
378 great_grand_child
->SetPositionConstraint(fixed_to_top_left_
);
380 // Case 1: scroll delta of 0, 0
381 child
->SetScrollDelta(gfx::Vector2d(0, 0));
382 ExecuteCalculateDrawProperties(root_
.get());
384 gfx::Transform expected_child_transform
;
385 expected_child_transform
.PreconcatTransform(rotation_about_z
);
387 gfx::Transform expected_grand_child_transform
;
388 expected_grand_child_transform
.PreconcatTransform(
389 rotation_about_z
); // child's local transform is inherited
390 // translation because of position occurs before layer's local transform.
391 expected_grand_child_transform
.Translate(8.0, 6.0);
392 expected_grand_child_transform
.PreconcatTransform(
393 rotation_about_z
); // grand_child's local transform
395 gfx::Transform expected_great_grand_child_transform
=
396 expected_grand_child_transform
;
398 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
399 child
->draw_transform());
400 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
401 grand_child
->draw_transform());
402 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
403 great_grand_child
->draw_transform());
405 // Case 2: scroll delta of 10, 20
406 child
->SetScrollDelta(gfx::Vector2d(10, 20));
407 ExecuteCalculateDrawProperties(root_
.get());
409 // Here the child and grand_child are affected by scroll delta, but the fixed
410 // position great_grand_child should not be affected.
411 expected_child_transform
.MakeIdentity();
412 expected_child_transform
.Translate(-10.0, -20.0); // scroll delta
413 expected_child_transform
.PreconcatTransform(rotation_about_z
);
415 expected_grand_child_transform
.MakeIdentity();
416 expected_grand_child_transform
.Translate(
417 -10.0, -20.0); // child's scroll delta is inherited
418 expected_grand_child_transform
.PreconcatTransform(
419 rotation_about_z
); // child's local transform is inherited
420 // translation because of position occurs before layer's local transform.
421 expected_grand_child_transform
.Translate(8.0, 6.0);
422 expected_grand_child_transform
.PreconcatTransform(
423 rotation_about_z
); // grand_child's local transform
425 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
426 child
->draw_transform());
427 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
428 grand_child
->draw_transform());
429 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
430 great_grand_child
->draw_transform());
432 // Case 3: fixed-container size delta of 20, 20
433 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
434 ExecuteCalculateDrawProperties(root_
.get());
436 // Top-left fixed-position layer should not be affected by container size.
437 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
438 child
->draw_transform());
439 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
440 grand_child
->draw_transform());
441 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
442 great_grand_child
->draw_transform());
444 // Case 4: Bottom-right fixed-position layer.
445 great_grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
446 ExecuteCalculateDrawProperties(root_
.get());
448 // Bottom-right fixed-position layer moves as container resizes.
449 expected_great_grand_child_transform
.MakeIdentity();
450 // Apply child layer transform.
451 expected_great_grand_child_transform
.PreconcatTransform(rotation_about_z
);
452 // Apply size delta from the child(container) layer.
453 expected_great_grand_child_transform
.Translate(20.0, 20.0);
454 // Apply layer position from the grand child layer.
455 expected_great_grand_child_transform
.Translate(8.0, 6.0);
456 // Apply grand child layer transform.
457 expected_great_grand_child_transform
.PreconcatTransform(rotation_about_z
);
459 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
460 child
->draw_transform());
461 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
462 grand_child
->draw_transform());
463 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
464 great_grand_child
->draw_transform());
467 TEST_F(LayerPositionConstraintTest
,
468 ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas
) {
469 // This test checks for correct scroll compensation when the fixed-position
470 // container has multiple ancestors that have nonzero scroll delta before
471 // reaching the space where the layer is fixed. In this test, each scroll
472 // delta occurs in a different space because of each layer's local transform.
473 // This test checks for correct scroll compensation when the fixed-position
474 // container is NOT the direct parent of the fixed-position layer, and the
475 // hierarchy has various transforms that have to be processed in the correct
477 LayerImpl
* child
= root_
->children()[0];
478 LayerImpl
* grand_child
= child
->children()[0];
479 LayerImpl
* great_grand_child
= grand_child
->children()[0];
481 gfx::Transform rotation_about_z
;
482 rotation_about_z
.RotateAboutZAxis(90.0);
484 child
->SetIsContainerForFixedPositionLayers(true);
485 child
->SetTransform(rotation_about_z
);
486 grand_child
->SetPosition(gfx::PointF(8.f
, 6.f
));
487 grand_child
->SetTransform(rotation_about_z
);
488 // great_grand_child is positioned upside-down with respect to the render
490 great_grand_child
->SetPositionConstraint(fixed_to_top_left_
);
492 // Case 1: scroll delta of 0, 0
493 child
->SetScrollDelta(gfx::Vector2d(0, 0));
494 ExecuteCalculateDrawProperties(root_
.get());
496 gfx::Transform expected_child_transform
;
497 expected_child_transform
.PreconcatTransform(rotation_about_z
);
499 gfx::Transform expected_grand_child_transform
;
500 expected_grand_child_transform
.PreconcatTransform(
501 rotation_about_z
); // child's local transform is inherited
502 // translation because of position occurs before layer's local transform.
503 expected_grand_child_transform
.Translate(8.0, 6.0);
504 expected_grand_child_transform
.PreconcatTransform(
505 rotation_about_z
); // grand_child's local transform
507 gfx::Transform expected_great_grand_child_transform
=
508 expected_grand_child_transform
;
510 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
511 child
->draw_transform());
512 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
513 grand_child
->draw_transform());
514 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
515 great_grand_child
->draw_transform());
517 // Case 2: scroll delta of 10, 20
518 child
->SetScrollDelta(gfx::Vector2d(10, 0));
519 grand_child
->SetScrollDelta(gfx::Vector2d(5, 0));
520 ExecuteCalculateDrawProperties(root_
.get());
522 // Here the child and grand_child are affected by scroll delta, but the fixed
523 // position great_grand_child should not be affected.
524 expected_child_transform
.MakeIdentity();
525 expected_child_transform
.Translate(-10.0, 0.0); // scroll delta
526 expected_child_transform
.PreconcatTransform(rotation_about_z
);
528 expected_grand_child_transform
.MakeIdentity();
529 expected_grand_child_transform
.Translate(
530 -10.0, 0.0); // child's scroll delta is inherited
531 expected_grand_child_transform
.PreconcatTransform(
532 rotation_about_z
); // child's local transform is inherited
533 expected_grand_child_transform
.Translate(-5.0,
534 0.0); // grand_child's scroll delta
535 // translation because of position occurs before layer's local transform.
536 expected_grand_child_transform
.Translate(8.0, 6.0);
537 expected_grand_child_transform
.PreconcatTransform(
538 rotation_about_z
); // grand_child's local transform
540 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
541 child
->draw_transform());
542 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
543 grand_child
->draw_transform());
544 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
545 great_grand_child
->draw_transform());
547 // Case 3: fixed-container size delta of 20, 20
548 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
549 ExecuteCalculateDrawProperties(root_
.get());
551 // Top-left fixed-position layer should not be affected by container size.
552 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
553 child
->draw_transform());
554 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
555 grand_child
->draw_transform());
556 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
557 great_grand_child
->draw_transform());
559 // Case 4: Bottom-right fixed-position layer.
560 great_grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
561 ExecuteCalculateDrawProperties(root_
.get());
563 // Bottom-right fixed-position layer moves as container resizes.
564 expected_great_grand_child_transform
.MakeIdentity();
565 // Apply child layer transform.
566 expected_great_grand_child_transform
.PreconcatTransform(rotation_about_z
);
567 // Apply size delta from the child(container) layer.
568 expected_great_grand_child_transform
.Translate(20.0, 20.0);
569 // Apply layer position from the grand child layer.
570 expected_great_grand_child_transform
.Translate(8.0, 6.0);
571 // Apply grand child layer transform.
572 expected_great_grand_child_transform
.PreconcatTransform(rotation_about_z
);
574 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
575 child
->draw_transform());
576 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
577 grand_child
->draw_transform());
578 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
579 great_grand_child
->draw_transform());
582 TEST_F(LayerPositionConstraintTest
,
583 ScrollCompensationForFixedPositionWithIntermediateSurfaceAndTransforms
) {
584 // This test checks for correct scroll compensation when the fixed-position
585 // container contributes to a different render surface than the fixed-position
586 // layer. In this case, the surface draw transforms also have to be accounted
587 // for when checking the scroll delta.
588 LayerImpl
* child
= root_
->children()[0];
589 LayerImpl
* grand_child
= child
->children()[0];
590 LayerImpl
* great_grand_child
= grand_child
->children()[0];
592 child
->SetIsContainerForFixedPositionLayers(true);
593 grand_child
->SetPosition(gfx::PointF(8.f
, 6.f
));
594 grand_child
->SetForceRenderSurface(true);
595 great_grand_child
->SetPositionConstraint(fixed_to_top_left_
);
596 great_grand_child
->SetDrawsContent(true);
598 gfx::Transform rotation_about_z
;
599 rotation_about_z
.RotateAboutZAxis(90.0);
600 grand_child
->SetTransform(rotation_about_z
);
602 // Case 1: scroll delta of 0, 0
603 child
->SetScrollDelta(gfx::Vector2d(0, 0));
604 ExecuteCalculateDrawProperties(root_
.get());
606 gfx::Transform expected_child_transform
;
607 gfx::Transform expected_surface_draw_transform
;
608 expected_surface_draw_transform
.Translate(8.0, 6.0);
609 expected_surface_draw_transform
.PreconcatTransform(rotation_about_z
);
610 gfx::Transform expected_grand_child_transform
;
611 gfx::Transform expected_great_grand_child_transform
;
612 ASSERT_TRUE(grand_child
->render_surface());
613 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
614 child
->draw_transform());
615 EXPECT_TRANSFORMATION_MATRIX_EQ(
616 expected_surface_draw_transform
,
617 grand_child
->render_surface()->draw_transform());
618 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
619 grand_child
->draw_transform());
620 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
621 great_grand_child
->draw_transform());
623 // Case 2: scroll delta of 10, 30
624 child
->SetScrollDelta(gfx::Vector2d(10, 30));
625 ExecuteCalculateDrawProperties(root_
.get());
627 // Here the grand_child remains unchanged, because it scrolls along with the
628 // render surface, and the translation is actually in the render surface. But,
629 // the fixed position great_grand_child is more awkward: its actually being
630 // drawn with respect to the render surface, but it needs to remain fixed with
631 // resepct to a container beyond that surface. So, the net result is that,
632 // unlike previous tests where the fixed position layer's transform remains
633 // unchanged, here the fixed position layer's transform explicitly contains
634 // the translation that cancels out the scroll.
635 expected_child_transform
.MakeIdentity();
636 expected_child_transform
.Translate(-10.0, -30.0); // scroll delta
638 expected_surface_draw_transform
.MakeIdentity();
639 expected_surface_draw_transform
.Translate(-10.0, -30.0); // scroll delta
640 expected_surface_draw_transform
.Translate(8.0, 6.0);
641 expected_surface_draw_transform
.PreconcatTransform(rotation_about_z
);
643 // The rotation and its inverse are needed to place the scroll delta
644 // compensation in the correct space. This test will fail if the
645 // rotation/inverse are backwards, too, so it requires perfect order of
647 expected_great_grand_child_transform
.MakeIdentity();
648 expected_great_grand_child_transform
.PreconcatTransform(
649 Inverse(rotation_about_z
));
650 // explicit canceling out the scroll delta that gets embedded in the fixed
651 // position layer's surface.
652 expected_great_grand_child_transform
.Translate(10.0, 30.0);
653 expected_great_grand_child_transform
.PreconcatTransform(rotation_about_z
);
655 ASSERT_TRUE(grand_child
->render_surface());
656 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
657 child
->draw_transform());
658 EXPECT_TRANSFORMATION_MATRIX_EQ(
659 expected_surface_draw_transform
,
660 grand_child
->render_surface()->draw_transform());
661 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
662 grand_child
->draw_transform());
663 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
664 great_grand_child
->draw_transform());
666 // Case 3: fixed-container size delta of 20, 20
667 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
668 ExecuteCalculateDrawProperties(root_
.get());
670 // Top-left fixed-position layer should not be affected by container size.
671 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
672 child
->draw_transform());
673 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
674 grand_child
->draw_transform());
675 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
676 great_grand_child
->draw_transform());
678 // Case 4: Bottom-right fixed-position layer.
679 great_grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
680 ExecuteCalculateDrawProperties(root_
.get());
682 // Bottom-right fixed-position layer moves as container resizes.
683 expected_great_grand_child_transform
.MakeIdentity();
684 // The rotation and its inverse are needed to place the scroll delta
685 // compensation in the correct space. This test will fail if the
686 // rotation/inverse are backwards, too, so it requires perfect order of
688 expected_great_grand_child_transform
.PreconcatTransform(
689 Inverse(rotation_about_z
));
690 // explicit canceling out the scroll delta that gets embedded in the fixed
691 // position layer's surface.
692 expected_great_grand_child_transform
.Translate(10.0, 30.0);
693 // Also apply size delta in the child(container) layer space.
694 expected_great_grand_child_transform
.Translate(20.0, 20.0);
695 expected_great_grand_child_transform
.PreconcatTransform(rotation_about_z
);
697 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
698 child
->draw_transform());
699 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
700 grand_child
->draw_transform());
701 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
702 great_grand_child
->draw_transform());
705 TEST_F(LayerPositionConstraintTest
,
706 ScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces
) {
707 // This test checks for correct scroll compensation when the fixed-position
708 // container contributes to a different render surface than the fixed-position
709 // layer, with additional render surfaces in-between. This checks that the
710 // conversion to ancestor surfaces is accumulated properly in the final matrix
712 LayerImpl
* child
= root_
->children()[0];
713 LayerImpl
* grand_child
= child
->children()[0];
714 LayerImpl
* great_grand_child
= grand_child
->children()[0];
716 // Add one more layer to the test tree for this scenario.
718 gfx::Transform identity
;
719 scoped_ptr
<LayerImpl
> fixed_position_child
=
720 LayerImpl::Create(host_impl_
.active_tree(), 5);
721 SetLayerPropertiesForTesting(fixed_position_child
.get(),
728 great_grand_child
->AddChild(fixed_position_child
.Pass());
730 LayerImpl
* fixed_position_child
= great_grand_child
->children()[0];
732 // Actually set up the scenario here.
733 child
->SetIsContainerForFixedPositionLayers(true);
734 grand_child
->SetPosition(gfx::PointF(8.f
, 6.f
));
735 grand_child
->SetForceRenderSurface(true);
736 great_grand_child
->SetPosition(gfx::PointF(40.f
, 60.f
));
737 great_grand_child
->SetForceRenderSurface(true);
738 fixed_position_child
->SetPositionConstraint(fixed_to_top_left_
);
739 fixed_position_child
->SetDrawsContent(true);
741 // The additional rotations, which are non-commutative with translations, help
742 // to verify that we have correct order-of-operations in the final scroll
743 // compensation. Note that rotating about the center of the layer ensures we
744 // do not accidentally clip away layers that we want to test.
745 gfx::Transform rotation_about_z
;
746 rotation_about_z
.Translate(50.0, 50.0);
747 rotation_about_z
.RotateAboutZAxis(90.0);
748 rotation_about_z
.Translate(-50.0, -50.0);
749 grand_child
->SetTransform(rotation_about_z
);
750 great_grand_child
->SetTransform(rotation_about_z
);
752 // Case 1: scroll delta of 0, 0
753 child
->SetScrollDelta(gfx::Vector2d(0, 0));
754 ExecuteCalculateDrawProperties(root_
.get());
756 gfx::Transform expected_child_transform
;
758 gfx::Transform expected_grand_child_surface_draw_transform
;
759 expected_grand_child_surface_draw_transform
.Translate(8.0, 6.0);
760 expected_grand_child_surface_draw_transform
.PreconcatTransform(
763 gfx::Transform expected_grand_child_transform
;
765 gfx::Transform expected_great_grand_child_surface_draw_transform
;
766 expected_great_grand_child_surface_draw_transform
.Translate(40.0, 60.0);
767 expected_great_grand_child_surface_draw_transform
.PreconcatTransform(
770 gfx::Transform expected_great_grand_child_transform
;
772 gfx::Transform expected_fixed_position_child_transform
;
774 ASSERT_TRUE(grand_child
->render_surface());
775 ASSERT_TRUE(great_grand_child
->render_surface());
776 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
777 child
->draw_transform());
778 EXPECT_TRANSFORMATION_MATRIX_EQ(
779 expected_grand_child_surface_draw_transform
,
780 grand_child
->render_surface()->draw_transform());
781 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
782 grand_child
->draw_transform());
783 EXPECT_TRANSFORMATION_MATRIX_EQ(
784 expected_great_grand_child_surface_draw_transform
,
785 great_grand_child
->render_surface()->draw_transform());
786 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
787 great_grand_child
->draw_transform());
788 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform
,
789 fixed_position_child
->draw_transform());
791 // Case 2: scroll delta of 10, 30
792 child
->SetScrollDelta(gfx::Vector2d(10, 30));
793 ExecuteCalculateDrawProperties(root_
.get());
795 expected_child_transform
.MakeIdentity();
796 expected_child_transform
.Translate(-10.0, -30.0); // scroll delta
798 expected_grand_child_surface_draw_transform
.MakeIdentity();
799 expected_grand_child_surface_draw_transform
.Translate(-10.0,
800 -30.0); // scroll delta
801 expected_grand_child_surface_draw_transform
.Translate(8.0, 6.0);
802 expected_grand_child_surface_draw_transform
.PreconcatTransform(
805 // grand_child, great_grand_child, and great_grand_child's surface are not
806 // expected to change, since they are all not fixed, and they are all drawn
807 // with respect to grand_child's surface that already has the scroll delta
810 // But the great-great grandchild, "fixed_position_child", should have a
811 // transform that explicitly cancels out the scroll delta. The expected
812 // transform is: compound_draw_transform.Inverse() * translate(positive scroll
813 // delta) * compound_origin_transform from great_grand_childSurface's origin
814 // to the root surface.
815 gfx::Transform compound_draw_transform
;
816 compound_draw_transform
.Translate(8.0,
817 6.0); // origin translation of grand_child
818 compound_draw_transform
.PreconcatTransform(
819 rotation_about_z
); // rotation of grand_child
820 compound_draw_transform
.Translate(
821 40.0, 60.0); // origin translation of great_grand_child
822 compound_draw_transform
.PreconcatTransform(
823 rotation_about_z
); // rotation of great_grand_child
825 expected_fixed_position_child_transform
.MakeIdentity();
826 expected_fixed_position_child_transform
.PreconcatTransform(
827 Inverse(compound_draw_transform
));
828 // explicit canceling out the scroll delta that gets embedded in the fixed
829 // position layer's surface.
830 expected_fixed_position_child_transform
.Translate(10.0, 30.0);
831 expected_fixed_position_child_transform
.PreconcatTransform(
832 compound_draw_transform
);
834 ASSERT_TRUE(grand_child
->render_surface());
835 ASSERT_TRUE(great_grand_child
->render_surface());
836 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
837 child
->draw_transform());
838 EXPECT_TRANSFORMATION_MATRIX_EQ(
839 expected_grand_child_surface_draw_transform
,
840 grand_child
->render_surface()->draw_transform());
841 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
842 grand_child
->draw_transform());
843 EXPECT_TRANSFORMATION_MATRIX_EQ(
844 expected_great_grand_child_surface_draw_transform
,
845 great_grand_child
->render_surface()->draw_transform());
846 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
847 great_grand_child
->draw_transform());
848 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform
,
849 fixed_position_child
->draw_transform());
852 // Case 3: fixed-container size delta of 20, 20
853 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
854 ExecuteCalculateDrawProperties(root_
.get());
856 // Top-left fixed-position layer should not be affected by container size.
857 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
858 child
->draw_transform());
859 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
860 grand_child
->draw_transform());
861 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
862 great_grand_child
->draw_transform());
863 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform
,
864 fixed_position_child
->draw_transform());
866 // Case 4: Bottom-right fixed-position layer.
867 fixed_position_child
->SetPositionConstraint(fixed_to_bottom_right_
);
868 ExecuteCalculateDrawProperties(root_
.get());
870 // Bottom-right fixed-position layer moves as container resizes.
871 expected_fixed_position_child_transform
.MakeIdentity();
872 expected_fixed_position_child_transform
.PreconcatTransform(
873 Inverse(compound_draw_transform
));
874 // explicit canceling out the scroll delta that gets embedded in the fixed
875 // position layer's surface.
876 expected_fixed_position_child_transform
.Translate(10.0, 30.0);
877 // Also apply size delta in the child(container) layer space.
878 expected_fixed_position_child_transform
.Translate(20.0, 20.0);
879 expected_fixed_position_child_transform
.PreconcatTransform(
880 compound_draw_transform
);
882 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
883 child
->draw_transform());
884 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
885 grand_child
->draw_transform());
886 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
887 great_grand_child
->draw_transform());
888 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform
,
889 fixed_position_child
->draw_transform());
892 TEST_F(LayerPositionConstraintTest
,
893 ScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface
) {
894 // This test checks for correct scroll compensation when the fixed-position
895 // container itself has a render surface. In this case, the container layer
896 // should be treated like a layer that contributes to a render target, and
897 // that render target is completely irrelevant; it should not affect the
898 // scroll compensation.
899 LayerImpl
* child
= root_
->children()[0];
900 LayerImpl
* grand_child
= child
->children()[0];
902 child
->SetIsContainerForFixedPositionLayers(true);
903 child
->SetForceRenderSurface(true);
904 grand_child
->SetPositionConstraint(fixed_to_top_left_
);
905 grand_child
->SetDrawsContent(true);
907 // Case 1: scroll delta of 0, 0
908 child
->SetScrollDelta(gfx::Vector2d(0, 0));
909 ExecuteCalculateDrawProperties(root_
.get());
911 gfx::Transform expected_surface_draw_transform
;
912 expected_surface_draw_transform
.Translate(0.0, 0.0);
913 gfx::Transform expected_child_transform
;
914 gfx::Transform expected_grand_child_transform
;
915 ASSERT_TRUE(child
->render_surface());
916 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform
,
917 child
->render_surface()->draw_transform());
918 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
919 child
->draw_transform());
920 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
921 grand_child
->draw_transform());
923 // Case 2: scroll delta of 10, 10
924 child
->SetScrollDelta(gfx::Vector2d(10, 10));
925 ExecuteCalculateDrawProperties(root_
.get());
927 // The surface is translated by scroll delta, the child transform doesn't
928 // change because it scrolls along with the surface, but the fixed position
929 // grand_child needs to compensate for the scroll translation.
930 expected_surface_draw_transform
.MakeIdentity();
931 expected_surface_draw_transform
.Translate(-10.0, -10.0);
932 expected_grand_child_transform
.MakeIdentity();
933 expected_grand_child_transform
.Translate(10.0, 10.0);
935 ASSERT_TRUE(child
->render_surface());
936 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform
,
937 child
->render_surface()->draw_transform());
938 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
939 child
->draw_transform());
940 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
941 grand_child
->draw_transform());
943 // Case 3: fixed-container size delta of 20, 20
944 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
945 ExecuteCalculateDrawProperties(root_
.get());
947 // Top-left fixed-position layer should not be affected by container size.
948 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
949 child
->draw_transform());
950 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
951 grand_child
->draw_transform());
953 // Case 4: Bottom-right fixed-position layer.
954 grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
955 ExecuteCalculateDrawProperties(root_
.get());
957 // Bottom-right fixed-position layer moves as container resizes.
958 expected_grand_child_transform
.MakeIdentity();
959 // The surface is translated by scroll delta, the child transform doesn't
960 // change because it scrolls along with the surface, but the fixed position
961 // grand_child needs to compensate for the scroll translation.
962 expected_grand_child_transform
.Translate(10.0, 10.0);
963 // Apply size delta from the child(container) layer.
964 expected_grand_child_transform
.Translate(20.0, 20.0);
966 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
967 child
->draw_transform());
968 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
969 grand_child
->draw_transform());
972 TEST_F(LayerPositionConstraintTest
,
973 ScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer
) {
974 // This test checks the scenario where a fixed-position layer also happens to
975 // be a container itself for a descendant fixed position layer. In particular,
976 // the layer should not accidentally be fixed to itself.
977 LayerImpl
* child
= root_
->children()[0];
978 LayerImpl
* grand_child
= child
->children()[0];
980 child
->SetIsContainerForFixedPositionLayers(true);
981 grand_child
->SetPositionConstraint(fixed_to_top_left_
);
983 // This should not confuse the grand_child. If correct, the grand_child would
984 // still be considered fixed to its container (i.e. "child").
985 grand_child
->SetIsContainerForFixedPositionLayers(true);
987 // Case 1: scroll delta of 0, 0
988 child
->SetScrollDelta(gfx::Vector2d(0, 0));
989 ExecuteCalculateDrawProperties(root_
.get());
991 gfx::Transform expected_child_transform
;
992 gfx::Transform expected_grand_child_transform
;
993 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
994 child
->draw_transform());
995 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
996 grand_child
->draw_transform());
998 // Case 2: scroll delta of 10, 10
999 child
->SetScrollDelta(gfx::Vector2d(10, 10));
1000 ExecuteCalculateDrawProperties(root_
.get());
1002 // Here the child is affected by scroll delta, but the fixed position
1003 // grand_child should not be affected.
1004 expected_child_transform
.MakeIdentity();
1005 expected_child_transform
.Translate(-10.0, -10.0);
1006 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1007 child
->draw_transform());
1008 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
1009 grand_child
->draw_transform());
1011 // Case 3: fixed-container size delta of 20, 20
1012 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
1013 ExecuteCalculateDrawProperties(root_
.get());
1015 // Top-left fixed-position layer should not be affected by container size.
1016 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1017 child
->draw_transform());
1018 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
1019 grand_child
->draw_transform());
1021 // Case 4: Bottom-right fixed-position layer.
1022 grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
1023 ExecuteCalculateDrawProperties(root_
.get());
1025 // Bottom-right fixed-position layer moves as container resizes.
1026 expected_grand_child_transform
.MakeIdentity();
1027 // Apply size delta from the child(container) layer.
1028 expected_grand_child_transform
.Translate(20.0, 20.0);
1030 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1031 child
->draw_transform());
1032 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
1033 grand_child
->draw_transform());
1036 TEST_F(LayerPositionConstraintTest
,
1037 ScrollCompensationForFixedPositionLayerThatHasNoContainer
) {
1038 // This test checks scroll compensation when a fixed-position layer does not
1039 // find any ancestor that is a "containerForFixedPositionLayers". In this
1040 // situation, the layer should be fixed to the root layer.
1041 LayerImpl
* child
= root_
->children()[0];
1042 LayerImpl
* grand_child
= child
->children()[0];
1044 gfx::Transform rotation_by_z
;
1045 rotation_by_z
.RotateAboutZAxis(90.0);
1047 root_
->SetTransform(rotation_by_z
);
1048 grand_child
->SetPositionConstraint(fixed_to_top_left_
);
1050 // Case 1: root scroll delta of 0, 0
1051 root_
->SetScrollDelta(gfx::Vector2d(0, 0));
1052 ExecuteCalculateDrawProperties(root_
.get());
1054 gfx::Transform identity_matrix
;
1056 EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z
, child
->draw_transform());
1057 EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z
,
1058 grand_child
->draw_transform());
1060 // Case 2: root scroll delta of 10, 10
1061 root_
->SetScrollDelta(gfx::Vector2d(10, 20));
1062 ExecuteCalculateDrawProperties(root_
.get());
1064 gfx::Transform expected_child_transform
;
1065 expected_child_transform
.Translate(-10.0, -20.0);
1066 expected_child_transform
.PreconcatTransform(rotation_by_z
);
1068 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1069 child
->draw_transform());
1070 EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z
,
1071 grand_child
->draw_transform());
1073 // Case 3: fixed-container size delta of 20, 20
1074 root_
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
1075 ExecuteCalculateDrawProperties(root_
.get());
1077 // Top-left fixed-position layer should not be affected by container size.
1078 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1079 child
->draw_transform());
1080 EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z
,
1081 grand_child
->draw_transform());
1083 // Case 4: Bottom-right fixed-position layer.
1084 grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
1085 ExecuteCalculateDrawProperties(root_
.get());
1087 gfx::Transform expected_grand_child_transform
;
1088 expected_grand_child_transform
.Translate(-20.0, 20.0);
1089 expected_grand_child_transform
.PreconcatTransform(rotation_by_z
);
1091 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1092 child
->draw_transform());
1093 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
1094 grand_child
->draw_transform());
1097 TEST_F(LayerPositionConstraintTest
,
1098 ScrollCompensationForFixedWithinFixedWithSameContainer
) {
1099 // This test checks scroll compensation for a fixed-position layer that is
1100 // inside of another fixed-position layer and both share the same container.
1101 // In this situation, the parent fixed-position layer will receive
1102 // the scroll compensation, and the child fixed-position layer does not
1103 // need to compensate further.
1105 LayerImpl
* child
= root_
->children()[0];
1106 LayerImpl
* grand_child
= child
->children()[0];
1107 LayerImpl
* great_grand_child
= grand_child
->children()[0];
1109 child
->SetIsContainerForFixedPositionLayers(true);
1110 grand_child
->SetPositionConstraint(fixed_to_top_left_
);
1112 // Note carefully - great_grand_child is fixed to bottom right, to test
1113 // sizeDelta being applied correctly; the compensation skips the grand_child
1114 // because it is fixed to top left.
1115 great_grand_child
->SetPositionConstraint(fixed_to_bottom_right_
);
1117 // Case 1: scrollDelta
1118 child
->SetScrollDelta(gfx::Vector2d(10, 10));
1119 ExecuteCalculateDrawProperties(root_
.get());
1121 // Here the child is affected by scroll delta, but the fixed position
1122 // grand_child should not be affected.
1123 gfx::Transform expected_child_transform
;
1124 expected_child_transform
.Translate(-10.0, -10.0);
1126 gfx::Transform expected_grand_child_transform
;
1127 gfx::Transform expected_great_grand_child_transform
;
1129 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1130 child
->draw_transform());
1131 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
1132 grand_child
->draw_transform());
1133 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
1134 great_grand_child
->draw_transform());
1136 // Case 2: sizeDelta
1137 child
->SetScrollDelta(gfx::Vector2d(0, 0));
1138 child
->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
1139 ExecuteCalculateDrawProperties(root_
.get());
1141 expected_child_transform
.MakeIdentity();
1143 expected_grand_child_transform
.MakeIdentity();
1145 // Fixed to bottom-right, size-delta compensation is applied.
1146 expected_great_grand_child_transform
.MakeIdentity();
1147 expected_great_grand_child_transform
.Translate(20.0, 20.0);
1149 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform
,
1150 child
->draw_transform());
1151 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform
,
1152 grand_child
->draw_transform());
1153 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform
,
1154 great_grand_child
->draw_transform());
1157 TEST_F(LayerPositionConstraintTest
,
1158 ScrollCompensationForFixedWithinFixedWithInterveningContainer
) {
1159 // This test checks scroll compensation for a fixed-position layer that is
1160 // inside of another fixed-position layer, but they have different fixed
1161 // position containers. In this situation, the child fixed-position element
1162 // would still have to compensate with respect to its container.
1164 LayerImpl
* container1
= root_
->children()[0];
1165 LayerImpl
* fixed_to_container1
= container1
->children()[0];
1166 LayerImpl
* container2
= fixed_to_container1
->children()[0];
1169 // Add one more layer to the hierarchy for this test.
1170 scoped_ptr
<LayerImpl
> fixed_to_container2_ptr
=
1171 LayerImpl::Create(host_impl_
.active_tree(), 5);
1172 container2
->AddChild(fixed_to_container2_ptr
.Pass());
1175 LayerImpl
* fixed_to_container2
= container2
->children()[0];
1177 container1
->SetIsContainerForFixedPositionLayers(true);
1178 fixed_to_container1
->SetPositionConstraint(fixed_to_top_left_
);
1179 container2
->SetIsContainerForFixedPositionLayers(true);
1180 fixed_to_container2
->SetPositionConstraint(fixed_to_top_left_
);
1182 container1
->SetScrollDelta(gfx::Vector2d(0, 15));
1183 container2
->SetScrollDelta(gfx::Vector2d(30, 0));
1184 ExecuteCalculateDrawProperties(root_
.get());
1186 gfx::Transform expected_container1_transform
;
1187 expected_container1_transform
.Translate(0.0, -15.0);
1189 gfx::Transform expected_fixed_to_container1_transform
;
1191 // Since the container is a descendant of the fixed layer above,
1192 // the expected draw transform for container2 would not
1193 // include the scrollDelta that was applied to container1.
1194 gfx::Transform expected_container2_transform
;
1195 expected_container2_transform
.Translate(-30.0, 0.0);
1197 gfx::Transform expected_fixed_to_container2_transform
;
1199 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container1_transform
,
1200 container1
->draw_transform());
1202 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container1_transform
,
1203 fixed_to_container1
->draw_transform());
1205 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container2_transform
,
1206 container2
->draw_transform());
1208 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container2_transform
,
1209 fixed_to_container2
->draw_transform());