зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1766192 - Choose the second best edge on the opposite side of the best edge. r=botond
The second best edge is used for `snap-overflow` feature [1]. The `snap-overflow` is applied when the following conditions are met. 1) A scroll snap target element is larger than the snapport (e.g. scrollport) in an axis 2) The distance between the best edge and the second best edge (on the opposite side of the best edge) is later than the snapport size in the axis There was a problem in our implementation. For example, in below diagram, D is the original destination of the given scroll operation, 1 is the best edge, 2 is the second best in our original implementation and 3 is of of the other snap points. In this case if there's an element larger than the distance between 1 and 3 and if the snapport size is larger than the distance between 1 and 2 but smaller than the distance between 1 and 3, we should apply `snap-overflow`. 2 1 D 3 |-|---|-----| There are a couple of test cases in wpt for this condition, for example there's one of them in oveflowing-snap-area.html [2]. That test case have been passed incorrectly due to our incorrect `snap-scope` implementation which will be fixed a subsequent change in this commit series. [1] https://drafts.csswg.org/css-scroll-snap-1/#snap-overflow [2] https://searchfox.org/mozilla-central/rev/13d69189a8abfc5064fe44944550b9b6eb4544f5/testing/web-platform/tests/css/css-scroll-snap/overflowing-snap-areas.html#131-137 Differential Revision: https://phabricator.services.mozilla.com/D144531
This commit is contained in:
Родитель
c6b806d1b3
Коммит
84149416a9
|
@ -32,10 +32,12 @@ class CalcSnapPoints final {
|
|||
nscoord* aSecondBestEdge, bool* aEdgeFound);
|
||||
nsPoint GetBestEdge() const;
|
||||
nscoord XDistanceBetweenBestAndSecondEdge() const {
|
||||
return std::abs(mBestEdge.x - mSecondBestEdge.x);
|
||||
return std::abs(
|
||||
NSCoordSaturatingSubtract(mSecondBestEdge.x, mBestEdge.x, nscoord_MAX));
|
||||
}
|
||||
nscoord YDistanceBetweenBestAndSecondEdge() const {
|
||||
return std::abs(mBestEdge.y - mSecondBestEdge.y);
|
||||
return std::abs(
|
||||
NSCoordSaturatingSubtract(mSecondBestEdge.y, mBestEdge.y, nscoord_MAX));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -45,8 +47,9 @@ class CalcSnapPoints final {
|
|||
nsPoint mStartPos; // gives the position before scrolling
|
||||
nsIntPoint mScrollingDirection; // always -1, 0, or 1
|
||||
nsPoint mBestEdge; // keeps track of the position of the current best edge
|
||||
nsPoint mSecondBestEdge; // keeps track of the position of the current
|
||||
// second best edge
|
||||
nsPoint mSecondBestEdge; // keeps track of the position of the current
|
||||
// second best edge on the opposite side of the best
|
||||
// edge
|
||||
bool mHorizontalEdgeFound; // true if mBestEdge.x is storing a valid
|
||||
// horizontal edge
|
||||
bool mVerticalEdgeFound; // true if mBestEdge.y is storing a valid vertical
|
||||
|
@ -74,6 +77,10 @@ CalcSnapPoints::CalcSnapPoints(ScrollUnit aUnit, const nsPoint& aDestination,
|
|||
mScrollingDirection.y = 1;
|
||||
}
|
||||
mBestEdge = aDestination;
|
||||
// We use NSCoordSaturatingSubtract to calculate the distance between a given
|
||||
// position and this second best edge position so that it can be an
|
||||
// uninitialized value as the maximum possible value, because the first
|
||||
// distance calculation would always be nscoord_MAX.
|
||||
mSecondBestEdge = nsPoint(nscoord_MAX, nscoord_MAX);
|
||||
mHorizontalEdgeFound = false;
|
||||
mVerticalEdgeFound = false;
|
||||
|
@ -131,6 +138,8 @@ void CalcSnapPoints::AddEdge(nscoord aEdge, nscoord aDestination,
|
|||
return;
|
||||
}
|
||||
|
||||
const bool isOnOppositeSide =
|
||||
((aEdge - aDestination) > 0) != ((*aBestEdge - aDestination) > 0);
|
||||
// A utility function to update the best and the second best edges in the
|
||||
// given conditions.
|
||||
// |aIsCloserThanBest| True if the current candidate is closer than the best
|
||||
|
@ -139,17 +148,25 @@ void CalcSnapPoints::AddEdge(nscoord aEdge, nscoord aDestination,
|
|||
// the second best edge.
|
||||
auto updateBestEdges = [&](bool aIsCloserThanBest, bool aIsCloserThanSecond) {
|
||||
if (aIsCloserThanBest) {
|
||||
*aSecondBestEdge = *aBestEdge;
|
||||
// Replace the second best edge with the current best edge only if the new
|
||||
// best edge (aEdge) is on the opposite side of the current best edge.
|
||||
if (isOnOppositeSide) {
|
||||
*aSecondBestEdge = *aBestEdge;
|
||||
}
|
||||
*aBestEdge = aEdge;
|
||||
} else if (aIsCloserThanSecond) {
|
||||
*aSecondBestEdge = aEdge;
|
||||
if (isOnOppositeSide) {
|
||||
*aSecondBestEdge = aEdge;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (mUnit == ScrollUnit::DEVICE_PIXELS || mUnit == ScrollUnit::LINES) {
|
||||
nscoord distance = std::abs(aEdge - aDestination);
|
||||
updateBestEdges(distance < std::abs(*aBestEdge - aDestination),
|
||||
distance < std::abs(*aSecondBestEdge - aDestination));
|
||||
updateBestEdges(
|
||||
distance < std::abs(*aBestEdge - aDestination),
|
||||
distance < std::abs(NSCoordSaturatingSubtract(
|
||||
*aSecondBestEdge, aDestination, nscoord_MAX)));
|
||||
} else if (mUnit == ScrollUnit::PAGES) {
|
||||
// distance to the edge from the scrolling destination in the direction of
|
||||
// scrolling
|
||||
|
@ -159,7 +176,8 @@ void CalcSnapPoints::AddEdge(nscoord aEdge, nscoord aDestination,
|
|||
nscoord curOvershoot = (*aBestEdge - aDestination) * aScrollingDirection;
|
||||
|
||||
nscoord secondOvershoot =
|
||||
(*aSecondBestEdge - aDestination) * aScrollingDirection;
|
||||
NSCoordSaturatingSubtract(*aSecondBestEdge, aDestination, nscoord_MAX) *
|
||||
aScrollingDirection;
|
||||
|
||||
// edges between the current position and the scrolling destination are
|
||||
// favoured to preserve context
|
||||
|
|
Загрузка…
Ссылка в новой задаче