Bug 1373835 - Cull out elements which will be invisible in the snapport for programatic scrolls. r=botond

As for scrolling on the compositor we don't cull out them since we don't know
the final snapport rect at the time when we send the information about
snapping to the compositor.  And we will handle it for APZ in bug 1531589.

https://drafts.csswg.org/css-scroll-snap-1/#snap-scope

Depends on D21632

Differential Revision: https://phabricator.services.mozilla.com/D21633

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Hiroyuki Ikezoe 2019-04-11 06:21:23 +00:00
Родитель fdc43c56d5
Коммит ee992bd0bb
4 изменённых файлов: 41 добавлений и 27 удалений

Просмотреть файл

@ -6525,10 +6525,17 @@ uint32_t nsIScrollableFrame::GetPerceivedScrollingDirections() const {
*/
static void AppendScrollPositionsForSnap(const nsIFrame* aFrame,
const nsIFrame* aScrolledFrame,
const Maybe<nsRect>& aSnapport,
ScrollSnapInfo& aSnapInfo) {
// FIXME: Bug 1373833: This target rect should be inflated by scroll-margin.
nsRect targetRect = nsLayoutUtils::TransformFrameRectToAncestor(
aFrame, aFrame->GetRectRelativeToSelf(), aScrolledFrame);
// Ignore elements outside of the snapport when we scroll to the given
// destination.
// https://drafts.csswg.org/css-scroll-snap-1/#snap-scope
if (aSnapport && !aSnapport->Intersects(targetRect)) {
return;
}
WritingMode writingMode = aScrolledFrame->GetWritingMode();
LogicalRect logicalTargetRect(writingMode, targetRect,
@ -6634,9 +6641,12 @@ static void AppendScrollPositionsForSnap(const nsIFrame* aFrame,
/**
* Collect the scroll positions corresponding to snap positions of frames in the
* subtree rooted at |aFrame|, relative to |aScrolledFrame|, into |aSnapInfo|.
* If |aSnapport| is given, elements outside of the range of |aSnapport| will be
* ignored.
*/
static void CollectScrollPositionsForSnap(nsIFrame* aFrame,
nsIFrame* aScrolledFrame,
const Maybe<nsRect>& aSnapport,
ScrollSnapInfo& aSnapInfo) {
MOZ_ASSERT(StaticPrefs::layout_css_scroll_snap_v1_enabled());
@ -6651,9 +6661,9 @@ static void CollectScrollPositionsForSnap(nsIFrame* aFrame,
StyleScrollSnapAlignKeyword::None ||
styleDisplay->mScrollSnapAlign.block !=
StyleScrollSnapAlignKeyword::None) {
AppendScrollPositionsForSnap(f, aScrolledFrame, aSnapInfo);
AppendScrollPositionsForSnap(f, aScrolledFrame, aSnapport, aSnapInfo);
}
CollectScrollPositionsForSnap(f, aScrolledFrame, aSnapInfo);
CollectScrollPositionsForSnap(f, aScrolledFrame, aSnapport, aSnapInfo);
}
}
}
@ -6697,7 +6707,8 @@ static void CollectScrollSnapCoordinates(nsIFrame* aFrame,
}
}
layers::ScrollSnapInfo ScrollFrameHelper::ComputeScrollSnapInfo() const {
layers::ScrollSnapInfo ScrollFrameHelper::ComputeScrollSnapInfo(
const Maybe<nsPoint>& aDestination) const {
ScrollSnapInfo result;
ScrollStyles styles = GetScrollStylesFromFrame();
@ -6730,9 +6741,20 @@ layers::ScrollSnapInfo ScrollFrameHelper::ComputeScrollSnapInfo() const {
if (StaticPrefs::layout_css_scroll_snap_v1_enabled()) {
// FIXME: Bug 1373832: The snapport should be deflated by scroll-padding.
result.mSnapportSize = GetScrollPortRect().Size();
nsSize snapportSize = GetScrollPortRect().Size();
CollectScrollPositionsForSnap(mScrolledFrame, mScrolledFrame, result);
Maybe<nsRect> snapportOnDestination;
if (aDestination) {
snapportOnDestination.emplace(
IsPhysicalLTR() ? nsRect(aDestination.value(), snapportSize)
: nsRect(nsPoint(aDestination->x - snapportSize.width,
aDestination->y),
snapportSize));
}
result.mSnapportSize = snapportSize;
CollectScrollPositionsForSnap(mScrolledFrame, mScrolledFrame,
snapportOnDestination, result);
return result;
}
@ -6742,17 +6764,18 @@ layers::ScrollSnapInfo ScrollFrameHelper::ComputeScrollSnapInfo() const {
return result;
}
layers::ScrollSnapInfo ScrollFrameHelper::GetScrollSnapInfo() const {
layers::ScrollSnapInfo ScrollFrameHelper::GetScrollSnapInfo(
const Maybe<nsPoint>& aDestination) const {
// TODO(botond): Should we cache it?
return ComputeScrollSnapInfo();
return ComputeScrollSnapInfo(aDestination);
}
bool ScrollFrameHelper::GetSnapPointForDestination(
nsIScrollableFrame::ScrollUnit aUnit, nsPoint aStartPos,
nsPoint& aDestination) {
Maybe<nsPoint> snapPoint = ScrollSnapUtils::GetSnapPointForDestination(
GetScrollSnapInfo(), aUnit, GetLayoutScrollRange(), aStartPos,
aDestination);
GetScrollSnapInfo(Some(aDestination)), aUnit, GetLayoutScrollRange(),
aStartPos, aDestination);
if (snapPoint) {
aDestination = snapPoint.ref();
return true;

Просмотреть файл

@ -409,7 +409,8 @@ class ScrollFrameHelper : public nsIReflowCallback {
nsIFrame* GetFrameForDir() const; // helper for Is{Physical,Bidi}LTR to find
// the frame whose directionality we use
ScrollSnapInfo ComputeScrollSnapInfo() const;
ScrollSnapInfo ComputeScrollSnapInfo(
const Maybe<nsPoint>& aDestination) const;
public:
bool IsScrollbarOnRight() const;
@ -473,7 +474,11 @@ class ScrollFrameHelper : public nsIReflowCallback {
bool UsesContainerScrolling() const;
ScrollSnapInfo GetScrollSnapInfo() const;
// In the case where |aDestination| is given, elements which are entirely out
// of view when the scroll position is moved to |aDestination| are not going
// to be used for snap positions.
ScrollSnapInfo GetScrollSnapInfo(
const mozilla::Maybe<nsPoint>& aDestination) const;
bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aVisibleRect, nsRect* aDirtyRect,
@ -1182,7 +1187,7 @@ class nsHTMLScrollFrame : public nsContainerFrame,
}
ScrollSnapInfo GetScrollSnapInfo() const override {
return mHelper.GetScrollSnapInfo();
return mHelper.GetScrollSnapInfo(Nothing());
}
virtual bool DragScroll(mozilla::WidgetEvent* aEvent) override {
@ -1668,7 +1673,7 @@ class nsXULScrollFrame final : public nsBoxFrame,
}
ScrollSnapInfo GetScrollSnapInfo() const override {
return mHelper.GetScrollSnapInfo();
return mHelper.GetScrollSnapInfo(Nothing());
}
virtual bool DragScroll(mozilla::WidgetEvent* aEvent) override {

Просмотреть файл

@ -1,7 +0,0 @@
[overflowing-snap-areas.html]
[Snap to current scroll position which is a valid snap position, as the snap area covers snapport on x and the distance between the previous(800) and next(1400) is larger than snapport(500).]
expected: FAIL
[Snap to current scroll position which is a valid snap position, as the snap area covers snapport on y and the distance between the previous(800) and next(1400) is larger than snapport(500).]
expected: FAIL

Просмотреть файл

@ -1,7 +0,0 @@
[snap-to-visible-areas.html]
[Only snap to visible area on X axis, even when the non-visible ones are closer]
expected: FAIL
[Only snap to visible area on Y axis, even when the non-visible ones are closer]
expected: FAIL