Bug 1402498 - Rename AsyncScrollBase to ScrollAnimationPhysics and use composition instead of inheritance. r?rhunt draft
authorMarkus Stange <mstange@themasta.com>
Fri, 22 Sep 2017 13:42:29 -0400
changeset 672906 2879bfab982715010c6e65483b8a049b309cdada
parent 672905 55eeebb91408a86b5f43647e4dbf7e36addae23b
child 672907 81237dbc3a41424bbaaad2e3c94c0aa1b41f1dd4
push id82420
push userbmo:mstange@themasta.com
push dateFri, 29 Sep 2017 22:38:50 +0000
reviewersrhunt
bugs1402498
milestone58.0a1
Bug 1402498 - Rename AsyncScrollBase to ScrollAnimationPhysics and use composition instead of inheritance. r?rhunt MozReview-Commit-ID: 7UFf0mZsrEr
dom/events/WheelHandlingHelper.cpp
gfx/layers/apz/src/GenericScrollAnimation.cpp
gfx/layers/apz/src/GenericScrollAnimation.h
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/KeyboardScrollAnimation.cpp
gfx/layers/apz/src/WheelScrollAnimation.cpp
layout/generic/AsyncScrollBase.cpp
layout/generic/AsyncScrollBase.h
layout/generic/ScrollAnimationPhysics.cpp
layout/generic/ScrollAnimationPhysics.h
layout/generic/moz.build
layout/generic/nsGfxScrollFrame.cpp
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -16,17 +16,17 @@
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsIScrollableFrame.h"
 #include "nsITimer.h"
 #include "nsPluginFrame.h"
 #include "nsPresContext.h"
 #include "prtime.h"
 #include "Units.h"
