Bug 1030221 - Make sure to clear overscroll if we cancel a fling. r=drs, a=2.0+
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 26 Jun 2014 18:49:11 -0400
changeset 207435 1e4a2e728730d4cb1b7325c6bc57722f905edf5d
parent 207434 54208d905243160d23de3a10366191d89f9241b9
child 207436 da6103e874b6217d462783654f76e61da73f1cdf
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrs, 2
bugs1030221
milestone32.0a2
Bug 1030221 - Make sure to clear overscroll if we cancel a fling. r=drs, a=2.0+
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -396,23 +396,44 @@ static uint32_t sAsyncPanZoomControllerC
 static TimeStamp
 GetFrameTime() {
   if (sFrameTime.IsNull()) {
     return TimeStamp::Now();
   }
   return sFrameTime;
 }
 
-class FlingAnimation: public AsyncPanZoomAnimation {
+// This is a base class for animations that can deal with
+// overscroll states. In particular, it ensures that overscroll
+// states are cleared when the animation is cancelled.
+class OverscrollableAnimation: public AsyncPanZoomAnimation {
+public:
+  OverscrollableAnimation(AsyncPanZoomController& aApzc,
+                          const TimeDuration& aRepaintInterval = TimeDuration::Forever())
+    : AsyncPanZoomAnimation(aRepaintInterval)
+    , mApzc(aApzc)
+  {
+  }
+
+  virtual void Cancel() MOZ_OVERRIDE
+  {
+    mApzc.mX.ClearOverscroll();
+    mApzc.mY.ClearOverscroll();
+  }
+
+protected:
+  AsyncPanZoomController& mApzc;
+};
+
+class FlingAnimation: public OverscrollableAnimation {
 public:
   FlingAnimation(AsyncPanZoomController& aApzc,
                  bool aApplyAcceleration,
                  bool aAllowOverscroll)
-    : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
-    , mApzc(aApzc)
+    : OverscrollableAnimation(aApzc, TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
     , mAllowOverscroll(aAllowOverscroll)
   {
     TimeStamp now = GetFrameTime();
     ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity());
 
     // If the last fling was very recent and in the same direction as this one,
     // boost the velocity to be the sum of the two. Check separate axes separately
     // because we could have two vertical flings with small horizontal components
@@ -551,17 +572,16 @@ private:
   }
 
   static float Accelerate(float aBase, float aSupplemental)
   {
     return (aBase * gfxPrefs::APZFlingAccelBaseMultiplier())
          + (aSupplemental * gfxPrefs::APZFlingAccelSupplementalMultiplier());
   }
 
-  AsyncPanZoomController& mApzc;
   bool mAllowOverscroll;
 };
 
 class ZoomAnimation: public AsyncPanZoomAnimation {
 public:
   ZoomAnimation(CSSPoint aStartOffset, CSSToScreenScale aStartZoom,
                 CSSPoint aEndOffset, CSSToScreenScale aEndZoom)
     : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration()))
@@ -614,42 +634,31 @@ private:
 
   // Target metrics for a zoom to animation. This is only valid when we are in
   // the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and
   // |mResolution| fields on this.
   CSSPoint mEndOffset;
   CSSToScreenScale mEndZoom;
 };
 
-class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation {
+class OverscrollSnapBackAnimation: public OverscrollableAnimation {
 public:
   OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc)
-    : mApzc(aApzc) {}
+    : OverscrollableAnimation(aApzc)
+  {
+  }
 
   virtual bool Sample(FrameMetrics& aFrameMetrics,
                       const TimeDuration& aDelta) MOZ_OVERRIDE
   {
     // Can't inline these variables due to short-circuit evaluation.
     bool continueX = mApzc.mX.SampleSnapBack(aDelta);
     bool continueY = mApzc.mY.SampleSnapBack(aDelta);
     return continueX || continueY;
   }
-
-  virtual void Cancel() MOZ_OVERRIDE
-  {
-    // If the snap-back animation is cancelled for some reason, we need to
-    // clear the overscroll, otherwise the user would be stuck in the
-    // overscrolled state (since touch blocks beginning in an overscrolled
-    // state are ignored).
-    mApzc.mX.ClearOverscroll();
-    mApzc.mY.ClearOverscroll();
-  }
-
-private:
-  AsyncPanZoomController& mApzc;
 };
 
 void
 AsyncPanZoomController::SetFrameTime(const TimeStamp& aTime) {
   sFrameTime = aTime;
 }
 
 void
@@ -1727,16 +1736,17 @@ void AsyncPanZoomController::StartAnimat
   ReentrantMonitorAutoEnter lock(mMonitor);
   mAnimation = aAnimation;
   mLastSampleTime = GetFrameTime();
   ScheduleComposite();
 }
 
 void AsyncPanZoomController::CancelAnimation() {
   ReentrantMonitorAutoEnter lock(mMonitor);
+  APZC_LOG("%p running CancelAnimation in state %d\n", this, mState);
   SetState(NOTHING);
   if (mAnimation) {
     mAnimation->Cancel();
     mAnimation = nullptr;
     // mAnimation->Cancel() may have done something that requires a repaint.
     RequestContentRepaint();
     ScheduleComposite();
     UpdateSharedCompositorFrameMetrics();
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -801,16 +801,17 @@ public:
    * during overscroll handoff for a fling. If we are not pannable, calls
    * mTreeManager->HandOffFling() to hand the fling off further.
    * Returns true iff. any APZC (whether this one or one further in the handoff
    * chain accepted the fling).
    */
   bool TakeOverFling(ScreenPoint aVelocity);
 
 private:
+  friend class OverscrollableAnimation;
   friend class FlingAnimation;
   friend class OverscrollSnapBackAnimation;
   // The initial velocity of the most recent fling.
   ScreenPoint mLastFlingVelocity;
   // The time at which the most recent fling started.
   TimeStamp mLastFlingTime;
 
   // Deal with overscroll resulting from a fling animation. This is only ever