| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |