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

Unified Diff: third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.h

Issue 2961613002: Slightly refactor StickyPositionScrollingConstraints API and add documentation (Closed)
Patch Set: Fix it's -> its Created 3 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.h
diff --git a/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.h b/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.h
index 428531757cec98cfd1175c4089b07cf026a6d1cb..0b95e3e0e45e473c25ba8eb6b881f1c086a1f82a 100644
--- a/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.h
+++ b/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.h
@@ -11,15 +11,32 @@
namespace blink {
-class LayoutBoxModelObject;
class PaintLayer;
class StickyPositionScrollingConstraints;
typedef WTF::HashMap<PaintLayer*, StickyPositionScrollingConstraints>
StickyConstraintsMap;
-// TODO(smcgruer): Add detailed comment explaining how
-// StickyPositionScrollingConstraints works.
+// Encapsulates the constraint information for a position: sticky element and
+// does calculation of the sticky offset for a given overflow clip rectangle.
+//
+// To avoid slowing down scrolling we cannot make the offset calculation a
+// layout-inducing event. Instead constraint information is cached during layout
+// and used as the scroll position changes to determine the current offset. In
+// most cases the only information that is needed is the sticky element's layout
+// rectangle and its containing block rectangle (both respective to the nearest
+// ancestor scroller which the element is sticking to), and the set of sticky
+// edge constraints (i.e. the distance from each edge the element should stick).
+//
+// For a given (non-cached) overflow clip rectangle, calculating the current
+// offset in most cases just requires sliding the (cached) sticky element
+// rectangle until it satisfies the (cached) sticky edge constraints for the
+// overflow clip rectangle, whilst not letting the sticky element rectangle
+// escape its (cached) containing block rect.
+//
+// Unfortunately this approach breaks down in the presence of nested sticky
+// elements. For those we apply more complicated logic, which is explained in
+// the implementation of |ComputeStickyOffset|.
class StickyPositionScrollingConstraints final {
chrishtr 2017/07/27 15:13:39 I think it would be good to add a representative e
smcgruer 2017/07/28 17:35:57 In terms of StickyPositionScrollingConstraints pub
chrishtr 2017/07/28 18:25:51 I think an example of the flow of information and
smcgruer 2017/07/31 15:22:34 Done.
public:
enum AnchorEdgeFlags {
@@ -36,8 +53,8 @@ class StickyPositionScrollingConstraints final {
right_offset_(0),
top_offset_(0),
bottom_offset_(0),
- nearest_sticky_box_shifting_sticky_box_(nullptr),
- nearest_sticky_box_shifting_containing_block_(nullptr) {}
+ nearest_sticky_layer_shifting_sticky_box_(nullptr),
+ nearest_sticky_layer_shifting_containing_block_(nullptr) {}
StickyPositionScrollingConstraints(
const StickyPositionScrollingConstraints& other)
@@ -50,23 +67,32 @@ class StickyPositionScrollingConstraints final {
other.scroll_container_relative_containing_block_rect_),
scroll_container_relative_sticky_box_rect_(
other.scroll_container_relative_sticky_box_rect_),
- nearest_sticky_box_shifting_sticky_box_(
- other.nearest_sticky_box_shifting_sticky_box_),
- nearest_sticky_box_shifting_containing_block_(
- other.nearest_sticky_box_shifting_containing_block_),
+ nearest_sticky_layer_shifting_sticky_box_(
+ other.nearest_sticky_layer_shifting_sticky_box_),
+ nearest_sticky_layer_shifting_containing_block_(
+ other.nearest_sticky_layer_shifting_containing_block_),
total_sticky_box_sticky_offset_(other.total_sticky_box_sticky_offset_),
total_containing_block_sticky_offset_(
other.total_containing_block_sticky_offset_) {}
- FloatSize ComputeStickyOffset(
- const FloatRect& viewport_rect,
- const StickyPositionScrollingConstraints* ancestor_sticky_box_constraints,
- const StickyPositionScrollingConstraints*
- ancestor_containing_block_constraints);
+ // Computes the sticky offset for a given overflow clip rect.
+ //
+ // This method is non-const as we cache internal state for performance; see
+ // documentation in the implementation for details.
+ FloatSize ComputeStickyOffset(const FloatRect& overflow_clip_rect,
+ const StickyConstraintsMap&);
+
+ // Returns the last-computed offset of the sticky box from its original
+ // position before scroll.
+ //
+ // This method exists for performance (to avoid recomputing the sticky offset)
+ // and must only be called when compositing inputs are clean for the sticky
+ // element. (Or after prepaint for SlimmingPaintV2).
+ FloatSize GetOffsetForStickyPosition(const StickyConstraintsMap&) const;
bool HasAncestorStickyElement() const {
- return nearest_sticky_box_shifting_sticky_box_ ||
- nearest_sticky_box_shifting_containing_block_;
+ return nearest_sticky_layer_shifting_sticky_box_ ||
+ nearest_sticky_layer_shifting_containing_block_;
}
AnchorEdges GetAnchorEdges() const { return anchor_edges_; }
@@ -74,7 +100,6 @@ class StickyPositionScrollingConstraints final {
return anchor_edges_ & flag;
}
void AddAnchorEdge(AnchorEdgeFlags edge_flag) { anchor_edges_ |= edge_flag; }
- void SetAnchorEdges(AnchorEdges edges) { anchor_edges_ = edges; }
float LeftOffset() const { return left_offset_; }
float RightOffset() const { return right_offset_; }
@@ -100,45 +125,18 @@ class StickyPositionScrollingConstraints final {
return scroll_container_relative_sticky_box_rect_;
}
- void SetNearestStickyBoxShiftingStickyBox(LayoutBoxModelObject* layer) {
- nearest_sticky_box_shifting_sticky_box_ = layer;
+ void SetNearestStickyLayerShiftingStickyBox(PaintLayer* layer) {
+ nearest_sticky_layer_shifting_sticky_box_ = layer;
}
- LayoutBoxModelObject* NearestStickyBoxShiftingStickyBox() const {
- return nearest_sticky_box_shifting_sticky_box_;
+ PaintLayer* NearestStickyLayerShiftingStickyBox() const {
+ return nearest_sticky_layer_shifting_sticky_box_;
}
- void SetNearestStickyBoxShiftingContainingBlock(LayoutBoxModelObject* layer) {
- nearest_sticky_box_shifting_containing_block_ = layer;
- }
- LayoutBoxModelObject* NearestStickyBoxShiftingContainingBlock() const {
- return nearest_sticky_box_shifting_containing_block_;
- }
-
- const FloatSize& GetTotalStickyBoxStickyOffset() const {
- return total_sticky_box_sticky_offset_;
- }
- const FloatSize& GetTotalContainingBlockStickyOffset() const {
- return total_containing_block_sticky_offset_;
+ void SetNearestStickyLayerShiftingContainingBlock(PaintLayer* layer) {
+ nearest_sticky_layer_shifting_containing_block_ = layer;
}
-
- // Returns the relative position of the sticky box and its original position
- // before scroll. This method is only safe to call if ComputeStickyOffset has
- // been invoked.
- FloatSize GetOffsetForStickyPosition(const StickyConstraintsMap&) const;
-
- const LayoutBoxModelObject* NearestStickyAncestor() const {
- // If we have one or more sticky ancestor elements between ourselves and our
- // containing block, |m_nearestStickyBoxShiftingStickyBox| points to the
- // closest. Otherwise, |m_nearestStickyBoxShiftingContainingBlock| points
- // to the the first sticky ancestor between our containing block (inclusive)
- // and our scroll ancestor (exclusive). Therefore our nearest sticky
- // ancestor is the former if it exists, or the latter otherwise.
- //
- // If both are null, then we have no sticky ancestors before our scroll
- // ancestor, so the correct action is to return null.
- return nearest_sticky_box_shifting_sticky_box_
- ? nearest_sticky_box_shifting_sticky_box_
- : nearest_sticky_box_shifting_containing_block_;
+ PaintLayer* NearestStickyLayerShiftingContainingBlock() const {
+ return nearest_sticky_layer_shifting_containing_block_;
}
bool operator==(const StickyPositionScrollingConstraints& other) const {
@@ -150,10 +148,10 @@ class StickyPositionScrollingConstraints final {
other.scroll_container_relative_containing_block_rect_ &&
scroll_container_relative_sticky_box_rect_ ==
other.scroll_container_relative_sticky_box_rect_ &&
- nearest_sticky_box_shifting_sticky_box_ ==
- other.nearest_sticky_box_shifting_sticky_box_ &&
- nearest_sticky_box_shifting_containing_block_ ==
- other.nearest_sticky_box_shifting_containing_block_ &&
+ nearest_sticky_layer_shifting_sticky_box_ ==
+ other.nearest_sticky_layer_shifting_sticky_box_ &&
+ nearest_sticky_layer_shifting_containing_block_ ==
+ other.nearest_sticky_layer_shifting_containing_block_ &&
total_sticky_box_sticky_offset_ ==
other.total_sticky_box_sticky_offset_ &&
total_containing_block_sticky_offset_ ==
@@ -165,31 +163,52 @@ class StickyPositionScrollingConstraints final {
}
private:
+ FloatSize AncestorStickyBoxOffset(const StickyConstraintsMap&);
+ FloatSize AncestorContainingBlockOffset(const StickyConstraintsMap&);
+
AnchorEdges anchor_edges_;
float left_offset_;
float right_offset_;
float top_offset_;
float bottom_offset_;
+
+ // The layout position of the sticky element's containing block rectangle,
chrishtr 2017/07/27 15:13:39 "The layout position of the containing block of th
smcgruer 2017/07/28 17:35:57 Done, though I'm not sure it improved readability
+ // relative to the scroll container. When calculating the sticky offset it is
+ // used to ensure the sticky element stays bounded by its containing block.
FloatRect scroll_container_relative_containing_block_rect_;
+
+ // The layout position of the sticky element. When calculating the sticky
chrishtr 2017/07/27 15:13:39 ...sticky element relative to its scroll container
smcgruer 2017/07/28 17:35:57 Done.
+ // offset it is used to determine how large the offset needs to be to satisfy
+ // the sticky constraints.
FloatRect scroll_container_relative_sticky_box_rect_;
- // In order to properly compute the stickyOffset, we need to know if we have
- // any sticky ancestors both between ourselves and our containing block and
- // between our containing block and the viewport. These ancestors are needed
- // to properly shift our constraining rects with regards to the containing
- // block and viewport.
- LayoutBoxModelObject* nearest_sticky_box_shifting_sticky_box_;
- LayoutBoxModelObject* nearest_sticky_box_shifting_containing_block_;
+ // In the case of nested sticky elements the layout position of the sticky
+ // element and its containing block are not accurate (as they are affected by
+ // ancestor sticky offsets). To ensure a correct sticky offset calculation in
+ // that case we must track any sticky ancestors between the sticky element and
+ // its containing block, and between its containing block and the overflow
+ // clip ancestor.
+ //
+ // See the implementation of |ComputeStickyOffset| for documentation on how
+ // these ancestors are used to correct the offset calculation.
+ PaintLayer* nearest_sticky_layer_shifting_sticky_box_;
+ PaintLayer* nearest_sticky_layer_shifting_containing_block_;
// For performance we cache our accumulated sticky offset to allow descendant
// sticky elements to offset their constraint rects. Because we can either
- // affect the sticky box constraint rect or the containing block constraint
- // rect, we need to accumulate both.
+ // affect a descendant element's sticky box constraint rect or containing
+ // block constraint rect, we need to accumulate two offsets.
+ //
+ // The sticky box offset accumulates the chain of sticky elements that are
+ // between this sticky element and its containing block. Any descendant using
+ // |total_sticky_box_sticky_offset_| has the same containing block as this
+ // element, so |total_sticky_box_sticky_offset_| does not accumulate
+ // containing block sticky offsets.
chrishtr 2017/07/27 15:13:39 Add example.
smcgruer 2017/07/28 17:35:57 Done.
//
- // The case where we can affect both the sticky box constraint rect and the
- // constraining block constriant rect for different sticky descendants is
- // quite complex. See the StickyPositionComplexTableNesting test in
- // LayoutBoxModelObjectTest.cpp.
+ // The containing block offset accumulates all sticky-related offsets between
+ // this element and the ancestor scroller. If this element is a containing
+ // block shifting ancestor for some descendant, it shifts the descendant's
+ // constraint rects by its entire offset.
FloatSize total_sticky_box_sticky_offset_;
FloatSize total_containing_block_sticky_offset_;
};

Powered by Google App Engine
This is Rietveld 408576698