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

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

Issue 1850703002: Revert "Adapt and reland old position sticky implementation from https://codereview.chromium.org/34… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 bool newStoleBodyBackground = toLayoutBoxModelObject(bodyLayout)->ba ckgroundStolenForBeingBody(style()); 275 bool newStoleBodyBackground = toLayoutBoxModelObject(bodyLayout)->ba ckgroundStolenForBeingBody(style());
276 bool oldStoleBodyBackground = oldStyle && toLayoutBoxModelObject(bod yLayout)->backgroundStolenForBeingBody(oldStyle); 276 bool oldStoleBodyBackground = oldStyle && toLayoutBoxModelObject(bod yLayout)->backgroundStolenForBeingBody(oldStyle);
277 if (newStoleBodyBackground != oldStoleBodyBackground 277 if (newStoleBodyBackground != oldStoleBodyBackground
278 && bodyLayout->style() && bodyLayout->style()->hasBackground()) { 278 && bodyLayout->style() && bodyLayout->style()->hasBackground()) {
279 bodyLayout->setShouldDoFullPaintInvalidation(); 279 bodyLayout->setShouldDoFullPaintInvalidation();
280 } 280 }
281 } 281 }
282 } 282 }
283 283
284 if (FrameView *frameView = view()->frameView()) { 284 if (FrameView *frameView = view()->frameView()) {
285 bool newStyleIsViewportConstained = style()->position() == FixedPosition ; 285 bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosit ion();
286 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->position() == FixedPosition; 286 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportCo nstrainedPosition();
287 bool newStyleIsSticky = style()->position() == StickyPosition;
288 bool oldStyleIsSticky = oldStyle && oldStyle->position() == StickyPositi on;
289
290 if (newStyleIsSticky != oldStyleIsSticky) {
291 if (newStyleIsSticky) {
292 frameView->addStickyPositionObject();
293 // During compositing inputs update we'll have the scroll
294 // ancestor without having to walk up the tree and can compute
295 // the sticky position constraints then.
296 if (layer())
297 layer()->setNeedsCompositingInputsUpdate();
298 } else {
299 // This may get re-added to viewport constrained objects if the object went
300 // from sticky to fixed.
301 frameView->removeViewportConstrainedObject(this);
302 frameView->removeStickyPositionObject();
303
304 // Remove sticky constraints for this layer.
305 if (layer()) {
306 DisableCompositingQueryAsserts disabler;
307 if (const PaintLayer* ancestorOverflowLayer = layer()->ances torOverflowLayer())
308 ancestorOverflowLayer->getScrollableArea()->invalidateSt ickyConstraintsFor(layer());
309 }
310 }
311 }
312
313 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { 287 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
314 if (newStyleIsViewportConstained && layer()) 288 if (newStyleIsViewportConstained && layer())
315 frameView->addViewportConstrainedObject(this); 289 frameView->addViewportConstrainedObject(this);
316 else 290 else
317 frameView->removeViewportConstrainedObject(this); 291 frameView->removeViewportConstrainedObject(this);
318 } 292 }
319 } 293 }
320 } 294 }
321 295
322 void LayoutBoxModelObject::invalidateStickyConstraints()
323 {
324 if (!layer())
325 return;
326
327 // This intentionally uses the stale ancestor overflow layer compositing
328 // input as if we have saved constraints for this layer they were saved
329 // in the previous frame.
330 DisableCompositingQueryAsserts disabler;
331 if (const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer ())
332 ancestorOverflowLayer->getScrollableArea()->invalidateAllStickyConstrain ts();
333 }
334
335 void LayoutBoxModelObject::createLayer(PaintLayerType type) 296 void LayoutBoxModelObject::createLayer(PaintLayerType type)
336 { 297 {
337 // If the current paint invalidation container is not a stacking context and this object is 298 // If the current paint invalidation container is not a stacking context and this object is
338 // stacked content, creating this layer may cause this object and its 299 // stacked content, creating this layer may cause this object and its
339 // descendants to change paint invalidation container. Therefore we must eag erly invalidate 300 // descendants to change paint invalidation container. Therefore we must eag erly invalidate
340 // them on the original paint invalidation container before creating the lay er. 301 // them on the original paint invalidation container before creating the lay er.
341 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && isRooted() && style Ref().isStacked()) { 302 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && isRooted() && style Ref().isStacked()) {
342 const LayoutBoxModelObject& currentPaintInvalidationContainer = containe rForPaintInvalidation(); 303 const LayoutBoxModelObject& currentPaintInvalidationContainer = containe rForPaintInvalidation();
343 if (!currentPaintInvalidationContainer.styleRef().isStackingContext()) 304 if (!currentPaintInvalidationContainer.styleRef().isStackingContext())
344 invalidatePaintIncludingNonSelfPaintingLayerDescendants(currentPaint InvalidationContainer); 305 invalidatePaintIncludingNonSelfPaintingLayerDescendants(currentPaint InvalidationContainer);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 605
645 else if (!style()->bottom().isAuto() 606 else if (!style()->bottom().isAuto()
646 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() 607 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
647 || !style()->bottom().hasPercent() 608 || !style()->bottom().hasPercent()
648 || containingBlock->stretchesToViewport())) 609 || containingBlock->stretchesToViewport()))
649 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight())); 610 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight()));
650 611
651 return offset; 612 return offset;
652 } 613 }
653 614
654 void LayoutBoxModelObject::updateStickyPositionConstraints() const
655 {
656 // TODO(flackr): This method is reasonably complicated and should have some direct unit testing.
657 const FloatSize constrainingSize = computeStickyConstrainingRect().size();
658
659 PaintLayerScrollableArea* scrollableArea = layer()->ancestorOverflowLayer()- >getScrollableArea();
660 StickyPositionScrollingConstraints constraints;
661 FloatSize skippedContainersOffset;
662 LayoutBlock* containingBlock = this->containingBlock();
663 // Skip anonymous containing blocks.
664 while (containingBlock->isAnonymous()) {
665 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location()));
666 containingBlock = containingBlock->containingBlock();
667 }
668 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject());
669
670 LayoutRect containerContentRect = containingBlock->contentBoxRect();
671 LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
672
673 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call
674 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine.
675 // Compute the container-relative area within which the sticky element is al lowed to move.
676 containerContentRect.contractEdges(
677 minimumValueForLength(style()->marginTop(), maxWidth),
678 minimumValueForLength(style()->marginRight(), maxWidth),
679 minimumValueForLength(style()->marginBottom(), maxWidth),
680 minimumValueForLength(style()->marginLeft(), maxWidth));
681
682 // Map to the scroll ancestor.
683 constraints.setScrollContainerRelativeContainingBlockRect(containingBlock->l ocalToAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox( ));
684
685 FloatRect stickyBoxRect = isLayoutInline()
686 ? FloatRect(toLayoutInline(this)->linesBoundingBox())
687 : FloatRect(toLayoutBox(this)->frameRect());
688 FloatRect flippedStickyBoxRect = stickyBoxRect;
689 containingBlock->flipForWritingMode(flippedStickyBoxRect);
690 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset;
691
692 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms.
693 // Map to the scroll ancestor.
694 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox();
695
696 // If the containing block is our scroll ancestor, its location will not inc lude the scroll offset which we need to include as
697 // part of the sticky box rect so we include it here.
698 if (containingBlock->hasOverflowClip()) {
699 FloatSize scrollOffset(toFloatSize(containingBlock->layer()->getScrollab leArea()->adjustedScrollOffset()));
700 stickyLocation -= scrollOffset;
701 }
702
703 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size()));
704
705 // 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.
706 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) +
707 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ()));
708 bool skipRight = false;
709 bool skipLeft = false;
710 if (!style()->left().isAuto() && !style()->right().isAuto()) {
711 if (horizontalOffsets > containerContentRect.width()
712 || horizontalOffsets + containerContentRect.width() > constrainingSi ze.width()) {
713 skipRight = style()->isLeftToRightDirection();
714 skipLeft = !skipRight;
715 }
716 }
717
718 if (!style()->left().isAuto() && !skipLeft) {
719 constraints.setLeftOffset(minimumValueForLength(style()->left(), LayoutU nit(constrainingSize.width())));
720 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Left);
721 }
722
723 if (!style()->right().isAuto() && !skipRight) {
724 constraints.setRightOffset(minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())));
725 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Right);
726 }
727
728 bool skipBottom = false;
729 // TODO(flackr): Exclude top or bottom edge offset depending on the writing mode when related
730 // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style /2014May/0286.html
731 LayoutUnit verticalOffsets = minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())) +
732 minimumValueForLength(style()->bottom(), LayoutUnit(constrainingSize.hei ght()));
733 if (!style()->top().isAuto() && !style()->bottom().isAuto()) {
734 if (verticalOffsets > containerContentRect.height()
735 || verticalOffsets + containerContentRect.height() > constrainingSiz e.height()) {
736 skipBottom = true;
737 }
738 }
739
740 if (!style()->top().isAuto()) {
741 constraints.setTopOffset(minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())));
742 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Top);
743 }
744
745 if (!style()->bottom().isAuto() && !skipBottom) {
746 constraints.setBottomOffset(minimumValueForLength(style()->bottom(), Lay outUnit(constrainingSize.height())));
747 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Bottom);
748 }
749 scrollableArea->stickyConstraintsMap().set(layer(), constraints);
750 }
751
752 FloatRect LayoutBoxModelObject::computeStickyConstrainingRect() const
753 {
754 if (layer()->ancestorOverflowLayer()->isRootLayer())
755 return view()->frameView()->visibleContentRect();
756
757 LayoutBox* enclosingClippingBox = toLayoutBox(layer()->ancestorOverflowLayer ()->layoutObject());
758 FloatRect constrainingRect;
759 constrainingRect = FloatRect(enclosingClippingBox->overflowClipRect(LayoutPo int()));
760 constrainingRect.move(enclosingClippingBox->paddingLeft(), enclosingClipping Box->paddingTop());
761 constrainingRect.contract(FloatSize(enclosingClippingBox->paddingLeft() + en closingClippingBox->paddingRight(),
762 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom ()));
763 return constrainingRect;
764 }
765
766 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const
767 {
768 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer();
769 // TODO: Force compositing input update if we ask for offset before composit ing inputs have been computed?
770 if (!ancestorOverflowLayer)
771 return LayoutSize();
772 FloatRect constrainingRect = computeStickyConstrainingRect();
773 PaintLayerScrollableArea* scrollableArea = ancestorOverflowLayer->getScrolla bleArea();
774
775 // The sticky offset is physical, so we can just return the delta computed i n absolute coords (though it may be wrong with transforms).
776 // TODO: Force compositing input update if we ask for offset with stale comp ositing inputs.
777 if (!scrollableArea->stickyConstraintsMap().contains(layer()))
778 return LayoutSize();
779 return LayoutSize(scrollableArea->stickyConstraintsMap().get(layer()).comput eStickyOffset(constrainingRect));
780 }
781
782 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeToOffsetParent(const L ayoutPoint& startPoint) const 615 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeToOffsetParent(const L ayoutPoint& startPoint) const
783 { 616 {
784 // If the element is the HTML body element or doesn't have a parent 617 // If the element is the HTML body element or doesn't have a parent
785 // return 0 and stop this algorithm. 618 // return 0 and stop this algorithm.
786 if (isBody() || !parent()) 619 if (isBody() || !parent())
787 return LayoutPoint(); 620 return LayoutPoint();
788 621
789 LayoutPoint referencePoint = startPoint; 622 LayoutPoint referencePoint = startPoint;
790 referencePoint.move(parent()->columnOffset(referencePoint)); 623 referencePoint.move(parent()->columnOffset(referencePoint));
791 624
792 // If the offsetParent of the element is null, or is the HTML body element, 625 // If the offsetParent of the element is null, or is the HTML body element,
793 // return the distance between the canvas origin and the left border edge 626 // return the distance between the canvas origin and the left border edge
794 // of the element and stop this algorithm. 627 // of the element and stop this algorithm.
795 Element* element = offsetParent(); 628 Element* element = offsetParent();
796 if (!element) 629 if (!element)
797 return referencePoint; 630 return referencePoint;
798 631
799 if (const LayoutBoxModelObject* offsetParent = element->layoutBoxModelObject ()) { 632 if (const LayoutBoxModelObject* offsetParent = element->layoutBoxModelObject ()) {
800 if (offsetParent->isBox() && !offsetParent->isBody()) 633 if (offsetParent->isBox() && !offsetParent->isBody())
801 referencePoint.move(-toLayoutBox(offsetParent)->borderLeft(), -toLay outBox(offsetParent)->borderTop()); 634 referencePoint.move(-toLayoutBox(offsetParent)->borderLeft(), -toLay outBox(offsetParent)->borderTop());
802 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { 635 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) {
803 if (isInFlowPositioned()) 636 if (isInFlowPositioned())
804 referencePoint.move(offsetForInFlowPosition()); 637 referencePoint.move(relativePositionOffset());
805 638
806 LayoutObject* current; 639 LayoutObject* current;
807 for (current = parent(); current != offsetParent && current->parent( ); current = current->parent()) { 640 for (current = parent(); current != offsetParent && current->parent( ); current = current->parent()) {
808 // FIXME: What are we supposed to do inside SVG content? 641 // FIXME: What are we supposed to do inside SVG content?
809 if (!isOutOfFlowPositioned()) { 642 if (!isOutOfFlowPositioned()) {
810 if (current->isBox() && !current->isTableRow()) 643 if (current->isBox() && !current->isTableRow())
811 referencePoint.moveBy(toLayoutBox(current)->topLeftLocat ion()); 644 referencePoint.moveBy(toLayoutBox(current)->topLeftLocat ion());
812 referencePoint.move(current->parent()->columnOffset(referenc ePoint)); 645 referencePoint.move(current->parent()->columnOffset(referenc ePoint));
813 } 646 }
814 } 647 }
815 648
816 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent ->isPositioned()) 649 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent ->isPositioned())
817 referencePoint.moveBy(toLayoutBox(offsetParent)->topLeftLocation ()); 650 referencePoint.moveBy(toLayoutBox(offsetParent)->topLeftLocation ());
818 } 651 }
819 } 652 }
820 653
821 return referencePoint; 654 return referencePoint;
822 } 655 }
823 656
824 LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const 657 LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const
825 { 658 {
826 if (isRelPositioned()) 659 return isRelPositioned() ? relativePositionOffset() : LayoutSize();
827 return relativePositionOffset();
828
829 if (isStickyPositioned())
830 return stickyPositionOffset();
831
832 return LayoutSize();
833 } 660 }
834 661
835 LayoutUnit LayoutBoxModelObject::offsetLeft() const 662 LayoutUnit LayoutBoxModelObject::offsetLeft() const
836 { 663 {
837 // Note that LayoutInline and LayoutBox override this to pass a different 664 // Note that LayoutInline and LayoutBox override this to pass a different
838 // startPoint to adjustedPositionRelativeToOffsetParent. 665 // startPoint to adjustedPositionRelativeToOffsetParent.
839 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); 666 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x();
840 } 667 }
841 668
842 LayoutUnit LayoutBoxModelObject::offsetTop() const 669 LayoutUnit LayoutBoxModelObject::offsetTop() const
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 if (offsetDependsOnPoint) 888 if (offsetDependsOnPoint)
1062 flags |= IsNonUniform; 889 flags |= IsNonUniform;
1063 if (isFixedPos) 890 if (isFixedPos)
1064 flags |= IsFixedPosition; 891 flags |= IsFixedPosition;
1065 if (hasTransform) 892 if (hasTransform)
1066 flags |= HasTransform; 893 flags |= HasTransform;
1067 if (shouldUseTransformFromContainer(container)) { 894 if (shouldUseTransformFromContainer(container)) {
1068 TransformationMatrix t; 895 TransformationMatrix t;
1069 getTransformFromContainer(container, containerOffset, t); 896 getTransformFromContainer(container, containerOffset, t);
1070 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustm entForSkippedAncestor.height().toFloat()); 897 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustm entForSkippedAncestor.height().toFloat());
1071 geometryMap.push(this, t, flags, LayoutSize()); 898 geometryMap.push(this, t, flags);
1072 } else { 899 } else {
1073 containerOffset += adjustmentForSkippedAncestor; 900 containerOffset += adjustmentForSkippedAncestor;
1074 geometryMap.push(this, containerOffset, flags, LayoutSize()); 901 geometryMap.push(this, containerOffset, flags);
1075 } 902 }
1076 903
1077 return ancestorSkipped ? ancestorToStopAt : container; 904 return ancestorSkipped ? ancestorToStopAt : container;
1078 } 905 }
1079 906
1080 void LayoutBoxModelObject::moveChildTo(LayoutBoxModelObject* toBoxModelObject, L ayoutObject* child, LayoutObject* beforeChild, bool fullRemoveInsert) 907 void LayoutBoxModelObject::moveChildTo(LayoutBoxModelObject* toBoxModelObject, L ayoutObject* child, LayoutObject* beforeChild, bool fullRemoveInsert)
1081 { 908 {
1082 // We assume that callers have cleared their positioned objects list for chi ld moves (!fullRemoveInsert) so the 909 // We assume that callers have cleared their positioned objects list for chi ld moves (!fullRemoveInsert) so the
1083 // positioned layoutObject maps don't become stale. It would be too slow to do the map lookup on each call. 910 // positioned layoutObject maps don't become stale. It would be too slow to do the map lookup on each call.
1084 ASSERT(!fullRemoveInsert || !isLayoutBlock() || !toLayoutBlock(this)->hasPos itionedObjects()); 911 ASSERT(!fullRemoveInsert || !isLayoutBlock() || !toLayoutBlock(this)->hasPos itionedObjects());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 if (rootElementStyle->hasBackground()) 973 if (rootElementStyle->hasBackground())
1147 return false; 974 return false;
1148 975
1149 if (node() != document().firstBodyElement()) 976 if (node() != document().firstBodyElement())
1150 return false; 977 return false;
1151 978
1152 return true; 979 return true;
1153 } 980 }
1154 981
1155 } // namespace blink 982 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698