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

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

Issue 2636253002: Handle nested position:sticky elements (Closed)
Patch Set: Remove accidental leftover whitespace Created 3 years, 10 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 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 FloatSize skippedContainersOffset; 780 FloatSize skippedContainersOffset;
781 LayoutBlock* containingBlock = this->containingBlock(); 781 LayoutBlock* containingBlock = this->containingBlock();
782 // The location container for boxes is not always the containing block. 782 // The location container for boxes is not always the containing block.
783 LayoutBox* locationContainer = isLayoutInline() 783 LayoutBox* locationContainer = isLayoutInline()
784 ? containingBlock 784 ? containingBlock
785 : toLayoutBox(this)->locationContainer(); 785 : toLayoutBox(this)->locationContainer();
786 // Skip anonymous containing blocks. 786 // Skip anonymous containing blocks.
787 while (containingBlock->isAnonymous()) { 787 while (containingBlock->isAnonymous()) {
788 containingBlock = containingBlock->containingBlock(); 788 containingBlock = containingBlock->containingBlock();
789 } 789 }
790 MapCoordinatesFlags flags = 0; 790 MapCoordinatesFlags flags = IgnoreSticky;
791 skippedContainersOffset = 791 skippedContainersOffset =
792 toFloatSize(locationContainer 792 toFloatSize(locationContainer
793 ->localToAncestorQuadWithoutTransforms( 793 ->localToAncestorQuadWithoutTransforms(
794 FloatQuad(), containingBlock, flags) 794 FloatQuad(), containingBlock, flags)
795 .boundingBox() 795 .boundingBox()
796 .location()); 796 .location());
797 LayoutBox* scrollAncestor = 797 LayoutBox* scrollAncestor =
798 layer()->ancestorOverflowLayer()->isRootLayer() 798 layer()->ancestorOverflowLayer()->isRootLayer()
799 ? nullptr 799 ? nullptr
800 : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); 800 : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 // the container is our scroll ancestor, we also need to remove the border 878 // the container is our scroll ancestor, we also need to remove the border
879 // box because we want the position from within the scroller border. 879 // box because we want the position from within the scroller border.
880 FloatSize containerBorderOffset(containingBlock->borderLeft(), 880 FloatSize containerBorderOffset(containingBlock->borderLeft(),
881 containingBlock->borderTop()); 881 containingBlock->borderTop());
882 stickyLocation -= containerBorderOffset; 882 stickyLocation -= containerBorderOffset;
883 constraints.setScrollContainerRelativeStickyBoxRect( 883 constraints.setScrollContainerRelativeStickyBoxRect(
884 FloatRect(scrollContainerRelativePaddingBoxRect.location() + 884 FloatRect(scrollContainerRelativePaddingBoxRect.location() +
885 toFloatSize(stickyLocation), 885 toFloatSize(stickyLocation),
886 flippedStickyBoxRect.size())); 886 flippedStickyBoxRect.size()));
887 887
888 // To correctly compute the offsets, the constraints need to know about any
889 // nested position:sticky between themselves and their containingBlock, and
890 // between the containingBlock and their scrollAncestor.
891 //
892 // The respective search ranges are [container, containingBlock) and
893 // [containingBlock, scrollAncestor).
894
895 // TODO(smcgruer): Fold these into the walks to find the containingBlock and
896 // scrollAncestor.
897 LayoutObject* maybeStickyAncestor = locationContainer;
898 while (maybeStickyAncestor && maybeStickyAncestor != containingBlock) {
899 if (maybeStickyAncestor->isStickyPositioned()) {
900 constraints.setNearestStickyElementShiftingStickyBox(
901 toLayoutBoxModelObject(maybeStickyAncestor));
902 break;
903 }
904 maybeStickyAncestor =
905 maybeStickyAncestor->isLayoutInline()
906 ? maybeStickyAncestor->containingBlock()
907 : toLayoutBox(maybeStickyAncestor)->locationContainer();
908 }
flackr 2017/01/31 18:33:00 Create a function for this common loop code, maybe
smcgruer 2017/01/31 20:42:16 I was intended to look at folding these into the w
flackr 2017/02/02 18:18:11 Yes, we should just clean it up with a helper func
909
910 // NOTE(smcgruer): We cannot use |scrollAncestor| here as it disregards the
911 // root ancestorOverflowLayer(), which we should include for the purposes of
912 // finding the nearest sticky element that shifts the containing block rect.
913 LayoutObject* ancestorOverflowLayer =
914 layer()->ancestorOverflowLayer()->layoutObject();
915 maybeStickyAncestor = containingBlock;
916 while (maybeStickyAncestor && maybeStickyAncestor != ancestorOverflowLayer) {
917 if (maybeStickyAncestor->isStickyPositioned()) {
918 constraints.setNearestStickyElementShiftingContainingBlock(
919 toLayoutBoxModelObject(maybeStickyAncestor));
920 break;
921 }
922 maybeStickyAncestor =
923 maybeStickyAncestor->isLayoutInline()
924 ? maybeStickyAncestor->containingBlock()
925 : toLayoutBox(maybeStickyAncestor)->locationContainer();
926 }
927
888 // We skip the right or top sticky offset if there is not enough space to 928 // We skip the right or top sticky offset if there is not enough space to
889 // honor both the left/right or top/bottom offsets. 929 // honor both the left/right or top/bottom offsets.
890 LayoutUnit horizontalOffsets = 930 LayoutUnit horizontalOffsets =
891 minimumValueForLength(style()->right(), 931 minimumValueForLength(style()->right(),
892 LayoutUnit(constrainingSize.width())) + 932 LayoutUnit(constrainingSize.width())) +
893 minimumValueForLength(style()->left(), 933 minimumValueForLength(style()->left(),
894 LayoutUnit(constrainingSize.width())); 934 LayoutUnit(constrainingSize.width()));
895 bool skipRight = false; 935 bool skipRight = false;
896 bool skipLeft = false; 936 bool skipLeft = false;
897 if (!style()->left().isAuto() && !style()->right().isAuto()) { 937 if (!style()->left().isAuto() && !style()->right().isAuto()) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const { 1015 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const {
976 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer(); 1016 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer();
977 // TODO: Force compositing input update if we ask for offset before 1017 // TODO: Force compositing input update if we ask for offset before
978 // compositing inputs have been computed? 1018 // compositing inputs have been computed?
979 if (!ancestorOverflowLayer) 1019 if (!ancestorOverflowLayer)
980 return LayoutSize(); 1020 return LayoutSize();
981 FloatRect constrainingRect = computeStickyConstrainingRect(); 1021 FloatRect constrainingRect = computeStickyConstrainingRect();
982 PaintLayerScrollableArea* scrollableArea = 1022 PaintLayerScrollableArea* scrollableArea =
983 ancestorOverflowLayer->getScrollableArea(); 1023 ancestorOverflowLayer->getScrollableArea();
984 1024
1025 auto it = scrollableArea->stickyConstraintsMap().find(layer());
1026
985 // The sticky offset is physical, so we can just return the delta computed in 1027 // The sticky offset is physical, so we can just return the delta computed in
986 // absolute coords (though it may be wrong with transforms). 1028 // absolute coords (though it may be wrong with transforms).
987 // TODO: Force compositing input update if we ask for offset with stale 1029 // TODO: Force compositing input update if we ask for offset with stale
988 // compositing inputs. 1030 // compositing inputs.
989 if (!scrollableArea->stickyConstraintsMap().contains(layer())) 1031 if (it == scrollableArea->stickyConstraintsMap().end())
990 return LayoutSize(); 1032 return LayoutSize();
1033
1034 StickyPositionScrollingConstraints& constraints = it->value;
1035
1036 FloatSize ancestorStickyBoxOffset;
1037 FloatSize ancestorContainingBlockOffset;
1038
1039 const LayoutBoxModelObject* toContainingBlock =
1040 constraints.nearestStickyElementShiftingStickyBox();
1041 if (toContainingBlock) {
1042 ancestorStickyBoxOffset = scrollableArea->stickyConstraintsMap()
1043 .get(toContainingBlock->layer())
flackr 2017/01/31 18:33:00 nit: Helper function to get sticky constraints for
smcgruer 2017/01/31 20:42:16 Done.
1044 .getTotalStickyBoxStickyOffset();
flackr 2017/01/31 18:33:00 It'd probably be cleaner to get these as part of c
smcgruer 2017/01/31 20:42:16 Done.
1045 }
1046
1047 const LayoutBoxModelObject* toViewport =
1048 constraints.nearestStickyElementShiftingContainingBlock();
1049 if (toViewport) {
1050 ancestorContainingBlockOffset = scrollableArea->stickyConstraintsMap()
1051 .get(toViewport->layer())
1052 .getTotalContainingBlockStickyOffset();
1053 }
1054
991 return LayoutSize( 1055 return LayoutSize(
992 scrollableArea->stickyConstraintsMap().get(layer()).computeStickyOffset( 1056 constraints.computeStickyOffset(constrainingRect, ancestorStickyBoxOffset,
993 constrainingRect)); 1057 ancestorContainingBlockOffset));
994 } 1058 }
995 1059
996 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo( 1060 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo(
997 const LayoutPoint& startPoint, 1061 const LayoutPoint& startPoint,
998 const Element* offsetParent) const { 1062 const Element* offsetParent) const {
999 // If the element is the HTML body element or doesn't have a parent 1063 // If the element is the HTML body element or doesn't have a parent
1000 // return 0 and stop this algorithm. 1064 // return 0 and stop this algorithm.
1001 if (isBody() || !parent()) 1065 if (isBody() || !parent())
1002 return LayoutPoint(); 1066 return LayoutPoint();
1003 1067
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 if (rootElementStyle->hasBackground()) 1416 if (rootElementStyle->hasBackground())
1353 return false; 1417 return false;
1354 1418
1355 if (node() != document().firstBodyElement()) 1419 if (node() != document().firstBodyElement())
1356 return false; 1420 return false;
1357 1421
1358 return true; 1422 return true;
1359 } 1423 }
1360 1424
1361 } // namespace blink 1425 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698