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.
4
5 #include "cc/layers/layer_position_constraint.h"
6
7 #include <vector>
8
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/test/test_shared_bitmap_manager.h"
14 #include "cc/trees/layer_tree_host_common.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace cc {
18 namespace {
19
SetLayerPropertiesForTesting(LayerImpl * layer,const gfx::Transform & transform,const gfx::Point3F & transform_origin,const gfx::PointF & position,const gfx::Size & bounds,bool flatten_transform)20 void SetLayerPropertiesForTesting(LayerImpl* layer,
21 const gfx::Transform& transform,
22 const gfx::Point3F& transform_origin,
23 const gfx::PointF& position,
24 const gfx::Size& bounds,
25 bool flatten_transform) {
26 layer->SetTransform(transform);
27 layer->SetTransformOrigin(transform_origin);
28 layer->SetPosition(position);
29 layer->SetBounds(bounds);
30 layer->SetShouldFlattenTransform(flatten_transform);
31 layer->SetContentBounds(bounds);
32 }
33
ExecuteCalculateDrawProperties(LayerImpl * root_layer,float device_scale_factor,float page_scale_factor,LayerImpl * page_scale_application_layer,bool can_use_lcd_text)34 void ExecuteCalculateDrawProperties(LayerImpl* root_layer,
35 float device_scale_factor,
36 float page_scale_factor,
37 LayerImpl* page_scale_application_layer,
38 bool can_use_lcd_text) {
39 gfx::Transform identity_matrix;
40 std::vector<LayerImpl*> dummy_render_surface_layer_list;
41 LayerImpl* scroll_layer = root_layer->children()[0];
42 gfx::Size device_viewport_size =
43 gfx::Size(root_layer->bounds().width() * device_scale_factor,
44 root_layer->bounds().height() * device_scale_factor);
45
46 // We are probably not testing what is intended if the scroll_layer bounds are
47 // empty.
48 DCHECK(!scroll_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);
56 }
57
ExecuteCalculateDrawProperties(LayerImpl * root_layer)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);
62 }
63
64 class LayerPositionConstraintTest : public testing::Test {
65 public:
LayerPositionConstraintTest()66 LayerPositionConstraintTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {
67 root_ = CreateTreeForTest();
68 scroll_ = root_->children()[0];
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);
73 }
74
CreateTreeForTest()75 scoped_ptr<LayerImpl> CreateTreeForTest() {
76 scoped_ptr<LayerImpl> root =
77 LayerImpl::Create(host_impl_.active_tree(), 42);
78 scoped_ptr<LayerImpl> scroll_layer =
79 LayerImpl::Create(host_impl_.active_tree(), 1);
80 scoped_ptr<LayerImpl> child =
81 LayerImpl::Create(host_impl_.active_tree(), 2);
82 scoped_ptr<LayerImpl> grand_child =
83 LayerImpl::Create(host_impl_.active_tree(), 3);
84 scoped_ptr<LayerImpl> great_grand_child =
85 LayerImpl::Create(host_impl_.active_tree(), 4);
86
87 gfx::Transform IdentityMatrix;
88 gfx::Point3F transform_origin;
89 gfx::PointF position;
90 gfx::Size bounds(200, 200);
91 gfx::Size clip_bounds(100, 100);
92 SetLayerPropertiesForTesting(scroll_layer.get(),
93 IdentityMatrix,
94 transform_origin,
95 position,
96 bounds,
97 true);
98 SetLayerPropertiesForTesting(
99 child.get(), IdentityMatrix, transform_origin, position, bounds, true);
100 SetLayerPropertiesForTesting(grand_child.get(),
101 IdentityMatrix,
102 transform_origin,
103 position,
104 bounds,
105 true);
106 SetLayerPropertiesForTesting(great_grand_child.get(),
107 IdentityMatrix,
108 transform_origin,
109 position,
110 bounds,
111 true);
112
113 root->SetBounds(clip_bounds);
114 scroll_layer->SetScrollClipLayer(root->id());
115 child->SetScrollClipLayer(root->id());
116 grand_child->SetScrollClipLayer(root->id());
117
118 grand_child->AddChild(great_grand_child.Pass());
119 child->AddChild(grand_child.Pass());
120 scroll_layer->AddChild(child.Pass());
121 root->AddChild(scroll_layer.Pass());
122
123 return root.Pass();
124 }
125
126 protected:
127 FakeImplProxy proxy_;
128 TestSharedBitmapManager shared_bitmap_manager_;
129 FakeLayerTreeHostImpl host_impl_;
130 scoped_ptr<LayerImpl> root_;
131 LayerImpl* scroll_;
132
133 LayerPositionConstraint fixed_to_top_left_;
134 LayerPositionConstraint fixed_to_bottom_right_;
135 };
136
137 namespace {
138
SetFixedContainerSizeDelta(LayerImpl * scroll_layer,const gfx::Vector2d & delta)139 void SetFixedContainerSizeDelta(LayerImpl* scroll_layer,
140 const gfx::Vector2d& delta) {
141 DCHECK(scroll_layer);
142 DCHECK(scroll_layer->scrollable());
143
144 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
145 container_layer->SetBoundsDelta(delta);
146 }
147 } // namespace
148
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithDirectContainer)149 TEST_F(LayerPositionConstraintTest,
150 ScrollCompensationForFixedPositionLayerWithDirectContainer) {
151 // This test checks for correct scroll compensation when the fixed-position
152 // container is the direct parent of the fixed-position layer.
153 LayerImpl* child = scroll_->children()[0];
154 LayerImpl* grand_child = child->children()[0];
155
156 child->SetIsContainerForFixedPositionLayers(true);
157 grand_child->SetPositionConstraint(fixed_to_top_left_);
158
159 // Case 1: scroll delta of 0, 0
160 child->SetScrollDelta(gfx::Vector2d(0, 0));
161 ExecuteCalculateDrawProperties(root_.get());
162
163 gfx::Transform expected_child_transform;
164 gfx::Transform expected_grand_child_transform = expected_child_transform;
165
166 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
167 child->draw_transform());
168 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
169 grand_child->draw_transform());
170
171 // Case 2: scroll delta of 10, 10
172 child->SetScrollDelta(gfx::Vector2d(10, 10));
173 ExecuteCalculateDrawProperties(root_.get());
174
175 // Here the child is affected by scroll delta, but the fixed position
176 // grand_child should not be affected.
177 expected_child_transform.MakeIdentity();
178 expected_child_transform.Translate(-10.0, -10.0);
179
180 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
181 child->draw_transform());
182 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
183 grand_child->draw_transform());
184
185 // Case 3: fixed-container size delta of 20, 20
186 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
187 ExecuteCalculateDrawProperties(root_.get());
188
189 // Top-left fixed-position layer should not be affected by container size.
190 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
191 child->draw_transform());
192 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
193 grand_child->draw_transform());
194
195 // Case 4: Bottom-right fixed-position layer.
196 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
197 ExecuteCalculateDrawProperties(root_.get());
198
199 // Bottom-right fixed-position layer moves as container resizes.
200 expected_grand_child_transform.MakeIdentity();
201 // Apply size delta from the child(container) layer.
202 expected_grand_child_transform.Translate(20.0, 20.0);
203
204 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
205 child->draw_transform());
206 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
207 grand_child->draw_transform());
208 }
209
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer)210 TEST_F(LayerPositionConstraintTest,
211 ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer) {
212 // This test checks for correct scroll compensation when the fixed-position
213 // container is the direct parent of the fixed-position layer, but that
214 // container is transformed. In this case, the fixed position element
215 // inherits the container's transform, but the scroll delta that has to be
216 // undone should not be affected by that transform.
217 //
218 // Transforms are in general non-commutative; using something like a
219 // non-uniform scale helps to verify that translations and non-uniform scales
220 // are applied in the correct order.
221 LayerImpl* child = scroll_->children()[0];
222 LayerImpl* grand_child = child->children()[0];
223
224 // This scale will cause child and grand_child to be effectively 200 x 800
225 // with respect to the render target.
226 gfx::Transform non_uniform_scale;
227 non_uniform_scale.Scale(2.0, 8.0);
228 child->SetTransform(non_uniform_scale);
229
230 child->SetIsContainerForFixedPositionLayers(true);
231 grand_child->SetPositionConstraint(fixed_to_top_left_);
232
233 // Case 1: scroll delta of 0, 0
234 child->SetScrollDelta(gfx::Vector2d(0, 0));
235 ExecuteCalculateDrawProperties(root_.get());
236
237 gfx::Transform expected_child_transform;
238 expected_child_transform.PreconcatTransform(non_uniform_scale);
239
240 gfx::Transform expected_grand_child_transform = expected_child_transform;
241
242 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
243 child->draw_transform());
244 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
245 grand_child->draw_transform());
246
247 // Case 2: scroll delta of 10, 20
248 child->SetScrollDelta(gfx::Vector2d(10, 20));
249 ExecuteCalculateDrawProperties(root_.get());
250
251 // The child should be affected by scroll delta, but the fixed position
252 // grand_child should not be affected.
253 expected_child_transform.MakeIdentity();
254 expected_child_transform.Translate(-10.0, -20.0); // scroll delta
255 expected_child_transform.PreconcatTransform(non_uniform_scale);
256
257 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
258 child->draw_transform());
259 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
260 grand_child->draw_transform());
261
262 // Case 3: fixed-container size delta of 20, 20
263 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
264 ExecuteCalculateDrawProperties(root_.get());
265
266 // Top-left fixed-position layer should not be affected by container size.
267 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
268 child->draw_transform());
269 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
270 grand_child->draw_transform());
271
272 // Case 4: Bottom-right fixed-position layer.
273 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
274 ExecuteCalculateDrawProperties(root_.get());
275
276 // Bottom-right fixed-position layer moves as container resizes.
277 expected_grand_child_transform.MakeIdentity();
278 // Apply child layer transform.
279 expected_grand_child_transform.PreconcatTransform(non_uniform_scale);
280 // Apply size delta from the child(container) layer.
281 expected_grand_child_transform.Translate(20.0, 20.0);
282
283 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
284 child->draw_transform());
285 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
286 grand_child->draw_transform());
287 }
288
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithDistantContainer)289 TEST_F(LayerPositionConstraintTest,
290 ScrollCompensationForFixedPositionLayerWithDistantContainer) {
291 // This test checks for correct scroll compensation when the fixed-position
292 // container is NOT the direct parent of the fixed-position layer.
293 LayerImpl* child = scroll_->children()[0];
294 LayerImpl* grand_child = child->children()[0];
295 LayerImpl* great_grand_child = grand_child->children()[0];
296
297 child->SetIsContainerForFixedPositionLayers(true);
298 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
299 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
300
301 // Case 1: scroll delta of 0, 0
302 child->SetScrollDelta(gfx::Vector2d(0, 0));
303 ExecuteCalculateDrawProperties(root_.get());
304
305 gfx::Transform expected_child_transform;
306 gfx::Transform expected_grand_child_transform;
307 expected_grand_child_transform.Translate(8.0, 6.0);
308
309 gfx::Transform expected_great_grand_child_transform =
310 expected_grand_child_transform;
311
312 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
313 child->draw_transform());
314 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
315 grand_child->draw_transform());
316 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
317 great_grand_child->draw_transform());
318
319 // Case 2: scroll delta of 10, 10
320 child->SetScrollDelta(gfx::Vector2d(10, 10));
321 ExecuteCalculateDrawProperties(root_.get());
322
323 // Here the child and grand_child are affected by scroll delta, but the fixed
324 // position great_grand_child should not be affected.
325 expected_child_transform.MakeIdentity();
326 expected_child_transform.Translate(-10.0, -10.0);
327 expected_grand_child_transform.MakeIdentity();
328 expected_grand_child_transform.Translate(-2.0, -4.0);
329 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
330 child->draw_transform());
331 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
332 grand_child->draw_transform());
333 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
334 great_grand_child->draw_transform());
335
336 // Case 3: fixed-container size delta of 20, 20
337 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
338 ExecuteCalculateDrawProperties(root_.get());
339
340 // Top-left fixed-position layer should not be affected by container size.
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());
347
348 // Case 4: Bottom-right fixed-position layer.
349 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
350 ExecuteCalculateDrawProperties(root_.get());
351
352 // Bottom-right fixed-position layer moves as container resizes.
353 expected_great_grand_child_transform.MakeIdentity();
354 // Apply size delta from the child(container) layer.
355 expected_great_grand_child_transform.Translate(20.0, 20.0);
356 // Apply layer position from the grand child layer.
357 expected_great_grand_child_transform.Translate(8.0, 6.0);
358
359 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
360 child->draw_transform());
361 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
362 grand_child->draw_transform());
363 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
364 great_grand_child->draw_transform());
365 }
366
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms)367 TEST_F(LayerPositionConstraintTest,
368 ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms) {
369 // This test checks for correct scroll compensation when the fixed-position
370 // container is NOT the direct parent of the fixed-position layer, and the
371 // hierarchy has various transforms that have to be processed in the correct
372 // order.
373 LayerImpl* child = scroll_->children()[0];
374 LayerImpl* grand_child = child->children()[0];
375 LayerImpl* great_grand_child = grand_child->children()[0];
376
377 gfx::Transform rotation_about_z;
378 rotation_about_z.RotateAboutZAxis(90.0);
379
380 child->SetIsContainerForFixedPositionLayers(true);
381 child->SetTransform(rotation_about_z);
382 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
383 grand_child->SetTransform(rotation_about_z);
384 // great_grand_child is positioned upside-down with respect to the render
385 // target.
386 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
387
388 // Case 1: scroll delta of 0, 0
389 child->SetScrollDelta(gfx::Vector2d(0, 0));
390 ExecuteCalculateDrawProperties(root_.get());
391
392 gfx::Transform expected_child_transform;
393 expected_child_transform.PreconcatTransform(rotation_about_z);
394
395 gfx::Transform expected_grand_child_transform;
396 expected_grand_child_transform.PreconcatTransform(
397 rotation_about_z); // child's local transform is inherited
398 // translation because of position occurs before layer's local transform.
399 expected_grand_child_transform.Translate(8.0, 6.0);
400 expected_grand_child_transform.PreconcatTransform(
401 rotation_about_z); // grand_child's local transform
402
403 gfx::Transform expected_great_grand_child_transform =
404 expected_grand_child_transform;
405
406 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
407 child->draw_transform());
408 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
409 grand_child->draw_transform());
410 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
411 great_grand_child->draw_transform());
412
413 // Case 2: scroll delta of 10, 20
414 child->SetScrollDelta(gfx::Vector2d(10, 20));
415 ExecuteCalculateDrawProperties(root_.get());
416
417 // Here the child and grand_child are affected by scroll delta, but the fixed
418 // position great_grand_child should not be affected.
419 expected_child_transform.MakeIdentity();
420 expected_child_transform.Translate(-10.0, -20.0); // scroll delta
421 expected_child_transform.PreconcatTransform(rotation_about_z);
422
423 expected_grand_child_transform.MakeIdentity();
424 expected_grand_child_transform.Translate(
425 -10.0, -20.0); // child's scroll delta is inherited
426 expected_grand_child_transform.PreconcatTransform(
427 rotation_about_z); // child's local transform is inherited
428 // translation because of position occurs before layer's local transform.
429 expected_grand_child_transform.Translate(8.0, 6.0);
430 expected_grand_child_transform.PreconcatTransform(
431 rotation_about_z); // grand_child's local transform
432
433 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
434 child->draw_transform());
435 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
436 grand_child->draw_transform());
437 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
438 great_grand_child->draw_transform());
439
440 // Case 3: fixed-container size delta of 20, 20
441 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
442 ExecuteCalculateDrawProperties(root_.get());
443
444 // Top-left fixed-position layer should not be affected by container size.
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());
451
452 // Case 4: Bottom-right fixed-position layer.
453 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
454 ExecuteCalculateDrawProperties(root_.get());
455
456 // Bottom-right fixed-position layer moves as container resizes.
457 expected_great_grand_child_transform.MakeIdentity();
458 // Apply child layer transform.
459 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
460 // Apply size delta from the child(container) layer.
461 expected_great_grand_child_transform.Translate(20.0, 20.0);
462 // Apply layer position from the grand child layer.
463 expected_great_grand_child_transform.Translate(8.0, 6.0);
464 // Apply grand child layer transform.
465 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
466
467 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
468 child->draw_transform());
469 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
470 grand_child->draw_transform());
471 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
472 great_grand_child->draw_transform());
473 }
474
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas)475 TEST_F(LayerPositionConstraintTest,
476 ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas) {
477 // This test checks for correct scroll compensation when the fixed-position
478 // container has multiple ancestors that have nonzero scroll delta before
479 // reaching the space where the layer is fixed. In this test, each scroll
480 // delta occurs in a different space because of each layer's local transform.
481 // This test checks for correct scroll compensation when the fixed-position
482 // container is NOT the direct parent of the fixed-position layer, and the
483 // hierarchy has various transforms that have to be processed in the correct
484 // order.
485 LayerImpl* child = scroll_->children()[0];
486 LayerImpl* grand_child = child->children()[0];
487 LayerImpl* great_grand_child = grand_child->children()[0];
488
489 gfx::Transform rotation_about_z;
490 rotation_about_z.RotateAboutZAxis(90.0);
491
492 child->SetIsContainerForFixedPositionLayers(true);
493 child->SetTransform(rotation_about_z);
494 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
495 grand_child->SetTransform(rotation_about_z);
496 // great_grand_child is positioned upside-down with respect to the render
497 // target.
498 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
499
500 // Case 1: scroll delta of 0, 0
501 child->SetScrollDelta(gfx::Vector2d(0, 0));
502 ExecuteCalculateDrawProperties(root_.get());
503
504 gfx::Transform expected_child_transform;
505 expected_child_transform.PreconcatTransform(rotation_about_z);
506
507 gfx::Transform expected_grand_child_transform;
508 expected_grand_child_transform.PreconcatTransform(
509 rotation_about_z); // child's local transform is inherited
510 // translation because of position occurs before layer's local transform.
511 expected_grand_child_transform.Translate(8.0, 6.0);
512 expected_grand_child_transform.PreconcatTransform(
513 rotation_about_z); // grand_child's local transform
514
515 gfx::Transform expected_great_grand_child_transform =
516 expected_grand_child_transform;
517
518 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
519 child->draw_transform());
520 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
521 grand_child->draw_transform());
522 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
523 great_grand_child->draw_transform());
524
525 // Case 2: scroll delta of 10, 20
526 child->SetScrollDelta(gfx::Vector2d(10, 0));
527 grand_child->SetScrollDelta(gfx::Vector2d(5, 0));
528 ExecuteCalculateDrawProperties(root_.get());
529
530 // Here the child and grand_child are affected by scroll delta, but the fixed
531 // position great_grand_child should not be affected.
532 expected_child_transform.MakeIdentity();
533 expected_child_transform.Translate(-10.0, 0.0); // scroll delta
534 expected_child_transform.PreconcatTransform(rotation_about_z);
535
536 expected_grand_child_transform.MakeIdentity();
537 expected_grand_child_transform.Translate(
538 -10.0, 0.0); // child's scroll delta is inherited
539 expected_grand_child_transform.PreconcatTransform(
540 rotation_about_z); // child's local transform is inherited
541 expected_grand_child_transform.Translate(-5.0,
542 0.0); // grand_child's scroll delta
543 // translation because of position occurs before layer's local transform.
544 expected_grand_child_transform.Translate(8.0, 6.0);
545 expected_grand_child_transform.PreconcatTransform(
546 rotation_about_z); // grand_child's local transform
547
548 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
549 child->draw_transform());
550 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
551 grand_child->draw_transform());
552 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
553 great_grand_child->draw_transform());
554
555 // Case 3: fixed-container size delta of 20, 20
556 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
557 ExecuteCalculateDrawProperties(root_.get());
558
559 // Top-left fixed-position layer should not be affected by container size.
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());
566
567 // Case 4: Bottom-right fixed-position layer.
568 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
569 ExecuteCalculateDrawProperties(root_.get());
570
571 // Bottom-right fixed-position layer moves as container resizes.
572 expected_great_grand_child_transform.MakeIdentity();
573 // Apply child layer transform.
574 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
575 // Apply size delta from the child(container) layer.
576 expected_great_grand_child_transform.Translate(20.0, 20.0);
577 // Apply layer position from the grand child layer.
578 expected_great_grand_child_transform.Translate(8.0, 6.0);
579 // Apply grand child layer transform.
580 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
581
582 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
583 child->draw_transform());
584 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
585 grand_child->draw_transform());
586 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
587 great_grand_child->draw_transform());
588 }
589
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionWithIntermediateSurfaceAndTransforms)590 TEST_F(LayerPositionConstraintTest,
591 ScrollCompensationForFixedPositionWithIntermediateSurfaceAndTransforms) {
592 // This test checks for correct scroll compensation when the fixed-position
593 // container contributes to a different render surface than the fixed-position
594 // layer. In this case, the surface draw transforms also have to be accounted
595 // for when checking the scroll delta.
596 LayerImpl* child = scroll_->children()[0];
597 LayerImpl* grand_child = child->children()[0];
598 LayerImpl* great_grand_child = grand_child->children()[0];
599
600 child->SetIsContainerForFixedPositionLayers(true);
601 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
602 grand_child->SetForceRenderSurface(true);
603 great_grand_child->SetPositionConstraint(fixed_to_top_left_);
604 great_grand_child->SetDrawsContent(true);
605
606 gfx::Transform rotation_about_z;
607 rotation_about_z.RotateAboutZAxis(90.0);
608 grand_child->SetTransform(rotation_about_z);
609
610 // Case 1: scroll delta of 0, 0
611 child->SetScrollDelta(gfx::Vector2d(0, 0));
612 ExecuteCalculateDrawProperties(root_.get());
613
614 gfx::Transform expected_child_transform;
615 gfx::Transform expected_surface_draw_transform;
616 expected_surface_draw_transform.Translate(8.0, 6.0);
617 expected_surface_draw_transform.PreconcatTransform(rotation_about_z);
618 gfx::Transform expected_grand_child_transform;
619 gfx::Transform expected_great_grand_child_transform;
620 ASSERT_TRUE(grand_child->render_surface());
621 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
622 child->draw_transform());
623 EXPECT_TRANSFORMATION_MATRIX_EQ(
624 expected_surface_draw_transform,
625 grand_child->render_surface()->draw_transform());
626 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
627 grand_child->draw_transform());
628 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
629 great_grand_child->draw_transform());
630
631 // Case 2: scroll delta of 10, 30
632 child->SetScrollDelta(gfx::Vector2d(10, 30));
633 ExecuteCalculateDrawProperties(root_.get());
634
635 // Here the grand_child remains unchanged, because it scrolls along with the
636 // render surface, and the translation is actually in the render surface. But,
637 // the fixed position great_grand_child is more awkward: its actually being
638 // drawn with respect to the render surface, but it needs to remain fixed with
639 // resepct to a container beyond that surface. So, the net result is that,
640 // unlike previous tests where the fixed position layer's transform remains
641 // unchanged, here the fixed position layer's transform explicitly contains
642 // the translation that cancels out the scroll.
643 expected_child_transform.MakeIdentity();
644 expected_child_transform.Translate(-10.0, -30.0); // scroll delta
645
646 expected_surface_draw_transform.MakeIdentity();
647 expected_surface_draw_transform.Translate(-10.0, -30.0); // scroll delta
648 expected_surface_draw_transform.Translate(8.0, 6.0);
649 expected_surface_draw_transform.PreconcatTransform(rotation_about_z);
650
651 // The rotation and its inverse are needed to place the scroll delta
652 // compensation in the correct space. This test will fail if the
653 // rotation/inverse are backwards, too, so it requires perfect order of
654 // operations.
655 expected_great_grand_child_transform.MakeIdentity();
656 expected_great_grand_child_transform.PreconcatTransform(
657 Inverse(rotation_about_z));
658 // explicit canceling out the scroll delta that gets embedded in the fixed
659 // position layer's surface.
660 expected_great_grand_child_transform.Translate(10.0, 30.0);
661 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
662
663 ASSERT_TRUE(grand_child->render_surface());
664 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
665 child->draw_transform());
666 EXPECT_TRANSFORMATION_MATRIX_EQ(
667 expected_surface_draw_transform,
668 grand_child->render_surface()->draw_transform());
669 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
670 grand_child->draw_transform());
671 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
672 great_grand_child->draw_transform());
673
674 // Case 3: fixed-container size delta of 20, 20
675 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
676 ExecuteCalculateDrawProperties(root_.get());
677
678 // Top-left fixed-position layer should not be affected by container size.
679 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
680 child->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());
685
686 // Case 4: Bottom-right fixed-position layer.
687 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
688 ExecuteCalculateDrawProperties(root_.get());
689
690 // Bottom-right fixed-position layer moves as container resizes.
691 expected_great_grand_child_transform.MakeIdentity();
692 // The rotation and its inverse are needed to place the scroll delta
693 // compensation in the correct space. This test will fail if the
694 // rotation/inverse are backwards, too, so it requires perfect order of
695 // operations.
696 expected_great_grand_child_transform.PreconcatTransform(
697 Inverse(rotation_about_z));
698 // explicit canceling out the scroll delta that gets embedded in the fixed
699 // position layer's surface.
700 expected_great_grand_child_transform.Translate(10.0, 30.0);
701 // Also apply size delta in the child(container) layer space.
702 expected_great_grand_child_transform.Translate(20.0, 20.0);
703 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
704
705 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
706 child->draw_transform());
707 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
708 grand_child->draw_transform());
709 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
710 great_grand_child->draw_transform());
711 }
712
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces)713 TEST_F(LayerPositionConstraintTest,
714 ScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces) {
715 // This test checks for correct scroll compensation when the fixed-position
716 // container contributes to a different render surface than the fixed-position
717 // layer, with additional render surfaces in-between. This checks that the
718 // conversion to ancestor surfaces is accumulated properly in the final matrix
719 // transform.
720 LayerImpl* child = scroll_->children()[0];
721 LayerImpl* grand_child = child->children()[0];
722 LayerImpl* great_grand_child = grand_child->children()[0];
723
724 // Add one more layer to the test tree for this scenario.
725 {
726 gfx::Transform identity;
727 scoped_ptr<LayerImpl> fixed_position_child =
728 LayerImpl::Create(host_impl_.active_tree(), 5);
729 SetLayerPropertiesForTesting(fixed_position_child.get(),
730 identity,
731 gfx::Point3F(),
732 gfx::PointF(),
733 gfx::Size(100, 100),
734 true);
735 great_grand_child->AddChild(fixed_position_child.Pass());
736 }
737 LayerImpl* fixed_position_child = great_grand_child->children()[0];
738
739 // Actually set up the scenario here.
740 child->SetIsContainerForFixedPositionLayers(true);
741 grand_child->SetPosition(gfx::PointF(8.f, 6.f));
742 grand_child->SetForceRenderSurface(true);
743 great_grand_child->SetPosition(gfx::PointF(40.f, 60.f));
744 great_grand_child->SetForceRenderSurface(true);
745 fixed_position_child->SetPositionConstraint(fixed_to_top_left_);
746 fixed_position_child->SetDrawsContent(true);
747
748 // The additional rotations, which are non-commutative with translations, help
749 // to verify that we have correct order-of-operations in the final scroll
750 // compensation. Note that rotating about the center of the layer ensures we
751 // do not accidentally clip away layers that we want to test.
752 gfx::Transform rotation_about_z;
753 rotation_about_z.Translate(50.0, 50.0);
754 rotation_about_z.RotateAboutZAxis(90.0);
755 rotation_about_z.Translate(-50.0, -50.0);
756 grand_child->SetTransform(rotation_about_z);
757 great_grand_child->SetTransform(rotation_about_z);
758
759 // Case 1: scroll delta of 0, 0
760 child->SetScrollDelta(gfx::Vector2d(0, 0));
761 ExecuteCalculateDrawProperties(root_.get());
762
763 gfx::Transform expected_child_transform;
764
765 gfx::Transform expected_grand_child_surface_draw_transform;
766 expected_grand_child_surface_draw_transform.Translate(8.0, 6.0);
767 expected_grand_child_surface_draw_transform.PreconcatTransform(
768 rotation_about_z);
769
770 gfx::Transform expected_grand_child_transform;
771
772 gfx::Transform expected_great_grand_child_surface_draw_transform;
773 expected_great_grand_child_surface_draw_transform.Translate(40.0, 60.0);
774 expected_great_grand_child_surface_draw_transform.PreconcatTransform(
775 rotation_about_z);
776
777 gfx::Transform expected_great_grand_child_transform;
778
779 gfx::Transform expected_fixed_position_child_transform;
780
781 ASSERT_TRUE(grand_child->render_surface());
782 ASSERT_TRUE(great_grand_child->render_surface());
783 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
784 child->draw_transform());
785 EXPECT_TRANSFORMATION_MATRIX_EQ(
786 expected_grand_child_surface_draw_transform,
787 grand_child->render_surface()->draw_transform());
788 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
789 grand_child->draw_transform());
790 EXPECT_TRANSFORMATION_MATRIX_EQ(
791 expected_great_grand_child_surface_draw_transform,
792 great_grand_child->render_surface()->draw_transform());
793 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
794 great_grand_child->draw_transform());
795 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
796 fixed_position_child->draw_transform());
797
798 // Case 2: scroll delta of 10, 30
799 child->SetScrollDelta(gfx::Vector2d(10, 30));
800 ExecuteCalculateDrawProperties(root_.get());
801
802 expected_child_transform.MakeIdentity();
803 expected_child_transform.Translate(-10.0, -30.0); // scroll delta
804
805 expected_grand_child_surface_draw_transform.MakeIdentity();
806 expected_grand_child_surface_draw_transform.Translate(-10.0,
807 -30.0); // scroll delta
808 expected_grand_child_surface_draw_transform.Translate(8.0, 6.0);
809 expected_grand_child_surface_draw_transform.PreconcatTransform(
810 rotation_about_z);
811
812 // grand_child, great_grand_child, and great_grand_child's surface are not
813 // expected to change, since they are all not fixed, and they are all drawn
814 // with respect to grand_child's surface that already has the scroll delta
815 // accounted for.
816
817 // But the great-great grandchild, "fixed_position_child", should have a
818 // transform that explicitly cancels out the scroll delta. The expected
819 // transform is: compound_draw_transform.Inverse() * translate(positive scroll
820 // delta) * compound_origin_transform from great_grand_childSurface's origin
821 // to the root surface.
822 gfx::Transform compound_draw_transform;
823 compound_draw_transform.Translate(8.0,
824 6.0); // origin translation of grand_child
825 compound_draw_transform.PreconcatTransform(
826 rotation_about_z); // rotation of grand_child
827 compound_draw_transform.Translate(
828 40.0, 60.0); // origin translation of great_grand_child
829 compound_draw_transform.PreconcatTransform(
830 rotation_about_z); // rotation of great_grand_child
831
832 expected_fixed_position_child_transform.MakeIdentity();
833 expected_fixed_position_child_transform.PreconcatTransform(
834 Inverse(compound_draw_transform));
835 // explicit canceling out the scroll delta that gets embedded in the fixed
836 // position layer's surface.
837 expected_fixed_position_child_transform.Translate(10.0, 30.0);
838 expected_fixed_position_child_transform.PreconcatTransform(
839 compound_draw_transform);
840
841 ASSERT_TRUE(grand_child->render_surface());
842 ASSERT_TRUE(great_grand_child->render_surface());
843 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
844 child->draw_transform());
845 EXPECT_TRANSFORMATION_MATRIX_EQ(
846 expected_grand_child_surface_draw_transform,
847 grand_child->render_surface()->draw_transform());
848 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
849 grand_child->draw_transform());
850 EXPECT_TRANSFORMATION_MATRIX_EQ(
851 expected_great_grand_child_surface_draw_transform,
852 great_grand_child->render_surface()->draw_transform());
853 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
854 great_grand_child->draw_transform());
855 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
856 fixed_position_child->draw_transform());
857
858
859 // Case 3: fixed-container size delta of 20, 20
860 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
861 ExecuteCalculateDrawProperties(root_.get());
862
863 // Top-left fixed-position layer should not be affected by container size.
864 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
865 child->draw_transform());
866 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
867 grand_child->draw_transform());
868 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
869 great_grand_child->draw_transform());
870 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
871 fixed_position_child->draw_transform());
872
873 // Case 4: Bottom-right fixed-position layer.
874 fixed_position_child->SetPositionConstraint(fixed_to_bottom_right_);
875 ExecuteCalculateDrawProperties(root_.get());
876
877 // Bottom-right fixed-position layer moves as container resizes.
878 expected_fixed_position_child_transform.MakeIdentity();
879 expected_fixed_position_child_transform.PreconcatTransform(
880 Inverse(compound_draw_transform));
881 // explicit canceling out the scroll delta that gets embedded in the fixed
882 // position layer's surface.
883 expected_fixed_position_child_transform.Translate(10.0, 30.0);
884 // Also apply size delta in the child(container) layer space.
885 expected_fixed_position_child_transform.Translate(20.0, 20.0);
886 expected_fixed_position_child_transform.PreconcatTransform(
887 compound_draw_transform);
888
889 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
890 child->draw_transform());
891 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
892 grand_child->draw_transform());
893 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
894 great_grand_child->draw_transform());
895 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
896 fixed_position_child->draw_transform());
897 }
898
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface)899 TEST_F(LayerPositionConstraintTest,
900 ScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface) {
901 // This test checks for correct scroll compensation when the fixed-position
902 // container itself has a render surface. In this case, the container layer
903 // should be treated like a layer that contributes to a render target, and
904 // that render target is completely irrelevant; it should not affect the
905 // scroll compensation.
906 LayerImpl* child = scroll_->children()[0];
907 LayerImpl* grand_child = child->children()[0];
908
909 child->SetIsContainerForFixedPositionLayers(true);
910 child->SetForceRenderSurface(true);
911 grand_child->SetPositionConstraint(fixed_to_top_left_);
912 grand_child->SetDrawsContent(true);
913
914 // Case 1: scroll delta of 0, 0
915 child->SetScrollDelta(gfx::Vector2d(0, 0));
916 ExecuteCalculateDrawProperties(root_.get());
917
918 gfx::Transform expected_surface_draw_transform;
919 expected_surface_draw_transform.Translate(0.0, 0.0);
920 gfx::Transform expected_child_transform;
921 gfx::Transform expected_grand_child_transform;
922 ASSERT_TRUE(child->render_surface());
923 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform,
924 child->render_surface()->draw_transform());
925 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
926 child->draw_transform());
927 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
928 grand_child->draw_transform());
929
930 // Case 2: scroll delta of 10, 10
931 child->SetScrollDelta(gfx::Vector2d(10, 10));
932 ExecuteCalculateDrawProperties(root_.get());
933
934 // The surface is translated by scroll delta, the child transform doesn't
935 // change because it scrolls along with the surface, but the fixed position
936 // grand_child needs to compensate for the scroll translation.
937 expected_surface_draw_transform.MakeIdentity();
938 expected_surface_draw_transform.Translate(-10.0, -10.0);
939 expected_grand_child_transform.MakeIdentity();
940 expected_grand_child_transform.Translate(10.0, 10.0);
941
942 ASSERT_TRUE(child->render_surface());
943 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform,
944 child->render_surface()->draw_transform());
945 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
946 child->draw_transform());
947 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
948 grand_child->draw_transform());
949
950 // Case 3: fixed-container size delta of 20, 20
951 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
952 ExecuteCalculateDrawProperties(root_.get());
953
954 // Top-left fixed-position layer should not be affected by container size.
955 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
956 child->draw_transform());
957 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
958 grand_child->draw_transform());
959
960 // Case 4: Bottom-right fixed-position layer.
961 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
962 ExecuteCalculateDrawProperties(root_.get());
963
964 // Bottom-right fixed-position layer moves as container resizes.
965 expected_grand_child_transform.MakeIdentity();
966 // The surface is translated by scroll delta, the child transform doesn't
967 // change because it scrolls along with the surface, but the fixed position
968 // grand_child needs to compensate for the scroll translation.
969 expected_grand_child_transform.Translate(10.0, 10.0);
970 // Apply size delta from the child(container) layer.
971 expected_grand_child_transform.Translate(20.0, 20.0);
972
973 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
974 child->draw_transform());
975 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
976 grand_child->draw_transform());
977 }
978
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer)979 TEST_F(LayerPositionConstraintTest,
980 ScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer) {
981 // This test checks the scenario where a fixed-position layer also happens to
982 // be a container itself for a descendant fixed position layer. In particular,
983 // the layer should not accidentally be fixed to itself.
984 LayerImpl* child = scroll_->children()[0];
985 LayerImpl* grand_child = child->children()[0];
986
987 child->SetIsContainerForFixedPositionLayers(true);
988 grand_child->SetPositionConstraint(fixed_to_top_left_);
989
990 // This should not confuse the grand_child. If correct, the grand_child would
991 // still be considered fixed to its container (i.e. "child").
992 grand_child->SetIsContainerForFixedPositionLayers(true);
993
994 // Case 1: scroll delta of 0, 0
995 child->SetScrollDelta(gfx::Vector2d(0, 0));
996 ExecuteCalculateDrawProperties(root_.get());
997
998 gfx::Transform expected_child_transform;
999 gfx::Transform expected_grand_child_transform;
1000 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1001 child->draw_transform());
1002 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1003 grand_child->draw_transform());
1004
1005 // Case 2: scroll delta of 10, 10
1006 child->SetScrollDelta(gfx::Vector2d(10, 10));
1007 ExecuteCalculateDrawProperties(root_.get());
1008
1009 // Here the child is affected by scroll delta, but the fixed position
1010 // grand_child should not be affected.
1011 expected_child_transform.MakeIdentity();
1012 expected_child_transform.Translate(-10.0, -10.0);
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());
1017
1018 // Case 3: fixed-container size delta of 20, 20
1019 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
1020 ExecuteCalculateDrawProperties(root_.get());
1021
1022 // Top-left fixed-position layer should not be affected by container size.
1023 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1024 child->draw_transform());
1025 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1026 grand_child->draw_transform());
1027
1028 // Case 4: Bottom-right fixed-position layer.
1029 grand_child->SetPositionConstraint(fixed_to_bottom_right_);
1030 ExecuteCalculateDrawProperties(root_.get());
1031
1032 // Bottom-right fixed-position layer moves as container resizes.
1033 expected_grand_child_transform.MakeIdentity();
1034 // Apply size delta from the child(container) layer.
1035 expected_grand_child_transform.Translate(20.0, 20.0);
1036
1037 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1038 child->draw_transform());
1039 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1040 grand_child->draw_transform());
1041 }
1042
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedWithinFixedWithSameContainer)1043 TEST_F(LayerPositionConstraintTest,
1044 ScrollCompensationForFixedWithinFixedWithSameContainer) {
1045 // This test checks scroll compensation for a fixed-position layer that is
1046 // inside of another fixed-position layer and both share the same container.
1047 // In this situation, the parent fixed-position layer will receive
1048 // the scroll compensation, and the child fixed-position layer does not
1049 // need to compensate further.
1050
1051 LayerImpl* child = scroll_->children()[0];
1052 LayerImpl* grand_child = child->children()[0];
1053 LayerImpl* great_grand_child = grand_child->children()[0];
1054
1055 child->SetIsContainerForFixedPositionLayers(true);
1056 grand_child->SetPositionConstraint(fixed_to_top_left_);
1057
1058 // Note carefully - great_grand_child is fixed to bottom right, to test
1059 // sizeDelta being applied correctly; the compensation skips the grand_child
1060 // because it is fixed to top left.
1061 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
1062
1063 // Case 1: scrollDelta
1064 child->SetScrollDelta(gfx::Vector2d(10, 10));
1065 ExecuteCalculateDrawProperties(root_.get());
1066
1067 // Here the child is affected by scroll delta, but the fixed position
1068 // grand_child should not be affected.
1069 gfx::Transform expected_child_transform;
1070 expected_child_transform.Translate(-10.0, -10.0);
1071
1072 gfx::Transform expected_grand_child_transform;
1073 gfx::Transform expected_great_grand_child_transform;
1074
1075 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1076 child->draw_transform());
1077 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1078 grand_child->draw_transform());
1079 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
1080 great_grand_child->draw_transform());
1081
1082 // Case 2: sizeDelta
1083 child->SetScrollDelta(gfx::Vector2d(0, 0));
1084 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20));
1085 ExecuteCalculateDrawProperties(root_.get());
1086
1087 expected_child_transform.MakeIdentity();
1088
1089 expected_grand_child_transform.MakeIdentity();
1090
1091 // Fixed to bottom-right, size-delta compensation is applied.
1092 expected_great_grand_child_transform.MakeIdentity();
1093 expected_great_grand_child_transform.Translate(20.0, 20.0);
1094
1095 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1096 child->draw_transform());
1097 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1098 grand_child->draw_transform());
1099 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
1100 great_grand_child->draw_transform());
1101 }
1102
TEST_F(LayerPositionConstraintTest,ScrollCompensationForFixedWithinFixedWithInterveningContainer)1103 TEST_F(LayerPositionConstraintTest,
1104 ScrollCompensationForFixedWithinFixedWithInterveningContainer) {
1105 // This test checks scroll compensation for a fixed-position layer that is
1106 // inside of another fixed-position layer, but they have different fixed
1107 // position containers. In this situation, the child fixed-position element
1108 // would still have to compensate with respect to its container.
1109
1110 LayerImpl* container1 = scroll_->children()[0];
1111 LayerImpl* fixed_to_container1 = container1->children()[0];
1112 LayerImpl* container2 = fixed_to_container1->children()[0];
1113
1114 {
1115 // Add one more layer to the hierarchy for this test.
1116 scoped_ptr<LayerImpl> fixed_to_container2_ptr =
1117 LayerImpl::Create(host_impl_.active_tree(), 5);
1118 container2->AddChild(fixed_to_container2_ptr.Pass());
1119 }
1120
1121 LayerImpl* fixed_to_container2 = container2->children()[0];
1122
1123 container1->SetIsContainerForFixedPositionLayers(true);
1124 fixed_to_container1->SetPositionConstraint(fixed_to_top_left_);
1125 container2->SetIsContainerForFixedPositionLayers(true);
1126 fixed_to_container2->SetPositionConstraint(fixed_to_top_left_);
1127
1128 container1->SetScrollDelta(gfx::Vector2d(0, 15));
1129 container2->SetScrollDelta(gfx::Vector2d(30, 0));
1130 ExecuteCalculateDrawProperties(root_.get());
1131
1132 gfx::Transform expected_container1_transform;
1133 expected_container1_transform.Translate(0.0, -15.0);
1134
1135 gfx::Transform expected_fixed_to_container1_transform;
1136
1137 // Since the container is a descendant of the fixed layer above,
1138 // the expected draw transform for container2 would not
1139 // include the scrollDelta that was applied to container1.
1140 gfx::Transform expected_container2_transform;
1141 expected_container2_transform.Translate(-30.0, 0.0);
1142
1143 gfx::Transform expected_fixed_to_container2_transform;
1144
1145 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container1_transform,
1146 container1->draw_transform());
1147
1148 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container1_transform,
1149 fixed_to_container1->draw_transform());
1150
1151 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container2_transform,
1152 container2->draw_transform());
1153
1154 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container2_transform,
1155 fixed_to_container2->draw_transform());
1156 }
1157 } // namespace
1158 } // namespace cc
1159