diff options
Diffstat (limited to 'layout/generic/ScrollSnapInfo.h')
-rw-r--r-- | layout/generic/ScrollSnapInfo.h | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/layout/generic/ScrollSnapInfo.h b/layout/generic/ScrollSnapInfo.h new file mode 100644 index 0000000000..bca148427b --- /dev/null +++ b/layout/generic/ScrollSnapInfo.h @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_layout_ScrollSnapInfo_h_ +#define mozilla_layout_ScrollSnapInfo_h_ + +#include <memory> +#include "mozilla/ScrollTypes.h" +#include "mozilla/ScrollSnapTargetId.h" +#include "mozilla/ServoStyleConsts.h" +#include "mozilla/Maybe.h" +#include "mozilla/layers/LayersTypes.h" +#include "nsPoint.h" + +class nsIContent; +class nsIFrame; +struct nsRect; +struct nsSize; +struct nsStyleDisplay; + +namespace mozilla { + +enum class StyleScrollSnapStrictness : uint8_t; +class WritingMode; + +struct SnapPoint { + SnapPoint() = default; + explicit SnapPoint(const nsPoint& aPoint) + : mX(Some(aPoint.x)), mY(Some(aPoint.y)) {} + SnapPoint(Maybe<nscoord>&& aX, Maybe<nscoord>&& aY) + : mX(std::move(aX)), mY(std::move(aY)) {} + + bool operator==(const SnapPoint& aOther) const { + return mX == aOther.mX && mY == aOther.mY; + } + + Maybe<nscoord> mX; + Maybe<nscoord> mY; +}; + +struct ScrollSnapInfo { + using ScrollDirection = layers::ScrollDirection; + ScrollSnapInfo(); + + bool operator==(const ScrollSnapInfo& aOther) const { + return mScrollSnapStrictnessX == aOther.mScrollSnapStrictnessX && + mScrollSnapStrictnessY == aOther.mScrollSnapStrictnessY && + mSnapTargets == aOther.mSnapTargets && + mXRangeWiderThanSnapport == aOther.mXRangeWiderThanSnapport && + mYRangeWiderThanSnapport == aOther.mYRangeWiderThanSnapport && + mSnapportSize == aOther.mSnapportSize; + } + + bool HasScrollSnapping() const; + bool HasSnapPositions() const; + + void InitializeScrollSnapStrictness(WritingMode aWritingMode, + const nsStyleDisplay* aDisplay); + + // The scroll frame's scroll-snap-type. + StyleScrollSnapStrictness mScrollSnapStrictnessX; + StyleScrollSnapStrictness mScrollSnapStrictnessY; + + struct SnapTarget { + // The scroll positions corresponding to scroll-snap-align values. + SnapPoint mSnapPoint; + + // https://drafts.csswg.org/css-scroll-snap/#scroll-snap-area + nsRect mSnapArea; + + // https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-stop + StyleScrollSnapStop mScrollSnapStop = StyleScrollSnapStop::Normal; + + // Use for tracking the last snapped target. + ScrollSnapTargetId mTargetId = ScrollSnapTargetId::None; + + SnapTarget() = default; + + SnapTarget(Maybe<nscoord>&& aSnapPositionX, Maybe<nscoord>&& aSnapPositionY, + const nsRect& aSnapArea, StyleScrollSnapStop aScrollSnapStop, + ScrollSnapTargetId aTargetId) + : mSnapPoint(std::move(aSnapPositionX), std::move(aSnapPositionY)), + mSnapArea(aSnapArea), + mScrollSnapStop(aScrollSnapStop), + mTargetId(aTargetId) {} + + bool operator==(const SnapTarget& aOther) const { + return mSnapPoint == aOther.mSnapPoint && mSnapArea == aOther.mSnapArea && + mScrollSnapStop == aOther.mScrollSnapStop && + mTargetId == aOther.mTargetId; + } + }; + + CopyableTArray<SnapTarget> mSnapTargets; + + // A utility function to iterate over the valid snap targets for the given + // |aDestination| until |aFunc| returns false. + void ForEachValidTargetFor( + const nsPoint& aDestination, + const std::function<bool(const SnapTarget&)>& aFunc) const; + + struct ScrollSnapRange { + ScrollSnapRange() = default; + + ScrollSnapRange(const nsRect& aSnapArea, ScrollDirection aDirection, + ScrollSnapTargetId aTargetId) + : mSnapArea(aSnapArea), mDirection(aDirection), mTargetId(aTargetId) {} + + nsRect mSnapArea; + ScrollDirection mDirection; + ScrollSnapTargetId mTargetId; + + bool operator==(const ScrollSnapRange& aOther) const { + return mDirection == aOther.mDirection && mSnapArea == aOther.mSnapArea && + mTargetId == aOther.mTargetId; + } + + nscoord Start() const { + return mDirection == ScrollDirection::eHorizontal ? mSnapArea.X() + : mSnapArea.Y(); + } + + nscoord End() const { + return mDirection == ScrollDirection::eHorizontal ? mSnapArea.XMost() + : mSnapArea.YMost(); + } + + // Returns true if |aPoint| is a valid snap position in this range. + bool IsValid(nscoord aPoint, nscoord aSnapportSize) const { + MOZ_ASSERT(End() - Start() > aSnapportSize); + return Start() <= aPoint && aPoint <= End() - aSnapportSize; + } + }; + // An array of the range that the target element is larger than the snapport + // on the axis. + // Snap positions in this range will be valid snap positions in the case where + // the distance between the closest snap position and the second closest snap + // position is still larger than the snapport size. + // See https://drafts.csswg.org/css-scroll-snap-1/#snap-overflow + // + // Note: This range contains scroll-margin values. + CopyableTArray<ScrollSnapRange> mXRangeWiderThanSnapport; + CopyableTArray<ScrollSnapRange> mYRangeWiderThanSnapport; + + // Note: This snapport size has been already deflated by scroll-padding. + nsSize mSnapportSize; +}; + +} // namespace mozilla + +#endif // mozilla_layout_ScrollSnapInfo_h_ |