diff options
6 files changed, 160 insertions, 117 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 7e7ab13..3a48355 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -48,6 +48,7 @@ import org.chromium.content.browser.LoadUrlParams; import org.chromium.content.browser.NavigationHistory; import org.chromium.content.browser.PageTransitionTypes; import org.chromium.content.common.CleanupReference; +import org.chromium.content_public.browser.GestureStateListener; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.gfx.DeviceDisplayInfo; @@ -382,7 +383,7 @@ public class AwContents { } //-------------------------------------------------------------------------------------------- - private class AwGestureStateListener implements ContentViewCore.GestureStateListener { + private class AwGestureStateListener extends GestureStateListener { @Override public void onPinchGestureStart() { // While it's possible to re-layout the view during a pinch gesture, the effect is very @@ -400,7 +401,8 @@ public class AwContents { } @Override - public void onFlingStartGesture(int velocityX, int velocityY) { + public void onFlingStartGesture( + int velocityX, int velocityY, int scrollOffsetY, int scrollExtentY) { mScrollOffsetManager.onFlingStartGesture(velocityX, velocityY); } @@ -517,7 +519,7 @@ public class AwContents { private static ContentViewCore createAndInitializeContentViewCore(ViewGroup containerView, InternalAccessDelegate internalDispatcher, int nativeWebContents, - ContentViewCore.GestureStateListener pinchGestureStateListener, + GestureStateListener gestureStateListener, ContentViewClient contentViewClient, ContentViewCore.ZoomControlsDelegate zoomControlsDelegate) { Context context = containerView.getContext(); @@ -526,7 +528,7 @@ public class AwContents { context instanceof Activity ? new ActivityWindowAndroid((Activity) context) : new WindowAndroid(context.getApplicationContext())); - contentViewCore.setGestureStateListener(pinchGestureStateListener); + contentViewCore.addGestureStateListener(gestureStateListener); contentViewCore.setContentViewClient(contentViewClient); contentViewCore.setZoomControlsDelegate(zoomControlsDelegate); return contentViewCore; diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java index 0634f59..42ee461 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java @@ -13,8 +13,8 @@ import org.chromium.android_webview.test.util.AwTestTouchUtils; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.JavascriptEventObserver; import org.chromium.base.test.util.Feature; -import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.test.util.CallbackHelper; +import org.chromium.content_public.browser.GestureStateListener; import org.chromium.ui.gfx.DeviceDisplayInfo; import java.util.concurrent.Callable; @@ -669,7 +669,7 @@ public class AndroidScrollIntegrationTest extends AwTestBase { } } - private static class TestGestureStateListener implements ContentViewCore.GestureStateListener { + private static class TestGestureStateListener extends GestureStateListener { private CallbackHelper mOnScrollUpdateGestureConsumedHelper = new CallbackHelper(); public CallbackHelper getOnScrollUpdateGestureConsumedHelper() { @@ -685,7 +685,8 @@ public class AndroidScrollIntegrationTest extends AwTestBase { } @Override - public void onFlingStartGesture(int velocityX, int velocityY) { + public void onFlingStartGesture( + int velocityX, int velocityY, int scrollOffsetY, int scrollExtentY) { } @Override @@ -726,7 +727,7 @@ public class AndroidScrollIntegrationTest extends AwTestBase { getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { - testContainerView.getContentViewCore().setGestureStateListener( + testContainerView.getContentViewCore().addGestureStateListener( testGestureStateListener); } }); diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java index 6c410eb..f870651 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java @@ -180,35 +180,4 @@ public class ContentViewClient { return false; } - /** - * Called when a fling start event is sent. Note: onFlingStopped() of the previous - * fling may be called after onFlingStarted() of the current fling, so if the - * client wants to manage the fling status, a counter should be used. - */ - public void onFlingStarted() { - } - - /** - * Called when a fling is stopped, or a fling start event didn't trigger a fling. - */ - public void onFlingStopped() { - } - - /** - * Called when a scroll gesture has begun. - */ - public void onScrollBeginEvent() { - } - - /** - * Called when a scroll gesture has ended. - */ - public void onScrollEndEvent() { - } - - /** - * Called when the scroll offsets or viewport dimensions may have changed. - */ - public void onScrollOrViewportChanged() { - } } diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index be4e5f9..0d2ee77 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -53,6 +53,8 @@ import com.google.common.annotations.VisibleForTesting; import org.chromium.base.CalledByNative; import org.chromium.base.CommandLine; import org.chromium.base.JNINamespace; +import org.chromium.base.ObserverList; +import org.chromium.base.ObserverList.RewindableIterator; import org.chromium.base.TraceEvent; import org.chromium.base.WeakContext; import org.chromium.content.R; @@ -69,6 +71,7 @@ import org.chromium.content.browser.input.SelectPopupDialog; import org.chromium.content.browser.input.SelectPopupItem; import org.chromium.content.browser.input.SelectionHandleController; import org.chromium.content.common.ContentSwitches; +import org.chromium.content_public.browser.GestureStateListener; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.ViewAndroid; import org.chromium.ui.base.ViewAndroidDelegate; @@ -182,45 +185,6 @@ public class ContentViewCore } /** - * An interface that allows the embedder to be notified of events and state changes related to - * gesture processing. - */ - public interface GestureStateListener { - /** - * Called when the pinch gesture starts. - */ - void onPinchGestureStart(); - - /** - * Called when the pinch gesture ends. - */ - void onPinchGestureEnd(); - - /** - * Called when the fling gesture is sent. - */ - void onFlingStartGesture(int vx, int vy); - - /** - * Called when the fling cancel gesture is sent. - */ - void onFlingCancelGesture(); - - /** - * Called when a fling event was not handled by the renderer. - */ - void onUnhandledFlingStartEvent(); - - /** - * Called to indicate that a scroll update gesture had been consumed by the page. - * This callback is called whenever any layer is scrolled (like a frame or div). It is - * not called when a JS touch handler consumes the event (preventDefault), it is not called - * for JS-initiated scrolling. - */ - void onScrollUpdateGestureConsumed(); - } - - /** * An interface for controlling visibility and state of embedder-provided zoom controls. */ public interface ZoomControlsDelegate { @@ -371,7 +335,8 @@ public class ContentViewCore private boolean mInForeground = false; private ContentViewGestureHandler mContentViewGestureHandler; - private GestureStateListener mGestureStateListener; + private final ObserverList<GestureStateListener> mGestureStateListeners; + private final RewindableIterator<GestureStateListener> mGestureStateListenersIterator; private ZoomManager mZoomManager; private ZoomControlsDelegate mZoomControlsDelegate; @@ -500,6 +465,8 @@ public class ContentViewCore mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint(); mAccessibilityManager = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); + mGestureStateListeners = new ObserverList<GestureStateListener>(); + mGestureStateListenersIterator = mGestureStateListeners.rewindableIterator(); } /** @@ -869,6 +836,7 @@ public class ContentViewCore mJavaScriptInterfaces.clear(); mRetainedJavaScriptObjects.clear(); unregisterAccessibilityContentObserver(); + mGestureStateListeners.clear(); } private void unregisterAccessibilityContentObserver() { @@ -1293,35 +1261,38 @@ public class ContentViewCore @SuppressWarnings("unused") @CalledByNative private void onFlingStartEventAck(int ackResult) { - if (ackResult == ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS - && mGestureStateListener != null) { - mGestureStateListener.onUnhandledFlingStartEvent(); + if (ackResult == ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) { + for (mGestureStateListenersIterator.rewind(); + mGestureStateListenersIterator.hasNext();) { + mGestureStateListenersIterator.next().onUnhandledFlingStartEvent(); + } } if (ackResult != ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_CONSUMED) { // No fling happened for the fling start event. // Cancel the fling status set when sending GestureFlingStart. - getContentViewClient().onFlingStopped(); + updateGestureStateListener(ContentViewGestureHandler.GESTURE_FLING_END, null); } } @SuppressWarnings("unused") @CalledByNative private void onScrollBeginEventAck() { - getContentViewClient().onScrollBeginEvent(); + updateGestureStateListener(ContentViewGestureHandler.GESTURE_SCROLL_START, null); } @SuppressWarnings("unused") @CalledByNative private void onScrollUpdateGestureConsumed() { - if (mGestureStateListener != null) { - mGestureStateListener.onScrollUpdateGestureConsumed(); + for (mGestureStateListenersIterator.rewind(); + mGestureStateListenersIterator.hasNext();) { + mGestureStateListenersIterator.next().onScrollUpdateGestureConsumed(); } } @SuppressWarnings("unused") @CalledByNative private void onScrollEndEventAck() { - getContentViewClient().onScrollEndEvent(); + updateGestureStateListener(ContentViewGestureHandler.GESTURE_SCROLL_END, null); } private void reportActionAfterDoubleTapUMA(int type) { @@ -1379,7 +1350,6 @@ public class ContentViewCore nativeScrollEnd(mNativeContentViewCore, timeMs); return true; case ContentViewGestureHandler.GESTURE_FLING_START: - mContentViewClient.onFlingStarted(); nativeFlingStart(mNativeContentViewCore, timeMs, x, y, b.getInt(ContentViewGestureHandler.VELOCITY_X, 0), b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0)); @@ -1427,30 +1397,61 @@ public class ContentViewCore UMAActionAfterDoubleTap.COUNT); } - public void setGestureStateListener(GestureStateListener pinchGestureStateListener) { - mGestureStateListener = pinchGestureStateListener; + /** + * Add a listener that gets alerted on gesture state changes. + * @param listener Listener to add. + */ + public void addGestureStateListener(GestureStateListener listener) { + mGestureStateListeners.addObserver(listener); } - void updateGestureStateListener(int gestureType, Bundle b) { - if (mGestureStateListener == null) return; + /** + * Removes a listener that was added to watch for gesture state changes. + * @param listener Listener to remove. + */ + public void removeGestureStateListener(GestureStateListener listener) { + mGestureStateListeners.removeObserver(listener); + } - switch (gestureType) { - case ContentViewGestureHandler.GESTURE_PINCH_BEGIN: - mGestureStateListener.onPinchGestureStart(); - break; - case ContentViewGestureHandler.GESTURE_PINCH_END: - mGestureStateListener.onPinchGestureEnd(); - break; - case ContentViewGestureHandler.GESTURE_FLING_START: - mGestureStateListener.onFlingStartGesture( - b.getInt(ContentViewGestureHandler.VELOCITY_X, 0), - b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0)); - break; - case ContentViewGestureHandler.GESTURE_FLING_CANCEL: - mGestureStateListener.onFlingCancelGesture(); - break; - default: - break; + void updateGestureStateListener(int gestureType, Bundle b) { + for (mGestureStateListenersIterator.rewind(); + mGestureStateListenersIterator.hasNext();) { + GestureStateListener listener = mGestureStateListenersIterator.next(); + switch (gestureType) { + case ContentViewGestureHandler.GESTURE_PINCH_BEGIN: + listener.onPinchGestureStart(); + break; + case ContentViewGestureHandler.GESTURE_PINCH_END: + listener.onPinchGestureEnd(); + break; + case ContentViewGestureHandler.GESTURE_FLING_START: + listener.onFlingStartGesture( + b.getInt(ContentViewGestureHandler.VELOCITY_X, 0), + b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0), + computeVerticalScrollOffset(), + computeVerticalScrollExtent()); + break; + case ContentViewGestureHandler.GESTURE_FLING_END: + listener.onFlingEndGesture( + computeVerticalScrollOffset(), + computeVerticalScrollExtent()); + break; + case ContentViewGestureHandler.GESTURE_FLING_CANCEL: + listener.onFlingCancelGesture(); + break; + case ContentViewGestureHandler.GESTURE_SCROLL_START: + listener.onScrollStarted( + computeVerticalScrollOffset(), + computeVerticalScrollExtent()); + break; + case ContentViewGestureHandler.GESTURE_SCROLL_END: + listener.onScrollEnded( + computeVerticalScrollOffset(), + computeVerticalScrollExtent()); + break; + default: + break; + } } } @@ -2444,7 +2445,12 @@ public class ContentViewCore onRenderCoordinatesUpdated(); if (scrollChanged || contentOffsetChanged) { - getContentViewClient().onScrollOrViewportChanged(); + for (mGestureStateListenersIterator.rewind(); + mGestureStateListenersIterator.hasNext();) { + mGestureStateListenersIterator.next().onScrollOffsetOrExtentChanged( + computeVerticalScrollOffset(), + computeVerticalScrollExtent()); + } } if (needTemporarilyHideHandles) temporarilyHideTextHandles(); @@ -3215,7 +3221,7 @@ public class ContentViewCore @CalledByNative private void onNativeFlingStopped() { - getContentViewClient().onFlingStopped(); + updateGestureStateListener(ContentViewGestureHandler.GESTURE_FLING_END, null); } private native WebContents nativeGetWebContentsAndroid(long nativeContentViewCoreImpl); diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java index 0e20ccc..9e4dba5 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java @@ -208,12 +208,13 @@ class ContentViewGestureHandler implements LongPressDelegate { static final int GESTURE_SCROLL_END = 8; static final int GESTURE_FLING_START = 9; static final int GESTURE_FLING_CANCEL = 10; - static final int GESTURE_PINCH_BEGIN = 11; - static final int GESTURE_PINCH_BY = 12; - static final int GESTURE_PINCH_END = 13; - static final int GESTURE_TAP_CANCEL = 14; - static final int GESTURE_LONG_TAP = 15; - static final int GESTURE_TAP_DOWN = 16; + static final int GESTURE_FLING_END = 11; + static final int GESTURE_PINCH_BEGIN = 12; + static final int GESTURE_PINCH_BY = 13; + static final int GESTURE_PINCH_END = 14; + static final int GESTURE_TAP_CANCEL = 15; + static final int GESTURE_LONG_TAP = 16; + static final int GESTURE_TAP_DOWN = 17; // These have to be kept in sync with content/port/common/input_event_ack_state.h static final int INPUT_EVENT_ACK_STATE_UNKNOWN = 0; diff --git a/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java b/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java new file mode 100644 index 0000000..7d404f2 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java @@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content_public.browser; + +/** + * A class that is notified of events and state changes related to gesture processing from + * the ContentViewCore. + */ +public class GestureStateListener { + /** + * Called when the pinch gesture starts. + */ + public void onPinchGestureStart() {} + + /** + * Called when the pinch gesture ends. + */ + public void onPinchGestureEnd() {} + + /** + * Called when the fling gesture is sent. + */ + public void onFlingStartGesture(int vx, int vy, int scrollOffsetY, int scrollExtentY) {} + + /** + * Called when the fling cancel gesture is sent. + */ + public void onFlingCancelGesture() {} + + /** + * Called when a fling has ended. + */ + public void onFlingEndGesture(int scrollOffsetY, int scrollExtentY) {} + + /** + * Called when a fling event was not handled by the renderer. + */ + public void onUnhandledFlingStartEvent() {} + + /** + * Called to indicate that a scroll update gesture had been consumed by the page. + * This callback is called whenever any layer is scrolled (like a frame or div). It is + * not called when a JS touch handler consumes the event (preventDefault), it is not called + * for JS-initiated scrolling. + */ + public void onScrollUpdateGestureConsumed() {} + + /* + * Called when a scroll gesture has started. + */ + public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {} + + /* + * Called when a scroll gesture has stopped. + */ + public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {} + + /* + * Called when the scroll offsets or extents may have changed. + */ + public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) {} +}
\ No newline at end of file |