Index: content/browser/android/content_view_core_impl.cc |
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc |
index 00b3442010290dafd518dcdc525b0d1ad4100529..64cd6edee5b496af45c82289d06d73158e951489 100644 |
--- a/content/browser/android/content_view_core_impl.cc |
+++ b/content/browser/android/content_view_core_impl.cc |
@@ -110,6 +110,31 @@ ScopedJavaLocalRef<jobject> CreateJavaRect( |
static_cast<int>(rect.bottom()))); |
} |
+bool PossiblyTriggeredByTimeout(const WebGestureEvent& event) { |
+ switch (event.type) { |
+ case WebInputEvent::GestureShowPress: |
+ case WebInputEvent::GestureLongPress: |
+ return true; |
+ // On Android, a GestureTap may be sent after a certain timeout window |
+ // if there is no GestureDoubleTap follow-up. |
+ case WebInputEvent::GestureTap: |
+ return true; |
+ // On Android, a GestureTapCancel may be triggered by the loss of window |
+ // focus (e.g., following a GestureLongPress). |
+ case WebInputEvent::GestureTapCancel: |
+ return true; |
+ default: |
+ break; |
+ } |
+ return false; |
+} |
+ |
+GestureEventPacket::GestureSource |
+ToGestureSource(const WebGestureEvent& event) { |
+ return PossiblyTriggeredByTimeout(event) ? GestureEventPacket::TOUCH_TIMEOUT |
+ : GestureEventPacket::SYNTHETIC; |
+} |
+ |
} // namespace |
// Enables a callback when the underlying WebContents is destroyed, to enable |
@@ -176,7 +201,9 @@ ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj, |
view_android_(view_android), |
window_android_(window_android), |
device_orientation_(0), |
- geolocation_needs_pause_(false) { |
+ geolocation_needs_pause_(false), |
+ gesture_event_queue_(this), |
+ handling_touch_event_(false) { |
CHECK(web_contents) << |
"A ContentViewCoreImpl should be created with a valid WebContents."; |
@@ -304,6 +331,22 @@ void ContentViewCoreImpl::RenderViewReady() { |
SendOrientationChangeEventInternal(); |
} |
+void ContentViewCoreImpl::ForwardGestureEvent( |
+ const blink::WebGestureEvent& event) { |
+ JNIEnv* env = AttachCurrentThread(); |
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); |
+ if (j_obj.is_null()) |
+ return; |
+ |
+ if (Java_ContentViewCore_onForwardingGestureEvent( |
+ env, j_obj.obj(), event.type, event.x, event.y)) |
+ return; |
+ |
+ RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
+ if (rwhv) |
+ rwhv->SendGestureEvent(event); |
+} |
+ |
RenderWidgetHostViewAndroid* |
ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() { |
RenderWidgetHostView* rwhv = NULL; |
@@ -497,20 +540,15 @@ void ContentViewCoreImpl::ShowSelectPopupMenu( |
} |
void ContentViewCoreImpl::ConfirmTouchEvent(InputEventAckState ack_result) { |
- JNIEnv* env = AttachCurrentThread(); |
- ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); |
- if (j_obj.is_null()) |
- return; |
- Java_ContentViewCore_confirmTouchEvent(env, j_obj.obj(), |
- static_cast<jint>(ack_result)); |
+ gesture_event_queue_.OnTouchEventAck(ack_result); |
} |
-void ContentViewCoreImpl::UnhandledFlingStartEvent() { |
+void ContentViewCoreImpl::UnhandledFlingStartEvent(float vx, float vy) { |
JNIEnv* env = AttachCurrentThread(); |
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); |
if (j_obj.is_null()) |
return; |
- Java_ContentViewCore_unhandledFlingStartEvent(env, j_obj.obj()); |
+ Java_ContentViewCore_unhandledFlingStartEvent(env, j_obj.obj(), vx, vy); |
} |
void ContentViewCoreImpl::OnScrollUpdateGestureConsumed() { |
@@ -521,16 +559,6 @@ void ContentViewCoreImpl::OnScrollUpdateGestureConsumed() { |
Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj()); |
} |
-void ContentViewCoreImpl::HasTouchEventHandlers(bool need_touch_events) { |
- JNIEnv* env = AttachCurrentThread(); |
- ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); |
- if (j_obj.is_null()) |
- return; |
- Java_ContentViewCore_hasTouchEventHandlers(env, |
- j_obj.obj(), |
- need_touch_events); |
-} |
- |
bool ContentViewCoreImpl::HasFocus() { |
JNIEnv* env = AttachCurrentThread(); |
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
@@ -896,21 +924,32 @@ void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env, |
} |
} |
-jboolean ContentViewCoreImpl::SendTouchEvent(JNIEnv* env, |
- jobject obj, |
- jlong time_ms, |
- jint type, |
- jobjectArray pts) { |
+void ContentViewCoreImpl::OnTouchEventHandlingBegin(JNIEnv* env, |
+ jobject obj, |
+ jlong time_ms, |
+ jint type, |
+ jobjectArray pts) { |
+ DCHECK(!handling_touch_event_); |
+ handling_touch_event_ = true; |
+ |
+ blink::WebTouchEvent event; |
+ TouchPoint::BuildWebTouchEvent(env, type, time_ms, GetDpiScale(), pts, event); |
+ pending_touch_event_ = event; |
+ |
+ pending_gesture_packet_ = GestureEventPacket::FromTouch(event); |
+} |
+ |
+void ContentViewCoreImpl::OnTouchEventHandlingEnd(JNIEnv* env, jobject obj) { |
+ DCHECK(handling_touch_event_); |
+ handling_touch_event_ = false; |
+ |
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
- if (rwhv) { |
- using blink::WebTouchEvent; |
- blink::WebTouchEvent event; |
- TouchPoint::BuildWebTouchEvent(env, type, time_ms, GetDpiScale(), pts, |
- event); |
- rwhv->SendTouchEvent(event); |
- return true; |
- } |
- return false; |
+ if (!rwhv) |
+ return; |
+ |
+ // Note: Order is important here, as the touch may be ack'ed synchronously |
+ gesture_event_queue_.OnGestureEventPacket(pending_gesture_packet_); |
+ rwhv->SendTouchEvent(pending_touch_event_); |
} |
float ContentViewCoreImpl::GetTouchPaddingDip() { |
@@ -980,9 +1019,18 @@ WebGestureEvent ContentViewCoreImpl::MakeGestureEvent( |
void ContentViewCoreImpl::SendGestureEvent( |
const blink::WebGestureEvent& event) { |
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
- if (rwhv) |
- rwhv->SendGestureEvent(event); |
+ if (handling_touch_event_) { |
+ pending_gesture_packet_.Push(event); |
+ return; |
+ } |
+ gesture_event_queue_.OnGestureEventPacket( |
+ GestureEventPacket::FromGesture(ToGestureSource(event), event)); |
+} |
+ |
+void ContentViewCoreImpl::SendSyntheticGestureEvent( |
+ const blink::WebGestureEvent& event) { |
+ gesture_event_queue_.OnGestureEventPacket( |
+ GestureEventPacket::FromGesture(GestureEventPacket::SYNTHETIC, event)); |
} |
void ContentViewCoreImpl::ScrollBegin(JNIEnv* env, |
@@ -1042,12 +1090,14 @@ void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms, |
WebInputEvent::GestureTap, time_ms, x, y); |
event.data.tap.tapCount = 1; |
- if (!disambiguation_popup_tap) { |
- const float touch_padding_dip = GetTouchPaddingDip(); |
- event.data.tap.width = touch_padding_dip; |
- event.data.tap.height = touch_padding_dip; |
+ if (disambiguation_popup_tap) { |
+ SendSyntheticGestureEvent(event); |
+ return; |
} |
+ const float touch_padding_dip = GetTouchPaddingDip(); |
+ event.data.tap.width = touch_padding_dip; |
+ event.data.tap.height = touch_padding_dip; |
SendGestureEvent(event); |
} |
@@ -1105,12 +1155,14 @@ void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms, |
WebGestureEvent event = MakeGestureEvent( |
WebInputEvent::GestureLongPress, time_ms, x, y); |
- if (!disambiguation_popup_tap) { |
- const float touch_padding_dip = GetTouchPaddingDip(); |
- event.data.longPress.width = touch_padding_dip; |
- event.data.longPress.height = touch_padding_dip; |
+ if (disambiguation_popup_tap) { |
+ SendSyntheticGestureEvent(event); |
+ return; |
} |
+ const float touch_padding_dip = GetTouchPaddingDip(); |
+ event.data.longPress.width = touch_padding_dip; |
+ event.data.longPress.height = touch_padding_dip; |
SendGestureEvent(event); |
} |
@@ -1120,12 +1172,14 @@ void ContentViewCoreImpl::LongTap(JNIEnv* env, jobject obj, jlong time_ms, |
WebGestureEvent event = MakeGestureEvent( |
WebInputEvent::GestureLongTap, time_ms, x, y); |
- if (!disambiguation_popup_tap) { |
- const float touch_padding_dip = GetTouchPaddingDip(); |
- event.data.longPress.width = touch_padding_dip; |
- event.data.longPress.height = touch_padding_dip; |
+ if (disambiguation_popup_tap) { |
+ SendSyntheticGestureEvent(event); |
+ return; |
} |
+ const float touch_padding_dip = GetTouchPaddingDip(); |
+ event.data.longPress.width = touch_padding_dip; |
+ event.data.longPress.height = touch_padding_dip; |
SendGestureEvent(event); |
} |