| Index: android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
|
| diff --git a/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java b/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
|
| index 4564b42ff04c4f76e2bf45c42611cd21bae64bb0..86f693b3fc198f38b75026c65b7e9ff6da8ff23d 100644
|
| --- a/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
|
| +++ b/android_webview/java/src/org/chromium/android_webview/AwScrollOffsetManager.java
|
| @@ -4,6 +4,10 @@
|
|
|
| package org.chromium.android_webview;
|
|
|
| +import android.widget.OverScroller;
|
| +
|
| +import com.google.common.annotations.VisibleForTesting;
|
| +
|
| import org.chromium.base.CalledByNative;
|
|
|
| /**
|
| @@ -12,6 +16,7 @@ import org.chromium.base.CalledByNative;
|
| *
|
| * Unless otherwise values (sizes, scroll offsets) are in physical pixels.
|
| */
|
| +@VisibleForTesting
|
| public class AwScrollOffsetManager {
|
| // The unit of all the values in this delegate are physical pixels.
|
| public interface Delegate {
|
| @@ -24,8 +29,11 @@ public class AwScrollOffsetManager {
|
| // operation, the native side shouldn't synchronously alter the scroll offset from within
|
| // this call.
|
| void scrollNativeTo(int x, int y);
|
| +
|
| int getContainerViewScrollX();
|
| int getContainerViewScrollY();
|
| +
|
| + void invalidate();
|
| }
|
|
|
| private final Delegate mDelegate;
|
| @@ -42,14 +50,24 @@ public class AwScrollOffsetManager {
|
| private int mContainerViewWidth;
|
| private int mContainerViewHeight;
|
|
|
| + // Whether we're in the middle of processing a touch event.
|
| private boolean mProcessingTouchEvent;
|
|
|
| + // Whether (and to what value) to update the native side scroll offset after we've finished
|
| + // provessing a touch event.
|
| private boolean mApplyDeferredNativeScroll;
|
| private int mDeferredNativeScrollX;
|
| private int mDeferredNativeScrollY;
|
|
|
| - public AwScrollOffsetManager(Delegate delegate) {
|
| + // The velocity of the last recorded fling,
|
| + private int mLastFlingVelocityX;
|
| + private int mLastFlingVelocityY;
|
| +
|
| + private OverScroller mScroller;
|
| +
|
| + public AwScrollOffsetManager(Delegate delegate, OverScroller overScroller) {
|
| mDelegate = delegate;
|
| + mScroller = overScroller;
|
| }
|
|
|
| //----- Scroll range and extent calculation methods -------------------------------------------
|
| @@ -133,12 +151,25 @@ public class AwScrollOffsetManager {
|
| }
|
|
|
| // Called by the native side to over-scroll the container view.
|
| - public void overscrollBy(int deltaX, int deltaY) {
|
| + public void overScrollBy(int deltaX, int deltaY) {
|
| + // TODO(mkosiba): Once http://crbug.com/260663 and http://crbug.com/261239 are fixed it
|
| + // should be possible to uncomment the following asserts:
|
| + // if (deltaX < 0) assert mDelegate.getContainerViewScrollX() == 0;
|
| + // if (deltaX > 0) assert mDelegate.getContainerViewScrollX() ==
|
| + // computeMaximumHorizontalScrollOffset();
|
| + scrollBy(deltaX, deltaY);
|
| + }
|
| +
|
| + private void scrollBy(int deltaX, int deltaY) {
|
| + if (deltaX == 0 && deltaY == 0) return;
|
| +
|
| final int scrollX = mDelegate.getContainerViewScrollX();
|
| final int scrollY = mDelegate.getContainerViewScrollY();
|
| final int scrollRangeX = computeMaximumHorizontalScrollOffset();
|
| final int scrollRangeY = computeMaximumVerticalScrollOffset();
|
|
|
| + // The android.view.View.overScrollBy method is used for both scrolling and over-scrolling
|
| + // which is why we use it here.
|
| mDelegate.overScrollContainerViewBy(deltaX, deltaY, scrollX, scrollY,
|
| scrollRangeX, scrollRangeY, mProcessingTouchEvent);
|
| }
|
| @@ -201,4 +232,62 @@ public class AwScrollOffsetManager {
|
|
|
| mDelegate.scrollNativeTo(x, y);
|
| }
|
| +
|
| + // Called at the beginning of every fling gesture.
|
| + public void onFlingStartGesture(int velocityX, int velocityY) {
|
| + mLastFlingVelocityX = velocityX;
|
| + mLastFlingVelocityY = velocityY;
|
| + }
|
| +
|
| + // Called whenever some other touch interaction requires the fling gesture to be canceled.
|
| + public void onFlingCancelGesture() {
|
| + // TODO(mkosiba): Support speeding up a fling by flinging again.
|
| + // http://crbug.com/265841
|
| + mScroller.forceFinished(true);
|
| + }
|
| +
|
| + // Called when a fling gesture is not handled by the renderer.
|
| + // We explicitly ask the renderer not to handle fling gestures targeted at the root
|
| + // scroll layer.
|
| + public void onUnhandledFlingStartEvent() {
|
| + flingScroll(-mLastFlingVelocityX, -mLastFlingVelocityY);
|
| + }
|
| +
|
| + // Starts the fling animation. Called both as a response to a fling gesture and as via the
|
| + // public WebView#flingScroll(int, int) API.
|
| + public void flingScroll(int velocityX, int velocityY) {
|
| + final int scrollX = mDelegate.getContainerViewScrollX();
|
| + final int scrollY = mDelegate.getContainerViewScrollY();
|
| + final int rangeX = computeMaximumHorizontalScrollOffset();
|
| + final int rangeY = computeMaximumVerticalScrollOffset();
|
| +
|
| + mScroller.fling(scrollX, scrollY, velocityX, velocityY,
|
| + 0, rangeX, 0, rangeY);
|
| + mDelegate.invalidate();
|
| + }
|
| +
|
| + // Called immediately before the draw to update the scroll offset.
|
| + public void computeScrollAndAbsorbGlow(OverScrollGlow overScrollGlow) {
|
| + final boolean stillAnimating = mScroller.computeScrollOffset();
|
| + if (!stillAnimating) return;
|
| +
|
| + final int oldX = mDelegate.getContainerViewScrollX();
|
| + final int oldY = mDelegate.getContainerViewScrollY();
|
| + int x = mScroller.getCurrX();
|
| + int y = mScroller.getCurrY();
|
| +
|
| + int rangeX = computeMaximumHorizontalScrollOffset();
|
| + int rangeY = computeMaximumVerticalScrollOffset();
|
| +
|
| + if (overScrollGlow != null) {
|
| + overScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY,
|
| + mScroller.getCurrVelocity());
|
| + }
|
| +
|
| + // The mScroller is configured not to go outside of the scrollable range, so this call
|
| + // should never result in attempting to scroll outside of the scrollable region.
|
| + scrollBy(x - oldX, y - oldY);
|
| +
|
| + mDelegate.invalidate();
|
| + }
|
| }
|
|
|