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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp

Issue 2020103002: Fix sticky constraints and update sticky layer positions recursively after scroll. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Simplify sticky box rect calculation. Created 4 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved. 7 * Copyright (C) 2010 Google Inc. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() 614 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
615 || !style()->bottom().hasPercent() 615 || !style()->bottom().hasPercent()
616 || containingBlock->stretchesToViewport())) 616 || containingBlock->stretchesToViewport()))
617 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight())); 617 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight()));
618 618
619 return offset; 619 return offset;
620 } 620 }
621 621
622 void LayoutBoxModelObject::updateStickyPositionConstraints() const 622 void LayoutBoxModelObject::updateStickyPositionConstraints() const
623 { 623 {
624 // TODO(flackr): This method is reasonably complicated and should have some direct unit testing.
625 const FloatSize constrainingSize = computeStickyConstrainingRect().size(); 624 const FloatSize constrainingSize = computeStickyConstrainingRect().size();
626 625
627 PaintLayerScrollableArea* scrollableArea = layer()->ancestorOverflowLayer()- >getScrollableArea(); 626 PaintLayerScrollableArea* scrollableArea = layer()->ancestorOverflowLayer()- >getScrollableArea();
628 StickyPositionScrollingConstraints constraints; 627 StickyPositionScrollingConstraints constraints;
629 FloatSize skippedContainersOffset; 628 FloatSize skippedContainersOffset;
630 LayoutBlock* containingBlock = this->containingBlock(); 629 LayoutBlock* containingBlock = this->containingBlock();
631 // Skip anonymous containing blocks. 630 // Skip anonymous containing blocks.
632 while (containingBlock->isAnonymous()) { 631 while (containingBlock->isAnonymous()) {
633 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location())); 632 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location()));
634 containingBlock = containingBlock->containingBlock(); 633 containingBlock = containingBlock->containingBlock();
635 } 634 }
636 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); 635 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject());
637 636
638 LayoutRect containerContentRect = containingBlock->contentBoxRect(); 637 LayoutRect containerContentRect = containingBlock->layoutOverflowRect();
639 LayoutUnit maxWidth = containingBlock->availableLogicalWidth(); 638 LayoutUnit maxContainerWidth = containingBlock->containingBlockLogicalWidthF orContent();
640
641 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call 639 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call
642 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine. 640 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine.
643 // Compute the container-relative area within which the sticky element is al lowed to move. 641 // Compute the container-relative area within which the sticky element is al lowed to move.
642 LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
643
644 // This is removing the padding of the containing block's overflow rect to g et the flow
645 // box rectangle and removing the margin of the sticky element to ensure tha t space between
646 // the sticky element and its containing flow box. It is an open issue wheth er the margin
647 // should collapse (See https://www.w3.org/TR/css-position-3/#sticky-pos).
644 containerContentRect.contractEdges( 648 containerContentRect.contractEdges(
645 minimumValueForLength(style()->marginTop(), maxWidth), 649 minimumValueForLength(containingBlock->style()->paddingTop(), maxContain erWidth) + minimumValueForLength(style()->marginTop(), maxWidth),
646 minimumValueForLength(style()->marginRight(), maxWidth), 650 minimumValueForLength(containingBlock->style()->paddingRight(), maxConta inerWidth) + minimumValueForLength(style()->marginRight(), maxWidth),
647 minimumValueForLength(style()->marginBottom(), maxWidth), 651 minimumValueForLength(containingBlock->style()->paddingBottom(), maxCont ainerWidth) + minimumValueForLength(style()->marginBottom(), maxWidth),
648 minimumValueForLength(style()->marginLeft(), maxWidth)); 652 minimumValueForLength(containingBlock->style()->paddingLeft(), maxContai nerWidth) + minimumValueForLength(style()->marginLeft(), maxWidth));
649 653
650 // Map to the scroll ancestor. 654 // Map to the scroll ancestor.
651 constraints.setScrollContainerRelativeContainingBlockRect(containingBlock->l ocalToAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox( )); 655 FloatRect scrollContainerRelativeContainingBlockRect(containingBlock->localT oAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox());
656 FloatSize scrollOffset(scrollAncestor ? toFloatSize(scrollAncestor->getScrol lableArea()->adjustedScrollOffset()) : FloatSize());
657
658 // The sticky position constraint rects should be independent of the current scroll position, so after
659 // mapping we add in the scroll position to get the container's position wit hin the ancestor scroller's
660 // unscrolled layout overflow.
661 if (containingBlock != scrollAncestor)
662 scrollContainerRelativeContainingBlockRect.move(scrollOffset);
663 constraints.setScrollContainerRelativeContainingBlockRect(scrollContainerRel ativeContainingBlockRect);
652 664
653 FloatRect stickyBoxRect = isLayoutInline() 665 FloatRect stickyBoxRect = isLayoutInline()
654 ? FloatRect(toLayoutInline(this)->linesBoundingBox()) 666 ? FloatRect(toLayoutInline(this)->linesBoundingBox())
655 : FloatRect(toLayoutBox(this)->frameRect()); 667 : FloatRect(toLayoutBox(this)->frameRect());
656 FloatRect flippedStickyBoxRect = stickyBoxRect; 668 FloatRect flippedStickyBoxRect = stickyBoxRect;
657 containingBlock->flipForWritingMode(flippedStickyBoxRect); 669 containingBlock->flipForWritingMode(flippedStickyBoxRect);
658 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset; 670 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset;
659 671
660 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms. 672 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms.
661 // Map to the scroll ancestor. 673 // Map to the scroll ancestor.
662 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox(); 674 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox();
663 675 // The sticky position constraint rects should be independent of the current scroll position, so after
664 // If the containing block is our scroll ancestor, its location will not inc lude the scroll offset which we need to include as 676 // mapping we add in the scroll position to get the container's position wit hin the ancestor scroller's
665 // part of the sticky box rect so we include it here. 677 // unscrolled layout overflow.
666 if (containingBlock->hasOverflowClip()) { 678 if (containingBlock != scrollAncestor)
667 FloatSize scrollOffset(toFloatSize(containingBlock->layer()->getScrollab leArea()->adjustedScrollOffset())); 679 scrollContainerRelativeContainerFrame.move(scrollOffset);
668 stickyLocation -= scrollOffset;
669 }
670 680
671 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size())); 681 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size()));
672 682
673 // We skip the right or top sticky offset if there is not enough space to ho nor both the left/right or top/bottom offsets. 683 // We skip the right or top sticky offset if there is not enough space to ho nor both the left/right or top/bottom offsets.
674 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) + 684 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) +
675 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ())); 685 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ()));
676 bool skipRight = false; 686 bool skipRight = false;
677 bool skipLeft = false; 687 bool skipLeft = false;
678 if (!style()->left().isAuto() && !style()->right().isAuto()) { 688 if (!style()->left().isAuto() && !style()->right().isAuto()) {
679 if (horizontalOffsets > containerContentRect.width() 689 if (horizontalOffsets > containerContentRect.width()
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 scrollableArea->stickyConstraintsMap().set(layer(), constraints); 727 scrollableArea->stickyConstraintsMap().set(layer(), constraints);
718 } 728 }
719 729
720 FloatRect LayoutBoxModelObject::computeStickyConstrainingRect() const 730 FloatRect LayoutBoxModelObject::computeStickyConstrainingRect() const
721 { 731 {
722 if (layer()->ancestorOverflowLayer()->isRootLayer()) 732 if (layer()->ancestorOverflowLayer()->isRootLayer())
723 return view()->frameView()->visibleContentRect(); 733 return view()->frameView()->visibleContentRect();
724 734
725 LayoutBox* enclosingClippingBox = toLayoutBox(layer()->ancestorOverflowLayer ()->layoutObject()); 735 LayoutBox* enclosingClippingBox = toLayoutBox(layer()->ancestorOverflowLayer ()->layoutObject());
726 FloatRect constrainingRect; 736 FloatRect constrainingRect;
727 constrainingRect = FloatRect(enclosingClippingBox->overflowClipRect(LayoutPo int())); 737 constrainingRect = FloatRect(enclosingClippingBox->overflowClipRect(LayoutPo int(DoublePoint(enclosingClippingBox->getScrollableArea()->adjustedScrollOffset( )))));
728 constrainingRect.move(enclosingClippingBox->paddingLeft(), enclosingClipping Box->paddingTop()); 738 constrainingRect.move(enclosingClippingBox->paddingLeft(), enclosingClipping Box->paddingTop());
729 constrainingRect.contract(FloatSize(enclosingClippingBox->paddingLeft() + en closingClippingBox->paddingRight(), 739 constrainingRect.contract(FloatSize(enclosingClippingBox->paddingLeft() + en closingClippingBox->paddingRight(),
730 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom ())); 740 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom ()));
731 return constrainingRect; 741 return constrainingRect;
732 } 742 }
733 743
734 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const 744 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const
735 { 745 {
736 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer(); 746 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer();
737 // TODO: Force compositing input update if we ask for offset before composit ing inputs have been computed? 747 // TODO: Force compositing input update if we ask for offset before composit ing inputs have been computed?
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 if (rootElementStyle->hasBackground()) 1125 if (rootElementStyle->hasBackground())
1116 return false; 1126 return false;
1117 1127
1118 if (node() != document().firstBodyElement()) 1128 if (node() != document().firstBodyElement())
1119 return false; 1129 return false;
1120 1130
1121 return true; 1131 return true;
1122 } 1132 }
1123 1133
1124 } // namespace blink 1134 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/frame/FrameView.cpp ('k') | third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698