Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: cc/trees/property_tree.cc

Issue 2733633002: Handle nested position:sticky elements correctly (compositor) (Closed)
Patch Set: Add comment referencing crbug.com/702229 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 6
7 #include <set> 7 #include <set>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 CombineTransformsBetween(dest_id, source_id, &dest_to_source); 339 CombineTransformsBetween(dest_id, source_id, &dest_to_source);
340 gfx::Transform source_to_dest; 340 gfx::Transform source_to_dest;
341 bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest); 341 bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest);
342 transform->PreconcatTransform(source_to_dest); 342 transform->PreconcatTransform(source_to_dest);
343 return all_are_invertible; 343 return all_are_invertible;
344 } 344 }
345 345
346 gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { 346 gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) {
347 if (node->sticky_position_constraint_id == -1) 347 if (node->sticky_position_constraint_id == -1)
348 return gfx::Vector2dF(); 348 return gfx::Vector2dF();
349 const StickyPositionNodeData* sticky_data = 349 StickyPositionNodeData* sticky_data = tree->StickyPositionData(node->id);
350 tree->StickyPositionData(node->id); 350 LayerStickyPositionConstraint& constraint = sticky_data->constraints;
351 const LayerStickyPositionConstraint& constraint = sticky_data->constraints;
352 ScrollNode* scroll_node = 351 ScrollNode* scroll_node =
353 tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor); 352 tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor);
354 gfx::ScrollOffset scroll_offset = 353 gfx::ScrollOffset scroll_offset =
355 tree->property_trees()->scroll_tree.current_scroll_offset( 354 tree->property_trees()->scroll_tree.current_scroll_offset(
356 scroll_node->owning_layer_id); 355 scroll_node->owning_layer_id);
357 gfx::PointF scroll_position(scroll_offset.x(), scroll_offset.y()); 356 gfx::PointF scroll_position(scroll_offset.x(), scroll_offset.y());
358 TransformNode* scroll_ancestor_transform_node = 357 TransformNode* scroll_ancestor_transform_node =
359 tree->Node(scroll_node->transform_id); 358 tree->Node(scroll_node->transform_id);
360 if (scroll_ancestor_transform_node->scrolls) { 359 if (scroll_ancestor_transform_node->scrolls) {
361 // The scroll position does not include snapping which shifts the scroll 360 // The scroll position does not include snapping which shifts the scroll
362 // offset to align to a pixel boundary, we need to manually include it here. 361 // offset to align to a pixel boundary, we need to manually include it here.
363 // In this case, snapping is caused by a scroll. 362 // In this case, snapping is caused by a scroll.
364 scroll_position -= scroll_ancestor_transform_node->snap_amount; 363 scroll_position -= scroll_ancestor_transform_node->snap_amount;
365 } 364 }
366 365
367 gfx::RectF clip( 366 gfx::RectF clip(
368 scroll_position, 367 scroll_position,
369 gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds( 368 gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds(
370 scroll_node->id))); 369 scroll_node->id)));
371 gfx::Vector2dF sticky_offset(
372 constraint.scroll_container_relative_sticky_box_rect.OffsetFromOrigin());
373 gfx::Vector2dF layer_offset(sticky_data->main_thread_offset); 370 gfx::Vector2dF layer_offset(sticky_data->main_thread_offset);
374 371
375 // In each of the following cases, we measure the limit which is the point 372 // In each of the following cases, we measure the limit which is the point
376 // that the element should stick to, clamping on one side to 0 (because sticky 373 // that the element should stick to, clamping on one side to 0 (because sticky
377 // only pushes elements in one direction). Then we clamp to how far we can 374 // only pushes elements in one direction). Then we clamp to how far we can
378 // push the element in that direction without being pushed outside of its 375 // push the element in that direction without being pushed outside of its
379 // containing block. 376 // containing block.
380 // 377 //
381 // Note: The order of applying the sticky constraints is applied such that 378 // Note: The order of applying the sticky constraints is applied such that
382 // left offset takes precedence over right offset, and top takes precedence 379 // left offset takes precedence over right offset, and top takes precedence
383 // over bottom offset. 380 // over bottom offset.
flackr 2017/03/17 15:01:55 This comment should probably stay next to the limi
smcgruer 2017/03/17 17:36:51 Done.
381
382 gfx::Vector2dF ancestor_sticky_box_offset;
383 if (sticky_data->nearest_node_shifting_sticky_box >= 0) {
384 ancestor_sticky_box_offset =
385 tree->StickyPositionData(sticky_data->nearest_node_shifting_sticky_box)
386 ->constraints.total_sticky_box_sticky_offset;
387 }
388
389 gfx::Vector2dF ancestor_containing_block_offset;
390 if (sticky_data->nearest_node_shifting_containing_block >= 0) {
391 ancestor_containing_block_offset =
392 tree->StickyPositionData(
393 sticky_data->nearest_node_shifting_containing_block)
394 ->constraints.total_containing_block_sticky_offset;
395 }
396
397 gfx::RectF sticky_box_rect =
flackr 2017/03/17 15:01:56 nit: Add a short comment explaining what this is d
smcgruer 2017/03/17 17:36:52 Done.
398 constraint.scroll_container_relative_sticky_box_rect +
399 ancestor_sticky_box_offset + ancestor_containing_block_offset;
400 gfx::RectF containing_block_rect =
401 constraint.scroll_container_relative_containing_block_rect +
402 ancestor_containing_block_offset;
403
404 gfx::Vector2dF sticky_offset(sticky_box_rect.OffsetFromOrigin());
405
384 if (constraint.is_anchored_right) { 406 if (constraint.is_anchored_right) {
385 float right_limit = clip.right() - constraint.right_offset; 407 float right_limit = clip.right() - constraint.right_offset;
386 float right_delta = std::min<float>( 408 float right_delta =
387 0, right_limit - 409 std::min<float>(0, right_limit - sticky_box_rect.right());
388 constraint.scroll_container_relative_sticky_box_rect.right()); 410 float available_space =
389 float available_space = std::min<float>( 411 std::min<float>(0, containing_block_rect.x() - sticky_box_rect.x());
390 0, constraint.scroll_container_relative_containing_block_rect.x() -
391 constraint.scroll_container_relative_sticky_box_rect.x());
392 if (right_delta < available_space) 412 if (right_delta < available_space)
393 right_delta = available_space; 413 right_delta = available_space;
394 sticky_offset.set_x(sticky_offset.x() + right_delta); 414 sticky_offset.set_x(sticky_offset.x() + right_delta);
395 } 415 }
396 if (constraint.is_anchored_left) { 416 if (constraint.is_anchored_left) {
397 float left_limit = clip.x() + constraint.left_offset; 417 float left_limit = clip.x() + constraint.left_offset;
398 float left_delta = std::max<float>( 418 float left_delta = std::max<float>(0, left_limit - sticky_box_rect.x());
399 0,
400 left_limit - constraint.scroll_container_relative_sticky_box_rect.x());
401 float available_space = std::max<float>( 419 float available_space = std::max<float>(
402 0, constraint.scroll_container_relative_containing_block_rect.right() - 420 0, containing_block_rect.right() - sticky_box_rect.right());
403 constraint.scroll_container_relative_sticky_box_rect.right());
404 if (left_delta > available_space) 421 if (left_delta > available_space)
405 left_delta = available_space; 422 left_delta = available_space;
406 sticky_offset.set_x(sticky_offset.x() + left_delta); 423 sticky_offset.set_x(sticky_offset.x() + left_delta);
407 } 424 }
408 if (constraint.is_anchored_bottom) { 425 if (constraint.is_anchored_bottom) {
409 float bottom_limit = clip.bottom() - constraint.bottom_offset; 426 float bottom_limit = clip.bottom() - constraint.bottom_offset;
410 float bottom_delta = std::min<float>( 427 float bottom_delta =
411 0, bottom_limit - 428 std::min<float>(0, bottom_limit - sticky_box_rect.bottom());
412 constraint.scroll_container_relative_sticky_box_rect.bottom()); 429 float available_space =
413 float available_space = std::min<float>( 430 std::min<float>(0, containing_block_rect.y() - sticky_box_rect.y());
414 0, constraint.scroll_container_relative_containing_block_rect.y() -
415 constraint.scroll_container_relative_sticky_box_rect.y());
416 if (bottom_delta < available_space) 431 if (bottom_delta < available_space)
417 bottom_delta = available_space; 432 bottom_delta = available_space;
418 sticky_offset.set_y(sticky_offset.y() + bottom_delta); 433 sticky_offset.set_y(sticky_offset.y() + bottom_delta);
419 } 434 }
420 if (constraint.is_anchored_top) { 435 if (constraint.is_anchored_top) {
421 float top_limit = clip.y() + constraint.top_offset; 436 float top_limit = clip.y() + constraint.top_offset;
422 float top_delta = std::max<float>( 437 float top_delta = std::max<float>(0, top_limit - sticky_box_rect.y());
423 0,
424 top_limit - constraint.scroll_container_relative_sticky_box_rect.y());
425 float available_space = std::max<float>( 438 float available_space = std::max<float>(
426 0, constraint.scroll_container_relative_containing_block_rect.bottom() - 439 0, containing_block_rect.bottom() - sticky_box_rect.bottom());
427 constraint.scroll_container_relative_sticky_box_rect.bottom());
428 if (top_delta > available_space) 440 if (top_delta > available_space)
429 top_delta = available_space; 441 top_delta = available_space;
430 sticky_offset.set_y(sticky_offset.y() + top_delta); 442 sticky_offset.set_y(sticky_offset.y() + top_delta);
431 } 443 }
444
445 constraint.total_sticky_box_sticky_offset =
446 ancestor_sticky_box_offset + sticky_offset -
447 sticky_box_rect.OffsetFromOrigin();
448 constraint.total_containing_block_sticky_offset =
449 ancestor_sticky_box_offset + ancestor_containing_block_offset +
450 sticky_offset - sticky_box_rect.OffsetFromOrigin();
flackr 2017/03/17 15:01:55 I think we should keep the passed in constraints c
smcgruer 2017/03/17 17:36:51 Done.
451
432 return sticky_offset - layer_offset - node->source_to_parent - 452 return sticky_offset - layer_offset - node->source_to_parent -
433 constraint.scroll_container_relative_sticky_box_rect 453 sticky_box_rect.OffsetFromOrigin();
434 .OffsetFromOrigin();
435 } 454 }
436 455
437 void TransformTree::UpdateLocalTransform(TransformNode* node) { 456 void TransformTree::UpdateLocalTransform(TransformNode* node) {
438 gfx::Transform transform = node->post_local; 457 gfx::Transform transform = node->post_local;
439 if (NeedsSourceToParentUpdate(node)) { 458 if (NeedsSourceToParentUpdate(node)) {
440 gfx::Transform to_parent; 459 gfx::Transform to_parent;
441 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent); 460 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent);
442 gfx::Vector2dF unsnapping; 461 gfx::Vector2dF unsnapping;
443 TransformNode* current; 462 TransformNode* current;
444 TransformNode* parent_node; 463 TransformNode* parent_node;
(...skipping 1669 matching lines...) Expand 10 before | Expand all | Expand 10 after
2114 const EffectNode* effect_node = effect_tree.Node(effect_id); 2133 const EffectNode* effect_node = effect_tree.Node(effect_id);
2115 2134
2116 if (effect_node->surface_contents_scale.x() != 0.0 && 2135 if (effect_node->surface_contents_scale.x() != 0.0 &&
2117 effect_node->surface_contents_scale.y() != 0.0) 2136 effect_node->surface_contents_scale.y() != 0.0)
2118 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(), 2137 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(),
2119 1.0 / effect_node->surface_contents_scale.y()); 2138 1.0 / effect_node->surface_contents_scale.y());
2120 return screen_space_transform; 2139 return screen_space_transform;
2121 } 2140 }
2122 2141
2123 } // namespace cc 2142 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698