summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-12 05:51:37 +0000
committerjdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-12 05:51:37 +0000
commitb2afd3d8ea8fa1fc0d8abb891a99d8ff2eabd30b (patch)
tree135b195cf9d7d4b9be0bc42970db81aba097a6a6
parent283bd1c9807a6a16d595de2bf04f00d9c5bed008 (diff)
downloadchromium_src-b2afd3d8ea8fa1fc0d8abb891a99d8ff2eabd30b.zip
chromium_src-b2afd3d8ea8fa1fc0d8abb891a99d8ff2eabd30b.tar.gz
chromium_src-b2afd3d8ea8fa1fc0d8abb891a99d8ff2eabd30b.tar.bz2
[Android] Use DIP coordinates with MotionEventAndroid
With this change, all MotionEvent implementations will use DIP coordinates, eliminating confusion and making the world a better place. All assumptions of integral coordinates in the gesture detection pipeline have been updated appropriately. BUG=332418 Review URL: https://codereview.chromium.org/220063002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263493 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/android/content_view_core_impl.cc9
-rw-r--r--content/browser/renderer_host/input/motion_event_android.cc114
-rw-r--r--content/browser/renderer_host/input/motion_event_android.h30
-rw-r--r--content/browser/renderer_host/input/touch_event_queue.cc11
-rw-r--r--content/browser/renderer_host/input/web_input_event_util.cc82
-rw-r--r--content/browser/renderer_host/input/web_input_event_util.h6
-rw-r--r--ui/events/gesture_detection/gesture_config_helper.cc18
-rw-r--r--ui/events/gesture_detection/gesture_config_helper.h10
-rw-r--r--ui/events/gesture_detection/gesture_config_helper_android.cc56
-rw-r--r--ui/events/gesture_detection/gesture_config_helper_aura.cc26
-rw-r--r--ui/events/gesture_detection/gesture_detector.cc44
-rw-r--r--ui/events/gesture_detection/gesture_detector.h28
-rw-r--r--ui/events/gesture_detection/gesture_provider.cc91
-rw-r--r--ui/events/gesture_detection/gesture_provider.h3
-rw-r--r--ui/events/gesture_detection/gesture_provider_unittest.cc86
-rw-r--r--ui/events/gesture_detection/scale_gesture_detector.cc18
-rw-r--r--ui/events/gesture_detection/scale_gesture_detector.h16
-rw-r--r--ui/events/gesture_detection/snap_scroll_controller.cc49
-rw-r--r--ui/events/gesture_detection/snap_scroll_controller.h16
19 files changed, 357 insertions, 356 deletions
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 6cd82b8..2369f6f 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -366,8 +366,7 @@ void ContentViewCoreImpl::RenderViewReady() {
}
void ContentViewCoreImpl::OnGestureEvent(const ui::GestureEventData& gesture) {
- SendGestureEvent(
- CreateWebGestureEventFromGestureEventData(gesture, 1.f / dpi_scale()));
+ SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
}
RenderWidgetHostViewAndroid*
@@ -1056,7 +1055,8 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
if (!rwhv)
return false;
- MotionEventAndroid event(env,
+ MotionEventAndroid event(1.f / dpi_scale(),
+ env,
motion_event,
time_ms,
android_action,
@@ -1143,8 +1143,7 @@ bool ContentViewCoreImpl::OnMotionEvent(const ui::MotionEvent& event) {
return true;
}
- rwhv->SendTouchEvent(
- CreateWebTouchEventFromMotionEvent(event, 1.f / dpi_scale()));
+ rwhv->SendTouchEvent(CreateWebTouchEventFromMotionEvent(event));
return true;
}
diff --git a/content/browser/renderer_host/input/motion_event_android.cc b/content/browser/renderer_host/input/motion_event_android.cc
index eea14e9..c0f1721 100644
--- a/content/browser/renderer_host/input/motion_event_android.cc
+++ b/content/browser/renderer_host/input/motion_event_android.cc
@@ -64,26 +64,28 @@ base::TimeTicks FromAndroidTime(int64 time_ms) {
} // namespace
-MotionEventAndroid::MotionEventAndroid(JNIEnv* env,
+MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
+ JNIEnv* env,
jobject event,
jlong time_ms,
jint android_action,
jint pointer_count,
jint history_size,
jint action_index,
- jfloat pos_x_0,
- jfloat pos_y_0,
- jfloat pos_x_1,
- jfloat pos_y_1,
+ jfloat pos_x_0_pixels,
+ jfloat pos_y_0_pixels,
+ jfloat pos_x_1_pixels,
+ jfloat pos_y_1_pixels,
jint pointer_id_0,
jint pointer_id_1,
- jfloat touch_major_0,
- jfloat touch_major_1)
+ jfloat touch_major_0_pixels,
+ jfloat touch_major_1_pixels)
: cached_time_(FromAndroidTime(time_ms)),
cached_action_(FromAndroidAction(android_action)),
cached_pointer_count_(pointer_count),
cached_history_size_(history_size),
cached_action_index_(action_index),
+ pix_to_dip_(pix_to_dip),
should_recycle_(false) {
DCHECK_GT(pointer_count, 0);
DCHECK_GE(history_size, 0);
@@ -91,32 +93,36 @@ MotionEventAndroid::MotionEventAndroid(JNIEnv* env,
event_.Reset(env, event);
DCHECK(event_.obj());
- cached_positions_[0] = gfx::PointF(pos_x_0, pos_y_0);
- cached_positions_[1] = gfx::PointF(pos_x_1, pos_y_1);
+ cached_positions_[0] = ToDips(gfx::PointF(pos_x_0_pixels, pos_y_0_pixels));
+ cached_positions_[1] = ToDips(gfx::PointF(pos_x_1_pixels, pos_y_1_pixels));
cached_pointer_ids_[0] = pointer_id_0;
cached_pointer_ids_[1] = pointer_id_1;
- cached_touch_majors_[0] = touch_major_0;
- cached_touch_majors_[1] = touch_major_1;
+ cached_touch_majors_[0] = ToDips(touch_major_0_pixels);
+ cached_touch_majors_[1] = ToDips(touch_major_1_pixels);
}
-MotionEventAndroid::MotionEventAndroid(JNIEnv* env, jobject event)
+MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
+ JNIEnv* env,
+ jobject event)
: cached_time_(FromAndroidTime(Java_MotionEvent_getEventTime(env, event))),
- cached_action_(FromAndroidAction(
- Java_MotionEvent_getActionMasked(env, event))),
+ cached_action_(
+ FromAndroidAction(Java_MotionEvent_getActionMasked(env, event))),
cached_pointer_count_(Java_MotionEvent_getPointerCount(env, event)),
cached_history_size_(Java_MotionEvent_getHistorySize(env, event)),
cached_action_index_(Java_MotionEvent_getActionIndex(env, event)),
+ pix_to_dip_(pix_to_dip),
should_recycle_(true) {
event_.Reset(env, event);
DCHECK(event_.obj());
for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
if (i < cached_pointer_count_) {
- cached_positions_[i].set_x(Java_MotionEvent_getXF_I(env, event, i));
- cached_positions_[i].set_y(Java_MotionEvent_getYF_I(env, event, i));
+ cached_positions_[i] =
+ ToDips(gfx::PointF(Java_MotionEvent_getXF_I(env, event, i),
+ Java_MotionEvent_getYF_I(env, event, i)));
cached_pointer_ids_[i] = Java_MotionEvent_getPointerId(env, event, i);
cached_touch_majors_[i] =
- Java_MotionEvent_getTouchMajorF_I(env, event, i);
+ ToDips(Java_MotionEvent_getTouchMajorF_I(env, event, i));
} else {
cached_pointer_ids_[i] = 0;
cached_touch_majors_[i] = 0.f;
@@ -131,6 +137,7 @@ MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& other)
cached_pointer_count_(other.cached_pointer_count_),
cached_history_size_(other.cached_history_size_),
cached_action_index_(other.cached_action_index_),
+ pix_to_dip_(other.pix_to_dip_),
should_recycle_(true) {
DCHECK(event_.obj());
for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
@@ -153,9 +160,7 @@ MotionEventAndroid::Action MotionEventAndroid::GetAction() const {
return cached_action_;
}
-int MotionEventAndroid::GetActionIndex() const {
- return cached_action_index_;
-}
+int MotionEventAndroid::GetActionIndex() const { return cached_action_index_; }
size_t MotionEventAndroid::GetPointerCount() const {
return cached_pointer_count_;
@@ -173,24 +178,24 @@ float MotionEventAndroid::GetX(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
return cached_positions_[pointer_index].x();
- return Java_MotionEvent_getXF_I(
- AttachCurrentThread(), event_.obj(), pointer_index);
+ return ToDips(Java_MotionEvent_getXF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
}
float MotionEventAndroid::GetY(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
return cached_positions_[pointer_index].y();
- return Java_MotionEvent_getYF_I(
- AttachCurrentThread(), event_.obj(), pointer_index);
+ return ToDips(Java_MotionEvent_getYF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
}
float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
return cached_touch_majors_[pointer_index];
- return Java_MotionEvent_getTouchMajorF_I(
- AttachCurrentThread(), event_.obj(), pointer_index);
+ return ToDips(Java_MotionEvent_getTouchMajorF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
}
float MotionEventAndroid::GetPressure(size_t pointer_index) const {
@@ -213,23 +218,23 @@ base::TimeTicks MotionEventAndroid::GetHistoricalEventTime(
AttachCurrentThread(), event_.obj(), historical_index));
}
-float MotionEventAndroid::GetHistoricalTouchMajor(size_t pointer_index,
- size_t historical_index)
- const {
- return Java_MotionEvent_getHistoricalTouchMajorF_I_I(
- AttachCurrentThread(), event_.obj(), pointer_index, historical_index);
+float MotionEventAndroid::GetHistoricalTouchMajor(
+ size_t pointer_index,
+ size_t historical_index) const {
+ return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
+ AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
}
float MotionEventAndroid::GetHistoricalX(size_t pointer_index,
size_t historical_index) const {
- return Java_MotionEvent_getHistoricalXF_I_I(
- AttachCurrentThread(), event_.obj(), pointer_index, historical_index);
+ return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
+ AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
}
float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
size_t historical_index) const {
- return Java_MotionEvent_getHistoricalYF_I_I(
- AttachCurrentThread(), event_.obj(), pointer_index, historical_index);
+ return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
+ AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
}
scoped_ptr<ui::MotionEvent> MotionEventAndroid::Clone() const {
@@ -237,18 +242,23 @@ scoped_ptr<ui::MotionEvent> MotionEventAndroid::Clone() const {
}
scoped_ptr<ui::MotionEvent> MotionEventAndroid::Cancel() const {
- return scoped_ptr<MotionEvent>(new MotionEventAndroid(
- AttachCurrentThread(),
- Obtain(GetDownTime(),
- GetEventTime(),
- MotionEventAndroid::ACTION_CANCEL,
- GetX(0),
- GetY(0)).obj()));
+ // The input coordinates to |MotionEventAndroid| are always in device pixels,
+ // but the cached coordinates are in DIPs.
+ const gfx::PointF position_pixels =
+ gfx::ScalePoint(cached_positions_[0], 1.f / pix_to_dip_);
+ return scoped_ptr<MotionEvent>(
+ new MotionEventAndroid(pix_to_dip_,
+ AttachCurrentThread(),
+ Obtain(GetDownTime(),
+ GetEventTime(),
+ MotionEventAndroid::ACTION_CANCEL,
+ position_pixels.x(),
+ position_pixels.y()).obj()));
}
float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
- return Java_MotionEvent_getTouchMinorF_I(
- AttachCurrentThread(), event_.obj(), pointer_index);
+ return ToDips(Java_MotionEvent_getTouchMinorF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
}
float MotionEventAndroid::GetOrientation() const {
@@ -260,6 +270,14 @@ base::TimeTicks MotionEventAndroid::GetDownTime() const {
Java_MotionEvent_getDownTime(AttachCurrentThread(), event_.obj()));
}
+float MotionEventAndroid::ToDips(float pixels) const {
+ return pixels * pix_to_dip_;
+}
+
+gfx::PointF MotionEventAndroid::ToDips(const gfx::PointF& point_pixels) const {
+ return gfx::ScalePoint(point_pixels, pix_to_dip_);
+}
+
// static
bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
return JNI_MotionEvent::RegisterNativesImpl(env);
@@ -277,14 +295,14 @@ base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
base::TimeTicks down_time,
base::TimeTicks event_time,
Action action,
- float x,
- float y) {
+ float x_pixels,
+ float y_pixels) {
return Java_MotionEvent_obtainAVME_J_J_I_F_F_I(AttachCurrentThread(),
ToAndroidTime(down_time),
ToAndroidTime(event_time),
ToAndroidAction(action),
- x,
- y,
+ x_pixels,
+ y_pixels,
0);
}
diff --git a/content/browser/renderer_host/input/motion_event_android.h b/content/browser/renderer_host/input/motion_event_android.h
index bcc9048..2b7f45f 100644
--- a/content/browser/renderer_host/input/motion_event_android.h
+++ b/content/browser/renderer_host/input/motion_event_android.h
@@ -16,25 +16,28 @@
namespace content {
// Implementation of ui::MotionEvent wrapping a native Android MotionEvent.
+// All *input* coordinates are in device pixels (as with Android MotionEvent),
+// while all *output* coordinates are in DIPs (as with WebTouchEvent).
class MotionEventAndroid : public ui::MotionEvent {
public:
// Forcing the caller to provide all cached values upon construction
// eliminates the need to perform a JNI call to retrieve values individually.
- MotionEventAndroid(JNIEnv* env,
+ MotionEventAndroid(float pix_to_dip,
+ JNIEnv* env,
jobject event,
jlong time_ms,
jint android_action,
jint pointer_count,
jint history_size,
jint action_index,
- jfloat pos_x_0,
- jfloat pos_y_0,
- jfloat pos_x_1,
- jfloat pos_y_1,
+ jfloat pos_x_0_pixels,
+ jfloat pos_y_0_pixels,
+ jfloat pos_x_1_pixels,
+ jfloat pos_y_1_pixels,
jint pointer_id_0,
jint pointer_id_1,
- jfloat touch_major_0,
- jfloat touch_major_1);
+ jfloat touch_major_0_pixels,
+ jfloat touch_major_1_pixels);
virtual ~MotionEventAndroid();
// ui::MotionEvent methods.
@@ -77,15 +80,18 @@ class MotionEventAndroid : public ui::MotionEvent {
base::TimeTicks down_time,
base::TimeTicks event_time,
Action action,
- float x,
- float y);
+ float x_pixels,
+ float y_pixels);
private:
MotionEventAndroid();
- MotionEventAndroid(JNIEnv* env, jobject event);
+ MotionEventAndroid(float pix_to_dip, JNIEnv* env, jobject event);
MotionEventAndroid(const MotionEventAndroid&);
MotionEventAndroid& operator=(const MotionEventAndroid&);
+ float ToDips(float pixels) const;
+ gfx::PointF ToDips(const gfx::PointF& pixels) const;
+
// Cache pointer coords, id's and major lengths for the most common
// touch-related scenarios, i.e., scrolling and pinching. This prevents
// redundant JNI fetches for the same bits.
@@ -103,6 +109,10 @@ class MotionEventAndroid : public ui::MotionEvent {
int cached_pointer_ids_[MAX_POINTERS_TO_CACHE];
float cached_touch_majors_[MAX_POINTERS_TO_CACHE];
+ // Used to convert pixel coordinates from the Java-backed MotionEvent to
+ // DIP coordinates cached/returned by the MotionEventAndroid.
+ const float pix_to_dip_;
+
// Whether |event_| should be recycled on destruction. This will only be true
// for those events generated via |Obtain(...)|.
bool should_recycle_;
diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc
index a6d8729..8662f4a 100644
--- a/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/content/browser/renderer_host/input/touch_event_queue.cc
@@ -21,6 +21,11 @@ using ui::LatencyInfo;
namespace content {
namespace {
+// Using a small epsilon when comparing slop distances allows pixel perfect
+// slop determination when using fractional DIP coordinates (assuming the slop
+// region and DPI scale are reasonably proportioned).
+const float kSlopEpsilon = .05f;
+
typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
@@ -167,6 +172,8 @@ class TouchEventQueue::TouchTimeoutHandler {
// Provides touchmove slop suppression for a single touch that remains within
// a given slop region, unless the touchstart is preventDefault'ed.
+// TODO(jdduke): Use a flag bundled with each TouchEvent declaring whether it
+// has exceeded the slop region, removing duplicated slop determination logic.
class TouchEventQueue::TouchMoveSlopSuppressor {
public:
TouchMoveSlopSuppressor(double slop_suppression_length_dips)
@@ -288,8 +295,8 @@ TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
dispatching_touch_(false),
touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT),
ack_timeout_enabled_(false),
- touchmove_slop_suppressor_(
- new TouchMoveSlopSuppressor(touchmove_suppression_length_dips)),
+ touchmove_slop_suppressor_(new TouchMoveSlopSuppressor(
+ touchmove_suppression_length_dips + kSlopEpsilon)),
absorbing_touch_moves_(false),
touch_scrolling_mode_(mode) {
DCHECK(client);
diff --git a/content/browser/renderer_host/input/web_input_event_util.cc b/content/browser/renderer_host/input/web_input_event_util.cc
index 37a0d60..8a7fd92 100644
--- a/content/browser/renderer_host/input/web_input_event_util.cc
+++ b/content/browser/renderer_host/input/web_input_event_util.cc
@@ -112,7 +112,7 @@ const char* GetKeyIdentifier(ui::KeyboardCode key_code) {
case ui::VKEY_UP:
return "Up";
case ui::VKEY_DELETE:
- return "U+007F"; // Standard says that DEL becomes U+007F.
+ return "U+007F"; // Standard says that DEL becomes U+007F.
case ui::VKEY_MEDIA_NEXT_TRACK:
return "MediaNextTrack";
case ui::VKEY_MEDIA_PREV_TRACK:
@@ -177,19 +177,17 @@ WebTouchPoint::State ToWebTouchPointState(MotionEvent::Action action,
}
WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
- size_t pointer_index,
- float scale) {
+ size_t pointer_index) {
WebTouchPoint touch;
touch.id = event.GetPointerId(pointer_index);
touch.state = ToWebTouchPointState(
event.GetAction(),
static_cast<int>(pointer_index) == event.GetActionIndex());
- touch.position.x = event.GetX(pointer_index) * scale;
- touch.position.y = event.GetY(pointer_index) * scale;
+ touch.position.x = event.GetX(pointer_index);
+ touch.position.y = event.GetY(pointer_index);
// TODO(joth): Raw event co-ordinates.
touch.screenPosition = touch.position;
- touch.radiusX = touch.radiusY =
- event.GetTouchMajor(pointer_index) * 0.5f * scale;
+ touch.radiusX = touch.radiusY = event.GetTouchMajor(pointer_index) * 0.5f;
touch.force = event.GetPressure(pointer_index);
return touch;
@@ -207,14 +205,15 @@ void UpdateWindowsKeyCodeAndKeyIdentifier(blink::WebKeyboardEvent* event,
if (id) {
base::strlcpy(event->keyIdentifier, id, sizeof(event->keyIdentifier) - 1);
} else {
- base::snprintf(event->keyIdentifier, sizeof(event->keyIdentifier), "U+%04X",
+ base::snprintf(event->keyIdentifier,
+ sizeof(event->keyIdentifier),
+ "U+%04X",
base::ToUpperASCII(static_cast<int>(windows_key_code)));
}
}
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
- const ui::MotionEvent& event,
- float scale) {
+ const ui::MotionEvent& event) {
blink::WebTouchEvent result;
result.type = ToWebInputEventType(event.GetAction());
@@ -229,84 +228,75 @@ blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
DCHECK_GT(result.touchesLength, 0U);
for (size_t i = 0; i < result.touchesLength; ++i)
- result.touches[i] = CreateWebTouchPoint(event, i, scale);
+ result.touches[i] = CreateWebTouchPoint(event, i);
return result;
}
WebGestureEvent CreateWebGestureEventFromGestureEventData(
- const ui::GestureEventData& data,
- float scale) {
+ const ui::GestureEventData& data) {
WebGestureEvent gesture;
- gesture.x = data.x * scale;
- gesture.y = data.y * scale;
+ gesture.x = data.x;
+ gesture.y = data.y;
gesture.timeStampSeconds = (data.time - base::TimeTicks()).InSecondsF();
gesture.sourceDevice = WebGestureEvent::Touchscreen;
switch (data.type) {
case ui::ET_GESTURE_SHOW_PRESS:
gesture.type = WebInputEvent::GestureShowPress;
- gesture.data.showPress.width =
- data.details.bounding_box_f().width() * scale;
- gesture.data.showPress.height =
- data.details.bounding_box_f().height() * scale;
+ gesture.data.showPress.width = data.details.bounding_box_f().width();
+ gesture.data.showPress.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_DOUBLE_TAP:
gesture.type = WebInputEvent::GestureDoubleTap;
DCHECK_EQ(1, data.details.tap_count());
gesture.data.tap.tapCount = data.details.tap_count();
- gesture.data.tap.width = data.details.bounding_box_f().width() * scale;
- gesture.data.tap.height = data.details.bounding_box_f().height() * scale;
+ gesture.data.tap.width = data.details.bounding_box_f().width();
+ gesture.data.tap.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_TAP:
gesture.type = WebInputEvent::GestureTap;
DCHECK_EQ(1, data.details.tap_count());
gesture.data.tap.tapCount = data.details.tap_count();
- gesture.data.tap.width = data.details.bounding_box_f().width() * scale;
- gesture.data.tap.height = data.details.bounding_box_f().height() * scale;
+ gesture.data.tap.width = data.details.bounding_box_f().width();
+ gesture.data.tap.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_TAP_UNCONFIRMED:
gesture.type = WebInputEvent::GestureTapUnconfirmed;
DCHECK_EQ(1, data.details.tap_count());
gesture.data.tap.tapCount = data.details.tap_count();
- gesture.data.tap.width = data.details.bounding_box_f().width() * scale;
- gesture.data.tap.height = data.details.bounding_box_f().height() * scale;
+ gesture.data.tap.width = data.details.bounding_box_f().width();
+ gesture.data.tap.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_LONG_PRESS:
gesture.type = WebInputEvent::GestureLongPress;
- gesture.data.longPress.width =
- data.details.bounding_box_f().width() * scale;
- gesture.data.longPress.height =
- data.details.bounding_box_f().height() * scale;
+ gesture.data.longPress.width = data.details.bounding_box_f().width();
+ gesture.data.longPress.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_LONG_TAP:
gesture.type = WebInputEvent::GestureLongTap;
- gesture.data.longPress.width =
- data.details.bounding_box_f().width() * scale;
- gesture.data.longPress.height =
- data.details.bounding_box_f().height() * scale;
+ gesture.data.longPress.width = data.details.bounding_box_f().width();
+ gesture.data.longPress.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_SCROLL_BEGIN:
gesture.type = WebInputEvent::GestureScrollBegin;
- gesture.data.scrollBegin.deltaXHint =
- data.details.scroll_x_hint() * scale;
- gesture.data.scrollBegin.deltaYHint =
- data.details.scroll_y_hint() * scale;
+ gesture.data.scrollBegin.deltaXHint = data.details.scroll_x_hint();
+ gesture.data.scrollBegin.deltaYHint = data.details.scroll_y_hint();
break;
case ui::ET_GESTURE_SCROLL_UPDATE:
gesture.type = WebInputEvent::GestureScrollUpdate;
- gesture.data.scrollUpdate.deltaX = data.details.scroll_x() * scale;
- gesture.data.scrollUpdate.deltaY = data.details.scroll_y() * scale;
- gesture.data.scrollUpdate.velocityX = data.details.velocity_x() * scale;
- gesture.data.scrollUpdate.velocityY = data.details.velocity_y() * scale;
+ gesture.data.scrollUpdate.deltaX = data.details.scroll_x();
+ gesture.data.scrollUpdate.deltaY = data.details.scroll_y();
+ gesture.data.scrollUpdate.velocityX = data.details.velocity_x();
+ gesture.data.scrollUpdate.velocityY = data.details.velocity_y();
break;
case ui::ET_GESTURE_SCROLL_END:
gesture.type = WebInputEvent::GestureScrollEnd;
break;
case ui::ET_SCROLL_FLING_START:
gesture.type = WebInputEvent::GestureFlingStart;
- gesture.data.flingStart.velocityX = data.details.velocity_x() * scale;
- gesture.data.flingStart.velocityY = data.details.velocity_y() * scale;
+ gesture.data.flingStart.velocityX = data.details.velocity_x();
+ gesture.data.flingStart.velocityY = data.details.velocity_y();
break;
case ui::ET_SCROLL_FLING_CANCEL:
gesture.type = WebInputEvent::GestureFlingCancel;
@@ -326,10 +316,8 @@ WebGestureEvent CreateWebGestureEventFromGestureEventData(
break;
case ui::ET_GESTURE_TAP_DOWN:
gesture.type = WebInputEvent::GestureTapDown;
- gesture.data.tapDown.width =
- data.details.bounding_box_f().width() * scale;
- gesture.data.tapDown.height =
- data.details.bounding_box_f().height() * scale;
+ gesture.data.tapDown.width = data.details.bounding_box_f().width();
+ gesture.data.tapDown.height = data.details.bounding_box_f().height();
break;
case ui::ET_GESTURE_BEGIN:
case ui::ET_GESTURE_END:
diff --git a/content/browser/renderer_host/input/web_input_event_util.h b/content/browser/renderer_host/input/web_input_event_util.h
index f3d3c46..4143a1c 100644
--- a/content/browser/renderer_host/input/web_input_event_util.h
+++ b/content/browser/renderer_host/input/web_input_event_util.h
@@ -25,14 +25,12 @@ CONTENT_EXPORT void UpdateWindowsKeyCodeAndKeyIdentifier(
// Creates a WebTouchEvent from |event|, scaling all size components from
// |event| by |scale|.
CONTENT_EXPORT blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
- const ui::MotionEvent& event,
- float scale);
+ const ui::MotionEvent& event);
// Creates a WebGestureEvent from |event|, scaling all size components from
// |event| by |scale|.
CONTENT_EXPORT blink::WebGestureEvent CreateWebGestureEventFromGestureEventData(
- const ui::GestureEventData& data,
- float scale);
+ const ui::GestureEventData& data);
} // namespace content
diff --git a/ui/events/gesture_detection/gesture_config_helper.cc b/ui/events/gesture_detection/gesture_config_helper.cc
index 86ad6c7..0039e2c 100644
--- a/ui/events/gesture_detection/gesture_config_helper.cc
+++ b/ui/events/gesture_detection/gesture_config_helper.cc
@@ -4,22 +4,14 @@
#include "ui/events/gesture_detection/gesture_config_helper.h"
-namespace ui {
-
-GestureDetector::Config DefaultGestureDetectorConfig() {
- return GestureDetector::Config();
-}
+#include "ui/gfx/screen.h"
-ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig() {
- return ScaleGestureDetector::Config();
-}
-
-SnapScrollController::Config DefaultSnapScrollControllerConfig() {
- return SnapScrollController::Config();
-}
+namespace ui {
GestureProvider::Config DefaultGestureProviderConfig() {
- return GestureProvider::Config();
+ GestureProvider::Config config;
+ config.display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ return config;
}
} // namespace ui
diff --git a/ui/events/gesture_detection/gesture_config_helper.h b/ui/events/gesture_detection/gesture_config_helper.h
index e37268d..0b54c36 100644
--- a/ui/events/gesture_detection/gesture_config_helper.h
+++ b/ui/events/gesture_detection/gesture_config_helper.h
@@ -9,19 +9,9 @@
#include "ui/events/gesture_detection/gesture_detector.h"
#include "ui/events/gesture_detection/gesture_provider.h"
#include "ui/events/gesture_detection/scale_gesture_detector.h"
-#include "ui/events/gesture_detection/snap_scroll_controller.h"
namespace ui {
-GESTURE_DETECTION_EXPORT GestureDetector::Config
-DefaultGestureDetectorConfig();
-
-GESTURE_DETECTION_EXPORT ScaleGestureDetector::Config
-DefaultScaleGestureDetectorConfig();
-
-GESTURE_DETECTION_EXPORT SnapScrollController::Config
-DefaultSnapScrollControllerConfig();
-
GESTURE_DETECTION_EXPORT GestureProvider::Config
DefaultGestureProviderConfig();
diff --git a/ui/events/gesture_detection/gesture_config_helper_android.cc b/ui/events/gesture_detection/gesture_config_helper_android.cc
index 3ed6b77..e37650a 100644
--- a/ui/events/gesture_detection/gesture_config_helper_android.cc
+++ b/ui/events/gesture_detection/gesture_config_helper_android.cc
@@ -10,59 +10,57 @@
using gfx::ViewConfiguration;
namespace ui {
-
+namespace {
// TODO(jdduke): Adopt GestureConfiguration on Android, crbug/339203.
-GestureDetector::Config DefaultGestureDetectorConfig() {
+GestureDetector::Config DefaultGestureDetectorConfig(
+ const gfx::Display& display) {
GestureDetector::Config config;
config.longpress_timeout = base::TimeDelta::FromMilliseconds(
ViewConfiguration::GetLongPressTimeoutInMs());
- config.showpress_timeout = base::TimeDelta::FromMilliseconds(
- ViewConfiguration::GetTapTimeoutInMs());
+ config.showpress_timeout =
+ base::TimeDelta::FromMilliseconds(ViewConfiguration::GetTapTimeoutInMs());
config.double_tap_timeout = base::TimeDelta::FromMilliseconds(
ViewConfiguration::GetDoubleTapTimeoutInMs());
- config.scaled_touch_slop = ViewConfiguration::GetTouchSlopInPixels();
- config.scaled_double_tap_slop = ViewConfiguration::GetDoubleTapSlopInPixels();
- config.scaled_minimum_fling_velocity =
- ViewConfiguration::GetMinimumFlingVelocityInPixelsPerSecond();
- config.scaled_maximum_fling_velocity =
- ViewConfiguration::GetMaximumFlingVelocityInPixelsPerSecond();
+ const float px_to_dp = 1.f / display.device_scale_factor();
+ config.touch_slop =
+ ViewConfiguration::GetTouchSlopInPixels() * px_to_dp;
+ config.double_tap_slop =
+ ViewConfiguration::GetDoubleTapSlopInPixels() * px_to_dp;
+ config.minimum_fling_velocity =
+ ViewConfiguration::GetMinimumFlingVelocityInPixelsPerSecond() * px_to_dp;
+ config.maximum_fling_velocity =
+ ViewConfiguration::GetMaximumFlingVelocityInPixelsPerSecond() * px_to_dp;
return config;
}
-ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig() {
+ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig(
+ const gfx::Display& display) {
ScaleGestureDetector::Config config;
- config.gesture_detector_config = DefaultGestureDetectorConfig();
+ config.gesture_detector_config = DefaultGestureDetectorConfig(display);
config.quick_scale_enabled = true;
+
+ const float px_to_dp = 1.f / display.device_scale_factor();
config.min_scaling_touch_major =
- ViewConfiguration::GetMinScalingTouchMajorInPixels();
- config.min_scaling_span = ViewConfiguration::GetMinScalingSpanInPixels();
+ ViewConfiguration::GetMinScalingTouchMajorInPixels() * px_to_dp;
+ config.min_scaling_span =
+ ViewConfiguration::GetMinScalingSpanInPixels() * px_to_dp;
return config;
}
-SnapScrollController::Config DefaultSnapScrollControllerConfig() {
- SnapScrollController::Config config;
-
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
-
- config.screen_width_pixels = display.GetSizeInPixel().width();
- config.screen_height_pixels = display.GetSizeInPixel().height();
- config.device_scale_factor = display.device_scale_factor();
-
- return config;
-}
+} // namespace
GestureProvider::Config DefaultGestureProviderConfig() {
GestureProvider::Config config;
- config.gesture_detector_config = DefaultGestureDetectorConfig();
- config.scale_gesture_detector_config = DefaultScaleGestureDetectorConfig();
- config.snap_scroll_controller_config = DefaultSnapScrollControllerConfig();
+ config.display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ config.gesture_detector_config = DefaultGestureDetectorConfig(config.display);
+ config.scale_gesture_detector_config =
+ DefaultScaleGestureDetectorConfig(config.display);
config.gesture_begin_end_types_enabled = false;
return config;
}
diff --git a/ui/events/gesture_detection/gesture_config_helper_aura.cc b/ui/events/gesture_detection/gesture_config_helper_aura.cc
index 25cce58..e7845ac 100644
--- a/ui/events/gesture_detection/gesture_config_helper_aura.cc
+++ b/ui/events/gesture_detection/gesture_config_helper_aura.cc
@@ -8,6 +8,7 @@
#include "ui/gfx/screen.h"
namespace ui {
+namespace {
GestureDetector::Config DefaultGestureDetectorConfig() {
GestureDetector::Config config;
@@ -18,13 +19,13 @@ GestureDetector::Config DefaultGestureDetectorConfig() {
GestureConfiguration::show_press_delay_in_ms());
config.double_tap_timeout = base::TimeDelta::FromMilliseconds(
GestureConfiguration::semi_long_press_time_in_seconds() * 1000.);
- config.scaled_touch_slop =
+ config.touch_slop =
GestureConfiguration::max_touch_move_in_pixels_for_click();
- config.scaled_double_tap_slop =
+ config.double_tap_slop =
GestureConfiguration::max_distance_between_taps_for_double_tap();
- config.scaled_minimum_fling_velocity =
+ config.minimum_fling_velocity =
GestureConfiguration::min_scroll_velocity();
- config.scaled_maximum_fling_velocity =
+ config.maximum_fling_velocity =
GestureConfiguration::fling_velocity_cap();
return config;
@@ -34,30 +35,19 @@ ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig() {
ScaleGestureDetector::Config config;
config.gesture_detector_config = DefaultGestureDetectorConfig();
- config.min_scaling_touch_major = GestureConfiguration::default_radius() / 2;
+ config.min_scaling_touch_major = GestureConfiguration::default_radius() * 2;
config.min_scaling_span =
GestureConfiguration::min_distance_for_pinch_scroll_in_pixels();
return config;
}
-SnapScrollController::Config DefaultSnapScrollControllerConfig() {
- SnapScrollController::Config config;
-
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
-
- config.screen_width_pixels = display.GetSizeInPixel().width();
- config.screen_height_pixels = display.GetSizeInPixel().height();
- config.device_scale_factor = display.device_scale_factor();
-
- return config;
-}
+} // namespace
GestureProvider::Config DefaultGestureProviderConfig() {
GestureProvider::Config config;
+ config.display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
config.gesture_detector_config = DefaultGestureDetectorConfig();
config.scale_gesture_detector_config = DefaultScaleGestureDetectorConfig();
- config.snap_scroll_controller_config = DefaultSnapScrollControllerConfig();
config.gesture_begin_end_types_enabled = true;
return config;
}
diff --git a/ui/events/gesture_detection/gesture_detector.cc b/ui/events/gesture_detection/gesture_detector.cc
index 8cf76e6..1628c26 100644
--- a/ui/events/gesture_detection/gesture_detector.cc
+++ b/ui/events/gesture_detection/gesture_detector.cc
@@ -12,6 +12,15 @@
namespace ui {
namespace {
+// Using a small epsilon when comparing slop distances allows pixel perfect
+// slop determination when using fractional DIP coordinates (assuming the slop
+// region and DPI scale are reasonably proportioned).
+const float kSlopEpsilon = .05f;
+
+// Minimum distance a scroll must have traveled from the last scroll/focal point
+// to trigger an |OnScroll| callback.
+const float kScrollEpsilon = .1f;
+
// Constants used by TimeoutGestureHandler.
enum TimeoutEvent {
SHOW_PRESS = 0,
@@ -28,10 +37,10 @@ GestureDetector::Config::Config()
: longpress_timeout(base::TimeDelta::FromMilliseconds(500)),
showpress_timeout(base::TimeDelta::FromMilliseconds(180)),
double_tap_timeout(base::TimeDelta::FromMilliseconds(300)),
- scaled_touch_slop(8),
- scaled_double_tap_slop(100),
- scaled_minimum_fling_velocity(50),
- scaled_maximum_fling_velocity(8000) {}
+ touch_slop(8),
+ double_tap_slop(100),
+ minimum_fling_velocity(50),
+ maximum_fling_velocity(8000) {}
GestureDetector::Config::~Config() {}
@@ -267,10 +276,10 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
DCHECK(double_tap_listener_);
handled |= double_tap_listener_->OnDoubleTapEvent(ev);
} else if (always_in_tap_region_) {
- const int delta_x = static_cast<int>(focus_x - down_focus_x_);
- const int delta_y = static_cast<int>(focus_y - down_focus_y_);
- int distance = (delta_x * delta_x) + (delta_y * delta_y);
- if (distance > touch_slop_square_) {
+ const float delta_x = focus_x - down_focus_x_;
+ const float delta_y = focus_y - down_focus_y_;
+ const float distance_square = delta_x * delta_x + delta_y * delta_y;
+ if (distance_square > touch_slop_square_) {
handled = listener_->OnScroll(
*current_down_event_, ev, scroll_x, scroll_y);
last_focus_x_ = focus_x;
@@ -278,9 +287,10 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
always_in_tap_region_ = false;
timeout_handler_->Stop();
}
- if (distance > double_tap_touch_slop_square_)
+ if (distance_square > double_tap_touch_slop_square_)
always_in_bigger_tap_region_ = false;
- } else if ((std::abs(scroll_x) >= 1) || (std::abs(scroll_y) >= 1)) {
+ } else if (std::abs(scroll_x) > kScrollEpsilon ||
+ std::abs(scroll_y) > kScrollEpsilon) {
handled =
listener_->OnScroll(*current_down_event_, ev, scroll_x, scroll_y);
last_focus_x_ = focus_x;
@@ -340,15 +350,15 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
void GestureDetector::Init(const Config& config) {
DCHECK(listener_);
- const int touch_slop = config.scaled_touch_slop;
- const int double_tap_touch_slop = touch_slop;
- const int double_tap_slop = config.scaled_double_tap_slop;
- min_fling_velocity_ = config.scaled_minimum_fling_velocity;
- max_fling_velocity_ = config.scaled_maximum_fling_velocity;
+ const float touch_slop = config.touch_slop + kSlopEpsilon;
+ const float double_tap_touch_slop = touch_slop;
+ const float double_tap_slop = config.double_tap_slop + kSlopEpsilon;
touch_slop_square_ = touch_slop * touch_slop;
double_tap_touch_slop_square_ = double_tap_touch_slop * double_tap_touch_slop;
double_tap_slop_square_ = double_tap_slop * double_tap_slop;
double_tap_timeout_ = config.double_tap_timeout;
+ min_fling_velocity_ = config.minimum_fling_velocity;
+ max_fling_velocity_ = config.maximum_fling_velocity;
}
void GestureDetector::OnShowPressTimeout() {
@@ -401,8 +411,8 @@ bool GestureDetector::IsConsideredDoubleTap(
double_tap_timeout_)
return false;
- int delta_x = static_cast<int>(first_down.GetX() - second_down.GetX());
- int delta_y = static_cast<int>(first_down.GetY() - second_down.GetY());
+ const float delta_x = first_down.GetX() - second_down.GetX();
+ const float delta_y = first_down.GetY() - second_down.GetY();
return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square_);
}
diff --git a/ui/events/gesture_detection/gesture_detector.h b/ui/events/gesture_detection/gesture_detector.h
index 29a004a..c09b31f 100644
--- a/ui/events/gesture_detection/gesture_detector.h
+++ b/ui/events/gesture_detection/gesture_detector.h
@@ -23,13 +23,23 @@ class GestureDetector {
struct GESTURE_DETECTION_EXPORT Config {
Config();
~Config();
+
base::TimeDelta longpress_timeout;
base::TimeDelta showpress_timeout;
base::TimeDelta double_tap_timeout;
- int scaled_touch_slop;
- int scaled_double_tap_slop;
- int scaled_minimum_fling_velocity;
- int scaled_maximum_fling_velocity;
+
+ // Distance a touch can wander before a scroll will occur (in dips).
+ float touch_slop;
+
+ // Distance the first touch can wander before it is no longer considered a
+ // double tap (in dips).
+ float double_tap_slop;
+
+ // Minimum velocity to initiate a fling (in dips/second).
+ float minimum_fling_velocity;
+
+ // Maximum velocity of an initiated fling (in dips/second).
+ float maximum_fling_velocity;
};
class GestureListener {
@@ -114,11 +124,11 @@ class GestureDetector {
GestureListener* const listener_;
DoubleTapListener* double_tap_listener_;
- int touch_slop_square_;
- int double_tap_touch_slop_square_;
- int double_tap_slop_square_;
- int min_fling_velocity_;
- int max_fling_velocity_;
+ float touch_slop_square_;
+ float double_tap_touch_slop_square_;
+ float double_tap_slop_square_;
+ float min_fling_velocity_;
+ float max_fling_velocity_;
base::TimeDelta double_tap_timeout_;
bool still_down_;
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc
index 0acbd19..d932a02 100644
--- a/ui/events/gesture_detection/gesture_provider.cc
+++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -94,7 +94,9 @@ GestureEventDetails CreateTapGestureDetails(EventType type,
// GestureProvider:::Config
GestureProvider::Config::Config()
- : disable_click_delay(false), gesture_begin_end_types_enabled(false) {}
+ : display(gfx::Display::kInvalidDisplayID, gfx::Rect(1, 1)),
+ disable_click_delay(false),
+ gesture_begin_end_types_enabled(false) {}
GestureProvider::Config::~Config() {}
@@ -104,11 +106,9 @@ class GestureProvider::ScaleGestureListenerImpl
: public ScaleGestureDetector::ScaleGestureListener {
public:
ScaleGestureListenerImpl(const ScaleGestureDetector::Config& config,
- float device_scale_factor,
GestureProvider* provider)
: scale_gesture_detector_(config, this),
provider_(provider),
- px_to_dp_(1.0f / device_scale_factor),
ignore_multitouch_events_(false),
pinch_event_sent_(false) {}
@@ -174,7 +174,7 @@ class GestureProvider::ScaleGestureListenerImpl
(detector.GetCurrentSpanY() - detector.GetPreviousSpanY()) * 0.5f;
scale = std::pow(scale > 1 ? 1.0f + kDoubleTapDragZoomSpeed
: 1.0f - kDoubleTapDragZoomSpeed,
- std::abs(dy * px_to_dp_));
+ std::abs(dy));
}
GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0);
provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE,
@@ -217,9 +217,6 @@ class GestureProvider::ScaleGestureListenerImpl
GestureProvider* const provider_;
- // TODO(jdduke): Remove this when all MotionEvent's use DIPs.
- const float px_to_dp_;
-
// Completely silence multi-touch (pinch) scaling events. Used in WebView when
// zoom support is turned off.
bool ignore_multitouch_events_;
@@ -237,23 +234,18 @@ class GestureProvider::GestureListenerImpl
public GestureDetector::DoubleTapListener {
public:
GestureListenerImpl(
+ const gfx::Display& display,
const GestureDetector::Config& gesture_detector_config,
- const SnapScrollController::Config& snap_scroll_controller_config,
bool disable_click_delay,
GestureProvider* provider)
: gesture_detector_(gesture_detector_config, this, this),
- snap_scroll_controller_(snap_scroll_controller_config),
+ snap_scroll_controller_(display),
provider_(provider),
disable_click_delay_(disable_click_delay),
- scaled_touch_slop_(gesture_detector_config.scaled_touch_slop),
- scaled_touch_slop_square_(scaled_touch_slop_ * scaled_touch_slop_),
+ touch_slop_(gesture_detector_config.touch_slop),
double_tap_timeout_(gesture_detector_config.double_tap_timeout),
ignore_single_tap_(false),
- seen_first_scroll_event_(false),
- last_raw_x_(0),
- last_raw_y_(0),
- accumulated_scroll_error_x_(0),
- accumulated_scroll_error_y_(0) {}
+ seen_first_scroll_event_(false) {}
virtual ~GestureListenerImpl() {}
@@ -276,10 +268,6 @@ class GestureProvider::GestureListenerImpl
current_down_time_ = e.GetEventTime();
ignore_single_tap_ = false;
seen_first_scroll_event_ = false;
- last_raw_x_ = e.GetRawX();
- last_raw_y_ = e.GetRawY();
- accumulated_scroll_error_x_ = 0;
- accumulated_scroll_error_y_ = 0;
GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN, 0, 0);
tap_details.set_bounding_box(
@@ -304,7 +292,7 @@ class GestureProvider::GestureListenerImpl
std::sqrt(distance_x * distance_x + distance_y * distance_y);
double epsilon = 1e-3;
if (distance > epsilon) {
- double ratio = std::max(0., distance - scaled_touch_slop_) / distance;
+ double ratio = std::max(0., distance - touch_slop_) / distance;
distance_x *= ratio;
distance_y *= ratio;
}
@@ -318,8 +306,6 @@ class GestureProvider::GestureListenerImpl
}
}
- last_raw_x_ = e2.GetRawX();
- last_raw_y_ = e2.GetRawY();
if (!provider_->IsScrollInProgress()) {
// Note that scroll start hints are in distance traveled, where
// scroll deltas are in the opposite direction.
@@ -337,20 +323,9 @@ class GestureProvider::GestureListenerImpl
scroll_details));
}
- // distance_x and distance_y is the scrolling offset since last OnScroll.
- // Because we are passing integers to Blink, this could introduce
- // rounding errors. The rounding errors will accumulate overtime.
- // To solve this, we should be adding back the rounding errors each time
- // when we calculate the new offset.
- // TODO(jdduke): Determine if we can simpy use floating point deltas, as
- // WebGestureEvent also takes floating point deltas for GestureScrollUpdate.
- int dx = (int)(distance_x + accumulated_scroll_error_x_);
- int dy = (int)(distance_y + accumulated_scroll_error_y_);
- accumulated_scroll_error_x_ += (distance_x - dx);
- accumulated_scroll_error_y_ += (distance_y - dy);
-
- if (dx || dy) {
- GestureEventDetails scroll_details(ET_GESTURE_SCROLL_UPDATE, -dx, -dy);
+ if (distance_x || distance_y) {
+ GestureEventDetails scroll_details(
+ ET_GESTURE_SCROLL_UPDATE, -distance_x, -distance_y);
provider_->Send(
CreateGesture(ET_GESTURE_SCROLL_UPDATE, e2, scroll_details));
}
@@ -384,10 +359,6 @@ class GestureProvider::GestureListenerImpl
}
virtual bool OnSingleTapUp(const MotionEvent& e) OVERRIDE {
- if (IsPointOutsideCurrentSlopRegion(e.GetRawX(), e.GetRawY())) {
- ignore_single_tap_ = true;
- return true;
- }
// This is a hack to address the issue where user hovers
// over a link for longer than double_tap_timeout_, then
// OnSingleTapConfirmed() is not triggered. But we still
@@ -487,16 +458,6 @@ class GestureProvider::GestureListenerImpl
}
private:
- bool IsPointOutsideCurrentSlopRegion(float x, float y) const {
- return IsDistanceGreaterThanTouchSlop(last_raw_x_ - x, last_raw_y_ - y);
- }
-
- bool IsDistanceGreaterThanTouchSlop(float distance_x,
- float distance_y) const {
- return distance_x * distance_x + distance_y * distance_y >
- scaled_touch_slop_square_;
- }
-
void SetIgnoreSingleTap(bool value) { ignore_single_tap_ = value; }
bool IsDoubleTapEnabled() const {
@@ -512,11 +473,7 @@ class GestureProvider::GestureListenerImpl
// double-tap gestures.
const bool disable_click_delay_;
- const int scaled_touch_slop_;
-
- // Cache of square of the scaled touch slop so we don't have to calculate it
- // on every touch.
- const int scaled_touch_slop_square_;
+ const float touch_slop_;
const base::TimeDelta double_tap_timeout_;
@@ -531,18 +488,6 @@ class GestureProvider::GestureListenerImpl
// gesture.
bool seen_first_scroll_event_;
- // Used to track the last rawX/Y coordinates for moves. This gives absolute
- // scroll distance.
- // Useful for full screen tracking.
- float last_raw_x_;
- float last_raw_y_;
-
- // Used to track the accumulated scroll error over time. This is used to
- // remove the
- // rounding error we introduced by passing integers to webkit.
- float accumulated_scroll_error_x_;
- float accumulated_scroll_error_y_;
-
DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl);
};
@@ -627,15 +572,13 @@ bool GestureProvider::IsClickDelayDisabled() const {
void GestureProvider::InitGestureDetectors(const Config& config) {
TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors");
gesture_listener_.reset(
- new GestureListenerImpl(config.gesture_detector_config,
- config.snap_scroll_controller_config,
+ new GestureListenerImpl(config.display,
+ config.gesture_detector_config,
config.disable_click_delay,
this));
- scale_gesture_listener_.reset(new ScaleGestureListenerImpl(
- config.scale_gesture_detector_config,
- config.snap_scroll_controller_config.device_scale_factor,
- this));
+ scale_gesture_listener_.reset(
+ new ScaleGestureListenerImpl(config.scale_gesture_detector_config, this));
UpdateDoubleTapDetectionSupport();
}
diff --git a/ui/events/gesture_detection/gesture_provider.h b/ui/events/gesture_detection/gesture_provider.h
index b8e85b7..41f0990 100644
--- a/ui/events/gesture_detection/gesture_provider.h
+++ b/ui/events/gesture_detection/gesture_provider.h
@@ -11,6 +11,7 @@
#include "ui/events/gesture_detection/gesture_detector.h"
#include "ui/events/gesture_detection/scale_gesture_detector.h"
#include "ui/events/gesture_detection/snap_scroll_controller.h"
+#include "ui/gfx/display.h"
namespace ui {
@@ -29,9 +30,9 @@ class GESTURE_DETECTION_EXPORT GestureProvider {
struct GESTURE_DETECTION_EXPORT Config {
Config();
~Config();
+ gfx::Display display;
GestureDetector::Config gesture_detector_config;
ScaleGestureDetector::Config scale_gesture_detector_config;
- SnapScrollController::Config snap_scroll_controller_config;
// If |disable_click_delay| is true and double-tap support is disabled,
// there will be no delay before tap events. When double-tap support is
diff --git a/ui/events/gesture_detection/gesture_provider_unittest.cc b/ui/events/gesture_detection/gesture_provider_unittest.cc
index 04ba3fc..5d9c664 100644
--- a/ui/events/gesture_detection/gesture_provider_unittest.cc
+++ b/ui/events/gesture_detection/gesture_provider_unittest.cc
@@ -131,8 +131,8 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient {
return sConfig;
}
- int GetTouchSlop() const {
- return GetDefaultConfig().gesture_detector_config.scaled_touch_slop;
+ float GetTouchSlop() const {
+ return GetDefaultConfig().gesture_detector_config.touch_slop;
}
base::TimeDelta GetLongPressTimeout() const {
@@ -156,8 +156,8 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient {
void CheckScrollEventSequenceForEndActionType(
MotionEvent::Action end_action_type) {
base::TimeTicks event_time = base::TimeTicks::Now();
- const int scroll_to_x = kFakeCoordX + 100;
- const int scroll_to_y = kFakeCoordY + 100;
+ const float scroll_to_x = kFakeCoordX + 100;
+ const float scroll_to_y = kFakeCoordY + 100;
int motion_event_id = 0;
MockMotionEvent event =
@@ -533,8 +533,8 @@ TEST_F(GestureProviderTest, DoubleTapDragZoomBasic) {
// Generate a scroll gesture and verify that the resulting scroll motion event
// has both absolute and relative position information.
TEST_F(GestureProviderTest, ScrollUpdateValues) {
- const int delta_x = 16;
- const int delta_y = 84;
+ const float delta_x = 16;
+ const float delta_y = 84;
const base::TimeTicks event_time = TimeTicks::Now();
@@ -625,8 +625,8 @@ TEST_F(GestureProviderTest, FractionalScroll) {
// Generate a scroll gesture and verify that the resulting scroll begin event
// has the expected hint values.
TEST_F(GestureProviderTest, ScrollBeginValues) {
- const int delta_x = 13;
- const int delta_y = 89;
+ const float delta_x = 13;
+ const float delta_y = 89;
const base::TimeTicks event_time = TimeTicks::Now();
@@ -789,8 +789,8 @@ TEST_F(GestureProviderTest, NoGestureLongPressDuringDoubleTap) {
// Verify that the touch slop region is removed from the first scroll delta to
// avoid a jump when starting to scroll.
TEST_F(GestureProviderTest, TouchSlopRemovedFromScroll) {
- const int scaled_touch_slop = GetTouchSlop();
- const int scroll_delta = 5;
+ const float touch_slop = GetTouchSlop();
+ const float scroll_delta = 5;
base::TimeTicks event_time = base::TimeTicks::Now();
@@ -801,7 +801,7 @@ TEST_F(GestureProviderTest, TouchSlopRemovedFromScroll) {
event = ObtainMotionEvent(event_time + kOneMicrosecond * 2,
MotionEvent::ACTION_MOVE,
kFakeCoordX,
- kFakeCoordY + scaled_touch_slop + scroll_delta);
+ kFakeCoordY + touch_slop + scroll_delta);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(ET_GESTURE_SCROLL_UPDATE, GetMostRecentGestureEventType());
@@ -811,6 +811,56 @@ TEST_F(GestureProviderTest, TouchSlopRemovedFromScroll) {
EXPECT_EQ(1, gesture.details.touch_points());
}
+// Verify that movement within the touch slop region does not generate a scroll,
+// and that the slop region is correct even when using fractional coordinates.
+TEST_F(GestureProviderTest, NoScrollWithinTouchSlop) {
+ const float touch_slop = GetTouchSlop();
+ const float scale_factor = 2.5f;
+ const int touch_slop_pixels = static_cast<int>(scale_factor * touch_slop);
+
+ base::TimeTicks event_time = base::TimeTicks::Now();
+
+ MockMotionEvent event =
+ ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN);
+ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
+
+ event = ObtainMotionEvent(event_time + kOneMicrosecond * 2,
+ MotionEvent::ACTION_MOVE,
+ kFakeCoordX + touch_slop_pixels / scale_factor,
+ kFakeCoordY);
+ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
+ EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
+
+ event = ObtainMotionEvent(event_time + kOneMicrosecond * 2,
+ MotionEvent::ACTION_MOVE,
+ kFakeCoordX,
+ kFakeCoordY + touch_slop_pixels / scale_factor);
+ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
+ EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
+
+ event = ObtainMotionEvent(event_time + kOneMicrosecond * 2,
+ MotionEvent::ACTION_MOVE,
+ kFakeCoordX - touch_slop_pixels / scale_factor,
+ kFakeCoordY);
+ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
+ EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
+
+ event = ObtainMotionEvent(event_time + kOneMicrosecond * 2,
+ MotionEvent::ACTION_MOVE,
+ kFakeCoordX,
+ kFakeCoordY - touch_slop_pixels / scale_factor);
+ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
+ EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
+
+ event =
+ ObtainMotionEvent(event_time + kOneMicrosecond * 2,
+ MotionEvent::ACTION_MOVE,
+ kFakeCoordX,
+ kFakeCoordY + (touch_slop_pixels + 1.f) / scale_factor);
+ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
+ EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
+}
+
TEST_F(GestureProviderTest, NoDoubleTapWhenExplicitlyDisabled) {
gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false);
@@ -1043,15 +1093,15 @@ TEST_F(GestureProviderTest, FixedPageScaleDuringDoubleTapDragZoom) {
// Verify that pinch zoom sends the proper event sequence.
TEST_F(GestureProviderTest, PinchZoom) {
base::TimeTicks event_time = base::TimeTicks::Now();
- const int scaled_touch_slop = GetTouchSlop();
+ const float touch_slop = GetTouchSlop();
int motion_event_id = 0;
gesture_provider_->SetDoubleTapSupportForPageEnabled(false);
gesture_provider_->SetDoubleTapSupportForPlatformEnabled(true);
gesture_provider_->SetMultiTouchSupportEnabled(true);
- int secondary_coord_x = kFakeCoordX + 20 * scaled_touch_slop;
- int secondary_coord_y = kFakeCoordY + 20 * scaled_touch_slop;
+ int secondary_coord_x = kFakeCoordX + 20 * touch_slop;
+ int secondary_coord_y = kFakeCoordY + 20 * touch_slop;
MockMotionEvent event =
ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN);
@@ -1075,8 +1125,8 @@ TEST_F(GestureProviderTest, PinchZoom) {
EXPECT_EQ(1U, GetReceivedGestureCount());
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
- secondary_coord_x += 5 * scaled_touch_slop;
- secondary_coord_y += 5 * scaled_touch_slop;
+ secondary_coord_x += 5 * touch_slop;
+ secondary_coord_y += 5 * touch_slop;
event = ObtainMotionEvent(event_time,
MotionEvent::ACTION_MOVE,
kFakeCoordX,
@@ -1095,8 +1145,8 @@ TEST_F(GestureProviderTest, PinchZoom) {
EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_UPDATE));
- secondary_coord_x += 2 * scaled_touch_slop;
- secondary_coord_y += 2 * scaled_touch_slop;
+ secondary_coord_x += 2 * touch_slop;
+ secondary_coord_y += 2 * touch_slop;
event = ObtainMotionEvent(event_time,
MotionEvent::ACTION_MOVE,
kFakeCoordX,
diff --git a/ui/events/gesture_detection/scale_gesture_detector.cc b/ui/events/gesture_detection/scale_gesture_detector.cc
index bf8a0d3..f9e091b 100644
--- a/ui/events/gesture_detection/scale_gesture_detector.cc
+++ b/ui/events/gesture_detection/scale_gesture_detector.cc
@@ -17,6 +17,11 @@ using base::TimeTicks;
namespace ui {
namespace {
+// Using a small epsilon when comparing slop distances allows pixel perfect
+// slop determination when using fractional DPI coordinates (assuming the slop
+// region and DPI scale are reasonably proportioned).
+const float kSlopEpsilon = .05f;
+
const int kTouchStabilizeTimeMs = 128;
const float kScaleFactor = .5f;
@@ -26,9 +31,9 @@ const float kScaleFactor = .5f;
// Note: These constants were taken directly from the default (unscaled)
// versions found in Android's ViewConfiguration.
ScaleGestureDetector::Config::Config()
- : quick_scale_enabled(true),
- min_scaling_touch_major(48),
- min_scaling_span(200) {}
+ : min_scaling_touch_major(48),
+ min_scaling_span(200),
+ quick_scale_enabled(true) {}
ScaleGestureDetector::Config::~Config() {}
@@ -72,9 +77,10 @@ ScaleGestureDetector::ScaleGestureDetector(const Config& config,
double_tap_mode_(DOUBLE_TAP_MODE_NONE),
event_before_or_above_starting_gesture_event_(false) {
DCHECK(listener_);
- span_slop_ = config.gesture_detector_config.scaled_touch_slop * 2;
+ span_slop_ =
+ (config.gesture_detector_config.touch_slop + kSlopEpsilon) * 2;
touch_min_major_ = config.min_scaling_touch_major;
- min_span_ = config.min_scaling_span;
+ min_span_ = config.min_scaling_span + kSlopEpsilon;
SetQuickScaleEnabled(config.quick_scale_enabled);
}
@@ -199,7 +205,7 @@ bool ScaleGestureDetector::OnTouchEvent(const MotionEvent& event) {
initial_span_ = prev_span_ = curr_span_ = span;
}
- const int min_span = InDoubleTapMode() ? span_slop_ : min_span_;
+ const float min_span = InDoubleTapMode() ? span_slop_ : min_span_;
if (!in_progress_ && span >= min_span &&
(was_in_progress || std::abs(span - initial_span_) > span_slop_)) {
prev_span_x_ = curr_span_x_ = span_x;
diff --git a/ui/events/gesture_detection/scale_gesture_detector.h b/ui/events/gesture_detection/scale_gesture_detector.h
index 2d83ca1..08b6288 100644
--- a/ui/events/gesture_detection/scale_gesture_detector.h
+++ b/ui/events/gesture_detection/scale_gesture_detector.h
@@ -24,9 +24,15 @@ class ScaleGestureDetector : public GestureDetector::SimpleGestureListener {
Config();
~Config();
GestureDetector::Config gesture_detector_config;
+
+ // Minimum accepted value for TouchMajor while scaling (in dips).
+ float min_scaling_touch_major;
+
+ // Minimum span needed to initiate a scaling gesture (in dips).
+ float min_scaling_span;
+
+ // Whether double-tap drag scaling is enabled.
bool quick_scale_enabled;
- int min_scaling_touch_major;
- int min_scaling_span;
};
class ScaleGestureListener {
@@ -120,8 +126,8 @@ class ScaleGestureDetector : public GestureDetector::SimpleGestureListener {
base::TimeTicks curr_time_;
base::TimeTicks prev_time_;
bool in_progress_;
- int span_slop_;
- int min_span_;
+ float span_slop_;
+ float min_span_;
// Bounds for recently seen values.
float touch_upper_;
@@ -129,7 +135,7 @@ class ScaleGestureDetector : public GestureDetector::SimpleGestureListener {
float touch_history_last_accepted_;
int touch_history_direction_;
base::TimeTicks touch_history_last_accepted_time_;
- int touch_min_major_;
+ float touch_min_major_;
float double_tap_focus_x_;
float double_tap_focus_y_;
DoubleTapMode double_tap_mode_;
diff --git a/ui/events/gesture_detection/snap_scroll_controller.cc b/ui/events/gesture_detection/snap_scroll_controller.cc
index 85ac432..bde5a35 100644
--- a/ui/events/gesture_detection/snap_scroll_controller.cc
+++ b/ui/events/gesture_detection/snap_scroll_controller.cc
@@ -7,19 +7,33 @@
#include <cmath>
#include "ui/events/gesture_detection/motion_event.h"
+#include "ui/gfx/display.h"
namespace ui {
namespace {
const int kSnapBound = 16;
-} // namespace
+const float kMinSnapChannelDistance = kSnapBound;
+const float kMaxSnapChannelDistance = kMinSnapChannelDistance * 3.f;
+const float kSnapChannelDipsPerScreenDip = kMinSnapChannelDistance / 480.f;
+
+float CalculateChannelDistance(const gfx::Display& display) {
+ if (display.bounds().IsEmpty())
+ return kMinSnapChannelDistance;
+
+ float screen_size =
+ std::abs(hypot(static_cast<float>(display.bounds().width()),
+ static_cast<float>(display.bounds().height())));
-SnapScrollController::Config::Config()
- : screen_width_pixels(1), screen_height_pixels(1), device_scale_factor(1) {}
+ float snap_channel_distance = screen_size * kSnapChannelDipsPerScreenDip;
+ return std::max(kMinSnapChannelDistance,
+ std::min(kMaxSnapChannelDistance, snap_channel_distance));
+}
+
+} // namespace
-SnapScrollController::Config::~Config() {}
-SnapScrollController::SnapScrollController(const Config& config)
- : channel_distance_(CalculateChannelDistance(config)),
+SnapScrollController::SnapScrollController(const gfx::Display& display)
+ : channel_distance_(CalculateChannelDistance(display)),
snap_scroll_mode_(SNAP_NONE),
first_touch_x_(-1),
first_touch_y_(-1),
@@ -89,27 +103,4 @@ void SnapScrollController::SetSnapScrollingMode(
}
}
-// static
-float SnapScrollController::CalculateChannelDistance(const Config& config) {
- float channel_distance = 16.f;
-
- const float screen_size = std::abs(
- hypot((float)config.screen_width_pixels / config.device_scale_factor,
- (float)config.screen_height_pixels / config.device_scale_factor));
- if (screen_size < 480.f) {
- channel_distance = 16.f;
- } else if (screen_size < 800.f) {
- channel_distance = 22.f;
- } else if (screen_size < 1120.f) {
- channel_distance = 28.f;
- } else {
- channel_distance = 34.f;
- }
- channel_distance = channel_distance * config.device_scale_factor;
- if (channel_distance < 16.f)
- channel_distance = 16.f;
-
- return channel_distance;
-}
-
} // namespace ui
diff --git a/ui/events/gesture_detection/snap_scroll_controller.h b/ui/events/gesture_detection/snap_scroll_controller.h
index ed8717b..753c2bc 100644
--- a/ui/events/gesture_detection/snap_scroll_controller.h
+++ b/ui/events/gesture_detection/snap_scroll_controller.h
@@ -8,6 +8,10 @@
#include "base/basictypes.h"
#include "ui/events/gesture_detection/gesture_detection_export.h"
+namespace gfx {
+class Display;
+}
+
namespace ui {
class MotionEvent;
@@ -17,15 +21,7 @@ class ZoomManager;
// Controls the scroll snapping behavior based on scroll updates.
class SnapScrollController {
public:
- struct GESTURE_DETECTION_EXPORT Config {
- Config();
- ~Config();
- int screen_width_pixels;
- int screen_height_pixels;
- float device_scale_factor;
- };
-
- explicit SnapScrollController(const Config& config);
+ explicit SnapScrollController(const gfx::Display& display);
~SnapScrollController();
// Updates the snap scroll mode based on the given X and Y distance to be
@@ -49,8 +45,6 @@ class SnapScrollController {
SNAP_VERT
};
- static float CalculateChannelDistance(const Config& config);
-
float channel_distance_;
SnapMode snap_scroll_mode_;
float first_touch_x_;