Bug 1448439 - Move Axis::FlingApplyFrictionOrCancel() to GenericFlingAnimation. r=kats draft
authorBotond Ballo <botond@mozilla.com>
Fri, 20 Apr 2018 14:02:38 -0400
changeset 788680 2290b72d3026878b34c86f437b0fac093d9fceac
parent 788679 b7361efece81ffc7b9185c2f6d827ca8c75e3eba
child 788681 e53f1d7bbe3e0a588f5d5ba530c59e03cdc50d69
push id108063
push userbballo@mozilla.com
push dateThu, 26 Apr 2018 20:42:29 +0000
reviewerskats
bugs1448439
milestone61.0a1
Bug 1448439 - Move Axis::FlingApplyFrictionOrCancel() to GenericFlingAnimation. r=kats The calculation in that function is specific to a particular physics model, so it's inappropriate to house it in Axis. Also do some light refactoring to this function, to make modifying the velocity the caller's responsibility (this becomes relevant in the next patch, where we factor out the physics logic into a class that can't modify the APZC). MozReview-Commit-ID: 5ALQd3LBx3O
gfx/layers/apz/src/Axis.cpp
gfx/layers/apz/src/Axis.h
gfx/layers/apz/src/GenericFlingAnimation.h
--- a/gfx/layers/apz/src/Axis.cpp
+++ b/gfx/layers/apz/src/Axis.cpp
@@ -367,33 +367,16 @@ CSSCoord Axis::ClampOriginToScrollableRe
 
   return result / zoom;
 }
 
 bool Axis::CanScrollNow() const {
   return !mAxisLocked && CanScroll();
 }
 
-bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta,
-                                      float aFriction,
-                                      float aThreshold) {
-  if (fabsf(mVelocity) <= aThreshold) {
-    // If the velocity is very low, just set it to 0 and stop the fling,
-    // otherwise we'll just asymptotically approach 0 and the user won't
-    // actually see any changes.
-    mVelocity = 0.0f;
-    return false;
-  }
-
-  mVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds()));
-  AXIS_LOG("%p|%s reduced velocity to %f due to friction\n",
-    mAsyncPanZoomController, Name(), mVelocity);
-  return true;
-}
-
 ParentLayerCoord Axis::DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const {
   ParentLayerCoord newOrigin = GetOrigin() + aDisplacement;
   ParentLayerCoord newCompositionEnd = GetCompositionEnd() + aDisplacement;
   // If the current pan plus a displacement takes the window to the left of or
   // above the current page rect.
   bool minus = newOrigin < GetPageStart();
   // If the current pan plus a displacement takes the window to the right of or
   // below the current page rect.
--- a/gfx/layers/apz/src/Axis.h
+++ b/gfx/layers/apz/src/Axis.h
@@ -151,29 +151,16 @@ public:
 
   /**
    * Gets the distance between the starting position of the touch supplied in
    * StartTouch() and the supplied position.
    */
   ParentLayerCoord PanDistance(ParentLayerCoord aPos) const;
 
   /**
-   * Applies friction during a fling, or cancels the fling if the velocity is
-   * too low. Returns true if the fling should continue to another frame, or
-   * false if it should end.
-   * |aDelta| is the amount of time that has passed since the last time
-   * friction was applied.
-   * |aFriction| is the amount of friction to apply.
-   * |aThreshold| is the velocity below which the fling is cancelled.
-   */
-  bool FlingApplyFrictionOrCancel(const TimeDuration& aDelta,
-                                  float aFriction,
-                                  float aThreshold);
-
-  /**
    * Returns true if the page has room to be scrolled along this axis.
    */
   bool CanScroll() const;
 
   /**
    * Returns whether this axis can scroll any more in a particular direction.
    */
   bool CanScroll(ParentLayerCoord aDelta) const;
--- a/gfx/layers/apz/src/GenericFlingAnimation.h
+++ b/gfx/layers/apz/src/GenericFlingAnimation.h
@@ -93,42 +93,46 @@ public:
    * or false if there is no fling or the fling has ended.
    */
   virtual bool DoSample(FrameMetrics& aFrameMetrics,
                         const TimeDuration& aDelta) override
   {
     float friction = gfxPrefs::APZFlingFriction();
     float threshold = gfxPrefs::APZFlingStoppedThreshold();
 
-    bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta, friction, threshold),
-         shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta, friction, threshold);
+    // Save the velocity locally instead of just passing it directly into
+    // SetVelocityVector(), because AdjustDisplacement() (called below)
+    // zeroes out the Axis velocity if we're in overscroll, and we need to
+    // hand off the velocity to the tree manager in such a case.
+    ParentLayerPoint velocity(
+        ApplyFrictionOrCancel(mApzc.mX.GetVelocity(), aDelta, friction, threshold),
+        ApplyFrictionOrCancel(mApzc.mY.GetVelocity(), aDelta, friction, threshold));
+    FLING_LOG("%p reduced velocity to %s due to friction\n",
+      &mApzc, ToString(mApzc.GetVelocityVector()).c_str());
+
+    mApzc.SetVelocityVector(velocity);
+
     // If we shouldn't continue the fling, let's just stop and repaint.
