зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1766192 - Do `snap-scope` with the snapped point rather than the destination point. r=botond
Differential Revision: https://phabricator.services.mozilla.com/D144533
This commit is contained in:
Родитель
9de4521753
Коммит
c73cba8151
|
@ -29,11 +29,15 @@ TEST_F(APZCSnappingTesterMock, Bug1265510) {
|
||||||
|
|
||||||
ScrollSnapInfo snap;
|
ScrollSnapInfo snap;
|
||||||
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
||||||
|
snap.mSnapportSize = CSSSize::ToAppUnits(
|
||||||
|
layerVisibleRegion[0].GetBounds().Size() * LayerToCSSScale(1.0));
|
||||||
|
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
snap.mSnapTargets.AppendElement(
|
||||||
Nothing(), Some(0 * AppUnitsPerCSSPixel()), nsRect()));
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(0 * AppUnitsPerCSSPixel()),
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
CSSRect::ToAppUnits(CSSRect(0, 0, 10, 10))));
|
||||||
Nothing(), Some(100 * AppUnitsPerCSSPixel()), nsRect()));
|
snap.mSnapTargets.AppendElement(
|
||||||
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(100 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 100, 10, 10))));
|
||||||
|
|
||||||
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics&) {
|
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics&) {
|
||||||
aSm.SetSnapInfo(ScrollSnapInfo(snap));
|
aSm.SetSnapInfo(ScrollSnapInfo(snap));
|
||||||
|
@ -102,11 +106,15 @@ TEST_F(APZCSnappingTesterMock, Snap_After_Pinch) {
|
||||||
// Set up some basic scroll snapping
|
// Set up some basic scroll snapping
|
||||||
ScrollSnapInfo snap;
|
ScrollSnapInfo snap;
|
||||||
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
||||||
|
snap.mSnapportSize = CSSSize::ToAppUnits(
|
||||||
|
layerVisibleRegion[0].GetBounds().Size() * LayerToCSSScale(1.0));
|
||||||
|
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
snap.mSnapTargets.AppendElement(
|
||||||
Nothing(), Some(0 * AppUnitsPerCSSPixel()), nsRect()));
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(0 * AppUnitsPerCSSPixel()),
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
CSSRect::ToAppUnits(CSSRect(0, 0, 10, 10))));
|
||||||
Nothing(), Some(100 * AppUnitsPerCSSPixel()), nsRect()));
|
snap.mSnapTargets.AppendElement(
|
||||||
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(100 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 100, 10, 10))));
|
||||||
|
|
||||||
// Save the scroll snap info on the root APZC.
|
// Save the scroll snap info on the root APZC.
|
||||||
// Also mark the root APZC as "root content", since APZC only allows
|
// Also mark the root APZC as "root content", since APZC only allows
|
||||||
|
@ -156,10 +164,14 @@ TEST_F(APZCSnappingTesterMock, SnapOnPanEndWithZeroVelocity) {
|
||||||
// Set up two snap points, 30 and 100.
|
// Set up two snap points, 30 and 100.
|
||||||
ScrollSnapInfo snap;
|
ScrollSnapInfo snap;
|
||||||
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
snap.mSnapportSize = CSSSize::ToAppUnits(
|
||||||
Nothing(), Some(30 * AppUnitsPerCSSPixel()), nsRect()));
|
layerVisibleRegion[0].GetBounds().Size() * LayerToCSSScale(1.0));
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
snap.mSnapTargets.AppendElement(
|
||||||
Nothing(), Some(100 * AppUnitsPerCSSPixel()), nsRect()));
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(30 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 30, 10, 10))));
|
||||||
|
snap.mSnapTargets.AppendElement(
|
||||||
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(100 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 100, 10, 10))));
|
||||||
|
|
||||||
// Save the scroll snap info on the root APZC.
|
// Save the scroll snap info on the root APZC.
|
||||||
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
|
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
|
||||||
|
@ -227,10 +239,14 @@ TEST_F(APZCSnappingTesterMock, SnapOnPanEndWithPositiveVelocity) {
|
||||||
// Set up two snap points, 30 and 100.
|
// Set up two snap points, 30 and 100.
|
||||||
ScrollSnapInfo snap;
|
ScrollSnapInfo snap;
|
||||||
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
snap.mSnapportSize = CSSSize::ToAppUnits(
|
||||||
Nothing(), Some(30 * AppUnitsPerCSSPixel()), nsRect()));
|
layerVisibleRegion[0].GetBounds().Size() * LayerToCSSScale(1.0));
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
snap.mSnapTargets.AppendElement(
|
||||||
Nothing(), Some(100 * AppUnitsPerCSSPixel()), nsRect()));
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(30 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 30, 10, 10))));
|
||||||
|
snap.mSnapTargets.AppendElement(
|
||||||
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(100 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 100, 10, 10))));
|
||||||
|
|
||||||
// Save the scroll snap info on the root APZC.
|
// Save the scroll snap info on the root APZC.
|
||||||
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
|
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
|
||||||
|
|
|
@ -27,11 +27,14 @@ TEST_F(APZCSnappingOnMomentumTesterMock, Snap_On_Momentum) {
|
||||||
// Set up some basic scroll snapping
|
// Set up some basic scroll snapping
|
||||||
ScrollSnapInfo snap;
|
ScrollSnapInfo snap;
|
||||||
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
snap.mScrollSnapStrictnessY = StyleScrollSnapStrictness::Mandatory;
|
||||||
|
snap.mSnapportSize = CSSSize::ToAppUnits(
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
layerVisibleRegion[0].GetBounds().Size() * LayerToCSSScale(1.0));
|
||||||
Nothing(), Some(0 * AppUnitsPerCSSPixel()), nsRect()));
|
snap.mSnapTargets.AppendElement(
|
||||||
snap.mSnapTargets.AppendElement(ScrollSnapInfo::SnapTarget(
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(0 * AppUnitsPerCSSPixel()),
|
||||||
Nothing(), Some(100 * AppUnitsPerCSSPixel()), nsRect()));
|
CSSRect::ToAppUnits(CSSRect(0, 0, 10, 10))));
|
||||||
|
snap.mSnapTargets.AppendElement(
|
||||||
|
ScrollSnapInfo::SnapTarget(Nothing(), Some(100 * AppUnitsPerCSSPixel()),
|
||||||
|
CSSRect::ToAppUnits(CSSRect(0, 100, 10, 10))));
|
||||||
|
|
||||||
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics&) {
|
ModifyFrameMetrics(root, [&](ScrollMetadata& aSm, FrameMetrics&) {
|
||||||
aSm.SetSnapInfo(ScrollSnapInfo(snap));
|
aSm.SetSnapInfo(ScrollSnapInfo(snap));
|
||||||
|
|
|
@ -39,6 +39,7 @@ class CalcSnapPoints final {
|
||||||
return std::abs(
|
return std::abs(
|
||||||
NSCoordSaturatingSubtract(mSecondBestEdge.y, mBestEdge.y, nscoord_MAX));
|
NSCoordSaturatingSubtract(mSecondBestEdge.y, mBestEdge.y, nscoord_MAX));
|
||||||
}
|
}
|
||||||
|
const nsPoint& Destination() const { return mDestination; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ScrollUnit mUnit;
|
ScrollUnit mUnit;
|
||||||
|
@ -207,6 +208,18 @@ void CalcSnapPoints::AddEdge(nscoord aEdge, nscoord aDestination,
|
||||||
static void ProcessSnapPositions(CalcSnapPoints& aCalcSnapPoints,
|
static void ProcessSnapPositions(CalcSnapPoints& aCalcSnapPoints,
|
||||||
const ScrollSnapInfo& aSnapInfo) {
|
const ScrollSnapInfo& aSnapInfo) {
|
||||||
for (const auto& target : aSnapInfo.mSnapTargets) {
|
for (const auto& target : aSnapInfo.mSnapTargets) {
|
||||||
|
nsPoint snapPoint(target.mSnapPositionX ? *target.mSnapPositionX
|
||||||
|
: aCalcSnapPoints.Destination().x,
|
||||||
|
target.mSnapPositionY ? *target.mSnapPositionY
|
||||||
|
: aCalcSnapPoints.Destination().y);
|
||||||
|
nsRect snappedPort = nsRect(snapPoint, aSnapInfo.mSnapportSize);
|
||||||
|
// Ignore snap points if snapping to the point would leave the snap area
|
||||||
|
// outside of the snapport.
|
||||||
|
// https://drafts.csswg.org/css-scroll-snap-1/#snap-scope
|
||||||
|
if (!snappedPort.Intersects(target.mSnapArea)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (target.mSnapPositionX) {
|
if (target.mSnapPositionX) {
|
||||||
aCalcSnapPoints.AddVerticalEdge(*target.mSnapPositionX);
|
aCalcSnapPoints.AddVerticalEdge(*target.mSnapPositionX);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7627,7 +7627,6 @@ static void AppendScrollPositionsForSnap(const nsIFrame* aFrame,
|
||||||
const nsIFrame* aScrolledFrame,
|
const nsIFrame* aScrolledFrame,
|
||||||
const nsRect& aScrolledRect,
|
const nsRect& aScrolledRect,
|
||||||
const nsMargin& aScrollPadding,
|
const nsMargin& aScrollPadding,
|
||||||
const Maybe<nsRect>& aSnapport,
|
|
||||||
WritingMode aWritingModeOnScroller,
|
WritingMode aWritingModeOnScroller,
|
||||||
ScrollSnapInfo& aSnapInfo) {
|
ScrollSnapInfo& aSnapInfo) {
|
||||||
nsRect targetRect = nsLayoutUtils::TransformFrameRectToAncestor(
|
nsRect targetRect = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||||
|
@ -7639,13 +7638,6 @@ static void AppendScrollPositionsForSnap(const nsIFrame* aFrame,
|
||||||
nsRect snapArea =
|
nsRect snapArea =
|
||||||
InflateByScrollMargin(targetRect, scrollMargin, aScrolledRect);
|
InflateByScrollMargin(targetRect, scrollMargin, aScrolledRect);
|
||||||
|
|
||||||
// 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(snapArea)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These snap range shouldn't be involved with scroll-margin since we just
|
// These snap range shouldn't be involved with scroll-margin since we just
|
||||||
// need the visible range of the target element.
|
// need the visible range of the target element.
|
||||||
if (snapArea.width > aSnapInfo.mSnapportSize.width) {
|
if (snapArea.width > aSnapInfo.mSnapportSize.width) {
|
||||||
|
@ -7764,13 +7756,13 @@ static void AppendScrollPositionsForSnap(const nsIFrame* aFrame,
|
||||||
/**
|
/**
|
||||||
* Collect the scroll positions corresponding to snap positions of frames in the
|
* Collect the scroll positions corresponding to snap positions of frames in the
|
||||||
* subtree rooted at |aFrame|, relative to |aScrolledFrame|, into |aSnapInfo|.
|
* 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(
|
static void CollectScrollPositionsForSnap(nsIFrame* aFrame,
|
||||||
nsIFrame* aFrame, nsIFrame* aScrolledFrame, const nsRect& aScrolledRect,
|
nsIFrame* aScrolledFrame,
|
||||||
const nsMargin& aScrollPadding, const Maybe<nsRect>& aSnapport,
|
const nsRect& aScrolledRect,
|
||||||
WritingMode aWritingModeOnScroller, ScrollSnapInfo& aSnapInfo) {
|
const nsMargin& aScrollPadding,
|
||||||
|
WritingMode aWritingModeOnScroller,
|
||||||
|
ScrollSnapInfo& aSnapInfo) {
|
||||||
// Snap positions only affect the nearest ancestor scroll container on the
|
// Snap positions only affect the nearest ancestor scroll container on the
|
||||||
// element's containing block chain.
|
// element's containing block chain.
|
||||||
nsIScrollableFrame* sf = do_QueryFrame(aFrame);
|
nsIScrollableFrame* sf = do_QueryFrame(aFrame);
|
||||||
|
@ -7786,12 +7778,12 @@ static void CollectScrollPositionsForSnap(
|
||||||
styleDisplay->mScrollSnapAlign.block !=
|
styleDisplay->mScrollSnapAlign.block !=
|
||||||
StyleScrollSnapAlignKeyword::None) {
|
StyleScrollSnapAlignKeyword::None) {
|
||||||
AppendScrollPositionsForSnap(f, aScrolledFrame, aScrolledRect,
|
AppendScrollPositionsForSnap(f, aScrolledFrame, aScrolledRect,
|
||||||
aScrollPadding, aSnapport,
|
aScrollPadding, aWritingModeOnScroller,
|
||||||
aWritingModeOnScroller, aSnapInfo);
|
aSnapInfo);
|
||||||
}
|
}
|
||||||
CollectScrollPositionsForSnap(f, aScrolledFrame, aScrolledRect,
|
CollectScrollPositionsForSnap(f, aScrolledFrame, aScrolledRect,
|
||||||
aScrollPadding, aSnapport,
|
aScrollPadding, aWritingModeOnScroller,
|
||||||
aWritingModeOnScroller, aSnapInfo);
|
aSnapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7867,20 +7859,12 @@ layers::ScrollSnapInfo ScrollFrameHelper::ComputeScrollSnapInfo(
|
||||||
|
|
||||||
nsRect snapport = GetScrollPortRect();
|
nsRect snapport = GetScrollPortRect();
|
||||||
nsMargin scrollPadding = GetScrollPadding();
|
nsMargin scrollPadding = GetScrollPadding();
|
||||||
|
snapport.Deflate(scrollPadding);
|
||||||
Maybe<nsRect> snapportOnDestination;
|
|
||||||
if (aDestination) {
|
|
||||||
snapport.MoveTo(aDestination.value());
|
|
||||||
snapport.Deflate(scrollPadding);
|
|
||||||
snapportOnDestination.emplace(snapport);
|
|
||||||
} else {
|
|
||||||
snapport.Deflate(scrollPadding);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.mSnapportSize = snapport.Size();
|
result.mSnapportSize = snapport.Size();
|
||||||
CollectScrollPositionsForSnap(mScrolledFrame, mScrolledFrame,
|
CollectScrollPositionsForSnap(mScrolledFrame, mScrolledFrame,
|
||||||
GetScrolledRect(), scrollPadding,
|
GetScrolledRect(), scrollPadding, writingMode,
|
||||||
snapportOnDestination, writingMode, result);
|
result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,11 @@
|
||||||
[keyboard.html]
|
[keyboard.html]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
[If there is no valid snap offset on the arrow key's direction other than the current offset, and the scroll-snap-type is proximity, go to the original intended offset]
|
[If there is no valid snap offset on the arrow key's direction other than the current offset, and the scroll-snap-type is proximity, go to the original intended offset]
|
||||||
expected: NOTRUN
|
expected: [TIMEOUT, NOTRUN, FAIL]
|
||||||
|
|
||||||
[If the original intended offset is valid as making a snap area cover the snapport, but there's a defined snap offset in between, use the defined snap offset.]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
||||||
[Snaps to top-left after pressing ArrowUp]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[Snaps to top-left after pressing ArrowLeft]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
||||||
[Snaps to top-right after pressing ArrowRight]
|
[Snaps to top-right after pressing ArrowRight]
|
||||||
expected:
|
expected:
|
||||||
if os == "mac": [NOTRUN, PASS, FAIL]
|
if os == "mac": [NOTRUN, PASS, FAIL]
|
||||||
NOTRUN
|
|
||||||
|
|
||||||
[If the original intended offset is valid as making a snap area cover thesnapport, and there's no other snap offset in between, use the originalintended offset]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
||||||
[If there is no valid snap offset on the arrow key's direction other than the current offset, and the scroll-snap-type is mandatory, stay at the current offset.]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
||||||
[Snaps to bottom-left after pressing ArrowDown]
|
[Snaps to bottom-left after pressing ArrowDown]
|
||||||
expected:
|
expected:
|
||||||
|
@ -30,4 +14,9 @@
|
||||||
if (os == "android") and swgl: PASS
|
if (os == "android") and swgl: PASS
|
||||||
if (os == "android") and not swgl: FAIL
|
if (os == "android") and not swgl: FAIL
|
||||||
if (os == "win") and swgl: PASS
|
if (os == "win") and swgl: PASS
|
||||||
[PASS, FAIL]
|
|
||||||
|
[If the original intended offset is valid as making a snap area cover the snapport, but there's a defined snap offset in between, use the defined snap offset.]
|
||||||
|
expected: [TIMEOUT, PASS]
|
||||||
|
|
||||||
|
[If there is no valid snap offset on the arrow key's direction other than the current offset, and the scroll-snap-type is mandatory, stay at the current offset.]
|
||||||
|
expected: [NOTRUN, PASS]
|
||||||
|
|
|
@ -7,7 +7,3 @@
|
||||||
|
|
||||||
[A scroll with intended direction and end position should not pass a snap area with scroll-snap-stop: always.]
|
[A scroll with intended direction and end position should not pass a snap area with scroll-snap-stop: always.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[A scroll with intended end position should always choose the closest snap position regardless of the scroll-snap-stop value.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
[scrollTo-scrollBy-snaps.html]
|
|
||||||
[assign scrollLeft and scrollTop for {left: 10000, top: -100} on div lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[assign scrollLeft and scrollTop for {left: 10000, top: -100} on viewport-defining element lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[scrollBy({left: 10000, top: -100}) on div lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[scrollTo({left: 10000, top: -100}) on div lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[scrollTo({left: 10000, top: -100}) on viewport-defining element lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[scrollTo({left: 10000, top: -100}) on window lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[scrollBy({left: 10000, top: -100}) on window lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[scrollBy({left: 10000, top: -100}) on viewport-defining element lands on (1000, 0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[snap-to-visible-areas-x-axis.html]
|
||||||
|
[Only snap to visible area on X axis, even when the non-visible ones are closer]
|
||||||
|
expected: FAIL
|
||||||
|
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1768393
|
|
@ -0,0 +1,4 @@
|
||||||
|
[snap-to-visible-areas-y-axis.html]
|
||||||
|
[Only snap to visible area on Y axis, even when the non-visible ones are closer]
|
||||||
|
expected: FAIL
|
||||||
|
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1768393
|
Загрузка…
Ссылка в новой задаче