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