зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1219296 - Factor out scroll snap information into a form that's usable by the compositor. r=kats
MozReview-Commit-ID: DTvu7UsKsBg --HG-- extra : rebase_source : 71831d884d128bc9e50aac55c7a8302f7ffe74f8
This commit is contained in:
Родитель
a74ec8c79b
Коммит
4690842281
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/gfx/Logging.h" // for Log
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp
|
||||
#include "nsString.h"
|
||||
#include "nsStyleCoord.h" // for nsStyleCoord
|
||||
|
||||
namespace IPC {
|
||||
template <typename T> struct ParamTraits;
|
||||
|
@ -751,6 +752,29 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
struct ScrollSnapInfo {
|
||||
ScrollSnapInfo()
|
||||
: mScrollSnapTypeX(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
|
||||
, mScrollSnapTypeY(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
|
||||
{}
|
||||
|
||||
// The scroll frame's scroll-snap-type.
|
||||
// One of NS_STYLE_SCROLL_SNAP_{NONE, MANDATORY, PROXIMITY}.
|
||||
uint8_t mScrollSnapTypeX;
|
||||
uint8_t mScrollSnapTypeY;
|
||||
|
||||
// The intervals derived from the scroll frame's scroll-snap-points.
|
||||
Maybe<nscoord> mScrollSnapIntervalX;
|
||||
Maybe<nscoord> mScrollSnapIntervalY;
|
||||
|
||||
// The scroll frame's scroll-snap-destination, in cooked form (to avoid
|
||||
// shipping the raw nsStyleCoord::CalcValue over IPC).
|
||||
nsPoint mScrollSnapDestination;
|
||||
|
||||
// The scroll-snap-coordinates of any descendant frames of the scroll frame,
|
||||
// relative to the origin of the scrolled frame.
|
||||
nsTArray<nsPoint> mScrollSnapCoordinates;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata about a scroll frame that's stored in the layer tree for use by
|
||||
|
|
|
@ -6010,9 +6010,26 @@ CalcSnapPoints::AddEdgeInterval(nscoord aInterval, nscoord aMinPos,
|
|||
}
|
||||
|
||||
static void
|
||||
ScrollSnapHelper(SnappingEdgeCallback& aCallback, nsIFrame* aFrame,
|
||||
nsIFrame* aScrolledFrame,
|
||||
const nsPoint &aScrollSnapDestination) {
|
||||
ProcessScrollSnapCoordinates(SnappingEdgeCallback& aCallback,
|
||||
const nsTArray<nsPoint>& aScrollSnapCoordinates,
|
||||
const nsPoint& aScrollSnapDestination) {
|
||||
for (nsPoint snapCoords : aScrollSnapCoordinates) {
|
||||
// Make them relative to the scroll snap destination.
|
||||
snapCoords -= aScrollSnapDestination;
|
||||
|
||||
aCallback.AddVerticalEdge(snapCoords.x);
|
||||
aCallback.AddHorizontalEdge(snapCoords.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the scroll-snap-coordinates of frames in the subtree rooted at
|
||||
* |aFrame|, relative to |aScrolledFrame|, into |aOutCoords|.
|
||||
*/
|
||||
void
|
||||
CollectScrollSnapCoordinates(nsIFrame* aFrame, nsIFrame* aScrolledFrame,
|
||||
nsTArray<nsPoint>& aOutCoords)
|
||||
{
|
||||
nsIFrame::ChildListIterator childLists(aFrame);
|
||||
for (; !childLists.IsDone(); childLists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(childLists.CurrentList());
|
||||
|
@ -6029,7 +6046,7 @@ ScrollSnapHelper(SnappingEdgeCallback& aCallback, nsIFrame* aFrame,
|
|||
for (size_t coordNum = 0; coordNum < coordCount; coordNum++) {
|
||||
const nsStyleImageLayers::Position &coordPosition =
|
||||
f->StyleDisplay()->mScrollSnapCoordinate[coordNum];
|
||||
nsPoint coordPoint = edgesRect.TopLeft() - aScrollSnapDestination;
|
||||
nsPoint coordPoint = edgesRect.TopLeft();
|
||||
coordPoint += nsPoint(coordPosition.mXPosition.mLength,
|
||||
coordPosition.mYPosition.mLength);
|
||||
if (coordPosition.mXPosition.mHasPercent) {
|
||||
|
@ -6041,68 +6058,110 @@ ScrollSnapHelper(SnappingEdgeCallback& aCallback, nsIFrame* aFrame,
|
|||
frameRect.height);
|
||||
}
|
||||
|
||||
aCallback.AddVerticalEdge(coordPoint.x);
|
||||
aCallback.AddHorizontalEdge(coordPoint.y);
|
||||
aOutCoords.AppendElement(coordPoint);
|
||||
}
|
||||
}
|
||||
|
||||
ScrollSnapHelper(aCallback, f, aScrolledFrame, aScrollSnapDestination);
|
||||
CollectScrollSnapCoordinates(f, aScrolledFrame, aOutCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layers::ScrollSnapInfo
|
||||
ComputeScrollSnapInfo(const ScrollFrameHelper& aScrollFrame)
|
||||
{
|
||||
ScrollSnapInfo result;
|
||||
|
||||
ScrollbarStyles styles = aScrollFrame.GetScrollbarStylesFromFrame();
|
||||
|
||||
if (styles.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_NONE &&
|
||||
styles.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_NONE) {
|
||||
// We won't be snapping, short-circuit the computation.
|
||||
return result;
|
||||
}
|
||||
|
||||
result.mScrollSnapTypeX = styles.mScrollSnapTypeX;
|
||||
result.mScrollSnapTypeY = styles.mScrollSnapTypeY;
|
||||
|
||||
nsSize scrollPortSize = aScrollFrame.GetScrollPortRect().Size();
|
||||
|
||||
result.mScrollSnapDestination = nsPoint(styles.mScrollSnapDestinationX.mLength,
|
||||
styles.mScrollSnapDestinationY.mLength);
|
||||
if (styles.mScrollSnapDestinationX.mHasPercent) {
|
||||
result.mScrollSnapDestination.x +=
|
||||
NSToCoordFloorClamped(styles.mScrollSnapDestinationX.mPercent *
|
||||
scrollPortSize.width);
|
||||
}
|
||||
if (styles.mScrollSnapDestinationY.mHasPercent) {
|
||||
result.mScrollSnapDestination.y +=
|
||||
NSToCoordFloorClamped(styles.mScrollSnapDestinationY.mPercent *
|
||||
scrollPortSize.height);
|
||||
}
|
||||
|
||||
if (styles.mScrollSnapPointsX.GetUnit() != eStyleUnit_None) {
|
||||
result.mScrollSnapIntervalX = Some(nsRuleNode::ComputeCoordPercentCalc(
|
||||
styles.mScrollSnapPointsX, scrollPortSize.width));
|
||||
}
|
||||
if (styles.mScrollSnapPointsY.GetUnit() != eStyleUnit_None) {
|
||||
result.mScrollSnapIntervalY = Some(nsRuleNode::ComputeCoordPercentCalc(
|
||||
styles.mScrollSnapPointsY, scrollPortSize.height));
|
||||
}
|
||||
|
||||
CollectScrollSnapCoordinates(aScrollFrame.GetScrolledFrame(),
|
||||
aScrollFrame.GetScrolledFrame(),
|
||||
result.mScrollSnapCoordinates);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
layers::ScrollSnapInfo
|
||||
ScrollFrameHelper::GetScrollSnapInfo() const
|
||||
{
|
||||
// TODO(botond): Should we cache it?
|
||||
return ComputeScrollSnapInfo(*this);
|
||||
}
|
||||
|
||||
bool
|
||||
ScrollFrameHelper::GetSnapPointForDestination(nsIScrollableFrame::ScrollUnit aUnit,
|
||||
nsPoint aStartPos,
|
||||
nsPoint &aDestination)
|
||||
{
|
||||
ScrollbarStyles styles = GetScrollbarStylesFromFrame();
|
||||
if (styles.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_NONE &&
|
||||
styles.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_NONE) {
|
||||
ScrollSnapInfo snapInfo = GetScrollSnapInfo();
|
||||
|
||||
if (snapInfo.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_NONE &&
|
||||
snapInfo.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsSize scrollPortSize = mScrollPort.Size();
|
||||
nsRect scrollRange = GetScrollRangeForClamping();
|
||||
|
||||
nsPoint destPos = nsPoint(styles.mScrollSnapDestinationX.mLength,
|
||||
styles.mScrollSnapDestinationY.mLength);
|
||||
if (styles.mScrollSnapDestinationX.mHasPercent) {
|
||||
destPos.x += NSToCoordFloorClamped(styles.mScrollSnapDestinationX.mPercent
|
||||
* scrollPortSize.width);
|
||||
}
|
||||
|
||||
if (styles.mScrollSnapDestinationY.mHasPercent) {
|
||||
destPos.y += NSToCoordFloorClamped(styles.mScrollSnapDestinationY.mPercent
|
||||
* scrollPortSize.height);
|
||||
}
|
||||
nsPoint destPos = snapInfo.mScrollSnapDestination;
|
||||
|
||||
CalcSnapPoints calcSnapPoints(aUnit, aDestination, aStartPos);
|
||||
|
||||
if (styles.mScrollSnapPointsX.GetUnit() != eStyleUnit_None) {
|
||||
nscoord interval = nsRuleNode::ComputeCoordPercentCalc(styles.mScrollSnapPointsX,
|
||||
scrollPortSize.width);
|
||||
if (snapInfo.mScrollSnapIntervalX.isSome()) {
|
||||
nscoord interval = snapInfo.mScrollSnapIntervalX.value();
|
||||
calcSnapPoints.AddVerticalEdgeInterval(scrollRange, interval, destPos.x);
|
||||
}
|
||||
if (styles.mScrollSnapPointsY.GetUnit() != eStyleUnit_None) {
|
||||
nscoord interval = nsRuleNode::ComputeCoordPercentCalc(styles.mScrollSnapPointsY,
|
||||
scrollPortSize.height);
|
||||
if (snapInfo.mScrollSnapIntervalY.isSome()) {
|
||||
nscoord interval = snapInfo.mScrollSnapIntervalY.value();
|
||||
calcSnapPoints.AddHorizontalEdgeInterval(scrollRange, interval, destPos.y);
|
||||
}
|
||||
|
||||
ScrollSnapHelper(calcSnapPoints, mScrolledFrame, mScrolledFrame, destPos);
|
||||
ProcessScrollSnapCoordinates(calcSnapPoints, snapInfo.mScrollSnapCoordinates, destPos);
|
||||
bool snapped = false;
|
||||
nsPoint finalPos = calcSnapPoints.GetBestEdge();
|
||||
nscoord proximityThreshold =
|
||||
Preferences::GetInt("layout.css.scroll-snap.proximity-threshold", 0);
|
||||
proximityThreshold = nsPresContext::CSSPixelsToAppUnits(proximityThreshold);
|
||||
if (styles.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY &&
|
||||
if (snapInfo.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY &&
|
||||
std::abs(aDestination.y - finalPos.y) > proximityThreshold) {
|
||||
finalPos.y = aDestination.y;
|
||||
} else {
|
||||
snapped = true;
|
||||
}
|
||||
if (styles.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY &&
|
||||
if (snapInfo.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY &&
|
||||
std::abs(aDestination.x - finalPos.x) > proximityThreshold) {
|
||||
finalPos.x = aDestination.x;
|
||||
} else {
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
typedef mozilla::CSSIntPoint CSSIntPoint;
|
||||
typedef mozilla::layout::ScrollbarActivity ScrollbarActivity;
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
|
||||
class AsyncScroll;
|
||||
|
@ -390,6 +391,8 @@ public:
|
|||
|
||||
bool UsesContainerScrolling() const;
|
||||
|
||||
ScrollSnapInfo GetScrollSnapInfo() const;
|
||||
|
||||
bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort);
|
||||
|
|
Загрузка…
Ссылка в новой задаче