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

Unified Diff: third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp

Issue 2346383005: Compute sticky position constraints without considering transforms. (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
index 0bba976b0be7e1ac39ba9c2a5334b26dc1dabd67..cb4e4dc4fa26c9f792bc5a6d21615e461fc31e8f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -41,6 +41,7 @@
#include "core/paint/PaintLayer.h"
#include "core/style/ShadowList.h"
#include "platform/LengthFunctions.h"
+#include "platform/geometry/TransformState.h"
#include "wtf/PtrUtil.h"
namespace blink {
@@ -693,33 +694,40 @@ void LayoutBoxModelObject::updateStickyPositionConstraints() const
}
LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject());
- LayoutRect containerContentRect = containingBlock->layoutOverflowRect();
LayoutUnit maxContainerWidth = containingBlock->isLayoutView() ? containingBlock->logicalWidth() : containingBlock->containingBlockLogicalWidthForContent();
// Sticky positioned element ignore any override logical width on the containing block (as they don't call
// containingBlockLogicalWidthForContent). It's unclear whether this is totally fine.
// Compute the container-relative area within which the sticky element is allowed to move.
LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
+ // Map the containing block to the scroll ancestor without transforms.
+ FloatRect scrollContainerRelativePaddingBoxRect(containingBlock->layoutOverflowRect());
+ if (containingBlock != scrollAncestor) {
+ FloatQuad localQuad(FloatRect(containingBlock->paddingBoxRect()));
+ TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad);
+ containingBlock->mapLocalToAncestor(scrollAncestor, transformState, ApplyContainerFlip);
+ transformState.flatten();
+ scrollContainerRelativePaddingBoxRect = transformState.lastPlanarQuad().boundingBox();
+
+ // The sticky position constraint rects should be independent of the current scroll position, so after
+ // mapping we add in the scroll position to get the container's position within the ancestor scroller's
+ // unscrolled layout overflow.
+ FloatSize scrollOffset(scrollAncestor ? toFloatSize(scrollAncestor->getScrollableArea()->adjustedScrollOffset()) : FloatSize());
+ scrollContainerRelativePaddingBoxRect.move(scrollOffset);
+ }
+
+ LayoutRect scrollContainerRelativeContainingBlockRect(scrollContainerRelativePaddingBoxRect);
// This is removing the padding of the containing block's overflow rect to get the flow
// box rectangle and removing the margin of the sticky element to ensure that space between
// the sticky element and its containing flow box. It is an open issue whether the margin
// should collapse (See https://www.w3.org/TR/css-position-3/#sticky-pos).
- containerContentRect.contractEdges(
+ scrollContainerRelativeContainingBlockRect.contractEdges(
minimumValueForLength(containingBlock->style()->paddingTop(), maxContainerWidth) + minimumValueForLength(style()->marginTop(), maxWidth),
minimumValueForLength(containingBlock->style()->paddingRight(), maxContainerWidth) + minimumValueForLength(style()->marginRight(), maxWidth),
minimumValueForLength(containingBlock->style()->paddingBottom(), maxContainerWidth) + minimumValueForLength(style()->marginBottom(), maxWidth),
minimumValueForLength(containingBlock->style()->paddingLeft(), maxContainerWidth) + minimumValueForLength(style()->marginLeft(), maxWidth));
- // Map to the scroll ancestor.
- FloatRect scrollContainerRelativeContainingBlockRect(containingBlock->localToAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox());
- FloatSize scrollOffset(scrollAncestor ? toFloatSize(scrollAncestor->getScrollableArea()->adjustedScrollOffset()) : FloatSize());
-
- // The sticky position constraint rects should be independent of the current scroll position, so after
- // mapping we add in the scroll position to get the container's position within the ancestor scroller's
- // unscrolled layout overflow.
- if (containingBlock != scrollAncestor)
- scrollContainerRelativeContainingBlockRect.move(scrollOffset);
- constraints.setScrollContainerRelativeContainingBlockRect(scrollContainerRelativeContainingBlockRect);
+ constraints.setScrollContainerRelativeContainingBlockRect(FloatRect(scrollContainerRelativeContainingBlockRect));
FloatRect stickyBoxRect = isLayoutInline()
? FloatRect(toLayoutInline(this)->linesBoundingBox())
@@ -728,16 +736,13 @@ void LayoutBoxModelObject::updateStickyPositionConstraints() const
containingBlock->flipForWritingMode(flippedStickyBoxRect);
FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContainersOffset;
- // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms.
- // Map to the scroll ancestor.
- FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAncestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAncestor).boundingBox();
- // The sticky position constraint rects should be independent of the current scroll position, so after
- // mapping we add in the scroll position to get the container's position within the ancestor scroller's
- // unscrolled layout overflow.
- if (containingBlock != scrollAncestor)
- scrollContainerRelativeContainerFrame.move(scrollOffset);
-
- constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContainerRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyBoxRect.size()));
+ // The scrollContainerRelativePaddingBoxRect's position is the padding box so we need to remove the border when finding
+ // the position of the sticky box within the scroll ancestor if the container is not our scroll ancestor.
+ if (containingBlock != scrollAncestor) {
+ FloatSize containerBorderOffset(containingBlock->borderLeft(), containingBlock->borderTop());
+ stickyLocation -= containerBorderOffset;
+ }
+ constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContainerRelativePaddingBoxRect.location() + toFloatSize(stickyLocation), flippedStickyBoxRect.size()));
// We skip the right or top sticky offset if there is not enough space to honor both the left/right or top/bottom offsets.
LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), LayoutUnit(constrainingSize.width())) +
@@ -745,8 +750,8 @@ void LayoutBoxModelObject::updateStickyPositionConstraints() const
bool skipRight = false;
bool skipLeft = false;
if (!style()->left().isAuto() && !style()->right().isAuto()) {
- if (horizontalOffsets > containerContentRect.width()
- || horizontalOffsets + containerContentRect.width() > constrainingSize.width()) {
+ if (horizontalOffsets > scrollContainerRelativeContainingBlockRect.width()
+ || horizontalOffsets + scrollContainerRelativeContainingBlockRect.width() > constrainingSize.width()) {
skipRight = style()->isLeftToRightDirection();
skipLeft = !skipRight;
}
@@ -768,8 +773,8 @@ void LayoutBoxModelObject::updateStickyPositionConstraints() const
LayoutUnit verticalOffsets = minimumValueForLength(style()->top(), LayoutUnit(constrainingSize.height())) +
minimumValueForLength(style()->bottom(), LayoutUnit(constrainingSize.height()));
if (!style()->top().isAuto() && !style()->bottom().isAuto()) {
- if (verticalOffsets > containerContentRect.height()
- || verticalOffsets + containerContentRect.height() > constrainingSize.height()) {
+ if (verticalOffsets > scrollContainerRelativeContainingBlockRect.height()
+ || verticalOffsets + scrollContainerRelativeContainingBlockRect.height() > constrainingSize.height()) {
skipBottom = true;
}
}
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698