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
17namespace cc {
18namespace {
19
20void 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
34void 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
58void 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
64class LayerPositionConstraintTest : public testing::Test {
65 public:
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
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
137namespace {
138
139void 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
149TEST_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
210TEST_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
289TEST_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
367TEST_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
475TEST_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
590TEST_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
713TEST_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
899TEST_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
979TEST_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
1043TEST_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
1103TEST_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