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