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