Bug 716863 - Abort uselessly continuing to fling subdocuments once they can't go any farther. r=Cwiiis
authorKartikaya Gupta <kgupta@mozilla.com>
Sat, 21 Jan 2012 12:44:44 -0500
changeset 86288 e862a60fdb13fabdd317a586beec3ce62c62c4bf
parent 86287 e5f5c1c96f4e2ab84f2f4b15ed86b0ae57d25bfb
child 86289 328f9cbb65984bf81db49f9c47310b41d7007bfb
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCwiiis
bugs716863
milestone12.0a1
Bug 716863 - Abort uselessly continuing to fling subdocuments once they can't go any farther. r=Cwiiis
mobile/android/base/ui/Axis.java
mobile/android/base/ui/SubdocumentScrollHelper.java
mobile/android/chrome/content/browser.js
--- a/mobile/android/base/ui/Axis.java
+++ b/mobile/android/base/ui/Axis.java
@@ -207,16 +207,22 @@ abstract class Axis {
         }
     }
 
     /* Advances a fling animation by one step. */
     boolean advanceFling() {
         if (mFlingState != FlingStates.FLINGING) {
             return false;
         }
+        if (mSubscroller.scrolling() && !mSubscroller.lastScrollSucceeded()) {
+            // if the subdocument stopped scrolling, it's because it reached the end
+            // of the subdocument. we don't do overscroll on subdocuments, so there's
+            // no point in continuing this fling.
+            return false;
+        }
 
         float excess = getExcess();
         if (mDisableSnap || FloatUtils.fuzzyEquals(excess, 0.0f)) {
             // If we aren't overscrolled, just apply friction.
             if (Math.abs(mVelocity) >= VELOCITY_THRESHOLD) {
                 mVelocity *= FRICTION_FAST;
             } else {
                 float t = mVelocity / VELOCITY_THRESHOLD;
--- a/mobile/android/base/ui/SubdocumentScrollHelper.java
+++ b/mobile/android/base/ui/SubdocumentScrollHelper.java
@@ -55,16 +55,17 @@ class SubdocumentScrollHelper implements
     private static String MESSAGE_SCROLL_ACK = "Gesture:ScrollAck";
 
     private final PanZoomController mPanZoomController;
     private final Handler mUiHandler;
 
     private boolean mOverridePanning;
     private boolean mOverrideScrollAck;
     private boolean mOverrideScrollPending;
+    private boolean mScrollSucceeded;
 
     SubdocumentScrollHelper(PanZoomController controller) {
         mPanZoomController = controller;
         // mUiHandler will be bound to the UI thread since that's where this constructor runs
         mUiHandler = new Handler();
 
         GeckoAppShell.registerGeckoEventListener(MESSAGE_PANNING_OVERRIDE, this);
         GeckoAppShell.registerGeckoEventListener(MESSAGE_CANCEL_OVERRIDE, this);
@@ -99,32 +100,38 @@ class SubdocumentScrollHelper implements
     void cancel() {
         mOverridePanning = false;
     }
 
     boolean scrolling() {
         return mOverridePanning;
     }
 
+    boolean lastScrollSucceeded() {
+        return mScrollSucceeded;
+    }
+
     // GeckoEventListener implementation
 
     public void handleMessage(final String event, final JSONObject message) {
         // this comes in on the gecko thread; hand off the handling to the UI thread
         mUiHandler.post(new Runnable() {
             public void run() {
                 Log.i(LOGTAG, "Got message: " + event);
                 try {
                     if (MESSAGE_PANNING_OVERRIDE.equals(event)) {
                         mOverridePanning = true;
                         mOverrideScrollAck = true;
                         mOverrideScrollPending = false;
+                        mScrollSucceeded = true;
                     } else if (MESSAGE_CANCEL_OVERRIDE.equals(event)) {
                         mOverridePanning = false;
                     } else if (MESSAGE_SCROLL_ACK.equals(event)) {
                         mOverrideScrollAck = true;
+                        mScrollSucceeded = message.getBoolean("scrolled");
                         if (mOverridePanning && mOverrideScrollPending) {
                             scrollBy(mPanZoomController.getDisplacement());
                         }
                     }
                 } catch (Exception e) {
                     Log.e(LOGTAG, "Exception handling message", e);
                 }
             }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2070,18 +2070,22 @@ var BrowserEventHandler = {
           sendMessageToJava({ gecko: { type: "Panning:CancelOverride" } });
           return;
         }
 
         this._firstScrollEvent = false;
       }
 
       // Scroll the scrollable element
-      this._scrollElementBy(this._scrollableElement, data.x, data.y);
-      sendMessageToJava({ gecko: { type: "Gesture:ScrollAck" } });
+      if (this._elementCanScroll(this._scrollableElement, data.x, data.y)) {
+        this._scrollElementBy(this._scrollableElement, data.x, data.y);
+        sendMessageToJava({ gecko: { type: "Gesture:ScrollAck", scrolled: true } });
+      } else {
+        sendMessageToJava({ gecko: { type: "Gesture:ScrollAck", scrolled: false } });
+      }
     } else if (aTopic == "Gesture:CancelTouch") {
       this._cancelTapHighlight();
     } else if (aTopic == "Gesture:ShowPress") {
       let data = JSON.parse(aData);
       let closest = ElementTouchHelper.elementFromPoint(BrowserApp.selectedBrowser.contentWindow, data.x, data.y);
       if (!closest)
         closest = ElementTouchHelper.anyElementFromPoint(BrowserApp.selectedBrowser.contentWindow, data.x, data.y);
       if (closest) {