summaryrefslogtreecommitdiffstats
path: root/layout/generic/ScrollAnimationMSDPhysics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/ScrollAnimationMSDPhysics.cpp')
-rw-r--r--layout/generic/ScrollAnimationMSDPhysics.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/layout/generic/ScrollAnimationMSDPhysics.cpp b/layout/generic/ScrollAnimationMSDPhysics.cpp
new file mode 100644
index 0000000000..2721891788
--- /dev/null
+++ b/layout/generic/ScrollAnimationMSDPhysics.cpp
@@ -0,0 +1,122 @@
+/* -*- 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/. */
+
+#include "ScrollAnimationMSDPhysics.h"
+#include "mozilla/StaticPrefs_general.h"
+
+using namespace mozilla;
+
+ScrollAnimationMSDPhysics::ScrollAnimationMSDPhysics(const nsPoint& aStartPos)
+ : mStartPos(aStartPos),
+ mModelX(
+ 0, 0, 0,
+ StaticPrefs::general_smoothScroll_msdPhysics_regularSpringConstant(),
+ 1),
+ mModelY(
+ 0, 0, 0,
+ StaticPrefs::general_smoothScroll_msdPhysics_regularSpringConstant(),
+ 1),
+ mIsFirstIteration(true) {}
+
+void ScrollAnimationMSDPhysics::Update(const TimeStamp& aTime,
+ const nsPoint& aDestination,
+ const nsSize& aCurrentVelocity) {
+ double springConstant = ComputeSpringConstant(aTime);
+
+ // mLastSimulatedTime is the most recent time that this animation has been
+ // "observed" at. We don't want to update back to a state in the past, so we
+ // set mStartTime to the more recent of mLastSimulatedTime and aTime.
+ // aTime can be in the past if we're processing an input event whose internal
+ // timestamp is in the past.
+ if (mLastSimulatedTime && aTime < mLastSimulatedTime) {
+ mStartTime = mLastSimulatedTime;
+ } else {
+ mStartTime = aTime;
+ }
+
+ if (!mIsFirstIteration) {
+ mStartPos = PositionAt(mStartTime);
+ }
+
+ mLastSimulatedTime = mStartTime;
+ mDestination = aDestination;
+ mModelX = AxisPhysicsMSDModel(mStartPos.x, aDestination.x,
+ aCurrentVelocity.width, springConstant, 1);
+ mModelY = AxisPhysicsMSDModel(mStartPos.y, aDestination.y,
+ aCurrentVelocity.height, springConstant, 1);
+ mIsFirstIteration = false;
+}
+
+void ScrollAnimationMSDPhysics::ApplyContentShift(const CSSPoint& aShiftDelta) {
+ // Rather than rebuilding the physics models to reflect the shift, just
+ // save it in a variable that's tacked onto the result of PositionAt().
+ // The shfit does not affect the velocity of the animation.
+ mContentShift += CSSPoint::ToAppUnits(aShiftDelta);
+}
+
+double ScrollAnimationMSDPhysics::ComputeSpringConstant(
+ const TimeStamp& aTime) {
+ if (!mPreviousEventTime) {
+ mPreviousEventTime = aTime;
+ mPreviousDelta = TimeDuration();
+ return StaticPrefs::
+ general_smoothScroll_msdPhysics_motionBeginSpringConstant();
+ }
+
+ TimeDuration delta = aTime - mPreviousEventTime;
+ TimeDuration previousDelta = mPreviousDelta;
+
+ mPreviousEventTime = aTime;
+ mPreviousDelta = delta;
+
+ double deltaMS = delta.ToMilliseconds();
+ if (deltaMS >=
+ StaticPrefs::
+ general_smoothScroll_msdPhysics_continuousMotionMaxDeltaMS()) {
+ return StaticPrefs::
+ general_smoothScroll_msdPhysics_motionBeginSpringConstant();
+ }
+
+ if (previousDelta &&
+ deltaMS >=
+ StaticPrefs::general_smoothScroll_msdPhysics_slowdownMinDeltaMS() &&
+ deltaMS >=
+ previousDelta.ToMilliseconds() *
+ StaticPrefs::
+ general_smoothScroll_msdPhysics_slowdownMinDeltaRatio()) {
+ // The rate of events has slowed (the time delta between events has
+ // increased) enough that we think that the current scroll motion is coming
+ // to a stop. Use a stiffer spring in order to reach the destination more
+ // quickly.
+ return StaticPrefs::
+ general_smoothScroll_msdPhysics_slowdownSpringConstant();
+ }
+
+ return StaticPrefs::general_smoothScroll_msdPhysics_regularSpringConstant();
+}
+
+void ScrollAnimationMSDPhysics::SimulateUntil(const TimeStamp& aTime) {
+ if (!mLastSimulatedTime || aTime < mLastSimulatedTime) {
+ return;
+ }
+ TimeDuration delta = aTime - mLastSimulatedTime;
+ mModelX.Simulate(delta);
+ mModelY.Simulate(delta);
+ mLastSimulatedTime = aTime;
+}
+
+nsPoint ScrollAnimationMSDPhysics::PositionAt(const TimeStamp& aTime) {
+ SimulateUntil(aTime);
+ return nsPoint(NSToCoordRound(mModelX.GetPosition()),
+ NSToCoordRound(mModelY.GetPosition())) +
+ mContentShift;
+}
+
+nsSize ScrollAnimationMSDPhysics::VelocityAt(const TimeStamp& aTime) {
+ SimulateUntil(aTime);
+ return nsSize(NSToCoordRound(mModelX.GetVelocity()),
+ NSToCoordRound(mModelY.GetVelocity()));
+}