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