Chromium Code Reviews| Index: cc/trees/property_tree.cc |
| diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc |
| index 912226b25e525f0e9045e26070783bbe0cb7c5eb..ba774a87e107772152bcb0ac3552585d3d8c9e19 100644 |
| --- a/cc/trees/property_tree.cc |
| +++ b/cc/trees/property_tree.cc |
| @@ -149,6 +149,8 @@ void TransformTree::clear() { |
| nodes_affected_by_outer_viewport_bounds_delta_.clear(); |
| cached_data_.clear(); |
| cached_data_.push_back(TransformCachedNodeData()); |
| + sticky_position_data_.clear(); |
| + sticky_position_data_free_ids_.clear(); |
| #if DCHECK_IS_ON() |
| TransformTree tree; |
| @@ -250,10 +252,13 @@ void TransformTree::UpdateTransforms(int id) { |
| TransformNode* target_node = Node(TargetId(id)); |
| TransformNode* source_node = Node(node->source_node_id); |
| property_trees()->UpdateCachedNumber(); |
| - if (node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) |
| + // TODO(flackr): Only dirty when scroll offset changes. |
| + if (node->sticky_position_constraint_id >= 0 || |
| + node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) { |
| UpdateLocalTransform(node); |
| - else |
| + } else { |
| UndoSnapping(node); |
| + } |
| UpdateScreenSpaceTransform(node, parent_node, target_node); |
| UpdateSurfaceContentsScale(node); |
| UpdateAnimationProperties(node, parent_node); |
| @@ -399,6 +404,78 @@ bool TransformTree::CombineInversesBetween(int source_id, |
| return all_are_invertible; |
| } |
| +TransformNode* ScrollingAncestor(TransformTree* tree, TransformNode* node) { |
|
ajuma
2016/09/08 22:08:54
This function seems to be unused?
flackr
2016/09/20 17:08:13
Removed. Yes, this ended up not being needed as we
|
| + do { |
| + node = tree->parent(node); |
| + } while (!node->scrolls); |
| + return node; |
| +} |
| + |
| +gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { |
| + if (node->sticky_position_constraint_id == -1) |
| + return gfx::Vector2dF(); |
| + const StickyPositionNodeData* sticky_data = |
| + tree->StickyPositionData(node->id); |
| + const LayerStickyPositionConstraint& constraint = sticky_data->constraints; |
| + ScrollNode* scroll_node = |
| + tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor); |
| + gfx::ScrollOffset scroll_offset = |
| + tree->property_trees()->scroll_tree.current_scroll_offset( |
| + scroll_node->owner_id); |
| + |
| + gfx::RectF clip(gfx::PointF(scroll_offset.x(), scroll_offset.y()), |
| + gfx::SizeF(scroll_node->scroll_clip_layer_bounds)); |
| + gfx::Vector2dF sticky_offset( |
| + constraint.absolute_sticky_box_rect.OffsetFromOrigin()); |
| + gfx::Vector2dF layer_offset(sticky_data->main_thread_offset); |
| + if (constraint.is_anchored_right) { |
|
ajuma
2016/09/08 22:08:54
Please explain (in a comment) what the math here i
flackr
2016/09/20 17:08:13
Done. I tried to summarize above.
|
| + float right_limit = clip.right() - constraint.right_offset; |
| + float right_delta = std::min<float>( |
| + 0, right_limit - constraint.absolute_sticky_box_rect.right()); |
| + float available_space = |
| + std::min<float>(0, constraint.absolute_containing_block_rect.x() - |
| + constraint.absolute_sticky_box_rect.x()); |
| + if (right_delta < available_space) |
| + right_delta = available_space; |
| + sticky_offset.set_x(sticky_offset.x() + right_delta); |
| + } |
| + if (constraint.is_anchored_left) { |
| + float left_limit = clip.x() + constraint.left_offset; |
| + float left_delta = std::max<float>( |
| + 0, left_limit - constraint.absolute_sticky_box_rect.x()); |
| + float available_space = |
| + std::max<float>(0, constraint.absolute_containing_block_rect.right() - |
| + constraint.absolute_sticky_box_rect.right()); |
| + if (left_delta > available_space) |
| + left_delta = available_space; |
| + sticky_offset.set_x(sticky_offset.x() + left_delta); |
| + } |
| + if (constraint.is_anchored_bottom) { |
| + float bottom_limit = clip.bottom() - constraint.bottom_offset; |
| + float bottom_delta = std::min<float>( |
| + 0, bottom_limit - constraint.absolute_sticky_box_rect.bottom()); |
| + float available_space = |
| + std::min<float>(0, constraint.absolute_containing_block_rect.y() - |
| + constraint.absolute_sticky_box_rect.y()); |
| + if (bottom_delta < available_space) |
| + bottom_delta = available_space; |
| + sticky_offset.set_y(sticky_offset.y() + bottom_delta); |
| + } |
| + if (constraint.is_anchored_top) { |
| + float top_limit = clip.y() + constraint.top_offset; |
| + float top_delta = |
| + std::max<float>(0, top_limit - constraint.absolute_sticky_box_rect.y()); |
| + float available_space = |
| + std::max<float>(0, constraint.absolute_containing_block_rect.bottom() - |
| + constraint.absolute_sticky_box_rect.bottom()); |
| + if (top_delta > available_space) |
| + top_delta = available_space; |
| + sticky_offset.set_y(sticky_offset.y() + top_delta); |
| + } |
| + return sticky_offset - layer_offset - |
| + constraint.absolute_sticky_box_rect.OffsetFromOrigin(); |
| +} |
| + |
| void TransformTree::UpdateLocalTransform(TransformNode* node) { |
| gfx::Transform transform = node->post_local; |
| if (NeedsSourceToParentUpdate(node)) { |
| @@ -450,6 +527,9 @@ void TransformTree::UpdateLocalTransform(TransformNode* node) { |
| fixed_position_adjustment.y()); |
| transform.PreconcatTransform(node->local); |
| transform.PreconcatTransform(node->pre_local); |
| + |
| + transform.Translate(StickyPositionOffset(this, node)); |
|
ajuma
2016/09/08 22:08:54
I'd have expected this to happen a couple lines ea
flackr
2016/09/20 17:08:13
Good catch, this is a position effect and shouldn'
|
| + |
| node->set_to_parent(transform); |
| node->needs_local_transform_update = false; |
| } |
| @@ -759,6 +839,31 @@ bool TransformTree::operator==(const TransformTree& other) const { |
| cached_data_ == other.cached_data(); |
| } |
| +StickyPositionNodeData* TransformTree::StickyPositionData(int node_id) { |
| + TransformNode* node = Node(node_id); |
| + int sticky_data_id = node->sticky_position_constraint_id; |
| + if (sticky_data_id == -1) { |
| + if (!sticky_position_data_free_ids_.empty()) { |
| + sticky_data_id = sticky_position_data_free_ids_.back(); |
| + sticky_position_data_free_ids_.pop_back(); |
| + } else { |
| + sticky_data_id = sticky_position_data_.size(); |
| + sticky_position_data_.push_back(StickyPositionNodeData()); |
| + } |
| + node->sticky_position_constraint_id = sticky_data_id; |
| + } |
| + return &sticky_position_data_[sticky_data_id]; |
| +} |
| + |
| +void TransformTree::SetNotSticky(int node_id) { |
| + TransformNode* node = Node(node_id); |
| + int sticky_data_id = node->sticky_position_constraint_id; |
| + if (sticky_data_id == -1) |
| + return; |
| + sticky_position_data_free_ids_.push_back(sticky_data_id); |
|
flackr
2016/09/08 17:52:30
I'm not sure if we always rebuild the tree when st
ajuma
2016/09/08 22:08:54
Since Layer::SetStickyPositionConstraint calls Set
flackr
2016/09/20 17:08:13
Done. I agree, I expect sticky / not sticky change
|
| + node->sticky_position_constraint_id = -1; |
| +} |
| + |
| void TransformTree::ToProtobuf(proto::PropertyTree* proto) const { |
|
flackr
2016/09/08 17:52:30
When is this used? Will the sticky position data n
ajuma
2016/09/08 22:08:54
This was added for Blimp, though currently they do
flackr
2016/09/20 17:08:13
Done.
|
| DCHECK(!proto->has_property_type()); |
| proto->set_property_type(proto::PropertyTree::Transform); |