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::PointF& anchor,
22 const gfx::PointF& position,
23 const gfx::Size& bounds,
24 bool flatten_transform,
26 layer->SetTransform(transform);
27 layer->SetAnchorPoint(anchor);
28 layer->SetPosition(position);
29 layer->SetBounds(bounds);
30 layer->SetShouldFlattenTransform(flatten_transform);
31 layer->SetIs3dSorted(is_3d_sorted);
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 LayerImpl* scroll_layer = root_layer->children()[0];
43 gfx::Size device_viewport_size =
44 gfx::Size(root_layer->bounds().width() * device_scale_factor,
45 root_layer->bounds().height() * device_scale_factor);
47 // We are probably not testing what is intended if the scroll_layer bounds are
49 DCHECK(!scroll_layer->bounds().IsEmpty());
50 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
51 root_layer, device_viewport_size, &dummy_render_surface_layer_list);
52 inputs.device_scale_factor = device_scale_factor;
53 inputs.page_scale_factor = page_scale_factor;
54 inputs.page_scale_application_layer = page_scale_application_layer;
55 inputs.can_use_lcd_text = can_use_lcd_text;
56 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
59 void ExecuteCalculateDrawProperties(LayerImpl* root_layer) {
60 LayerImpl* page_scale_application_layer = NULL;
61 ExecuteCalculateDrawProperties(
62 root_layer, 1.f, 1.f, page_scale_application_layer, false);
65 class LayerPositionConstraintTest : public testing::Test {
67 LayerPositionConstraintTest()
68 : host_impl_(&proxy_) {
69 root_ = CreateTreeForTest();
70 scroll_ = root_->children()[0];
71 fixed_to_top_left_.set_is_fixed_position(true);
72 fixed_to_bottom_right_.set_is_fixed_position(true);
73 fixed_to_bottom_right_.set_is_fixed_to_right_edge(true);
74 fixed_to_bottom_right_.set_is_fixed_to_bottom_edge(true);
77 scoped_ptr<LayerImpl> CreateTreeForTest() {
78 scoped_ptr<LayerImpl> root =
79 LayerImpl::Create(host_impl_.active_tree(), 42);
80 scoped_ptr<LayerImpl> scroll_layer =
81 LayerImpl::Create(host_impl_.active_tree(), 1);
82 scoped_ptr<LayerImpl> child =
83 LayerImpl::Create(host_impl_.active_tree(), 2);
84 scoped_ptr<LayerImpl> grand_child =
85 LayerImpl::Create(host_impl_.active_tree(), 3);
86 scoped_ptr<LayerImpl> great_grand_child =
87 LayerImpl::Create(host_impl_.active_tree(), 4);
89 gfx::Transform IdentityMatrix;
92 gfx::Size bounds(200, 200);
93 gfx::Size clip_bounds(100, 100);
94 SetLayerPropertiesForTesting(scroll_layer.get(),
101 SetLayerPropertiesForTesting(child.get(),
108 SetLayerPropertiesForTesting(grand_child.get(),
115 SetLayerPropertiesForTesting(great_grand_child.get(),
123 root->SetBounds(clip_bounds);
124 scroll_layer->SetScrollClipLayer(root->id());
125 child->SetScrollClipLayer(root->id());
126 grand_child->SetScrollClipLayer(root->id());
128 grand_child->AddChild(great_grand_child.Pass());
129 child->AddChild(grand_child.Pass());
130 scroll_layer->AddChild(child.Pass());
131 root->AddChild(scroll_layer.Pass());
137 FakeImplProxy proxy_;
138 FakeLayerTreeHostImpl host_impl_;
139 scoped_ptr<LayerImpl> root_;
142 LayerPositionConstraint fixed_to_top_left_;
143 LayerPositionConstraint fixed_to_bottom_right_;
148 void SetFixedContainerSizeDelta(LayerImpl* scroll_layer,
149 const gfx::Vector2d& delta) {
150 DCHECK(scroll_layer);
151 DCHECK(scroll_layer->scrollable());
153 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
154 gfx::Size container_size(container_layer->bounds());
155 gfx::Size new_container_size(container_size.width() + delta.x(),
156 container_size.height() + delta.y());
157 container_layer->SetTemporaryImplBounds(new_container_size);
161 TEST_F(LayerPositionConstraintTest,
162 ScrollCompensationForFixedPositionLayerWithDirectContainer) {
163 // This test checks for correct scroll compensation when the fixed-position
164 // container is the direct parent of the fixed-position layer.
165 LayerImpl* child = scroll_->children()[0];
166 LayerImpl* grand_child = child->children()[0];
168 child->SetIsContainerForFixedPositionLayers(true);
169 grand_child->SetPositionConstraint(fixed_to_top_left_);
171 // Case 1: scroll delta of 0, 0
172 child->SetScrollDelta(gfx::Vector2d(0, 0));
173 ExecuteCalculateDrawProperties(root_.get());
175 gfx::Transform expected_child_transform;
176 gfx::Transform expected_grand_child_transform = expected_child_transform;
178 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
179 child->draw_transform());
180 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
181 grand_child->draw_transform());
183 // Case 2: scroll delta of 10, 10
184 child->SetScrollDelta(gfx::Vector2d(10, 10));
185 ExecuteCalculateDrawProperties(root_.get());
187 // Here the child is affected by scroll delta, but the fixed position
188 // grand_child should not be affected.
189 expected_child_transform.MakeIdentity();
190 expected_child_transform.Translate(-10.0, -10.0);
192 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
193 child->draw_transform());
194 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
195 grand_child->draw_transform());
197 // Case 3: fixed-container size delta of 20, 20
198 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
199 ExecuteCalculateDrawProperties(root_.get());
201 // Top-left fixed-position layer should not be affected by container size.
202 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
203 child->draw_transform());
204 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
205 grand_child->draw_transform());
207 // Case 4: Bottom-right fixed-position layer.
208 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
209 ExecuteCalculateDrawProperties(root_.get());
211 // Bottom-right fixed-position layer moves as container resizes.
212 expected_grand_child_transform.MakeIdentity();
213 // Apply size delta from the child(container) layer.
214 expected_grand_child_transform.Translate(20.0, 20.0);
216 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
217 child->draw_transform());
218 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
219 grand_child->draw_transform());
222 TEST_F(LayerPositionConstraintTest,
223 ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer) {
224 // This test checks for correct scroll compensation when the fixed-position
225 // container is the direct parent of the fixed-position layer, but that
226 // container is transformed. In this case, the fixed position element
227 // inherits the container's transform, but the scroll delta that has to be
228 // undone should not be affected by that transform.
230 // Transforms are in general non-commutative; using something like a
231 // non-uniform scale helps to verify that translations and non-uniform scales
232 // are applied in the correct order.
233 LayerImpl* child = scroll_->children()[0];
234 LayerImpl* grand_child = child->children()[0];
236 // This scale will cause child and grand_child to be effectively 200 x 800
237 // with respect to the render target.
238 gfx::Transform non_uniform_scale;
239 non_uniform_scale.Scale(2.0, 8.0);
240 child->SetTransform(non_uniform_scale);
242 child->SetIsContainerForFixedPositionLayers(true);
243 grand_child->SetPositionConstraint(fixed_to_top_left_);
245 // Case 1: scroll delta of 0, 0
246 child->SetScrollDelta(gfx::Vector2d(0, 0));
247 ExecuteCalculateDrawProperties(root_.get());
249 gfx::Transform expected_child_transform;
250 expected_child_transform.PreconcatTransform(non_uniform_scale);
252 gfx::Transform expected_grand_child_transform = expected_child_transform;
254 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
255 child->draw_transform());
256 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
257 grand_child->draw_transform());
259 // Case 2: scroll delta of 10, 20
260 child->SetScrollDelta(gfx::Vector2d(10, 20));
261 ExecuteCalculateDrawProperties(root_.get());
263 // The child should be affected by scroll delta, but the fixed position
264 // grand_child should not be affected.
265 expected_child_transform.MakeIdentity();
266 expected_child_transform.Translate(-10.0, -20.0); // scroll delta
267 expected_child_transform.PreconcatTransform(non_uniform_scale);
269 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
270 child->draw_transform());
271 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
272 grand_child->draw_transform());
274 // Case 3: fixed-container size delta of 20, 20
275 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
276 ExecuteCalculateDrawProperties(root_.get());
278 // Top-left fixed-position layer should not be affected by container size.
279 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
280 child->draw_transform());
281 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
282 grand_child->draw_transform());
284 // Case 4: Bottom-right fixed-position layer.
285 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
286 ExecuteCalculateDrawProperties(root_.get());
288 // Bottom-right fixed-position layer moves as container resizes.
289 expected_grand_child_transform.MakeIdentity();
290 // Apply child layer transform.
291 expected_grand_child_transform.PreconcatTransform(non_uniform_scale);
292 // Apply size delta from the child(container) layer.
293 expected_grand_child_transform.Translate(20.0, 20.0);
295 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
296 child->draw_transform());
297 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
298 grand_child->draw_transform());
301 TEST_F(LayerPositionConstraintTest,
302 ScrollCompensationForFixedPositionLayerWithDistantContainer) {
303 // This test checks for correct scroll compensation when the fixed-position
304 // container is NOT the direct parent of the fixed-position layer.
305 LayerImpl* child = scroll_->children()[0];
306 LayerImpl* grand_child = child->children()[0];
307 LayerImpl* great_grand_child = grand_child->children()[0];
309 child->SetIsContainerForFixedPositionLayers(true);
310 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
311 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
313 // Case 1: scroll delta of 0, 0
314 child->SetScrollDelta(gfx::Vector2d(0, 0));
315 ExecuteCalculateDrawProperties(root_.get());
317 gfx::Transform expected_child_transform;
318 gfx::Transform expected_grand_child_transform;
319 expected_grand_child_transform.Translate(8.0, 6.0);
321 gfx::Transform expected_great_grand_child_transform =
322 expected_grand_child_transform;
324 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
325 child->draw_transform());
326 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
327 grand_child->draw_transform());
328 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
329 great_grand_child->draw_transform());
331 // Case 2: scroll delta of 10, 10
332 child->SetScrollDelta(gfx::Vector2d(10, 10));
333 ExecuteCalculateDrawProperties(root_.get());
335 // Here the child and grand_child are affected by scroll delta, but the fixed
336 // position great_grand_child should not be affected.
337 expected_child_transform.MakeIdentity();
338 expected_child_transform.Translate(-10.0, -10.0);
339 expected_grand_child_transform.MakeIdentity();
340 expected_grand_child_transform.Translate(-2.0, -4.0);
341 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
342 child->draw_transform());
343 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
344 grand_child->draw_transform());
345 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
346 great_grand_child->draw_transform());
348 // Case 3: fixed-container size delta of 20, 20
349 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
350 ExecuteCalculateDrawProperties(root_.get());
352 // Top-left fixed-position layer should not be affected by container size.
353 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
354 child->draw_transform());
355 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
356 grand_child->draw_transform());
357 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
358 great_grand_child->draw_transform());
360 // Case 4: Bottom-right fixed-position layer.
361 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
362 ExecuteCalculateDrawProperties(root_.get());
364 // Bottom-right fixed-position layer moves as container resizes.
365 expected_great_grand_child_transform.MakeIdentity();
366 // Apply size delta from the child(container) layer.
367 expected_great_grand_child_transform.Translate(20.0, 20.0);
368 // Apply layer position from the grand child layer.
369 expected_great_grand_child_transform.Translate(8.0, 6.0);
371 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
372 child->draw_transform());
373 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
374 grand_child->draw_transform());
375 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
376 great_grand_child->draw_transform());
379 TEST_F(LayerPositionConstraintTest,
380 ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms) {
381 // This test checks for correct scroll compensation when the fixed-position
382 // container is NOT the direct parent of the fixed-position layer, and the
383 // hierarchy has various transforms that have to be processed in the correct
385 LayerImpl* child = scroll_->children()[0];
386 LayerImpl* grand_child = child->children()[0];
387 LayerImpl* great_grand_child = grand_child->children()[0];
389 gfx::Transform rotation_about_z;
390 rotation_about_z.RotateAboutZAxis(90.0);
392 child->SetIsContainerForFixedPositionLayers(true);
393 child->SetTransform(rotation_about_z);
394 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
395 grand_child->SetTransform(rotation_about_z);
396 // great_grand_child is positioned upside-down with respect to the render
398 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
400 // Case 1: scroll delta of 0, 0
401 child->SetScrollDelta(gfx::Vector2d(0, 0));
402 ExecuteCalculateDrawProperties(root_.get());
404 gfx::Transform expected_child_transform;
405 expected_child_transform.PreconcatTransform(rotation_about_z);
407 gfx::Transform expected_grand_child_transform;
408 expected_grand_child_transform.PreconcatTransform(
409 rotation_about_z); // child's local transform is inherited
410 // translation because of position occurs before layer's local transform.
411 expected_grand_child_transform.Translate(8.0, 6.0);
412 expected_grand_child_transform.PreconcatTransform(
413 rotation_about_z); // grand_child's local transform
415 gfx::Transform expected_great_grand_child_transform =
416 expected_grand_child_transform;
418 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
419 child->draw_transform());
420 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
421 grand_child->draw_transform());
422 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
423 great_grand_child->draw_transform());
425 // Case 2: scroll delta of 10, 20
426 child->SetScrollDelta(gfx::Vector2d(10, 20));
427 ExecuteCalculateDrawProperties(root_.get());
429 // Here the child and grand_child are affected by scroll delta, but the fixed
430 // position great_grand_child should not be affected.
431 expected_child_transform.MakeIdentity();
432 expected_child_transform.Translate(-10.0, -20.0); // scroll delta
433 expected_child_transform.PreconcatTransform(rotation_about_z);
435 expected_grand_child_transform.MakeIdentity();
436 expected_grand_child_transform.Translate(
437 -10.0, -20.0); // child's scroll delta is inherited
438 expected_grand_child_transform.PreconcatTransform(
439 rotation_about_z); // child's local transform is inherited
440 // translation because of position occurs before layer's local transform.
441 expected_grand_child_transform.Translate(8.0, 6.0);
442 expected_grand_child_transform.PreconcatTransform(
443 rotation_about_z); // grand_child's local transform
445 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
446 child->draw_transform());
447 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
448 grand_child->draw_transform());
449 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
450 great_grand_child->draw_transform());
452 // Case 3: fixed-container size delta of 20, 20
453 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
454 ExecuteCalculateDrawProperties(root_.get());
456 // Top-left fixed-position layer should not be affected by container size.
457 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
458 child->draw_transform());
459 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
460 grand_child->draw_transform());
461 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
462 great_grand_child->draw_transform());
464 // Case 4: Bottom-right fixed-position layer.
465 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
466 ExecuteCalculateDrawProperties(root_.get());
468 // Bottom-right fixed-position layer moves as container resizes.
469 expected_great_grand_child_transform.MakeIdentity();
470 // Apply child layer transform.
471 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
472 // Apply size delta from the child(container) layer.
473 expected_great_grand_child_transform.Translate(20.0, 20.0);
474 // Apply layer position from the grand child layer.
475 expected_great_grand_child_transform.Translate(8.0, 6.0);
476 // Apply grand child layer transform.
477 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
479 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
480 child->draw_transform());
481 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
482 grand_child->draw_transform());
483 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
484 great_grand_child->draw_transform());
487 TEST_F(LayerPositionConstraintTest,
488 ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas) {
489 // This test checks for correct scroll compensation when the fixed-position
490 // container has multiple ancestors that have nonzero scroll delta before
491 // reaching the space where the layer is fixed. In this test, each scroll
492 // delta occurs in a different space because of each layer's local transform.
493 // This test checks for correct scroll compensation when the fixed-position
494 // container is NOT the direct parent of the fixed-position layer, and the
495 // hierarchy has various transforms that have to be processed in the correct
497 LayerImpl* child = scroll_->children()[0];
498 LayerImpl* grand_child = child->children()[0];
499 LayerImpl* great_grand_child = grand_child->children()[0];
501 gfx::Transform rotation_about_z;
502 rotation_about_z.RotateAboutZAxis(90.0);
504 child->SetIsContainerForFixedPositionLayers(true);
505 child->SetTransform(rotation_about_z);
506 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
507 grand_child->SetTransform(rotation_about_z);
508 // great_grand_child is positioned upside-down with respect to the render
510 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
512 // Case 1: scroll delta of 0, 0
513 child->SetScrollDelta(gfx::Vector2d(0, 0));
514 ExecuteCalculateDrawProperties(root_.get());
516 gfx::Transform expected_child_transform;
517 expected_child_transform.PreconcatTransform(rotation_about_z);
519 gfx::Transform expected_grand_child_transform;
520 expected_grand_child_transform.PreconcatTransform(
521 rotation_about_z); // child's local transform is inherited
522 // translation because of position occurs before layer's local transform.
523 expected_grand_child_transform.Translate(8.0, 6.0);
524 expected_grand_child_transform.PreconcatTransform(
525 rotation_about_z); // grand_child's local transform
527 gfx::Transform expected_great_grand_child_transform =
528 expected_grand_child_transform;
530 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
531 child->draw_transform());
532 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
533 grand_child->draw_transform());
534 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
535 great_grand_child->draw_transform());
537 // Case 2: scroll delta of 10, 20
538 child->SetScrollDelta(gfx::Vector2d(10, 0));
539 grand_child->SetScrollDelta(gfx::Vector2d(5, 0));
540 ExecuteCalculateDrawProperties(root_.get());
542 // Here the child and grand_child are affected by scroll delta, but the fixed
543 // position great_grand_child should not be affected.
544 expected_child_transform.MakeIdentity();
545 expected_child_transform.Translate(-10.0, 0.0); // scroll delta
546 expected_child_transform.PreconcatTransform(rotation_about_z);
548 expected_grand_child_transform.MakeIdentity();
549 expected_grand_child_transform.Translate(
550 -10.0, 0.0); // child's scroll delta is inherited
551 expected_grand_child_transform.PreconcatTransform(
552 rotation_about_z); // child's local transform is inherited
553 expected_grand_child_transform.Translate(-5.0,
554 0.0); // grand_child's scroll delta
555 // translation because of position occurs before layer's local transform.
556 expected_grand_child_transform.Translate(8.0, 6.0);
557 expected_grand_child_transform.PreconcatTransform(
558 rotation_about_z); // grand_child's local transform
560 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
561 child->draw_transform());
562 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
563 grand_child->draw_transform());
564 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
565 great_grand_child->draw_transform());
567 // Case 3: fixed-container size delta of 20, 20
568 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
569 ExecuteCalculateDrawProperties(root_.get());
571 // Top-left fixed-position layer should not be affected by container size.
572 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
573 child->draw_transform());
574 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
575 grand_child->draw_transform());
576 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
577 great_grand_child->draw_transform());
579 // Case 4: Bottom-right fixed-position layer.
580 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
581 ExecuteCalculateDrawProperties(root_.get());
583 // Bottom-right fixed-position layer moves as container resizes.
584 expected_great_grand_child_transform.MakeIdentity();
585 // Apply child layer transform.
586 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
587 // Apply size delta from the child(container) layer.
588 expected_great_grand_child_transform.Translate(20.0, 20.0);
589 // Apply layer position from the grand child layer.
590 expected_great_grand_child_transform.Translate(8.0, 6.0);
591 // Apply grand child layer transform.
592 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
594 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
595 child->draw_transform());
596 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
597 grand_child->draw_transform());
598 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
599 great_grand_child->draw_transform());
602 TEST_F(LayerPositionConstraintTest,
603 ScrollCompensationForFixedPositionWithIntermediateSurfaceAndTransforms) {
604 // This test checks for correct scroll compensation when the fixed-position
605 // container contributes to a different render surface than the fixed-position
606 // layer. In this case, the surface draw transforms also have to be accounted
607 // for when checking the scroll delta.
608 LayerImpl* child = scroll_->children()[0];
609 LayerImpl* grand_child = child->children()[0];
610 LayerImpl* great_grand_child = grand_child->children()[0];
612 child->SetIsContainerForFixedPositionLayers(true);
613 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
614 grand_child->SetForceRenderSurface(true);
615 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
616 great_grand_child->SetDrawsContent(true);
618 gfx::Transform rotation_about_z;
619 rotation_about_z.RotateAboutZAxis(90.0);
620 grand_child->SetTransform(rotation_about_z);
622 // Case 1: scroll delta of 0, 0
623 child->SetScrollDelta(gfx::Vector2d(0, 0));
624 ExecuteCalculateDrawProperties(root_.get());
626 gfx::Transform expected_child_transform;
627 gfx::Transform expected_surface_draw_transform;
628 expected_surface_draw_transform.Translate(8.0, 6.0);
629 expected_surface_draw_transform.PreconcatTransform(rotation_about_z);
630 gfx::Transform expected_grand_child_transform;
631 gfx::Transform expected_great_grand_child_transform;
632 ASSERT_TRUE(grand_child->render_surface());
633 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
634 child->draw_transform());
635 EXPECT_TRANSFORMATION_MATRIX_EQ(
636 expected_surface_draw_transform,
637 grand_child->render_surface()->draw_transform());
638 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
639 grand_child->draw_transform());
640 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
641 great_grand_child->draw_transform());
643 // Case 2: scroll delta of 10, 30
644 child->SetScrollDelta(gfx::Vector2d(10, 30));
645 ExecuteCalculateDrawProperties(root_.get());
647 // Here the grand_child remains unchanged, because it scrolls along with the
648 // render surface, and the translation is actually in the render surface. But,
649 // the fixed position great_grand_child is more awkward: its actually being
650 // drawn with respect to the render surface, but it needs to remain fixed with
651 // resepct to a container beyond that surface. So, the net result is that,
652 // unlike previous tests where the fixed position layer's transform remains
653 // unchanged, here the fixed position layer's transform explicitly contains
654 // the translation that cancels out the scroll.
655 expected_child_transform.MakeIdentity();
656 expected_child_transform.Translate(-10.0, -30.0); // scroll delta
658 expected_surface_draw_transform.MakeIdentity();
659 expected_surface_draw_transform.Translate(-10.0, -30.0); // scroll delta
660 expected_surface_draw_transform.Translate(8.0, 6.0);
661 expected_surface_draw_transform.PreconcatTransform(rotation_about_z);
663 // The rotation and its inverse are needed to place the scroll delta
664 // compensation in the correct space. This test will fail if the
665 // rotation/inverse are backwards, too, so it requires perfect order of
667 expected_great_grand_child_transform.MakeIdentity();
668 expected_great_grand_child_transform.PreconcatTransform(
669 Inverse(rotation_about_z));
670 // explicit canceling out the scroll delta that gets embedded in the fixed
671 // position layer's surface.
672 expected_great_grand_child_transform.Translate(10.0, 30.0);
673 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
675 ASSERT_TRUE(grand_child->render_surface());
676 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
677 child->draw_transform());
678 EXPECT_TRANSFORMATION_MATRIX_EQ(
679 expected_surface_draw_transform,
680 grand_child->render_surface()->draw_transform());
681 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
682 grand_child->draw_transform());
683 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
684 great_grand_child->draw_transform());
686 // Case 3: fixed-container size delta of 20, 20
687 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
688 ExecuteCalculateDrawProperties(root_.get());
690 // Top-left fixed-position layer should not be affected by container size.
691 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
692 child->draw_transform());
693 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
694 grand_child->draw_transform());
695 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
696 great_grand_child->draw_transform());
698 // Case 4: Bottom-right fixed-position layer.
699 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
700 ExecuteCalculateDrawProperties(root_.get());
702 // Bottom-right fixed-position layer moves as container resizes.
703 expected_great_grand_child_transform.MakeIdentity();
704 // The rotation and its inverse are needed to place the scroll delta
705 // compensation in the correct space. This test will fail if the
706 // rotation/inverse are backwards, too, so it requires perfect order of
708 expected_great_grand_child_transform.PreconcatTransform(
709 Inverse(rotation_about_z));
710 // explicit canceling out the scroll delta that gets embedded in the fixed
711 // position layer's surface.
712 expected_great_grand_child_transform.Translate(10.0, 30.0);
713 // Also apply size delta in the child(container) layer space.
714 expected_great_grand_child_transform.Translate(20.0, 20.0);
715 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
717 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
718 child->draw_transform());
719 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
720 grand_child->draw_transform());
721 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
722 great_grand_child->draw_transform());
725 TEST_F(LayerPositionConstraintTest,
726 ScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces) {
727 // This test checks for correct scroll compensation when the fixed-position
728 // container contributes to a different render surface than the fixed-position
729 // layer, with additional render surfaces in-between. This checks that the
730 // conversion to ancestor surfaces is accumulated properly in the final matrix
732 LayerImpl* child = scroll_->children()[0];
733 LayerImpl* grand_child = child->children()[0];
734 LayerImpl* great_grand_child = grand_child->children()[0];
736 // Add one more layer to the test tree for this scenario.
738 gfx::Transform identity;
739 scoped_ptr<LayerImpl> fixed_position_child =
740 LayerImpl::Create(host_impl_.active_tree(), 5);
741 SetLayerPropertiesForTesting(fixed_position_child.get(),
748 great_grand_child->AddChild(fixed_position_child.Pass());
750 LayerImpl* fixed_position_child = great_grand_child->children()[0];
752 // Actually set up the scenario here.
753 child->SetIsContainerForFixedPositionLayers(true);
754 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
755 grand_child->SetForceRenderSurface(true);
756 great_grand_child->SetPosition(gfx::PointF(40.f, 60.f));
757 great_grand_child->SetForceRenderSurface(true);
758 fixed_position_child->SetPositionConstraint(fixed_to_top_left_);
759 fixed_position_child->SetDrawsContent(true);
761 // The additional rotations, which are non-commutative with translations, help
762 // to verify that we have correct order-of-operations in the final scroll
763 // compensation. Note that rotating about the center of the layer ensures we
764 // do not accidentally clip away layers that we want to test.
765 gfx::Transform rotation_about_z;
766 rotation_about_z.Translate(50.0, 50.0);
767 rotation_about_z.RotateAboutZAxis(90.0);
768 rotation_about_z.Translate(-50.0, -50.0);
769 grand_child->SetTransform(rotation_about_z);
770 great_grand_child->SetTransform(rotation_about_z);
772 // Case 1: scroll delta of 0, 0
773 child->SetScrollDelta(gfx::Vector2d(0, 0));
774 ExecuteCalculateDrawProperties(root_.get());
776 gfx::Transform expected_child_transform;
778 gfx::Transform expected_grand_child_surface_draw_transform;
779 expected_grand_child_surface_draw_transform.Translate(8.0, 6.0);
780 expected_grand_child_surface_draw_transform.PreconcatTransform(
783 gfx::Transform expected_grand_child_transform;
785 gfx::Transform expected_great_grand_child_surface_draw_transform;
786 expected_great_grand_child_surface_draw_transform.Translate(40.0, 60.0);
787 expected_great_grand_child_surface_draw_transform.PreconcatTransform(
790 gfx::Transform expected_great_grand_child_transform;
792 gfx::Transform expected_fixed_position_child_transform;
794 ASSERT_TRUE(grand_child->render_surface());
795 ASSERT_TRUE(great_grand_child->render_surface());
796 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
797 child->draw_transform());
798 EXPECT_TRANSFORMATION_MATRIX_EQ(
799 expected_grand_child_surface_draw_transform,
800 grand_child->render_surface()->draw_transform());
801 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
802 grand_child->draw_transform());
803 EXPECT_TRANSFORMATION_MATRIX_EQ(
804 expected_great_grand_child_surface_draw_transform,
805 great_grand_child->render_surface()->draw_transform());
806 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
807 great_grand_child->draw_transform());
808 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
809 fixed_position_child->draw_transform());
811 // Case 2: scroll delta of 10, 30
812 child->SetScrollDelta(gfx::Vector2d(10, 30));
813 ExecuteCalculateDrawProperties(root_.get());
815 expected_child_transform.MakeIdentity();
816 expected_child_transform.Translate(-10.0, -30.0); // scroll delta
818 expected_grand_child_surface_draw_transform.MakeIdentity();
819 expected_grand_child_surface_draw_transform.Translate(-10.0,
820 -30.0); // scroll delta
821 expected_grand_child_surface_draw_transform.Translate(8.0, 6.0);
822 expected_grand_child_surface_draw_transform.PreconcatTransform(
825 // grand_child, great_grand_child, and great_grand_child's surface are not
826 // expected to change, since they are all not fixed, and they are all drawn
827 // with respect to grand_child's surface that already has the scroll delta
830 // But the great-great grandchild, "fixed_position_child", should have a
831 // transform that explicitly cancels out the scroll delta. The expected
832 // transform is: compound_draw_transform.Inverse() * translate(positive scroll
833 // delta) * compound_origin_transform from great_grand_childSurface's origin
834 // to the root surface.
835 gfx::Transform compound_draw_transform;
836 compound_draw_transform.Translate(8.0,
837 6.0); // origin translation of grand_child
838 compound_draw_transform.PreconcatTransform(
839 rotation_about_z); // rotation of grand_child
840 compound_draw_transform.Translate(
841 40.0, 60.0); // origin translation of great_grand_child
842 compound_draw_transform.PreconcatTransform(
843 rotation_about_z); // rotation of great_grand_child
845 expected_fixed_position_child_transform.MakeIdentity();
846 expected_fixed_position_child_transform.PreconcatTransform(
847 Inverse(compound_draw_transform));
848 // explicit canceling out the scroll delta that gets embedded in the fixed
849 // position layer's surface.
850 expected_fixed_position_child_transform.Translate(10.0, 30.0);
851 expected_fixed_position_child_transform.PreconcatTransform(
852 compound_draw_transform);
854 ASSERT_TRUE(grand_child->render_surface());
855 ASSERT_TRUE(great_grand_child->render_surface());
856 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
857 child->draw_transform());
858 EXPECT_TRANSFORMATION_MATRIX_EQ(
859 expected_grand_child_surface_draw_transform,
860 grand_child->render_surface()->draw_transform());
861 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
862 grand_child->draw_transform());
863 EXPECT_TRANSFORMATION_MATRIX_EQ(
864 expected_great_grand_child_surface_draw_transform,
865 great_grand_child->render_surface()->draw_transform());
866 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
867 great_grand_child->draw_transform());
868 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
869 fixed_position_child->draw_transform());
872 // Case 3: fixed-container size delta of 20, 20
873 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
874 ExecuteCalculateDrawProperties(root_.get());
876 // Top-left fixed-position layer should not be affected by container size.
877 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
878 child->draw_transform());
879 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
880 grand_child->draw_transform());
881 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
882 great_grand_child->draw_transform());
883 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
884 fixed_position_child->draw_transform());
886 // Case 4: Bottom-right fixed-position layer.
887 fixed_position_child->SetPositionConstraint(fixed_to_bottom_right_);
888 ExecuteCalculateDrawProperties(root_.get());
890 // Bottom-right fixed-position layer moves as container resizes.
891 expected_fixed_position_child_transform.MakeIdentity();
892 expected_fixed_position_child_transform.PreconcatTransform(
893 Inverse(compound_draw_transform));
894 // explicit canceling out the scroll delta that gets embedded in the fixed
895 // position layer's surface.
896 expected_fixed_position_child_transform.Translate(10.0, 30.0);
897 // Also apply size delta in the child(container) layer space.
898 expected_fixed_position_child_transform.Translate(20.0, 20.0);
899 expected_fixed_position_child_transform.PreconcatTransform(
900 compound_draw_transform);
902 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
903 child->draw_transform());
904 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
905 grand_child->draw_transform());
906 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
907 great_grand_child->draw_transform());
908 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
909 fixed_position_child->draw_transform());
912 TEST_F(LayerPositionConstraintTest,
913 ScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface) {
914 // This test checks for correct scroll compensation when the fixed-position
915 // container itself has a render surface. In this case, the container layer
916 // should be treated like a layer that contributes to a render target, and
917 // that render target is completely irrelevant; it should not affect the
918 // scroll compensation.
919 LayerImpl* child = scroll_->children()[0];
920 LayerImpl* grand_child = child->children()[0];
922 child->SetIsContainerForFixedPositionLayers(true);
923 child->SetForceRenderSurface(true);
924 grand_child->SetPositionConstraint(fixed_to_top_left_);
925 grand_child->SetDrawsContent(true);
927 // Case 1: scroll delta of 0, 0
928 child->SetScrollDelta(gfx::Vector2d(0, 0));
929 ExecuteCalculateDrawProperties(root_.get());
931 gfx::Transform expected_surface_draw_transform;
932 expected_surface_draw_transform.Translate(0.0, 0.0);
933 gfx::Transform expected_child_transform;
934 gfx::Transform expected_grand_child_transform;
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 2: scroll delta of 10, 10
944 child->SetScrollDelta(gfx::Vector2d(10, 10));
945 ExecuteCalculateDrawProperties(root_.get());
947 // The surface is translated by scroll delta, the child transform doesn't
948 // change because it scrolls along with the surface, but the fixed position
949 // grand_child needs to compensate for the scroll translation.
950 expected_surface_draw_transform.MakeIdentity();
951 expected_surface_draw_transform.Translate(-10.0, -10.0);
952 expected_grand_child_transform.MakeIdentity();
953 expected_grand_child_transform.Translate(10.0, 10.0);
955 ASSERT_TRUE(child->render_surface());
956 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform,
957 child->render_surface()->draw_transform());
958 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
959 child->draw_transform());
960 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
961 grand_child->draw_transform());
963 // Case 3: fixed-container size delta of 20, 20
964 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
965 ExecuteCalculateDrawProperties(root_.get());
967 // Top-left fixed-position layer should not be affected by container size.
968 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
969 child->draw_transform());
970 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
971 grand_child->draw_transform());
973 // Case 4: Bottom-right fixed-position layer.
974 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
975 ExecuteCalculateDrawProperties(root_.get());
977 // Bottom-right fixed-position layer moves as container resizes.
978 expected_grand_child_transform.MakeIdentity();
979 // The surface is translated by scroll delta, the child transform doesn't
980 // change because it scrolls along with the surface, but the fixed position
981 // grand_child needs to compensate for the scroll translation.
982 expected_grand_child_transform.Translate(10.0, 10.0);
983 // Apply size delta from the child(container) layer.
984 expected_grand_child_transform.Translate(20.0, 20.0);
986 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
987 child->draw_transform());
988 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
989 grand_child->draw_transform());
992 TEST_F(LayerPositionConstraintTest,
993 ScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer) {
994 // This test checks the scenario where a fixed-position layer also happens to
995 // be a container itself for a descendant fixed position layer. In particular,
996 // the layer should not accidentally be fixed to itself.
997 LayerImpl* child = scroll_->children()[0];
998 LayerImpl* grand_child = child->children()[0];
1000 child->SetIsContainerForFixedPositionLayers(true);
1001 grand_child->SetPositionConstraint(fixed_to_top_left_);
1003 // This should not confuse the grand_child. If correct, the grand_child would
1004 // still be considered fixed to its container (i.e. "child").
1005 grand_child->SetIsContainerForFixedPositionLayers(true);
1007 // Case 1: scroll delta of 0, 0
1008 child->SetScrollDelta(gfx::Vector2d(0, 0));
1009 ExecuteCalculateDrawProperties(root_.get());
1011 gfx::Transform expected_child_transform;
1012 gfx::Transform expected_grand_child_transform;
1013 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1014 child->draw_transform());
1015 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1016 grand_child->draw_transform());
1018 // Case 2: scroll delta of 10, 10
1019 child->SetScrollDelta(gfx::Vector2d(10, 10));
1020 ExecuteCalculateDrawProperties(root_.get());
1022 // Here the child is affected by scroll delta, but the fixed position
1023 // grand_child should not be affected.
1024 expected_child_transform.MakeIdentity();
1025 expected_child_transform.Translate(-10.0, -10.0);
1026 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1027 child->draw_transform());
1028 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1029 grand_child->draw_transform());
1031 // Case 3: fixed-container size delta of 20, 20
1032 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
1033 ExecuteCalculateDrawProperties(root_.get());
1035 // Top-left fixed-position layer should not be affected by container size.
1036 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1037 child->draw_transform());
1038 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1039 grand_child->draw_transform());
1041 // Case 4: Bottom-right fixed-position layer.
1042 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
1043 ExecuteCalculateDrawProperties(root_.get());
1045 // Bottom-right fixed-position layer moves as container resizes.
1046 expected_grand_child_transform.MakeIdentity();
1047 // Apply size delta from the child(container) layer.
1048 expected_grand_child_transform.Translate(20.0, 20.0);
1050 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1051 child->draw_transform());
1052 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1053 grand_child->draw_transform());
1056 TEST_F(LayerPositionConstraintTest,
1057 ScrollCompensationForFixedWithinFixedWithSameContainer) {
1058 // This test checks scroll compensation for a fixed-position layer that is
1059 // inside of another fixed-position layer and both share the same container.
1060 // In this situation, the parent fixed-position layer will receive
1061 // the scroll compensation, and the child fixed-position layer does not
1062 // need to compensate further.
1064 LayerImpl* child = scroll_->children()[0];
1065 LayerImpl* grand_child = child->children()[0];
1066 LayerImpl* great_grand_child = grand_child->children()[0];
1068 child->SetIsContainerForFixedPositionLayers(true);
1069 grand_child->SetPositionConstraint(fixed_to_top_left_);
1071 // Note carefully - great_grand_child is fixed to bottom right, to test
1072 // sizeDelta being applied correctly; the compensation skips the grand_child
1073 // because it is fixed to top left.
1074 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
1076 // Case 1: scrollDelta
1077 child->SetScrollDelta(gfx::Vector2d(10, 10));
1078 ExecuteCalculateDrawProperties(root_.get());
1080 // Here the child is affected by scroll delta, but the fixed position
1081 // grand_child should not be affected.
1082 gfx::Transform expected_child_transform;
1083 expected_child_transform.Translate(-10.0, -10.0);
1085 gfx::Transform expected_grand_child_transform;
1086 gfx::Transform expected_great_grand_child_transform;
1088 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1089 child->draw_transform());
1090 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1091 grand_child->draw_transform());
1092 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
1093 great_grand_child->draw_transform());
1095 // Case 2: sizeDelta
1096 child->SetScrollDelta(gfx::Vector2d(0, 0));
1097 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
1098 ExecuteCalculateDrawProperties(root_.get());
1100 expected_child_transform.MakeIdentity();
1102 expected_grand_child_transform.MakeIdentity();
1104 // Fixed to bottom-right, size-delta compensation is applied.
1105 expected_great_grand_child_transform.MakeIdentity();
1106 expected_great_grand_child_transform.Translate(20.0, 20.0);
1108 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1109 child->draw_transform());
1110 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1111 grand_child->draw_transform());
1112 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
1113 great_grand_child->draw_transform());
1116 TEST_F(LayerPositionConstraintTest,
1117 ScrollCompensationForFixedWithinFixedWithInterveningContainer) {
1118 // This test checks scroll compensation for a fixed-position layer that is
1119 // inside of another fixed-position layer, but they have different fixed
1120 // position containers. In this situation, the child fixed-position element
1121 // would still have to compensate with respect to its container.
1123 LayerImpl* container1 = scroll_->children()[0];
1124 LayerImpl* fixed_to_container1 = container1->children()[0];
1125 LayerImpl* container2 = fixed_to_container1->children()[0];
1128 // Add one more layer to the hierarchy for this test.
1129 scoped_ptr<LayerImpl> fixed_to_container2_ptr =
1130 LayerImpl::Create(host_impl_.active_tree(), 5);
1131 container2->AddChild(fixed_to_container2_ptr.Pass());
1134 LayerImpl* fixed_to_container2 = container2->children()[0];
1136 container1->SetIsContainerForFixedPositionLayers(true);
1137 fixed_to_container1->SetPositionConstraint(fixed_to_top_left_);
1138 container2->SetIsContainerForFixedPositionLayers(true);
1139 fixed_to_container2->SetPositionConstraint(fixed_to_top_left_);
1141 container1->SetScrollDelta(gfx::Vector2d(0, 15));
1142 container2->SetScrollDelta(gfx::Vector2d(30, 0));
1143 ExecuteCalculateDrawProperties(root_.get());
1145 gfx::Transform expected_container1_transform;
1146 expected_container1_transform.Translate(0.0, -15.0);
1148 gfx::Transform expected_fixed_to_container1_transform;
1150 // Since the container is a descendant of the fixed layer above,
1151 // the expected draw transform for container2 would not
1152 // include the scrollDelta that was applied to container1.
1153 gfx::Transform expected_container2_transform;
1154 expected_container2_transform.Translate(-30.0, 0.0);
1156 gfx::Transform expected_fixed_to_container2_transform;
1158 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container1_transform,
1159 container1->draw_transform());
1161 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container1_transform,
1162 fixed_to_container1->draw_transform());
1164 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container2_transform,
1165 container2->draw_transform());
1167 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container2_transform,
1168 fixed_to_container2->draw_transform());