-    if (!shouldContinueFlingX && !shouldContinueFlingY) {
+    if (IsZero(velocity)) {
       FLING_LOG("%p ending fling animation. overscrolled=%d\n", &mApzc, mApzc.IsOverscrolled());
       // This APZC or an APZC further down the handoff chain may be be overscrolled.
       // Start a snap-back animation on the overscrolled APZC.
       // Note:
       //   This needs to be a deferred task even though it can safely run
       //   while holding mRecursiveMutex, because otherwise, if the overscrolled APZC
       //   is this one, then the SetState(NOTHING) in UpdateAnimation will
       //   stomp on the SetState(SNAP_BACK) it does.
       mDeferredTasks.AppendElement(NewRunnableMethod<AsyncPanZoomController*>(
         "layers::OverscrollHandoffChain::SnapBackOverscrolledApzc",
         mOverscrollHandoffChain.get(),
         &OverscrollHandoffChain::SnapBackOverscrolledApzc,
         &mApzc));
       return false;
     }
 
-    // AdjustDisplacement() zeroes out the Axis velocity if we're in overscroll.
-    // Since we need to hand off the velocity to the tree manager in such a case,
-    // we save it here. Would be ParentLayerVector instead of ParentLayerPoint
-    // if we had vector classes.
-    ParentLayerPoint velocity = mApzc.GetVelocityVector();
-
     ParentLayerPoint offset = velocity * aDelta.ToMilliseconds();
 
     // Ordinarily we might need to do a ScheduleComposite if either of
     // the following AdjustDisplacement calls returns true, but this
     // is already running as part of a FlingAnimation, so we'll be compositing
     // per frame of animation anyway.
     ParentLayerPoint overscroll;
     ParentLayerPoint adjustedOffset;
@@ -193,16 +197,39 @@ private:
   }
 
   static float Accelerate(float aBase, float aSupplemental)
   {
     return (aBase * gfxPrefs::APZFlingAccelBaseMultiplier())
          + (aSupplemental * gfxPrefs::APZFlingAccelSupplementalMultiplier());
   }
 
+  /**
+   * Applies friction to the given velocity and returns the result, or
+   * returns zero if the velocity is too low.
+   * |aVelocity| is the incoming velocity.
+   * |aDelta| is the amount of time that has passed since the last time
+   * friction was applied.
+   * |aFriction| is the amount of friction to apply.
+   * |aThreshold| is the velocity below which the fling is cancelled.
+   */
+  static float ApplyFrictionOrCancel(float aVelocity, const TimeDuration& aDelta,
+                                     float aFriction, float aThreshold)
+  {
+    if (fabsf(aVelocity) <= aThreshold) {
+      // If the velocity is very low, just set it to 0 and stop the fling,
+      // otherwise we'll just asymptotically approach 0 and the user won't
+      // actually see any changes.
+      return 0.0f;
+    }
+
+    aVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds()));
+    return aVelocity;
+  }
+
   AsyncPanZoomController& mApzc;
   RefPtr<const OverscrollHandoffChain> mOverscrollHandoffChain;
   RefPtr<const AsyncPanZoomController> mScrolledApzc;
 };
 
 } // namespace layers
 } // namespace mozilla