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

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

Issue 2636253002: Handle nested position:sticky elements (Closed)
Patch Set: Use ancestorOverflowLayer instead of stickyAncestor + test fixing 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 855 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 // the container is our scroll ancestor, we also need to remove the border 866 // the container is our scroll ancestor, we also need to remove the border
867 // box because we want the position from within the scroller border. 867 // box because we want the position from within the scroller border.
868 FloatSize containerBorderOffset(containingBlock->borderLeft(), 868 FloatSize containerBorderOffset(containingBlock->borderLeft(),
869 containingBlock->borderTop()); 869 containingBlock->borderTop());
870 stickyLocation -= containerBorderOffset; 870 stickyLocation -= containerBorderOffset;
871 constraints.setScrollContainerRelativeStickyBoxRect( 871 constraints.setScrollContainerRelativeStickyBoxRect(
872 FloatRect(scrollContainerRelativePaddingBoxRect.location() + 872 FloatRect(scrollContainerRelativePaddingBoxRect.location() +
873 toFloatSize(stickyLocation), 873 toFloatSize(stickyLocation),
874 flippedStickyBoxRect.size())); 874 flippedStickyBoxRect.size()));
875 875
876 // To correctly compute the offsets, the constraints need to know about any
877 // nested position:sticky between themselves and their containingBlock, and
878 // between the containingBlock and their scrollAncestor.
879 //
880 // The respective search ranges are [parent(), containingBlock) and
881 // [containingBlock, scrollAncestor).
882
883 // TODO(smcgruer): Fold these into the walks to find the containingBlock and
884 // scrollAncestor.
885
886 LayoutObject* maybeStickyAncestor = parent();
887 while (maybeStickyAncestor && maybeStickyAncestor != containingBlock) {
888 if (maybeStickyAncestor->isStickyPositioned()) {
889 constraints.setNearestStickyElementShiftingStickyBox(
890 toLayoutBoxModelObject(maybeStickyAncestor));
891 break;
892 }
893 maybeStickyAncestor = maybeStickyAncestor->parent();
894 }
895
896 // NOTE(smcgruer): We cannot use |scrollAncestor| here as it disregards the
897 // root ancestorOverflowLayer(), which we should include for the purposes of
898 // finding the nearest sticky element that shifts the containing block rect.
899 LayoutObject* ancestorOverflowLayer =
900 layer()->ancestorOverflowLayer()->layoutObject();
901 maybeStickyAncestor = containingBlock;
902 while (maybeStickyAncestor && maybeStickyAncestor != ancestorOverflowLayer) {
903 if (maybeStickyAncestor->isStickyPositioned()) {
904 constraints.setNearestStickyElementShiftingContainingBlock(
905 toLayoutBoxModelObject(maybeStickyAncestor));
906 break;
907 }
908 maybeStickyAncestor = maybeStickyAncestor->parent();
flackr 2017/01/24 20:28:48 Technically we should be following the locationCon
smcgruer 2017/01/28 00:55:31 Done.
909 }
910
876 // We skip the right or top sticky offset if there is not enough space to 911 // We skip the right or top sticky offset if there is not enough space to
877 // honor both the left/right or top/bottom offsets. 912 // honor both the left/right or top/bottom offsets.
878 LayoutUnit horizontalOffsets = 913 LayoutUnit horizontalOffsets =
879 minimumValueForLength(style()->right(), 914 minimumValueForLength(style()->right(),
880 LayoutUnit(constrainingSize.width())) + 915 LayoutUnit(constrainingSize.width())) +
881 minimumValueForLength(style()->left(), 916 minimumValueForLength(style()->left(),
882 LayoutUnit(constrainingSize.width())); 917 LayoutUnit(constrainingSize.width()));
883 bool skipRight = false; 918 bool skipRight = false;
884 bool skipLeft = false; 919 bool skipLeft = false;
885 if (!style()->left().isAuto() && !style()->right().isAuto()) { 920 if (!style()->left().isAuto() && !style()->right().isAuto()) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const { 998 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const {
964 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer(); 999 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer();
965 // TODO: Force compositing input update if we ask for offset before 1000 // TODO: Force compositing input update if we ask for offset before
966 // compositing inputs have been computed? 1001 // compositing inputs have been computed?
967 if (!ancestorOverflowLayer) 1002 if (!ancestorOverflowLayer)
968 return LayoutSize(); 1003 return LayoutSize();
969 FloatRect constrainingRect = computeStickyConstrainingRect(); 1004 FloatRect constrainingRect = computeStickyConstrainingRect();
970 PaintLayerScrollableArea* scrollableArea = 1005 PaintLayerScrollableArea* scrollableArea =
971 ancestorOverflowLayer->getScrollableArea(); 1006 ancestorOverflowLayer->getScrollableArea();
972 1007
1008 auto it = scrollableArea->stickyConstraintsMap().find(layer());
1009
973 // The sticky offset is physical, so we can just return the delta computed in 1010 // The sticky offset is physical, so we can just return the delta computed in
974 // absolute coords (though it may be wrong with transforms). 1011 // absolute coords (though it may be wrong with transforms).
975 // TODO: Force compositing input update if we ask for offset with stale 1012 // TODO: Force compositing input update if we ask for offset with stale
976 // compositing inputs. 1013 // compositing inputs.
977 if (!scrollableArea->stickyConstraintsMap().contains(layer())) 1014 if (it == scrollableArea->stickyConstraintsMap().end())
978 return LayoutSize(); 1015 return LayoutSize();
1016
1017 StickyPositionScrollingConstraints& constraints = it->value;
1018
1019 FloatSize ancestorStickyBoxOffset;
1020 FloatSize ancestorContainingBlockOffset;
1021
1022 const LayoutBoxModelObject* toContainingBlock =
1023 constraints.nearestStickyElementShiftingStickyBox();
1024 if (toContainingBlock) {
1025 ancestorStickyBoxOffset = scrollableArea->stickyConstraintsMap()
1026 .get(toContainingBlock->layer())
1027 .getTotalStickyBoxStickyOffset();
1028 }
1029
1030 const LayoutBoxModelObject* toViewport =
1031 constraints.nearestStickyElementShiftingContainingBlock();
1032 if (toViewport) {
1033 ancestorContainingBlockOffset = scrollableArea->stickyConstraintsMap()
1034 .get(toViewport->layer())
1035 .getTotalContainingBlockStickyOffset();
1036 }
1037
979 return LayoutSize( 1038 return LayoutSize(
980 scrollableArea->stickyConstraintsMap().get(layer()).computeStickyOffset( 1039 constraints.computeStickyOffset(constrainingRect, ancestorStickyBoxOffset,
981 constrainingRect)); 1040 ancestorContainingBlockOffset));
982 } 1041 }
983 1042
984 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo( 1043 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo(
985 const LayoutPoint& startPoint, 1044 const LayoutPoint& startPoint,
986 const Element* offsetParent) const { 1045 const Element* offsetParent) const {
987 // If the element is the HTML body element or doesn't have a parent 1046 // If the element is the HTML body element or doesn't have a parent
988 // return 0 and stop this algorithm. 1047 // return 0 and stop this algorithm.
989 if (isBody() || !parent()) 1048 if (isBody() || !parent())
990 return LayoutPoint(); 1049 return LayoutPoint();
991 1050
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 if (rootElementStyle->hasBackground()) 1399 if (rootElementStyle->hasBackground())
1341 return false; 1400 return false;
1342 1401
1343 if (node() != document().firstBodyElement()) 1402 if (node() != document().firstBodyElement())
1344 return false; 1403 return false;
1345 1404
1346 return true; 1405 return true;
1347 } 1406 }
1348 1407
1349 } // namespace blink 1408 } // 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