summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java85
1 files changed, 46 insertions, 39 deletions
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 32c8ad5..528fb4c 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
@@ -122,10 +122,14 @@ class ContentViewGestureHandler implements LongPressDelegate {
// fling ends.
private boolean mFlingMayBeActive;
+ // Used to remove the touch slop from the initial scroll event in a scroll gesture.
private boolean mSeenFirstScrollEvent;
private boolean mPinchInProgress = false;
+ // Guard against nested |trySendPendingEventsToNative()| loops.
+ private boolean mSendingPendingEventsToNative = false;
+
private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
//On single tap this will store the x, y coordinates of the touch.
@@ -779,14 +783,7 @@ class ContentViewGestureHandler implements LongPressDelegate {
endDoubleTapDragIfNecessary(null);
}
- if (offerTouchEventToJavaScript(event)) {
- // offerTouchEventToJavaScript returns true to indicate the event was sent
- // to the render process. If it is not subsequently handled, it will
- // be returned via confirmTouchEvent(false) and eventually passed to
- // processTouchEvent asynchronously.
- return true;
- }
- return processTouchEvent(event);
+ return queueEvent(event);
} finally {
TraceEvent.end("onTouchEvent");
}
@@ -842,8 +839,18 @@ class ContentViewGestureHandler implements LongPressDelegate {
}
}
- private boolean offerTouchEventToJavaScript(MotionEvent event) {
- if (mTouchHandlingState == NO_TOUCH_HANDLER) return false;
+ /**
+ * Queues or coalesces |event| into the pending queue.
+ * - If there are no touch handlers, |event| will skip the queue and be processed immediately.
+ * - If there are no pending events, |event| will be sent to native or processed immediately,
+ * depending on the disposition of the current gesture sequence.
+ * @return Whether the event was queued OR processed.
+ */
+ private boolean queueEvent(MotionEvent event) {
+ if (mTouchHandlingState == NO_TOUCH_HANDLER) {
+ assert mPendingMotionEvents.isEmpty();
+ return processTouchEvent(event);
+ }
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
// Avoid flooding the renderer process with move events: if the previous pending
@@ -854,7 +861,7 @@ class ContentViewGestureHandler implements LongPressDelegate {
&& previousEvent != mPendingMotionEvents.peekFirst()
&& previousEvent.getActionMasked() == MotionEvent.ACTION_MOVE
&& previousEvent.getPointerCount() == event.getPointerCount()) {
- TraceEvent.instant("offerTouchEventToJavaScript:EventCoalesced",
+ TraceEvent.instant("queueEvent:EventCoalesced",
"QueueSize = " + mPendingMotionEvents.size());
MotionEvent.PointerCoords[] coords =
new MotionEvent.PointerCoords[event.getPointerCount()];
@@ -866,25 +873,17 @@ class ContentViewGestureHandler implements LongPressDelegate {
return true;
}
}
- if (mPendingMotionEvents.isEmpty()) {
- // Add the event to the pending queue prior to calling sendPendingEventToNative.
- // When sending an event to native, the callback to confirmTouchEvent can be
- // synchronous or asynchronous and confirmTouchEvent expects the event to be
- // in the queue when it is called.
- MotionEvent clone = MotionEvent.obtain(event);
- mPendingMotionEvents.add(clone);
-
- int forward = sendPendingEventToNative();
- if (forward != EVENT_FORWARDED_TO_NATIVE) mPendingMotionEvents.remove(clone);
- return forward != EVENT_NOT_FORWARDED;
+
+ // Copy the event, as the original may get mutated after this method returns.
+ MotionEvent clone = MotionEvent.obtain(event);
+ mPendingMotionEvents.add(clone);
+ if (mPendingMotionEvents.size() == 1) {
+ trySendPendingEventsToNative();
} else {
- TraceEvent.instant("offerTouchEventToJavaScript:EventQueued",
+ TraceEvent.instant("queueEvent:EventQueued",
"QueueSize = " + mPendingMotionEvents.size());
- // Copy the event, as the original may get mutated after this method returns.
- MotionEvent clone = MotionEvent.obtain(event);
- mPendingMotionEvents.add(clone);
- return true;
}
+ return true;
}
private int sendPendingEventToNative() {
@@ -1029,19 +1028,27 @@ class ContentViewGestureHandler implements LongPressDelegate {
}
private void trySendPendingEventsToNative() {
- while (!mPendingMotionEvents.isEmpty()) {
- int forward = sendPendingEventToNative();
- if (forward == EVENT_FORWARDED_TO_NATIVE) break;
-
- // Even though we missed sending one event to native, as long as we haven't
- // received INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, we should keep sending
- // events on the queue to native.
- MotionEvent event = mPendingMotionEvents.removeFirst();
- if (mTouchHandlingState != JAVASCRIPT_CONSUMING_GESTURE
- && forward != EVENT_DROPPED) {
- processTouchEvent(event);
+ // Avoid nested send loops (possible when acks are synchronous), instead
+ // relying on the top-most call to dispatch any queued events.
+ if (mSendingPendingEventsToNative) return;
+ try {
+ mSendingPendingEventsToNative = true;
+ while (!mPendingMotionEvents.isEmpty()) {
+ int forward = sendPendingEventToNative();
+ if (forward == EVENT_FORWARDED_TO_NATIVE) break;
+
+ // Even though we missed sending one event to native, as long as we haven't
+ // received INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, we should keep sending
+ // events on the queue to native.
+ MotionEvent event = mPendingMotionEvents.removeFirst();
+ if (mTouchHandlingState != JAVASCRIPT_CONSUMING_GESTURE
+ && forward != EVENT_DROPPED) {
+ processTouchEvent(event);
+ }
+ recycleEvent(event);
}
- recycleEvent(event);
+ } finally {
+ mSendingPendingEventsToNative = false;
}
}