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