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

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: Merge with master and add comment explaining container content rect. Created 4 years, 6 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 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() 625 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
626 || !style()->bottom().hasPercent() 626 || !style()->bottom().hasPercent()
627 || containingBlock->stretchesToViewport())) 627 || containingBlock->stretchesToViewport()))
628 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight())); 628 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight()));
629 629
630 return offset; 630 return offset;
631 } 631 }
632 632
633 void LayoutBoxModelObject::updateStickyPositionConstraints() const 633 void LayoutBoxModelObject::updateStickyPositionConstraints() const
634 { 634 {
635 // TODO(flackr): This method is reasonably complicated and should have some direct unit testing.
636 const FloatSize constrainingSize = computeStickyConstrainingRect().size(); 635 const FloatSize constrainingSize = computeStickyConstrainingRect().size();
637 636
638 PaintLayerScrollableArea* scrollableArea = layer()->ancestorOverflowLayer()- >getScrollableArea(); 637 PaintLayerScrollableArea* scrollableArea = layer()->ancestorOverflowLayer()- >getScrollableArea();
639 StickyPositionScrollingConstraints constraints; 638 StickyPositionScrollingConstraints constraints;
640 FloatSize skippedContainersOffset; 639 FloatSize skippedContainersOffset;
641 LayoutBlock* containingBlock = this->containingBlock(); 640 LayoutBlock* containingBlock = this->containingBlock();
642 // Skip anonymous containing blocks. 641 // Skip anonymous containing blocks.
643 while (containingBlock->isAnonymous()) { 642 while (containingBlock->isAnonymous()) {
644 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location())); 643 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location()));
645 containingBlock = containingBlock->containingBlock(); 644 containingBlock = containingBlock->containingBlock();
646 } 645 }
647 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); 646 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject());
648 647
649 LayoutRect containerContentRect = containingBlock->contentBoxRect(); 648 LayoutRect containerContentRect = containingBlock->layoutOverflowRect();
650 LayoutUnit maxWidth = containingBlock->availableLogicalWidth(); 649 LayoutUnit maxContainerWidth = containingBlock->containingBlockLogicalWidthF orContent();
651
652 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call 650 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call
653 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine. 651 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine.
654 // Compute the container-relative area within which the sticky element is al lowed to move. 652 // Compute the container-relative area within which the sticky element is al lowed to move.
653 LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
654
655 // This is removing the padding of the containing block's overflow rect to g et the flow
656 // box rectangle and removing the margin of the sticky element to ensure tha t space between
657 // the sticky element and its containing flow box. It is an open issue wheth er the margin
658 // should collapse (See https://www.w3.org/TR/css-position-3/#sticky-pos).
655 containerContentRect.contractEdges( 659 containerContentRect.contractEdges(
656 minimumValueForLength(style()->marginTop(), maxWidth), 660 minimumValueForLength(containingBlock->style()->paddingTop(), maxContain erWidth) + minimumValueForLength(style()->marginTop(), maxWidth),
657 minimumValueForLength(style()->marginRight(), maxWidth), 661 minimumValueForLength(containingBlock->style()->paddingRight(), maxConta inerWidth) + minimumValueForLength(style()->marginRight(), maxWidth),
658 minimumValueForLength(style()->marginBottom(), maxWidth), 662 minimumValueForLength(containingBlock->style()->paddingBottom(), maxCont ainerWidth) + minimumValueForLength(style()->marginBottom(), maxWidth),
659 minimumValueForLength(style()->marginLeft(), maxWidth)); 663 minimumValueForLength(containingBlock->style()->paddingLeft(), maxContai nerWidth) + minimumValueForLength(style()->marginLeft(), maxWidth));
660 664
661 // Map to the scroll ancestor. 665 // Map to the scroll ancestor.
662 constraints.setScrollContainerRelativeContainingBlockRect(containingBlock->l ocalToAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox( )); 666 FloatRect scrollContainerRelativeContainingBlockRect(containingBlock->localT oAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox());
667 FloatSize scrollOffset(scrollAncestor ? toFloatSize(scrollAncestor->getScrol lableArea()->adjustedScrollOffset()) : FloatSize());
668
669 // Include scroll offset in container position if the container is not our s croll ancestor.
670 if (containingBlock != scrollAncestor)
chrishtr 2016/06/16 11:03:59 If containingBlock == scrollAncestor, scrollContai
flackr 2016/06/29 13:21:06 Correct.
671 scrollContainerRelativeContainingBlockRect.move(scrollOffset);
672 constraints.setScrollContainerRelativeContainingBlockRect(scrollContainerRel ativeContainingBlockRect);
663 673
664 FloatRect stickyBoxRect = isLayoutInline() 674 FloatRect stickyBoxRect = isLayoutInline()
665 ? FloatRect(toLayoutInline(this)->linesBoundingBox()) 675 ? FloatRect(toLayoutInline(this)->linesBoundingBox())
666 : FloatRect(toLayoutBox(this)->frameRect()); 676 : FloatRect(toLayoutBox(this)->frameRect());
667 FloatRect flippedStickyBoxRect = stickyBoxRect; 677 FloatRect flippedStickyBoxRect = stickyBoxRect;
668 containingBlock->flipForWritingMode(flippedStickyBoxRect); 678 containingBlock->flipForWritingMode(flippedStickyBoxRect);
669 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset; 679 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset;
670 680
671 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms. 681 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms.
672 // Map to the scroll ancestor. 682 // Map to the scroll ancestor.
673 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox(); 683 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox();
684 scrollContainerRelativeContainerFrame.move(scrollOffset);
674 685
675 // If the containing block is our scroll ancestor, its location will not inc lude the scroll offset which we need to include as 686 // If the containing block is our scroll ancestor, its location will not inc lude the scroll offset which we need to include as
676 // part of the sticky box rect so we include it here. 687 // part of the sticky box rect so we include it here.
677 if (containingBlock->hasOverflowClip()) { 688 if (containingBlock == scrollAncestor)
678 FloatSize scrollOffset(toFloatSize(containingBlock->layer()->getScrollab leArea()->adjustedScrollOffset()));
679 stickyLocation -= scrollOffset; 689 stickyLocation -= scrollOffset;
680 }
681 690
682 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size())); 691 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size()));
683 692
684 // 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. 693 // 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.
685 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) + 694 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) +
686 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ())); 695 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ()));
687 bool skipRight = false; 696 bool skipRight = false;
688 bool skipLeft = false; 697 bool skipLeft = false;
689 if (!style()->left().isAuto() && !style()->right().isAuto()) { 698 if (!style()->left().isAuto() && !style()->right().isAuto()) {
690 if (horizontalOffsets > containerContentRect.width() 699 if (horizontalOffsets > containerContentRect.width()
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 scrollableArea->stickyConstraintsMap().set(layer(), constraints); 737 scrollableArea->stickyConstraintsMap().set(layer(), constraints);
729 } 738 }
730 739
731 FloatRect LayoutBoxModelObject::computeStickyConstrainingRect() const 740 FloatRect LayoutBoxModelObject::computeStickyConstrainingRect() const
732 { 741 {
733 if (layer()->ancestorOverflowLayer()->isRootLayer()) 742 if (layer()->ancestorOverflowLayer()->isRootLayer())
734 return view()->frameView()->visibleContentRect(); 743 return view()->frameView()->visibleContentRect();
735 744
736 LayoutBox* enclosingClippingBox = toLayoutBox(layer()->ancestorOverflowLayer ()->layoutObject()); 745 LayoutBox* enclosingClippingBox = toLayoutBox(layer()->ancestorOverflowLayer ()->layoutObject());
737 FloatRect constrainingRect; 746 FloatRect constrainingRect;
738 constrainingRect = FloatRect(enclosingClippingBox->overflowClipRect(LayoutPo int())); 747 constrainingRect = FloatRect(enclosingClippingBox->overflowClipRect(LayoutPo int(DoublePoint(enclosingClippingBox->getScrollableArea()->adjustedScrollOffset( )))));
739 constrainingRect.move(enclosingClippingBox->paddingLeft(), enclosingClipping Box->paddingTop()); 748 constrainingRect.move(enclosingClippingBox->paddingLeft(), enclosingClipping Box->paddingTop());
740 constrainingRect.contract(FloatSize(enclosingClippingBox->paddingLeft() + en closingClippingBox->paddingRight(), 749 constrainingRect.contract(FloatSize(enclosingClippingBox->paddingLeft() + en closingClippingBox->paddingRight(),
741 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom ())); 750 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom ()));
742 return constrainingRect; 751 return constrainingRect;
743 } 752 }
744 753
745 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const 754 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const
746 { 755 {
747 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer(); 756 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer();
748 // TODO: Force compositing input update if we ask for offset before composit ing inputs have been computed? 757 // 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
1126 if (rootElementStyle->hasBackground()) 1135 if (rootElementStyle->hasBackground())
1127 return false; 1136 return false;
1128 1137
1129 if (node() != document().firstBodyElement()) 1138 if (node() != document().firstBodyElement())
1130 return false; 1139 return false;
1131 1140
1132 return true; 1141 return true;
1133 } 1142 }
1134 1143
1135 } // namespace blink 1144 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698