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 cc78b8fee9f295da1055e6e37c8f32b5e29034bc..3452b26e4bb65034c8d8ec8b13b33e09dc7dce50 100644 |
--- a/content/browser/android/content_view_core_impl.cc |
+++ b/content/browser/android/content_view_core_impl.cc |
@@ -24,6 +24,7 @@ |
#include "content/browser/frame_host/navigation_entry_impl.h" |
#include "content/browser/media/android/browser_media_player_manager.h" |
#include "content/browser/renderer_host/compositor_impl_android.h" |
+#include "content/browser/renderer_host/input/motion_event_android.h" |
#include "content/browser/renderer_host/input/web_input_event_builders_android.h" |
#include "content/browser/renderer_host/java/java_bound_object.h" |
#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h" |
@@ -112,26 +113,7 @@ ScopedJavaLocalRef<jobject> CreateJavaRect( |
static_cast<int>(rect.bottom()))); |
} |
-bool PossiblyTriggeredByTouchTimeout(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; |
-} |
- |
-int ToContentViewGestureHandlerType(WebInputEvent::Type type) { |
+int ToGestureEventType(WebInputEvent::Type type) { |
switch (type) { |
case WebInputEvent::GestureScrollBegin: |
return SCROLL_START; |
@@ -174,6 +156,12 @@ int ToContentViewGestureHandlerType(WebInputEvent::Type type) { |
}; |
} |
+float GetPrimaryDisplayDeviceScaleFactor() { |
+ const gfx::Display& display = |
+ gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
+ return display.device_scale_factor(); |
+} |
+ |
} // namespace |
// Enables a callback when the underlying WebContents is destroyed, to enable |
@@ -233,23 +221,19 @@ ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, |
java_ref_(env, obj), |
web_contents_(static_cast<WebContentsImpl*>(web_contents)), |
root_layer_(cc::Layer::Create()), |
+ dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()), |
vsync_interval_(base::TimeDelta::FromMicroseconds( |
kDefaultVSyncIntervalMicros)), |
expected_browser_composite_time_(base::TimeDelta::FromMicroseconds( |
kDefaultVSyncIntervalMicros * kDefaultBrowserCompositeVSyncFraction)), |
view_android_(view_android), |
window_android_(window_android), |
+ gesture_provider_(this, 1.f / dpi_scale_), |
device_orientation_(0), |
- geolocation_needs_pause_(false), |
- touch_disposition_gesture_filter_(this), |
- handling_touch_event_(false) { |
+ geolocation_needs_pause_(false) { |
CHECK(web_contents) << |
"A ContentViewCoreImpl should be created with a valid WebContents."; |
- const gfx::Display& display = |
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
- dpi_scale_ = display.device_scale_factor(); |
- |
// Currently, the only use case we have for overriding a user agent involves |
// spoofing a desktop Linux user agent for "Request desktop site". |
// Automatically set it for all WebContents so that it is available when a |
@@ -374,11 +358,8 @@ void ContentViewCoreImpl::RenderViewReady() { |
SendOrientationChangeEventInternal(); |
} |
-void ContentViewCoreImpl::ForwardGestureEvent( |
- const blink::WebGestureEvent& event) { |
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
- if (rwhv) |
- rwhv->SendGestureEvent(event); |
+void ContentViewCoreImpl::OnGestureEvent(const blink::WebGestureEvent& event) { |
+ SendGestureEvent(event); |
} |
RenderWidgetHostViewAndroid* |
@@ -572,7 +553,7 @@ void ContentViewCoreImpl::ShowSelectPopupMenu( |
} |
void ContentViewCoreImpl::ConfirmTouchEvent(InputEventAckState ack_result) { |
- touch_disposition_gesture_filter_.OnTouchEventAck(ack_result); |
+ gesture_provider_.OnTouchEventAck(ack_result); |
} |
void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event, |
@@ -644,12 +625,14 @@ bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) { |
const blink::WebGestureEvent& gesture = |
static_cast<const blink::WebGestureEvent&>(event); |
- int gesture_type = ToContentViewGestureHandlerType(event.type); |
+ int gesture_type = ToGestureEventType(event.type); |
return Java_ContentViewCore_filterTapOrPressEvent(env, |
j_obj.obj(), |
gesture_type, |
gesture.x * GetDpiScale(), |
gesture.y * GetDpiScale()); |
+ |
+ // TODO(jdduke): Also report double-tap UMA, crbug/347568. |
} |
bool ContentViewCoreImpl::HasFocus() { |
@@ -1011,44 +994,20 @@ void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env, |
} |
} |
-void ContentViewCoreImpl::OnTouchEventHandlingBegin(JNIEnv* env, |
- jobject obj, |
- jobject motion_event) { |
- DCHECK(!handling_touch_event_); |
- handling_touch_event_ = true; |
- |
- pending_touch_event_ = |
- WebTouchEventBuilder::Build(motion_event, GetDpiScale()); |
- |
- pending_gesture_packet_ = |
- GestureEventPacket::FromTouch(pending_touch_event_); |
-} |
- |
-void ContentViewCoreImpl::OnTouchEventHandlingEnd(JNIEnv* env, jobject obj) { |
- if (!handling_touch_event_) |
- return; |
- |
- GestureEventPacket gesture_packet; |
- std::swap(gesture_packet, pending_gesture_packet_); |
- |
- handling_touch_event_ = false; |
- |
+jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, |
+ jobject obj, |
+ jobject motion_event) { |
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
if (!rwhv) |
- return; |
+ return false; |
- // Note: Order is important here, as the touch may be ack'ed synchronously |
- TouchDispositionGestureFilter::PacketResult result = |
- touch_disposition_gesture_filter_.OnGestureEventPacket(gesture_packet); |
- if (result != TouchDispositionGestureFilter::SUCCESS) { |
- NOTREACHED() << "Invalid touch gesture sequence detected."; |
- return; |
- } |
- rwhv->SendTouchEvent(pending_touch_event_); |
-} |
+ MotionEventAndroid event(env, motion_event, false); |
+ |
+ if (!gesture_provider_.OnTouchEvent(event)) |
+ return false; |
-float ContentViewCoreImpl::GetTouchPaddingDip() { |
- return 48.0f / GetDpiScale(); |
+ rwhv->SendTouchEvent(WebTouchEventBuilder::Build(event, GetDpiScale())); |
+ return true; |
} |
float ContentViewCoreImpl::GetDpiScale() const { |
@@ -1106,35 +1065,9 @@ WebGestureEvent ContentViewCoreImpl::MakeGestureEvent( |
void ContentViewCoreImpl::SendGestureEvent( |
const blink::WebGestureEvent& event) { |
- // Gestures received while |handling_touch_event_| will accumulate until |
- // touch handling finishes, at which point the gestures will be pushed to the |
- // |touch_disposition_gesture_filter_|. |
- if (handling_touch_event_) { |
- pending_gesture_packet_.Push(event); |
- return; |
- } |
- |
- // TODO(jdduke): In general, timeout-based gestures *should* have the same |
- // timestamp as the initial TouchStart of the current sequence. We should |
- // verify that this is true, and use that as another timeout check. |
- if (PossiblyTriggeredByTouchTimeout(event)) { |
- TouchDispositionGestureFilter::PacketResult result = |
- touch_disposition_gesture_filter_.OnGestureEventPacket( |
- GestureEventPacket::FromTouchTimeout(event)); |
- DCHECK_EQ(TouchDispositionGestureFilter::SUCCESS, result); |
- return; |
- } |
- |
- // If |event| was not (directly or indirectly) touch-derived, treat it as |
- // a synthetic gesture event. |
- SendSyntheticGestureEvent(event); |
-} |
- |
-void ContentViewCoreImpl::SendSyntheticGestureEvent( |
- const blink::WebGestureEvent& event) { |
- // Synthetic gestures (e.g., those not generated directly by touches |
- // for which we expect an ack), should be forwarded directly. |
- ForwardGestureEvent(event); |
+ RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
+ if (rwhv) |
+ rwhv->SendGestureEvent(event); |
} |
void ContentViewCoreImpl::ScrollBegin(JNIEnv* env, |
@@ -1172,7 +1105,6 @@ void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms, |
jfloat x, jfloat y, jfloat vx, jfloat vy) { |
WebGestureEvent event = MakeGestureEvent( |
WebInputEvent::GestureFlingStart, time_ms, x, y); |
- |
event.data.flingStart.velocityX = vx / GetDpiScale(); |
event.data.flingStart.velocityY = vy / GetDpiScale(); |
@@ -1186,64 +1118,11 @@ void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) { |
} |
void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms, |
- jfloat x, jfloat y, |
- jboolean disambiguation_popup_tap) { |
+ jfloat x, jfloat y) { |
WebGestureEvent event = MakeGestureEvent( |
WebInputEvent::GestureTap, time_ms, x, y); |
- |
event.data.tap.tapCount = 1; |
- // Disambiguation popup gestures are treated as synthetic because their |
- // generating touches were never forwarded to the renderer. |
- 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); |
-} |
- |
-void ContentViewCoreImpl::SingleTapUnconfirmed(JNIEnv* env, jobject obj, |
- jlong time_ms, |
- jfloat x, jfloat y) { |
- WebGestureEvent event = MakeGestureEvent( |
- WebInputEvent::GestureTapUnconfirmed, time_ms, x, y); |
- |
- event.data.tap.tapCount = 1; |
- |
- const float touch_padding_dip = GetTouchPaddingDip(); |
- event.data.tap.width = touch_padding_dip; |
- event.data.tap.height = touch_padding_dip; |
- |
- SendGestureEvent(event); |
-} |
- |
-void ContentViewCoreImpl::ShowPress(JNIEnv* env, jobject obj, |
- jlong time_ms, |
- jfloat x, jfloat y) { |
- WebGestureEvent event = MakeGestureEvent( |
- WebInputEvent::GestureShowPress, time_ms, x, y); |
- SendGestureEvent(event); |
-} |
- |
-void ContentViewCoreImpl::TapCancel(JNIEnv* env, |
- jobject obj, |
- jlong time_ms, |
- jfloat x, |
- jfloat y) { |
- WebGestureEvent event = MakeGestureEvent( |
- WebInputEvent::GestureTapCancel, time_ms, x, y); |
- SendGestureEvent(event); |
-} |
- |
-void ContentViewCoreImpl::TapDown(JNIEnv* env, jobject obj, |
- jlong time_ms, |
- jfloat x, jfloat y) { |
- WebGestureEvent event = MakeGestureEvent( |
- WebInputEvent::GestureTapDown, time_ms, x, y); |
SendGestureEvent(event); |
} |
@@ -1255,40 +1134,10 @@ void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms, |
} |
void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms, |
- jfloat x, jfloat y, |
- jboolean disambiguation_popup_tap) { |
+ jfloat x, jfloat y) { |
WebGestureEvent event = MakeGestureEvent( |
WebInputEvent::GestureLongPress, time_ms, x, y); |
- // Disambiguation popup gestures are treated as synthetic because their |
- // generating touches were never forwarded to the renderer. |
- 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); |
-} |
- |
-void ContentViewCoreImpl::LongTap(JNIEnv* env, jobject obj, jlong time_ms, |
- jfloat x, jfloat y, |
- jboolean disambiguation_popup_tap) { |
- WebGestureEvent event = MakeGestureEvent( |
- WebInputEvent::GestureLongTap, time_ms, x, y); |
- |
- // Disambiguation popup gestures are treated as synthetic because their |
- // generating touches were never forwarded to the renderer. |
- 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); |
} |
@@ -1333,6 +1182,36 @@ void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj, |
} |
} |
+void ContentViewCoreImpl::ResetGestureDetectors(JNIEnv* env, jobject obj) { |
+ gesture_provider_.ResetGestureDetectors(); |
+} |
+ |
+void ContentViewCoreImpl::IgnoreRemainingTouchEvents(JNIEnv* env, jobject obj) { |
+ gesture_provider_.CancelActiveTouchSequence(); |
+} |
+ |
+void ContentViewCoreImpl::OnWindowFocusLost(JNIEnv* env, jobject obj) { |
+ gesture_provider_.CancelActiveTouchSequence(); |
+} |
+ |
+void ContentViewCoreImpl::SetDoubleTapSupportForPageEnabled(JNIEnv* env, |
+ jobject obj, |
+ jboolean enabled) { |
+ gesture_provider_.SetDoubleTapSupportForPageEnabled(enabled); |
+} |
+ |
+void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env, |
+ jobject obj, |
+ jboolean enabled) { |
+ gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled); |
+} |
+ |
+void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env, |
+ jobject obj, |
+ jboolean enabled) { |
+ gesture_provider_.SetMultiTouchSupportEnabled(enabled); |
+} |
+ |
void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) { |
web_contents_->GetController().LoadIfNecessary(); |
} |
@@ -1744,31 +1623,6 @@ void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj, |
} |
} |
-void ContentViewCoreImpl::SendSingleTapUma(JNIEnv* env, |
- jobject obj, |
- jint type, |
- jint count) { |
- UMA_HISTOGRAM_ENUMERATION("Event.SingleTapType", type, count); |
-} |
- |
-void ContentViewCoreImpl::SendActionAfterDoubleTapUma(JNIEnv* env, |
- jobject obj, |
- jint type, |
- jboolean has_delay, |
- jint count) { |
- // This UMA stat tracks a user's action after a double tap within |
- // k seconds (where k == 5 currently). This UMA will tell us if |
- // removing the tap gesture delay will lead to significantly more |
- // accidental navigations after a double tap. |
- if (has_delay) { |
- UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapWithDelay", type, |
- count); |
- } else { |
- UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapNoDelay", type, |
- count); |
- } |
-} |
- |
void ContentViewCoreImpl::SendOrientationChangeEventInternal() { |
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); |
if (rwhv) |