Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(773)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java

Issue 120513005: [Android] Perform eager gesture recognition on MotionEvents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Findbugs fix Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 5bd4ed79fe778231d725e699352fe3364bdfc25d..06c8eeb0bd600563374d44927c20220c8c1961f9 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
@@ -23,6 +23,7 @@ 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;
@@ -198,11 +199,6 @@ public class ContentViewCore
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();
@@ -210,7 +206,7 @@ public class ContentViewCore
/**
* Called when a fling event was not handled by the renderer.
*/
- void onUnhandledFlingStartEvent();
+ void onUnhandledFlingStartEvent(int velocityX, int velocityY);
/**
* Called to indicate that a scroll update gesture had been consumed by the page.
@@ -464,12 +460,16 @@ 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;
+
private ViewAndroid mViewAndroid;
private SmartClipDataListener mSmartClipDataListener = null;
/** ActionAfterDoubleTap defined in tools/metrics/histograms/histograms.xml. */
- public static class UMAActionAfterDoubleTap {
+ 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;
@@ -477,13 +477,19 @@ public class ContentViewCore
}
/** TapDelayType defined in tools/metrics/histograms/histograms.xml. */
- public static class UMASingleTapType {
+ 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.
*
@@ -1027,7 +1033,7 @@ public class ContentViewCore
* Stops loading the current web contents.
*/
public void stopLoading() {
- reportActionAfterDoubleTapUMA(ContentViewCore.UMAActionAfterDoubleTap.NAVIGATE_STOP);
+ reportActionAfterDoubleTapUMA(UMAActionAfterDoubleTap.NAVIGATE_STOP);
if (mNativeContentViewCore != 0) nativeStopLoading(mNativeContentViewCore);
}
@@ -1338,30 +1344,22 @@ public class ContentViewCore
}
@Override
- public boolean sendTouchEvent(long timeMs, int action, TouchPoint[] pts) {
- if (mNativeContentViewCore != 0) {
- return nativeSendTouchEvent(mNativeContentViewCore, timeMs, action, pts);
- }
- return false;
- }
-
- @SuppressWarnings("unused")
- @CalledByNative
- private void hasTouchEventHandlers(boolean hasTouchHandlers) {
- mContentViewGestureHandler.hasTouchEventHandlers(hasTouchHandlers);
+ public void onTouchEventHandlingBegin(long timeMs, int action, TouchPoint[] pts) {
+ if (mNativeContentViewCore == 0) return;
+ nativeOnTouchEventHandlingBegin(mNativeContentViewCore, timeMs, action, pts);
}
- @SuppressWarnings("unused")
- @CalledByNative
- private void confirmTouchEvent(int ackResult) {
- mContentViewGestureHandler.confirmTouchEvent(ackResult);
+ @Override
+ public void onTouchEventHandlingEnd() {
+ if (mNativeContentViewCore == 0) return;
+ nativeOnTouchEventHandlingEnd(mNativeContentViewCore);
}
@SuppressWarnings("unused")
@CalledByNative
- private void unhandledFlingStartEvent() {
+ private void unhandledFlingStartEvent(float vx, float vy) {
if (mGestureStateListener != null) {
- mGestureStateListener.onUnhandledFlingStartEvent();
+ mGestureStateListener.onUnhandledFlingStartEvent((int) vx, (int) vy);
}
}
@@ -1373,16 +1371,23 @@ public class ContentViewCore
}
}
- private void reportActionAfterDoubleTapUMA(int type) {
- mContentViewGestureHandler.reportActionAfterDoubleTapUMA(type);
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private boolean onForwardingGestureEvent(int type, int x, int y) {
jdduke (slow) 2014/01/18 16:36:01 TODO: Fix |type|, as it's completely bogus. WebIn
+ if (offerGestureToEmbedder(type)) return true;
+ updateTextHandlesForGesture(type);
+ updateGestureStateListener(type);
+ updateForTapOrPress(type, x, y);
+ updateForDoubleTapUMA(type);
+ if (type == ContentViewGestureHandler.GESTURE_SCROLL_BY) {
+ mZoomControlsDelegate.invokeZoomPicker();
+ }
+ return false;
}
@Override
public boolean sendGesture(int type, long timeMs, int x, int y, Bundle b) {
- if (offerGestureToEmbedder(type)) return false;
if (mNativeContentViewCore == 0) return false;
- updateTextHandlesForGesture(type);
- updateGestureStateListener(type, b);
switch (type) {
case ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE:
nativeShowPressState(mNativeContentViewCore, timeMs, x, y);
@@ -1400,17 +1405,19 @@ public class ContentViewCore
nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false);
return true;
case ContentViewGestureHandler.GESTURE_SINGLE_TAP_CONFIRMED:
- handleTapOrPress(timeMs, x, y, 0,
- b.getBoolean(ContentViewGestureHandler.SHOW_PRESS, false));
+ if (!b.getBoolean(ContentViewGestureHandler.SHOW_PRESS, false)) {
+ nativeShowPressState(mNativeContentViewCore, timeMs, x, y);
+ }
+ nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false);
return true;
case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UNCONFIRMED:
nativeSingleTapUnconfirmed(mNativeContentViewCore, timeMs, x, y);
return true;
case ContentViewGestureHandler.GESTURE_LONG_PRESS:
- handleTapOrPress(timeMs, x, y, IS_LONG_PRESS, false);
+ nativeLongPress(mNativeContentViewCore, timeMs, x, y, false);
return true;
case ContentViewGestureHandler.GESTURE_LONG_TAP:
- handleTapOrPress(timeMs, x, y, IS_LONG_TAP, false);
+ nativeLongTap(mNativeContentViewCore, timeMs, x, y, false);
return true;
case ContentViewGestureHandler.GESTURE_SCROLL_START: {
int dx = b.getInt(ContentViewGestureHandler.DELTA_HINT_X);
@@ -1455,31 +1462,11 @@ public class ContentViewCore
sendGesture(ContentViewGestureHandler.GESTURE_DOUBLE_TAP, timeMs, x, y, b);
}
- @Override
- public void sendSingleTapUMA(int type) {
- if (mNativeContentViewCore == 0) return;
- nativeSendSingleTapUma(
- mNativeContentViewCore,
- type,
- UMASingleTapType.COUNT);
- }
-
- @Override
- public void sendActionAfterDoubleTapUMA(int type,
- boolean clickDelayEnabled) {
- if (mNativeContentViewCore == 0) return;
- nativeSendActionAfterDoubleTapUma(
- mNativeContentViewCore,
- type,
- clickDelayEnabled,
- UMAActionAfterDoubleTap.COUNT);
- }
-
public void setGestureStateListener(GestureStateListener pinchGestureStateListener) {
mGestureStateListener = pinchGestureStateListener;
}
- void updateGestureStateListener(int gestureType, Bundle b) {
+ void updateGestureStateListener(int gestureType) {
if (mGestureStateListener == null) return;
switch (gestureType) {
@@ -1489,11 +1476,6 @@ public class ContentViewCore
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;
@@ -2024,8 +2006,11 @@ public class ContentViewCore
}
}
- private void handleTapOrPress(
- long timeMs, float xPix, float yPix, int isLongPressOrTap, boolean showPress) {
+ private void updateForTapOrPress(int type, float xPix, float yPix) {
+ if (type != ContentViewGestureHandler.GESTURE_SINGLE_TAP_CONFIRMED
jdduke (slow) 2014/01/18 16:36:01 TODO(jdduke): These types are all wrong. We need
+ && type != ContentViewGestureHandler.GESTURE_LONG_PRESS
+ && type != ContentViewGestureHandler.GESTURE_LONG_TAP) return;
+
if (mContainerView.isFocusable() && mContainerView.isFocusableInTouchMode()
&& !mContainerView.isFocused()) {
mContainerView.requestFocus();
@@ -2033,29 +2018,77 @@ public class ContentViewCore
if (!mPopupZoomer.isShowing()) mPopupZoomer.setLastTouch(xPix, yPix);
- if (isLongPressOrTap == IS_LONG_PRESS) {
+ if (type == ContentViewGestureHandler.GESTURE_LONG_PRESS) {
getInsertionHandleController().allowAutomaticShowing();
getSelectionHandleController().allowAutomaticShowing();
- if (mNativeContentViewCore != 0) {
- nativeLongPress(mNativeContentViewCore, timeMs, xPix, yPix, false);
- }
- } else if (isLongPressOrTap == IS_LONG_TAP) {
+ } else if (type == ContentViewGestureHandler.GESTURE_LONG_TAP) {
getInsertionHandleController().allowAutomaticShowing();
getSelectionHandleController().allowAutomaticShowing();
- if (mNativeContentViewCore != 0) {
- nativeLongTap(mNativeContentViewCore, timeMs, xPix, yPix, false);
- }
} else {
- if (!showPress && mNativeContentViewCore != 0) {
- nativeShowPressState(mNativeContentViewCore, timeMs, xPix, yPix);
- }
if (mSelectionEditable) getInsertionHandleController().allowAutomaticShowing();
- if (mNativeContentViewCore != 0) {
- nativeSingleTap(mNativeContentViewCore, timeMs, xPix, yPix, false);
+ }
+ }
+
+ // 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 == ContentViewGestureHandler.GESTURE_SINGLE_TAP_UP
+ || type == ContentViewGestureHandler.GESTURE_SINGLE_TAP_CONFIRMED) {
+ sendSingleTapUMA(mContentViewGestureHandler.isDoubleTapDisabled() ?
+ UMASingleTapType.UNDELAYED_TAP : UMASingleTapType.DELAYED_TAP);
+ } else if (type == ContentViewGestureHandler.GESTURE_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;
}
@@ -2794,7 +2827,6 @@ public class ContentViewCore
/**
* Invokes the graphical zoom picker widget for this ContentView.
*/
- @Override
public void invokeZoomPicker() {
mZoomControlsDelegate.invokeZoomPicker();
}
@@ -3289,9 +3321,11 @@ public class ContentViewCore
long nativeContentViewCoreImpl, int orientation);
// All touch events (including flings, scrolls etc) accept coordinates in physical pixels.
- private native boolean nativeSendTouchEvent(
+ private native void nativeOnTouchEventHandlingBegin(
long nativeContentViewCoreImpl, long timeMs, int action, TouchPoint[] pts);
+ private native void nativeOnTouchEventHandlingEnd(long nativeContentViewCoreImpl);
+
private native int nativeSendMouseMoveEvent(
long nativeContentViewCoreImpl, long timeMs, float x, float y);

Powered by Google App Engine
This is Rietveld 408576698