1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ScrollAnimationMSDPhysics.h"
8 #include "mozilla/StaticPrefs_general.h"
10 using namespace mozilla
;
12 ScrollAnimationMSDPhysics::ScrollAnimationMSDPhysics(const nsPoint
& aStartPos
)
13 : mStartPos(aStartPos
),
16 StaticPrefs::general_smoothScroll_msdPhysics_regularSpringConstant(),
20 StaticPrefs::general_smoothScroll_msdPhysics_regularSpringConstant(),
22 mIsFirstIteration(true) {}
24 void ScrollAnimationMSDPhysics::Update(const TimeStamp
& aTime
,
25 const nsPoint
& aDestination
,
26 const nsSize
& aCurrentVelocity
) {
27 double springConstant
= ComputeSpringConstant(aTime
);
29 // mLastSimulatedTime is the most recent time that this animation has been
30 // "observed" at. We don't want to update back to a state in the past, so we
31 // set mStartTime to the more recent of mLastSimulatedTime and aTime.
32 // aTime can be in the past if we're processing an input event whose internal
33 // timestamp is in the past.
34 if (mLastSimulatedTime
&& aTime
< mLastSimulatedTime
) {
35 mStartTime
= mLastSimulatedTime
;
40 if (!mIsFirstIteration
) {
41 mStartPos
= PositionAt(mStartTime
);
44 mLastSimulatedTime
= mStartTime
;
45 mDestination
= aDestination
;
46 mModelX
= AxisPhysicsMSDModel(mStartPos
.x
, aDestination
.x
,
47 aCurrentVelocity
.width
, springConstant
, 1);
48 mModelY
= AxisPhysicsMSDModel(mStartPos
.y
, aDestination
.y
,
49 aCurrentVelocity
.height
, springConstant
, 1);
50 mIsFirstIteration
= false;
53 void ScrollAnimationMSDPhysics::ApplyContentShift(const CSSPoint
& aShiftDelta
) {
54 // Rather than rebuilding the physics models to reflect the shift, just
55 // save it in a variable that's tacked onto the result of PositionAt().
56 // The shfit does not affect the velocity of the animation.
57 mContentShift
+= CSSPoint::ToAppUnits(aShiftDelta
);
60 double ScrollAnimationMSDPhysics::ComputeSpringConstant(
61 const TimeStamp
& aTime
) {
62 if (!mPreviousEventTime
) {
63 mPreviousEventTime
= aTime
;
64 mPreviousDelta
= TimeDuration();
66 general_smoothScroll_msdPhysics_motionBeginSpringConstant();
69 TimeDuration delta
= aTime
- mPreviousEventTime
;
70 TimeDuration previousDelta
= mPreviousDelta
;
72 mPreviousEventTime
= aTime
;
73 mPreviousDelta
= delta
;
75 double deltaMS
= delta
.ToMilliseconds();
78 general_smoothScroll_msdPhysics_continuousMotionMaxDeltaMS()) {
80 general_smoothScroll_msdPhysics_motionBeginSpringConstant();
85 StaticPrefs::general_smoothScroll_msdPhysics_slowdownMinDeltaMS() &&
87 previousDelta
.ToMilliseconds() *
89 general_smoothScroll_msdPhysics_slowdownMinDeltaRatio()) {
90 // The rate of events has slowed (the time delta between events has
91 // increased) enough that we think that the current scroll motion is coming
92 // to a stop. Use a stiffer spring in order to reach the destination more
95 general_smoothScroll_msdPhysics_slowdownSpringConstant();
98 return StaticPrefs::general_smoothScroll_msdPhysics_regularSpringConstant();
101 void ScrollAnimationMSDPhysics::SimulateUntil(const TimeStamp
& aTime
) {
102 if (!mLastSimulatedTime
|| aTime
< mLastSimulatedTime
) {
105 TimeDuration delta
= aTime
- mLastSimulatedTime
;
106 mModelX
.Simulate(delta
);
107 mModelY
.Simulate(delta
);
108 mLastSimulatedTime
= aTime
;
111 nsPoint
ScrollAnimationMSDPhysics::PositionAt(const TimeStamp
& aTime
) {
112 SimulateUntil(aTime
);
113 return nsPoint(NSToCoordRound(mModelX
.GetPosition()),
114 NSToCoordRound(mModelY
.GetPosition())) +
118 nsSize
ScrollAnimationMSDPhysics::VelocityAt(const TimeStamp
& aTime
) {
119 SimulateUntil(aTime
);
120 return nsSize(NSToCoordRound(mModelX
.GetVelocity()),
121 NSToCoordRound(mModelY
.GetVelocity()));