Chromium Code Reviews| Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| 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 df8988f9b6bd9812907efa8baa47058937238c95..097298341337bd094f522706ae159f1fdd03992d 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 |
| @@ -21,7 +21,6 @@ import android.os.Build; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.ResultReceiver; |
| -import android.os.SystemClock; |
| import android.provider.Browser; |
| import android.provider.Settings; |
| import android.text.Editable; |
| @@ -56,7 +55,6 @@ import org.chromium.base.ObserverList; |
| import org.chromium.base.ObserverList.RewindableIterator; |
| import org.chromium.base.TraceEvent; |
| import org.chromium.content.R; |
| -import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate; |
| import org.chromium.content.browser.accessibility.AccessibilityInjector; |
| import org.chromium.content.browser.accessibility.BrowserAccessibilityManager; |
| import org.chromium.content.browser.input.AdapterInputConnection; |
| @@ -90,8 +88,7 @@ import java.util.Map; |
| * being tied to the view system. |
| */ |
| @JNINamespace("content") |
| -public class ContentViewCore |
| - implements MotionEventDelegate, NavigationClient, AccessibilityStateChangeListener { |
| +public class ContentViewCore implements NavigationClient, AccessibilityStateChangeListener { |
| private static final String TAG = "ContentViewCore"; |
| @@ -317,7 +314,6 @@ public class ContentViewCore |
| private boolean mInForeground = false; |
| - private ContentViewGestureHandler mContentViewGestureHandler; |
| private final ObserverList<GestureStateListener> mGestureStateListeners; |
| private final RewindableIterator<GestureStateListener> mGestureStateListenersIterator; |
| private ZoomControlsDelegate mZoomControlsDelegate; |
| @@ -407,39 +403,19 @@ public class ContentViewCore |
| // vsync. |
| private boolean mRequestedVSyncForInput = false; |
| - // Used for tracking UMA ActionAfterDoubleTap to tell user's immediate |
| - // action after a double tap. |
| - private long mLastDoubleTapTimeMs; |
| - |
| // On single tap this will store the x, y coordinates of the touch. |
| private int mSingleTapX; |
| private int mSingleTapY; |
| + // Whether a touch scroll sequence is active, used to hide text selection |
| + // handles. Note that a scroll sequence will *always* bound a pinch |
| + // sequence, so this will also be true for the duration of a pinch gesture. |
| + private boolean touchScrollInProgress = false; |
|
Ted C
2014/02/28 19:52:33
needs to be mTouchScrollInProgress. Also, you don
jdduke (slow)
2014/02/28 20:22:04
Done.
|
| + |
| private ViewAndroid mViewAndroid; |
| private SmartClipDataListener mSmartClipDataListener = null; |
| - /** ActionAfterDoubleTap defined in tools/metrics/histograms/histograms.xml. */ |
| - private static class UMAActionAfterDoubleTap { |
| - public static final int NAVIGATE_BACK = 0; |
| - public static final int NAVIGATE_STOP = 1; |
| - public static final int NO_ACTION = 2; |
| - public static final int COUNT = 3; |
| - } |
| - |
| - /** TapDelayType defined in tools/metrics/histograms/histograms.xml. */ |
| - private static class UMASingleTapType { |
| - public static final int DELAYED_TAP = 0; |
| - public static final int UNDELAYED_TAP = 1; |
| - public static final int COUNT = 2; |
| - } |
| - |
| - /** |
| - * Used by UMA stat for tracking accidental double tap navigations. Specifies the amount of |
| - * time after a double tap within which actions will be recorded to the UMA stat. |
| - */ |
| - private static final long ACTION_AFTER_DOUBLE_TAP_WINDOW_MS = 5000; |
| - |
| /** |
| * Constructs a new ContentViewCore. Embedders must call initialize() after constructing |
| * a ContentViewCore and before using it. |
| @@ -684,9 +660,6 @@ public class ContentViewCore |
| viewAndroidNativePointer = mViewAndroid.getNativePointer(); |
| } |
| - // Note ContentViewGestureHandler initialization must occur before nativeInit |
| - // because nativeInit may callback into hasTouchEventHandlers. |
| - mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this); |
| mZoomControlsDelegate = new ZoomControlsDelegate() { |
| @Override |
| public void invokeZoomPicker() {} |
| @@ -922,7 +895,6 @@ public class ContentViewCore |
| * Stops loading the current web contents. |
| */ |
| public void stopLoading() { |
| - reportActionAfterDoubleTapUMA(UMAActionAfterDoubleTap.NAVIGATE_STOP); |
| if (mNativeContentViewCore != 0) nativeStopLoading(mNativeContentViewCore); |
| } |
| @@ -1079,7 +1051,6 @@ public class ContentViewCore |
| * Goes to the navigation entry before the current one. |
| */ |
| public void goBack() { |
| - reportActionAfterDoubleTapUMA(UMAActionAfterDoubleTap.NAVIGATE_BACK); |
| if (mWebContents != null) mWebContents.getNavigationController().goBack(); |
| } |
| @@ -1171,17 +1142,34 @@ public class ContentViewCore |
| mRequestedVSyncForInput = true; |
| addVSyncSubscriber(); |
| } |
| - return mContentViewGestureHandler.onTouchEvent(event); |
| + |
| + final int eventAction = event.getActionMasked(); |
| + |
| + // Only these actions have any effect on gesture detection. Other |
| + // actions have no corresponding WebTouchEvent type and may confuse the |
| + // touch pipline, so we ignore them entirely. |
| + if (eventAction != MotionEvent.ACTION_DOWN |
| + && eventAction != MotionEvent.ACTION_UP |
| + && eventAction != MotionEvent.ACTION_CANCEL |
| + && eventAction != MotionEvent.ACTION_MOVE |
| + && eventAction != MotionEvent.ACTION_POINTER_DOWN |
| + && eventAction != MotionEvent.ACTION_POINTER_UP) { |
| + return false; |
| + } |
| + |
| + if (mNativeContentViewCore == 0) return false; |
| + return nativeOnTouchEvent(mNativeContentViewCore, event); |
| } |
| - /** @see ContentViewGestureHandler#setIgnoreRemainingTouchEvents */ |
| public void setIgnoreRemainingTouchEvents() { |
| - mContentViewGestureHandler.setIgnoreRemainingTouchEvents(); |
| + if (mNativeContentViewCore == 0) return; |
| + nativeIgnoreRemainingTouchEvents(mNativeContentViewCore); |
| } |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void onFlingStartEventConsumed(int vx, int vy) { |
| + touchScrollInProgress = false; |
| temporarilyHideTextHandles(); |
| for (mGestureStateListenersIterator.rewind(); |
| mGestureStateListenersIterator.hasNext();) { |
| @@ -1193,6 +1181,7 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void onFlingStartEventHadNoConsumer(int vx, int vy) { |
| + touchScrollInProgress = false; |
| for (mGestureStateListenersIterator.rewind(); |
| mGestureStateListenersIterator.hasNext();) { |
| mGestureStateListenersIterator.next().onUnhandledFlingStartEvent(vx, vy); |
| @@ -1208,6 +1197,7 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void onScrollBeginEventAck() { |
| + touchScrollInProgress = true; |
| temporarilyHideTextHandles(); |
| mZoomControlsDelegate.invokeZoomPicker(); |
| updateGestureStateListener(GestureEventType.SCROLL_START); |
| @@ -1226,6 +1216,7 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void onScrollEndEventAck() { |
| + touchScrollInProgress = false; |
| updateGestureStateListener(GestureEventType.SCROLL_END); |
| } |
| @@ -1258,99 +1249,9 @@ public class ContentViewCore |
| return true; |
| } |
| updateForTapOrPress(type, x, y); |
| - updateForDoubleTapUMA(type); |
| return false; |
| } |
| - @Override |
| - public void onTouchEventHandlingBegin(MotionEvent event) { |
| - if (mNativeContentViewCore == 0) return; |
| - nativeOnTouchEventHandlingBegin(mNativeContentViewCore,event); |
| - } |
| - |
| - @Override |
| - public void onTouchEventHandlingEnd() { |
| - if (mNativeContentViewCore == 0) return; |
| - nativeOnTouchEventHandlingEnd(mNativeContentViewCore); |
| - } |
| - |
| - /** |
| - * Note: These events may or may not actually be forwarded to the renderer, |
| - * depending on ack disposition of the underlying touch events. All listening |
| - * for sent gestures should take place in {@link #filterGestureEvent(int, int, int)}. |
| - */ |
| - @Override |
| - public boolean onGestureEventCreated(int type, long timeMs, int x, int y, Bundle b) { |
| - if (mNativeContentViewCore == 0) return false; |
| - switch (type) { |
| - case GestureEventType.SHOW_PRESS: |
| - nativeShowPress(mNativeContentViewCore, timeMs, x, y); |
| - return true; |
| - case GestureEventType.TAP_CANCEL: |
| - nativeTapCancel(mNativeContentViewCore, timeMs, x, y); |
| - return true; |
| - case GestureEventType.TAP_DOWN: |
| - nativeTapDown(mNativeContentViewCore, timeMs, x, y); |
| - return true; |
| - case GestureEventType.DOUBLE_TAP: |
| - nativeDoubleTap(mNativeContentViewCore, timeMs, x, y); |
| - return true; |
| - case GestureEventType.SINGLE_TAP_UP: |
| - nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false); |
| - return true; |
| - case GestureEventType.SINGLE_TAP_CONFIRMED: |
| - if (!b.getBoolean(ContentViewGestureHandler.SHOW_PRESS, false)) { |
| - nativeShowPress(mNativeContentViewCore, timeMs, x, y); |
| - } |
| - nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false); |
| - return true; |
| - case GestureEventType.SINGLE_TAP_UNCONFIRMED: |
| - nativeSingleTapUnconfirmed(mNativeContentViewCore, timeMs, x, y); |
| - return true; |
| - case GestureEventType.LONG_PRESS: |
| - nativeLongPress(mNativeContentViewCore, timeMs, x, y, false); |
| - return true; |
| - case GestureEventType.LONG_TAP: |
| - nativeLongTap(mNativeContentViewCore, timeMs, x, y, false); |
| - return true; |
| - case GestureEventType.SCROLL_START: { |
| - int dx = b.getInt(ContentViewGestureHandler.DELTA_HINT_X); |
| - int dy = b.getInt(ContentViewGestureHandler.DELTA_HINT_Y); |
| - nativeScrollBegin(mNativeContentViewCore, timeMs, x, y, dx, dy); |
| - return true; |
| - } |
| - case GestureEventType.SCROLL_BY: { |
| - int dx = b.getInt(ContentViewGestureHandler.DISTANCE_X); |
| - int dy = b.getInt(ContentViewGestureHandler.DISTANCE_Y); |
| - nativeScrollBy(mNativeContentViewCore, timeMs, x, y, dx, dy); |
| - return true; |
| - } |
| - case GestureEventType.SCROLL_END: |
| - nativeScrollEnd(mNativeContentViewCore, timeMs); |
| - return true; |
| - case GestureEventType.FLING_START: |
| - nativeFlingStart(mNativeContentViewCore, timeMs, x, y, |
| - b.getInt(ContentViewGestureHandler.VELOCITY_X, 0), |
| - b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0)); |
| - return true; |
| - case GestureEventType.FLING_CANCEL: |
| - nativeFlingCancel(mNativeContentViewCore, timeMs); |
| - return true; |
| - case GestureEventType.PINCH_BEGIN: |
| - nativePinchBegin(mNativeContentViewCore, timeMs, x, y); |
| - return true; |
| - case GestureEventType.PINCH_BY: |
| - nativePinchBy(mNativeContentViewCore, timeMs, x, y, |
| - b.getFloat(ContentViewGestureHandler.DELTA, 0)); |
| - return true; |
| - case GestureEventType.PINCH_END: |
| - nativePinchEnd(mNativeContentViewCore, timeMs); |
| - return true; |
| - default: |
| - return false; |
| - } |
| - } |
| - |
| @VisibleForTesting |
| public void sendDoubleTapForTest(long timeMs, int x, int y) { |
| if (mNativeContentViewCore == 0) return; |
| @@ -1488,15 +1389,15 @@ public class ContentViewCore |
| } |
| private void onRenderCoordinatesUpdated() { |
| - if (mContentViewGestureHandler == null) return; |
| + if (mNativeContentViewCore == 0) return; |
| // We disable double tap zoom for pages that have a width=device-width |
| // or narrower viewport (indicating that this is a mobile-optimized or |
| // responsive web design, so text will be legible without zooming). |
| // We also disable it for pages that disallow the user from zooming in |
| // or out (even if they don't have a device-width or narrower viewport). |
| - mContentViewGestureHandler.updateShouldDisableDoubleTap( |
| - mRenderCoordinates.hasMobileViewport() || mRenderCoordinates.hasFixedPageScale()); |
| + nativeSetDoubleTapSupportForPageEnabled(mNativeContentViewCore, |
| + !mRenderCoordinates.hasMobileViewport() && !mRenderCoordinates.hasFixedPageScale()); |
| } |
| private void hidePopupDialog() { |
| @@ -1517,7 +1418,8 @@ public class ContentViewCore |
| } |
| private void resetGestureDetectors() { |
| - mContentViewGestureHandler.resetGestureHandlers(); |
| + if (mNativeContentViewCore == 0) return; |
| + nativeResetGestureDetectors(mNativeContentViewCore); |
| } |
| /** |
| @@ -1730,7 +1632,8 @@ public class ContentViewCore |
| */ |
| public void onWindowFocusChanged(boolean hasWindowFocus) { |
| if (!hasWindowFocus) { |
| - mContentViewGestureHandler.onWindowFocusLost(); |
| + if (mNativeContentViewCore == 0) return; |
| + nativeOnWindowFocusLost(mNativeContentViewCore); |
| } |
| } |
| @@ -1993,76 +1896,18 @@ public class ContentViewCore |
| return mSingleTapY; |
| } |
| - // Watch for the UMA "action after double tap" timer expiring and reset |
| - // the timer if necessary. |
| - private void updateDoubleTapUmaTimer() { |
| - if (mLastDoubleTapTimeMs == 0) return; |
| - |
| - long nowMs = SystemClock.uptimeMillis(); |
| - if ((nowMs - mLastDoubleTapTimeMs) >= ACTION_AFTER_DOUBLE_TAP_WINDOW_MS) { |
| - // Time expired, user took no action (that we care about). |
| - sendActionAfterDoubleTapUMA(UMAActionAfterDoubleTap.NO_ACTION); |
| - mLastDoubleTapTimeMs = 0; |
| - } |
| - } |
| - |
| - private void updateForDoubleTapUMA(int type) { |
| - updateDoubleTapUmaTimer(); |
| - |
| - if (type == GestureEventType.SINGLE_TAP_UP |
| - || type == GestureEventType.SINGLE_TAP_CONFIRMED) { |
| - sendSingleTapUMA(mContentViewGestureHandler.isDoubleTapDisabled() ? |
| - UMASingleTapType.UNDELAYED_TAP : UMASingleTapType.DELAYED_TAP); |
| - } else if (type == GestureEventType.DOUBLE_TAP) { |
| - // Make sure repeated double taps don't get silently dropped from |
| - // the statistics. |
| - if (mLastDoubleTapTimeMs > 0) { |
| - sendActionAfterDoubleTapUMA(UMAActionAfterDoubleTap.NO_ACTION); |
| - } |
| - |
| - mLastDoubleTapTimeMs = SystemClock.uptimeMillis(); |
| - } |
| - } |
| - |
| - private void reportActionAfterDoubleTapUMA(int type) { |
| - updateDoubleTapUmaTimer(); |
| - |
| - if (mLastDoubleTapTimeMs == 0) return; |
| - |
| - long nowMs = SystemClock.uptimeMillis(); |
| - if ((nowMs - mLastDoubleTapTimeMs) < ACTION_AFTER_DOUBLE_TAP_WINDOW_MS) { |
| - sendActionAfterDoubleTapUMA(type); |
| - mLastDoubleTapTimeMs = 0; |
| - } |
| - } |
| - |
| - private void sendSingleTapUMA(int type) { |
| - if (mNativeContentViewCore == 0) return; |
| - nativeSendSingleTapUma( |
| - mNativeContentViewCore, |
| - type, |
| - UMASingleTapType.COUNT); |
| - } |
| - |
| - private void sendActionAfterDoubleTapUMA(int type) { |
| - if (mNativeContentViewCore == 0) return; |
| - nativeSendActionAfterDoubleTapUma( |
| - mNativeContentViewCore, |
| - type, |
| - !mContentViewGestureHandler.isClickDelayDisabled(), |
| - UMAActionAfterDoubleTap.COUNT); |
| - } |
| - |
| public void setZoomControlsDelegate(ZoomControlsDelegate zoomControlsDelegate) { |
| mZoomControlsDelegate = zoomControlsDelegate; |
| } |
| public void updateMultiTouchZoomSupport(boolean supportsMultiTouchZoom) { |
| - mContentViewGestureHandler.updateMultiTouchSupport(supportsMultiTouchZoom); |
| + if (mNativeContentViewCore == 0) return; |
| + nativeSetMultiTouchZoomSupportEnabled(mNativeContentViewCore, supportsMultiTouchZoom); |
| } |
| public void updateDoubleTapSupport(boolean supportsDoubleTap) { |
| - mContentViewGestureHandler.updateDoubleTapSupport(supportsDoubleTap); |
| + if (mNativeContentViewCore == 0) return; |
| + nativeSetDoubleTapSupportEnabled(mNativeContentViewCore, supportsDoubleTap); |
| } |
| public void selectPopupMenuItems(int[] indices) { |
| @@ -2374,10 +2219,7 @@ public class ContentViewCore |
| } |
| private boolean allowTextHandleFadeIn() { |
| - if (mContentViewGestureHandler.isNativeScrolling() || |
| - mContentViewGestureHandler.isNativePinching()) { |
| - return false; |
| - } |
| + if (touchScrollInProgress) return false; |
| if (mPopupZoomer.isShowing()) return false; |
| @@ -3233,6 +3075,7 @@ public class ContentViewCore |
| @CalledByNative |
| private void onNativeFlingStopped() { |
| + touchScrollInProgress = false; |
| updateGestureStateListener(GestureEventType.FLING_END); |
| } |
| @@ -3268,10 +3111,7 @@ public class ContentViewCore |
| long nativeContentViewCoreImpl, int orientation); |
| // All touch events (including flings, scrolls etc) accept coordinates in physical pixels. |
| - private native void nativeOnTouchEventHandlingBegin( |
| - long nativeContentViewCoreImpl, MotionEvent event); |
| - |
| - private native void nativeOnTouchEventHandlingEnd(long nativeContentViewCoreImpl); |
| + private native boolean nativeOnTouchEvent(long nativeContentViewCoreImpl, MotionEvent event); |
| private native int nativeSendMouseMoveEvent( |
| long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| @@ -3297,27 +3137,12 @@ public class ContentViewCore |
| private native void nativeSingleTap( |
| long nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap); |
| - private native void nativeSingleTapUnconfirmed( |
| - long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| - |
| - private native void nativeShowPress( |
| - long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| - |
| - private native void nativeTapCancel( |
| - long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| - |
| - private native void nativeTapDown( |
| - long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| - |
| private native void nativeDoubleTap( |
| long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| private native void nativeLongPress( |
| long nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap); |
| - private native void nativeLongTap( |
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap); |
| - |
| private native void nativePinchBegin( |
| long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| @@ -3331,6 +3156,19 @@ public class ContentViewCore |
| private native void nativeMoveCaret(long nativeContentViewCoreImpl, float x, float y); |
| + private native void nativeResetGestureDetectors(long nativeContentViewCoreImpl); |
| + |
| + private native void nativeIgnoreRemainingTouchEvents(long nativeContentViewCoreImpl); |
| + |
| + private native void nativeOnWindowFocusLost(long nativeContentViewCoreImpl); |
| + |
| + private native void nativeSetDoubleTapSupportForPageEnabled( |
| + long nativeContentViewCoreImpl, boolean enabled); |
| + private native void nativeSetDoubleTapSupportEnabled( |
| + long nativeContentViewCoreImpl, boolean enabled); |
| + private native void nativeSetMultiTouchZoomSupportEnabled( |
| + long nativeContentViewCoreImpl, boolean enabled); |
| + |
| private native void nativeLoadIfNecessary(long nativeContentViewCoreImpl); |
| private native void nativeRequestRestoreLoad(long nativeContentViewCoreImpl); |
| @@ -3404,12 +3242,6 @@ public class ContentViewCore |
| private native void nativeSetAccessibilityEnabled( |
| long nativeContentViewCoreImpl, boolean enabled); |
| - private native void nativeSendSingleTapUma(long nativeContentViewCoreImpl, |
| - int type, int count); |
| - |
| - private native void nativeSendActionAfterDoubleTapUma(long nativeContentViewCoreImpl, |
| - int type, boolean hasDelay, int count); |
| - |
| private native void nativeExtractSmartClipData(long nativeContentViewCoreImpl, |
| int x, int y, int w, int h); |
| } |