-#include "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 
 namespace mozilla {
 
 /******************************************************************/
 /* mozilla::DeltaValues                                           */
 /******************************************************************/
 
 DeltaValues::DeltaValues(WidgetWheelEvent* aEvent)
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -10,18 +10,18 @@
 #include "gfxPrefs.h"
 #include "nsPoint.h"
 
 namespace mozilla {
 namespace layers {
 
 GenericScrollAnimation::GenericScrollAnimation(AsyncPanZoomController& aApzc,
                                                const nsPoint& aInitialPosition)
-  : AsyncScrollBase(aInitialPosition)
-  , mApzc(aApzc)
+  : mApzc(aApzc)
+  , mAnimationPhysics(aInitialPosition)
   , mFinalDestination(aInitialPosition)
   , mForceVerticalOverscroll(false)
 {
 }
 
 void
 GenericScrollAnimation::UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
 {
@@ -36,51 +36,51 @@ GenericScrollAnimation::UpdateDestinatio
   mFinalDestination = aDestination;
 
   Update(aTime, aCurrentVelocity);
 }
 
 void
 GenericScrollAnimation::Update(TimeStamp aTime, const nsSize& aCurrentVelocity)
 {
-  if (mIsFirstIteration) {
-    InitializeHistory(aTime);
+  if (mAnimationPhysics.mIsFirstIteration) {
+    mAnimationPhysics.InitializeHistory(aTime);
   }
 
   // Clamp the final destination to the scrollable area.
   CSSPoint clamped = CSSPoint::FromAppUnits(mFinalDestination);
   clamped.x = mApzc.mX.ClampOriginToScrollableRect(clamped.x);
   clamped.y = mApzc.mY.ClampOriginToScrollableRect(clamped.y);
   mFinalDestination = CSSPoint::ToAppUnits(clamped);
 
-  AsyncScrollBase::Update(aTime, mFinalDestination, aCurrentVelocity);
+  mAnimationPhysics.Update(aTime, mFinalDestination, aCurrentVelocity);
 }
 
 bool
 GenericScrollAnimation::DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta)
 {
   TimeStamp now = mApzc.GetFrameTime();
   CSSToParentLayerScale2D zoom = aFrameMetrics.GetZoom();
 
   // If the animation is finished, make sure the final position is correct by
   // using one last displacement. Otherwise, compute the delta via the timing
   // function as normal.
-  bool finished = IsFinished(now);
+  bool finished = mAnimationPhysics.IsFinished(now);
   nsPoint sampledDest = finished
-                        ? mDestination
-                        : PositionAt(now);
+                        ? mAnimationPhysics.mDestination
+                        : mAnimationPhysics.PositionAt(now);
   ParentLayerPoint displacement =
     (CSSPoint::FromAppUnits(sampledDest) - aFrameMetrics.GetScrollOffset()) * zoom;
 
   if (finished) {
     mApzc.mX.SetVelocity(0);
     mApzc.mY.SetVelocity(0);
   } else if (!IsZero(displacement)) {
     // Convert velocity from AppUnits/Seconds to ParentLayerCoords/Milliseconds
-    nsSize velocity = VelocityAt(now);
+    nsSize velocity = mAnimationPhysics.VelocityAt(now);
     ParentLayerPoint velocityPL =
       CSSPoint::FromAppUnits(nsPoint(velocity.width, velocity.height)) * zoom;
     mApzc.mX.SetVelocity(velocityPL.x / 1000.0);
     mApzc.mY.SetVelocity(velocityPL.y / 1000.0);
   }
 
   // Note: we ignore overscroll for generic animations.
   ParentLayerPoint adjustedOffset, overscroll;
--- a/gfx/layers/apz/src/GenericScrollAnimation.h
+++ b/gfx/layers/apz/src/GenericScrollAnimation.h
@@ -3,45 +3,45 @@
 /* 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_layers_GenericScrollAnimation_h_
 #define mozilla_layers_GenericScrollAnimation_h_
 
 #include "AsyncPanZoomAnimation.h"
-#include "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 
 class GenericScrollAnimation
-  : public AsyncPanZoomAnimation,
-    public AsyncScrollBase
+  : public AsyncPanZoomAnimation
 {
 public:
   GenericScrollAnimation(AsyncPanZoomController& aApzc,
                          const nsPoint& aInitialPosition);
 
   bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override;
 
   void UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity);
   void UpdateDestination(TimeStamp aTime, nsPoint aDestination, const nsSize& aCurrentVelocity);
 
   CSSPoint GetDestination() const {
     return CSSPoint::FromAppUnits(mFinalDestination);
   }
 
 private:
   void Update(TimeStamp aTime, const nsSize& aCurrentVelocity);
-
+ 
 protected:
   AsyncPanZoomController& mApzc;
+  ScrollAnimationPhysics mAnimationPhysics;
   nsPoint mFinalDestination;
   bool mForceVerticalOverscroll;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_GenericScrollAnimation_h_
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et 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 "InputBlockState.h"
 #include "AsyncPanZoomController.h"         // for AsyncPanZoomController
-#include "AsyncScrollBase.h"                // for kScrollSeriesTimeoutMs
+#include "ScrollAnimationPhysics.h"         // for kScrollSeriesTimeoutMs
 #include "gfxPrefs.h"                       // for gfxPrefs
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Telemetry.h"              // for Telemetry
 #include "mozilla/layers/APZCTreeManager.h" // for AllowedTouchBehavior
 #include "OverscrollHandoffState.h"
 #include "QueuedInput.h"
 
 #define TBS_LOG(...)
--- a/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
+++ b/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
@@ -14,31 +14,31 @@ namespace layers {
 KeyboardScrollAnimation::KeyboardScrollAnimation(AsyncPanZoomController& aApzc,
                                                  const nsPoint& aInitialPosition,
                                                  KeyboardScrollAction::KeyboardScrollActionType aType)
   : GenericScrollAnimation(aApzc, aInitialPosition)
 {
   switch (aType) {
     case KeyboardScrollAction::eScrollCharacter:
     case KeyboardScrollAction::eScrollLine: {
-      mOriginMaxMS = clamped(gfxPrefs::LineSmoothScrollMaxDurationMs(), 0, 10000);
-      mOriginMinMS = clamped(gfxPrefs::LineSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+      mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::LineSmoothScrollMaxDurationMs(), 0, 10000);
+      mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::LineSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
       break;
     }
     case KeyboardScrollAction::eScrollPage: {
-      mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
-      mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+      mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
+      mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
       break;
     }
     case KeyboardScrollAction::eScrollComplete: {
-      mOriginMaxMS = clamped(gfxPrefs::OtherSmoothScrollMaxDurationMs(), 0, 10000);
-      mOriginMinMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+      mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::OtherSmoothScrollMaxDurationMs(), 0, 10000);
+      mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
       break;
     }
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
-  mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
-  mIntervalRatio = std::max(1.0, mIntervalRatio);
+  mAnimationPhysics.mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
+  mAnimationPhysics.mIntervalRatio = std::max(1.0, mAnimationPhysics.mIntervalRatio);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/WheelScrollAnimation.cpp
+++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp
@@ -17,28 +17,28 @@ WheelScrollAnimation::WheelScrollAnimati
                                            const nsPoint& aInitialPosition,
                                            ScrollWheelInput::ScrollDeltaType aDeltaType)
   : GenericScrollAnimation(aApzc, aInitialPosition)
 {
   mForceVerticalOverscroll = !mApzc.mScrollMetadata.AllowVerticalScrollWithWheel();
 
   switch (aDeltaType) {
   case ScrollWheelInput::SCROLLDELTA_PAGE:
-    mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
-    mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
+    mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
     break;
   case ScrollWheelInput::SCROLLDELTA_PIXEL:
-    mOriginMaxMS = clamped(gfxPrefs::PixelSmoothScrollMaxDurationMs(), 0, 10000);
-    mOriginMinMS = clamped(gfxPrefs::PixelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::PixelSmoothScrollMaxDurationMs(), 0, 10000);
+    mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::PixelSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
     break;
   case ScrollWheelInput::SCROLLDELTA_LINE:
-    mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
-    mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
+    mAnimationPhysics.mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mAnimationPhysics.mOriginMaxMS);
     break;
   }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
-  mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
-  mIntervalRatio = std::max(1.0, mIntervalRatio);
+  mAnimationPhysics.mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
+  mAnimationPhysics.mIntervalRatio = std::max(1.0, mAnimationPhysics.mIntervalRatio);
 }
 
 } // namespace layers
 } // namespace mozilla
rename from layout/generic/AsyncScrollBase.cpp
rename to layout/generic/ScrollAnimationPhysics.cpp
--- a/layout/generic/AsyncScrollBase.cpp
+++ b/layout/generic/ScrollAnimationPhysics.cpp
@@ -1,28 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 #include "gfxPrefs.h"
 
 using namespace mozilla;
 
-AsyncScrollBase::AsyncScrollBase(nsPoint aStartPos)
+ScrollAnimationPhysics::ScrollAnimationPhysics(nsPoint aStartPos)
  : mIsFirstIteration(true)
  , mStartPos(aStartPos)
 {
 }
 
 void
-AsyncScrollBase::Update(TimeStamp aTime,
-                        nsPoint aDestination,
-                        const nsSize& aCurrentVelocity)
+ScrollAnimationPhysics::Update(TimeStamp aTime,
+                               nsPoint aDestination,
+                               const nsSize& aCurrentVelocity)
 {
   TimeDuration duration = ComputeDuration(aTime);
   nsSize currentVelocity = aCurrentVelocity;
 
   if (!mIsFirstIteration) {
     // If an additional event has not changed the destination, then do not let
     // another minimum duration reset slow things down.  If it would then
     // instead continue with the existing timing function.
@@ -42,17 +42,17 @@ AsyncScrollBase::Update(TimeStamp aTime,
   InitTimingFunction(mTimingFunctionX, mStartPos.x, currentVelocity.width,
                      aDestination.x);
   InitTimingFunction(mTimingFunctionY, mStartPos.y, currentVelocity.height,
                      aDestination.y);
   mIsFirstIteration = false;
 }
 
 TimeDuration
-AsyncScrollBase::ComputeDuration(TimeStamp aTime)
+ScrollAnimationPhysics::ComputeDuration(TimeStamp aTime)
 {
   // Average last 3 delta durations (rounding errors up to 2ms are negligible for us)
   int32_t eventsDeltaMs = (aTime - mPrevEventTime[2]).ToMilliseconds() / 3;
   mPrevEventTime[2] = mPrevEventTime[1];
   mPrevEventTime[1] = mPrevEventTime[0];
   mPrevEventTime[0] = aTime;
 
   // Modulate duration according to events rate (quicker events -> shorter durations).
@@ -61,71 +61,71 @@ AsyncScrollBase::ComputeDuration(TimeSta
   // scrolling quickly. To reduce fluctuations of the duration, we average event
   // intervals using the recent 4 timestamps (now + three prev -> 3 intervals).
   int32_t durationMS = clamped<int32_t>(eventsDeltaMs * mIntervalRatio, mOriginMinMS, mOriginMaxMS);
 
   return TimeDuration::FromMilliseconds(durationMS);
 }
 
 void
-AsyncScrollBase::InitializeHistory(TimeStamp aTime)
+ScrollAnimationPhysics::InitializeHistory(TimeStamp aTime)
 {
   // Starting a new scroll (i.e. not when extending an existing scroll animation),
   // create imaginary prev timestamps with maximum relevant intervals between them.
 
   // Longest relevant interval (which results in maximum duration)
   TimeDuration maxDelta = TimeDuration::FromMilliseconds(mOriginMaxMS / mIntervalRatio);
   mPrevEventTime[0] = aTime              - maxDelta;
   mPrevEventTime[1] = mPrevEventTime[0]  - maxDelta;
   mPrevEventTime[2] = mPrevEventTime[1]  - maxDelta;
 }
 
 void
-AsyncScrollBase::InitTimingFunction(nsSMILKeySpline& aTimingFunction,
-                                    nscoord aCurrentPos,
-                                    nscoord aCurrentVelocity,
-                                    nscoord aDestination)
+ScrollAnimationPhysics::InitTimingFunction(nsSMILKeySpline& aTimingFunction,
+                                           nscoord aCurrentPos,
+                                           nscoord aCurrentVelocity,
+                                           nscoord aDestination)
 {
   if (aDestination == aCurrentPos || gfxPrefs::SmoothScrollCurrentVelocityWeighting() == 0) {
     aTimingFunction.Init(0, 0, 1 - gfxPrefs::SmoothScrollStopDecelerationWeighting(), 1);
     return;
   }
 
   const TimeDuration oneSecond = TimeDuration::FromSeconds(1);
   double slope = aCurrentVelocity * (mDuration / oneSecond) / (aDestination - aCurrentPos);
   double normalization = sqrt(1.0 + slope * slope);
   double dt = 1.0 / normalization * gfxPrefs::SmoothScrollCurrentVelocityWeighting();
   double dxy = slope / normalization * gfxPrefs::SmoothScrollCurrentVelocityWeighting();
   aTimingFunction.Init(dt, dxy, 1 - gfxPrefs::SmoothScrollStopDecelerationWeighting(), 1);
 }
 
 nsPoint
-AsyncScrollBase::PositionAt(TimeStamp aTime) const
+ScrollAnimationPhysics::PositionAt(TimeStamp aTime) const
 {
   double progressX = mTimingFunctionX.GetSplineValue(ProgressAt(aTime));
   double progressY = mTimingFunctionY.GetSplineValue(ProgressAt(aTime));
   return nsPoint(NSToCoordRound((1 - progressX) * mStartPos.x + progressX * mDestination.x),
                  NSToCoordRound((1 - progressY) * mStartPos.y + progressY * mDestination.y));
 }
 
 nsSize
-AsyncScrollBase::VelocityAt(TimeStamp aTime) const
+ScrollAnimationPhysics::VelocityAt(TimeStamp aTime) const
 {
   double timeProgress = ProgressAt(aTime);
   return nsSize(VelocityComponent(timeProgress, mTimingFunctionX,
                                   mStartPos.x, mDestination.x),
                 VelocityComponent(timeProgress, mTimingFunctionY,
                                   mStartPos.y, mDestination.y));
 }
 
 nscoord
-AsyncScrollBase::VelocityComponent(double aTimeProgress,
-                                   const nsSMILKeySpline& aTimingFunction,
-                                   nscoord aStart,
-                                   nscoord aDestination) const
+ScrollAnimationPhysics::VelocityComponent(double aTimeProgress,
+                                          const nsSMILKeySpline& aTimingFunction,
+                                          nscoord aStart,
+                                          nscoord aDestination) const
 {
   double dt, dxy;
   aTimingFunction.GetSplineDerivativeValues(aTimeProgress, dt, dxy);
   if (dt == 0)
     return dxy >= 0 ? nscoord_MAX : nscoord_MIN;
 
   const TimeDuration oneSecond = TimeDuration::FromSeconds(1);
   double slope = dxy / dt;
rename from layout/generic/AsyncScrollBase.h
rename to layout/generic/ScrollAnimationPhysics.h
--- a/layout/generic/AsyncScrollBase.h
+++ b/layout/generic/ScrollAnimationPhysics.h
@@ -1,93 +1,93 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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_AsyncScrollBase_h_
-#define mozilla_layout_AsyncScrollBase_h_
+#ifndef mozilla_layout_ScrollAnimationPhysics_h_
+#define mozilla_layout_ScrollAnimationPhysics_h_
 
 #include "mozilla/TimeStamp.h"
 #include "nsPoint.h"
 #include "nsSMILKeySpline.h"
 
 namespace mozilla {
 
 // This is the base class for driving scroll wheel animation on both the
 // compositor and main thread.
-class AsyncScrollBase
+class ScrollAnimationPhysics
 {
 public:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
-  explicit AsyncScrollBase(nsPoint aStartPos);
+  explicit ScrollAnimationPhysics(nsPoint aStartPos);
 
   void Update(TimeStamp aTime,
               nsPoint aDestination,
               const nsSize& aCurrentVelocity);
 
   // Get the velocity at a point in time in nscoords/sec.
   nsSize VelocityAt(TimeStamp aTime) const;
 
   // Returns the expected scroll position at a given point in time, in app
   // units, relative to the scroll frame.
   nsPoint PositionAt(TimeStamp aTime) const;
 
   bool IsFinished(TimeStamp aTime) {
     return aTime > mStartTime + mDuration;
   }
 
+  // Initialize event history.
+  void InitializeHistory(TimeStamp aTime);
+
+  // Cached Preferences value.
+  //
+  // These values are minimum and maximum animation duration per event origin,
+  // and a global ratio which defines how longer is the animation's duration
+  // compared to the average recent events intervals (such that for a relatively
+  // consistent events rate, the next event arrives before current animation ends)
+  int32_t mOriginMinMS;
+  int32_t mOriginMaxMS;
+  double mIntervalRatio;
+  nsPoint mDestination;
+  bool mIsFirstIteration;
+
 protected:
   double ProgressAt(TimeStamp aTime) const {
     return clamped((aTime - mStartTime) / mDuration, 0.0, 1.0);
   }
 
   nscoord VelocityComponent(double aTimeProgress,
                             const nsSMILKeySpline& aTimingFunction,
                             nscoord aStart, nscoord aDestination) const;
 
   // Calculate duration, possibly dynamically according to events rate and
   // event origin. (also maintain previous timestamps - which are only used
   // here).
   TimeDuration ComputeDuration(TimeStamp aTime);
 
-  // Initialize event history.
-  void InitializeHistory(TimeStamp aTime);
-
   // Initializes the timing function in such a way that the current velocity is
   // preserved.
   void InitTimingFunction(nsSMILKeySpline& aTimingFunction,
                           nscoord aCurrentPos, nscoord aCurrentVelocity,
                           nscoord aDestination);
 
   // mPrevEventTime holds previous 3 timestamps for intervals averaging (to
   // reduce duration fluctuations). When AsyncScroll is constructed and no
   // previous timestamps are available (indicated with mIsFirstIteration),
   // initialize mPrevEventTime using imaginary previous timestamps with maximum
   // relevant intervals between them.
   TimeStamp mPrevEventTime[3];
-  bool mIsFirstIteration;
 
   TimeStamp mStartTime;
 
-  // Cached Preferences value.
-  //
-  // These values are minimum and maximum animation duration per event origin,
-  // and a global ratio which defines how longer is the animation's duration
-  // compared to the average recent events intervals (such that for a relatively
-  // consistent events rate, the next event arrives before current animation ends)
-  int32_t mOriginMinMS;
-  int32_t mOriginMaxMS;
-  double mIntervalRatio;
-
   nsPoint mStartPos;
   TimeDuration mDuration;
-  nsPoint mDestination;
   nsSMILKeySpline mTimingFunctionX;
   nsSMILKeySpline mTimingFunctionY;
 };
 
 // Helper for accelerated wheel deltas. This can be called from the main thread
 // or the APZ Controller thread.
 static inline double
 ComputeAcceleratedWheelDelta(double aDelta, int32_t aCounter, int32_t aFactor)
@@ -97,9 +97,9 @@ ComputeAcceleratedWheelDelta(double aDel
   }
   return (aDelta * aCounter * double(aFactor) / 10);
 }
 
 static const uint32_t kScrollSeriesTimeoutMs = 80; // in milliseconds
 
 } // namespace mozilla
 
-#endif // mozilla_layout_AsyncScrollBase_h_
+#endif // mozilla_layout_ScrollAnimationPhysics_h_
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -63,17 +63,16 @@ with Files('Sticky*'):
 
 with Files('nsPluginFrame.*'):
     BUG_COMPONENT = ('Core', 'Plug-ins')
 
 with Files('nsVideoFrame.*'):
     BUG_COMPONENT = ('Core', 'Audio/Video')
 
 EXPORTS += [
-    'AsyncScrollBase.h',
     'nsCanvasFrame.h',
     'nsContainerFrame.h',
     'nsDirection.h',
     'nsFrame.h',
     'nsFrameIdList.h',
     'nsFrameList.h',
     'nsFrameSelection.h',
     'nsFrameState.h',
@@ -96,16 +95,17 @@ EXPORTS += [
     'nsRubyFrame.h',
     'nsRubyTextContainerFrame.h',
     'nsRubyTextFrame.h',
     'nsSplittableFrame.h',
     'nsSubDocumentFrame.h',
     'nsTextFrameUtils.h',
     'nsTextRunTransformations.h',
     'RubyUtils.h',
+    'ScrollAnimationPhysics.h',
     'ScrollbarActivity.h',
     'ScrollSnap.h',
     'TextDrawTarget.h',
     'Visibility.h',
 ]
 
 EXPORTS.mozilla += [
     'CSSAlignUtils.h',
@@ -117,17 +117,16 @@ EXPORTS.mozilla += [
     'WritingModes.h',
 ]
 
 EXPORTS.mozilla.layout += [
     'FrameChildList.h',
 ]
 
 UNIFIED_SOURCES += [
-    'AsyncScrollBase.cpp',
     'BlockReflowInput.cpp',
     'BRFrame.cpp',
     'CSSAlignUtils.cpp',
     'CSSOrderAwareFrameIterator.cpp',
     'DetailsFrame.cpp',
     'FrameChildList.cpp',
     'MathMLTextRunFactory.cpp',
     'nsAbsoluteContainingBlock.cpp',
@@ -172,16 +171,17 @@ UNIFIED_SOURCES += [
     'nsSubDocumentFrame.cpp',
     'nsTextFrame.cpp',
     'nsTextFrameUtils.cpp',
     'nsTextRunTransformations.cpp',
     'nsVideoFrame.cpp',
     'ReflowInput.cpp',
     'ReflowOutput.cpp',
     'RubyUtils.cpp',
+    'ScrollAnimationPhysics.cpp',
     'ScrollbarActivity.cpp',
     'ScrollSnap.cpp',
     'ScrollVelocityQueue.cpp',
     'StickyScrollContainer.cpp',
     'TextOverflow.cpp',
     'ViewportFrame.cpp',
 ]
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -52,17 +52,17 @@
 #include "nsRefreshDriver.h"
 #include "nsThemeConstants.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsIScrollPositionListener.h"
 #include "StickyScrollContainer.h"
 #include "nsIFrameInlines.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
-#include "AsyncScrollBase.h"
+#include "ScrollAnimationPhysics.h"
 #include "ScrollSnap.h"
 #include "UnitTransforms.h"
 #include "nsPluginFrame.h"
 #include "nsSliderFrame.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include <mozilla/layers/AxisPhysicsModel.h>
 #include <mozilla/layers/AxisPhysicsMSDModel.h>
 #include "mozilla/layers/LayerTransactionChild.h"
@@ -1794,25 +1794,24 @@ private:
   nsRect mRange;
   mozilla::TimeStamp mLastRefreshTime;
   ScrollFrameHelper *mCallee;
   nscoord mOneDevicePixelInAppUnits;
 };
 
 // AsyncScroll has ref counting.
 class ScrollFrameHelper::AsyncScroll final
-  : public nsARefreshObserver,
-    public AsyncScrollBase
+  : public nsARefreshObserver
 {
 public:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
   explicit AsyncScroll(nsPoint aStartPos)
-    : AsyncScrollBase(aStartPos)
+    : mAnimationPhysics(aStartPos)
     , mCallee(nullptr)
   {
     Telemetry::SetHistogramRecordingEnabled(
       Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, true);
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
@@ -1825,16 +1824,18 @@ private:
 public:
   void InitSmoothScroll(TimeStamp aTime, nsPoint aDestination,
                         nsIAtom *aOrigin, const nsRect& aRange,
                         const nsSize& aCurrentVelocity);
   void Init(const nsRect& aRange) {
     mRange = aRange;
   }
 
+  ScrollAnimationPhysics mAnimationPhysics;
+
   // Most recent scroll origin.
   RefPtr<nsIAtom> mOrigin;
 
   // Allowed destination positions around mDestination
   nsRect mRange;
   bool mIsSmoothScroll;
 
 private:
@@ -1901,70 +1902,70 @@ ScrollFrameHelper::AsyncScroll::InitPref
     // changes we should never have aOrigin == nsGkAtoms::restore here.
     aOrigin = nsGkAtoms::other;
   }
   // Likewise we should never get APZ-triggered scrolls here, and if that changes
   // something is likely broken somewhere.
   MOZ_ASSERT(aOrigin != nsGkAtoms::apz);
 
   // Read preferences only on first iteration or for a different event origin.
-  if (!mIsFirstIteration && aOrigin == mOrigin) {
+  if (!mAnimationPhysics.mIsFirstIteration && aOrigin == mOrigin) {
     return;
   }
 
   mOrigin = aOrigin;
-  mOriginMinMS = mOriginMaxMS = 0;
+  mAnimationPhysics.mOriginMinMS = mAnimationPhysics.mOriginMaxMS = 0;
   bool isOriginSmoothnessEnabled = false;
-  mIntervalRatio = 1;
+  mAnimationPhysics.mIntervalRatio = 1;
 
   // Default values for all preferences are defined in all.js
   static const int32_t kDefaultMinMS = 150, kDefaultMaxMS = 150;
   static const bool kDefaultIsSmoothEnabled = true;
 
   nsAutoCString originName;
   aOrigin->ToUTF8String(originName);
   nsAutoCString prefBase = NS_LITERAL_CSTRING("general.smoothScroll.") + originName;
 
   isOriginSmoothnessEnabled = Preferences::GetBool(prefBase.get(), kDefaultIsSmoothEnabled);
   if (isOriginSmoothnessEnabled) {
     nsAutoCString prefMin = prefBase + NS_LITERAL_CSTRING(".durationMinMS");
     nsAutoCString prefMax = prefBase + NS_LITERAL_CSTRING(".durationMaxMS");
-    mOriginMinMS = Preferences::GetInt(prefMin.get(), kDefaultMinMS);
-    mOriginMaxMS = Preferences::GetInt(prefMax.get(), kDefaultMaxMS);
+    mAnimationPhysics.mOriginMinMS = Preferences::GetInt(prefMin.get(), kDefaultMinMS);
+    mAnimationPhysics.mOriginMaxMS = Preferences::GetInt(prefMax.get(), kDefaultMaxMS);
 
     static const int32_t kSmoothScrollMaxAllowedAnimationDurationMS = 10000;
-    mOriginMaxMS = clamped(mOriginMaxMS, 0, kSmoothScrollMaxAllowedAnimationDurationMS);
-    mOriginMinMS = clamped(mOriginMinMS, 0, mOriginMaxMS);
+    mAnimationPhysics.mOriginMaxMS = clamped(mAnimationPhysics.mOriginMaxMS, 0, kSmoothScrollMaxAllowedAnimationDurationMS);
+    mAnimationPhysics.mOriginMinMS = clamped(mAnimationPhysics.mOriginMinMS, 0, mAnimationPhysics.mOriginMaxMS);
   }
 
   // Keep the animation duration longer than the average event intervals
   //   (to "connect" consecutive scroll animations before the scroll comes to a stop).
   static const double kDefaultDurationToIntervalRatio = 2; // Duplicated at all.js
-  mIntervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio",
-                                       kDefaultDurationToIntervalRatio * 100) / 100.0;
+  mAnimationPhysics.mIntervalRatio = Preferences::GetInt("general.smoothScroll.durationToIntervalRatio",
+                                                      kDefaultDurationToIntervalRatio * 100) / 100.0;
 
   // Duration should be at least as long as the intervals -> ratio is at least 1
-  mIntervalRatio = std::max(1.0, mIntervalRatio);
-
-  if (mIsFirstIteration) {
-    InitializeHistory(aTime);
+  mAnimationPhysics.mIntervalRatio = std::max(1.0, mAnimationPhysics.mIntervalRatio);
+
+  if (mAnimationPhysics.mIsFirstIteration) {
+    mAnimationPhysics.InitializeHistory(aTime);
   }
 }
 
 void
 ScrollFrameHelper::AsyncScroll::InitSmoothScroll(TimeStamp aTime,
                                                  nsPoint aDestination,
                                                  nsIAtom *aOrigin,
                                                  const nsRect& aRange,
                                                  const nsSize& aCurrentVelocity)
 {
   InitPreferences(aTime, aOrigin);
   mRange = aRange;
 
-  Update(aTime, aDestination, aCurrentVelocity);
+  mAnimationPhysics.Update(aTime, aDestination, aCurrentVelocity);
 }
 
 bool
 ScrollFrameHelper::IsSmoothScrollingEnabled()
 {
   return Preferences::GetBool(SMOOTH_SCROLL_PREF_NAME, false);
 }
 
@@ -2123,18 +2124,18 @@ ScrollFrameHelper::AsyncScrollCallback(S
     "Did not expect AsyncScrollCallback without an active async scroll.");
 
   if (!aInstance || !aInstance->mAsyncScroll) {
     return;  // XXX wallpaper bug 1107353 for now.
   }
 
   nsRect range = aInstance->mAsyncScroll->mRange;
   if (aInstance->mAsyncScroll->mIsSmoothScroll) {
-    if (!aInstance->mAsyncScroll->IsFinished(aTime)) {
-      nsPoint destination = aInstance->mAsyncScroll->PositionAt(aTime);
+    if (!aInstance->mAsyncScroll->mAnimationPhysics.IsFinished(aTime)) {
+      nsPoint destination = aInstance->mAsyncScroll->mAnimationPhysics.PositionAt(aTime);
       // Allow this scroll operation to land on any pixel boundary between the
       // current position and the final allowed range.  (We don't want
       // intermediate steps to be more constrained than the final step!)
       nsRect intermediateRange =
         nsRect(aInstance->GetScrollPosition(), nsSize()).UnionEdges(range);
       aInstance->ScrollToImpl(destination, intermediateRange);
       // 'aInstance' might be destroyed here
       return;
@@ -2287,17 +2288,17 @@ ScrollFrameHelper::ScrollToWithOrigin(ns
     if (aMode == nsIScrollableFrame::SMOOTH_MSD) {
       mIgnoreMomentumScroll = true;
       if (!mAsyncSmoothMSDScroll) {
         nsPoint sv = mVelocityQueue.GetVelocity();
         currentVelocity.width = sv.x;
         currentVelocity.height = sv.y;
         if (mAsyncScroll) {
           if (mAsyncScroll->mIsSmoothScroll) {
-            currentVelocity = mAsyncScroll->VelocityAt(now);
+            currentVelocity = mAsyncScroll->mAnimationPhysics.VelocityAt(now);
           }
           mAsyncScroll = nullptr;
         }
 
         if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) && WantAsyncScroll()) {
           if (mApzSmoothScrollDestination == Some(mDestination) &&
               mScrollGeneration == sScrollGenerationCounter) {
             // If we already sent APZ a smooth-scroll request to this