Commit 32a40c21 authored by jdduke@chromium.org's avatar jdduke@chromium.org

Ignore min/max gesture bounds for mouse or stylus-derived gestures

The min/max gesture bounds are a semi-hacky workaround for unpredictable touch
devices. For mouse and stylus inputs, we should avoid applying these bounds,
preventing undesirable side-effects like tap disambiguation for mouse clicks.

BUG=403368

Review URL: https://codereview.chromium.org/468043003

Cr-Commit-Position: refs/heads/master@{#289477}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289477 0039d316-1c4b-4281-b951-d872f2087c98
parent 4c728d7d
...@@ -57,6 +57,22 @@ class GestureTextSelectorTest : public testing::Test, ...@@ -57,6 +57,22 @@ class GestureTextSelectorTest : public testing::Test,
} }
protected: protected:
static GestureEventData CreateGesture(ui::EventType type,
base::TimeTicks event_time,
float x,
float y) {
return GestureEventData(GestureEventDetails(type, 0, 0),
0,
MotionEvent::TOOL_TYPE_FINGER,
event_time,
x,
y,
x,
y,
1,
gfx::RectF(0, 0, 0, 0));
}
scoped_ptr<GestureTextSelector> selector_; scoped_ptr<GestureTextSelector> selector_;
std::vector<std::string> event_log_; std::vector<std::string> event_log_;
}; };
...@@ -130,25 +146,22 @@ TEST_F(GestureTextSelectorTest, PenDragging) { ...@@ -130,25 +146,22 @@ TEST_F(GestureTextSelectorTest, PenDragging) {
// 3. DOUBLE TAP // 3. DOUBLE TAP
// Suppress most gesture events when in text selection mode. // Suppress most gesture events when in text selection mode.
event_time += base::TimeDelta::FromMilliseconds(10); event_time += base::TimeDelta::FromMilliseconds(10);
const GestureEventData double_tap( const GestureEventData double_tap =
GestureEventDetails(ui::ET_GESTURE_DOUBLE_TAP, 0, 0), 0, event_time, CreateGesture(ui::ET_GESTURE_DOUBLE_TAP, event_time, x2, y2);
x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0));
EXPECT_TRUE(selector_->OnGestureEvent(double_tap)); EXPECT_TRUE(selector_->OnGestureEvent(double_tap));
EXPECT_TRUE(event_log_.empty()); EXPECT_TRUE(event_log_.empty());
// 4. ET_GESTURE_SCROLL_BEGIN // 4. ET_GESTURE_SCROLL_BEGIN
event_time += base::TimeDelta::FromMilliseconds(10); event_time += base::TimeDelta::FromMilliseconds(10);
const GestureEventData scroll_begin( const GestureEventData scroll_begin =
GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0), 0, event_time, CreateGesture(ui::ET_GESTURE_SCROLL_BEGIN, event_time, x1, y1);
x1, y1, x1, y1, 1, gfx::RectF(0, 0, 0, 0));
EXPECT_TRUE(selector_->OnGestureEvent(scroll_begin)); EXPECT_TRUE(selector_->OnGestureEvent(scroll_begin));
EXPECT_EQ(1u, event_log_.size()); // Unselect EXPECT_EQ(1u, event_log_.size()); // Unselect
// 5. ET_GESTURE_SCROLL_UPDATE // 5. ET_GESTURE_SCROLL_UPDATE
event_time += base::TimeDelta::FromMilliseconds(10); event_time += base::TimeDelta::FromMilliseconds(10);
const GestureEventData scroll_update( const GestureEventData scroll_update =
GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 0, 0), 0, event_time, CreateGesture(ui::ET_GESTURE_SCROLL_UPDATE, event_time, x2, y2);
x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0));
EXPECT_TRUE(selector_->OnGestureEvent(scroll_update)); EXPECT_TRUE(selector_->OnGestureEvent(scroll_update));
EXPECT_EQ(3u, event_log_.size()); // Unselect, Show, SelectRange EXPECT_EQ(3u, event_log_.size()); // Unselect, Show, SelectRange
EXPECT_STREQ("SelectRange", event_log_.back().c_str()); EXPECT_STREQ("SelectRange", event_log_.back().c_str());
...@@ -163,9 +176,8 @@ TEST_F(GestureTextSelectorTest, PenDragging) { ...@@ -163,9 +176,8 @@ TEST_F(GestureTextSelectorTest, PenDragging) {
// 7. ET_GESTURE_SCROLL_END // 7. ET_GESTURE_SCROLL_END
event_time += base::TimeDelta::FromMilliseconds(10); event_time += base::TimeDelta::FromMilliseconds(10);
const GestureEventData scroll_end( const GestureEventData scroll_end =
GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0), 0, event_time, CreateGesture(ui::ET_GESTURE_SCROLL_END, event_time, x2, y2);
x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0));
EXPECT_TRUE(selector_->OnGestureEvent(scroll_end)); EXPECT_TRUE(selector_->OnGestureEvent(scroll_end));
EXPECT_EQ(3u, event_log_.size()); // NO CHANGE EXPECT_EQ(3u, event_log_.size()); // NO CHANGE
} }
...@@ -186,9 +198,8 @@ TEST_F(GestureTextSelectorTest, TapToSelectWord) { ...@@ -186,9 +198,8 @@ TEST_F(GestureTextSelectorTest, TapToSelectWord) {
// 5. TAP_DOWN // 5. TAP_DOWN
event_time += base::TimeDelta::FromMilliseconds(10); event_time += base::TimeDelta::FromMilliseconds(10);
const GestureEventData tap_down( const GestureEventData tap_down =
GestureEventDetails(ui::ET_GESTURE_TAP_DOWN, 0, 0), 0, event_time, CreateGesture(ui::ET_GESTURE_TAP_DOWN, event_time, x2, y2);
x2, y2, x2, y2, 1, gfx::RectF(0, 0, 0, 0));
EXPECT_TRUE(selector_->OnGestureEvent(tap_down)); EXPECT_TRUE(selector_->OnGestureEvent(tap_down));
EXPECT_TRUE(event_log_.empty()); EXPECT_TRUE(event_log_.empty());
...@@ -210,9 +221,8 @@ TEST_F(GestureTextSelectorTest, TapToSelectWord) { ...@@ -210,9 +221,8 @@ TEST_F(GestureTextSelectorTest, TapToSelectWord) {
// 4. TAP // 4. TAP
event_time += base::TimeDelta::FromMilliseconds(10); event_time += base::TimeDelta::FromMilliseconds(10);
const GestureEventData tap( const GestureEventData tap =
GestureEventDetails(ui::ET_GESTURE_TAP, 0, 0), 0, event_time, CreateGesture(ui::ET_GESTURE_TAP, event_time, x1, y1);
x1, y1, x1, y1, 1, gfx::RectF(0, 0, 0, 0));
EXPECT_TRUE(selector_->OnGestureEvent(tap)); EXPECT_TRUE(selector_->OnGestureEvent(tap));
EXPECT_EQ(1u, event_log_.size()); // LongPress EXPECT_EQ(1u, event_log_.size()); // LongPress
EXPECT_STREQ("LongPress", event_log_.back().c_str()); EXPECT_STREQ("LongPress", event_log_.back().c_str());
......
...@@ -64,6 +64,8 @@ MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) { ...@@ -64,6 +64,8 @@ MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) {
return MotionEventAndroid::TOOL_TYPE_STYLUS; return MotionEventAndroid::TOOL_TYPE_STYLUS;
case TOOL_TYPE_MOUSE: case TOOL_TYPE_MOUSE:
return MotionEventAndroid::TOOL_TYPE_MOUSE; return MotionEventAndroid::TOOL_TYPE_MOUSE;
case TOOL_TYPE_ERASER:
return MotionEventAndroid::TOOL_TYPE_ERASER;
default: default:
NOTREACHED() << "Invalid Android MotionEvent tool type: " NOTREACHED() << "Invalid Android MotionEvent tool type: "
<< android_tool_type; << android_tool_type;
......
...@@ -10,6 +10,7 @@ namespace ui { ...@@ -10,6 +10,7 @@ namespace ui {
GestureEventData::GestureEventData(const GestureEventDetails& details, GestureEventData::GestureEventData(const GestureEventDetails& details,
int motion_event_id, int motion_event_id,
MotionEvent::ToolType primary_tool_type,
base::TimeTicks time, base::TimeTicks time,
float x, float x,
float y, float y,
...@@ -19,6 +20,7 @@ GestureEventData::GestureEventData(const GestureEventDetails& details, ...@@ -19,6 +20,7 @@ GestureEventData::GestureEventData(const GestureEventDetails& details,
const gfx::RectF& bounding_box) const gfx::RectF& bounding_box)
: details(details), : details(details),
motion_event_id(motion_event_id), motion_event_id(motion_event_id),
primary_tool_type(primary_tool_type),
time(time), time(time),
x(x), x(x),
y(y), y(y),
...@@ -34,6 +36,7 @@ GestureEventData::GestureEventData(EventType type, ...@@ -34,6 +36,7 @@ GestureEventData::GestureEventData(EventType type,
const GestureEventData& other) const GestureEventData& other)
: details(type, 0, 0), : details(type, 0, 0),
motion_event_id(other.motion_event_id), motion_event_id(other.motion_event_id),
primary_tool_type(other.primary_tool_type),
time(other.time), time(other.time),
x(other.x), x(other.x),
y(other.y), y(other.y),
...@@ -44,7 +47,12 @@ GestureEventData::GestureEventData(EventType type, ...@@ -44,7 +47,12 @@ GestureEventData::GestureEventData(EventType type,
} }
GestureEventData::GestureEventData() GestureEventData::GestureEventData()
: motion_event_id(0), x(0), y(0), raw_x(0), raw_y(0) { : motion_event_id(0),
primary_tool_type(MotionEvent::TOOL_TYPE_UNKNOWN),
x(0),
y(0),
raw_x(0),
raw_y(0) {
} }
} // namespace ui } // namespace ui
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_detection_export.h" #include "ui/events/gesture_detection/gesture_detection_export.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/events/gesture_event_details.h" #include "ui/events/gesture_event_details.h"
namespace ui { namespace ui {
...@@ -17,6 +18,7 @@ class GestureEventDataPacket; ...@@ -17,6 +18,7 @@ class GestureEventDataPacket;
struct GESTURE_DETECTION_EXPORT GestureEventData { struct GESTURE_DETECTION_EXPORT GestureEventData {
GestureEventData(const GestureEventDetails&, GestureEventData(const GestureEventDetails&,
int motion_event_id, int motion_event_id,
MotionEvent::ToolType primary_tool_type,
base::TimeTicks time, base::TimeTicks time,
float x, float x,
float y, float y,
...@@ -30,6 +32,7 @@ struct GESTURE_DETECTION_EXPORT GestureEventData { ...@@ -30,6 +32,7 @@ struct GESTURE_DETECTION_EXPORT GestureEventData {
GestureEventDetails details; GestureEventDetails details;
int motion_event_id; int motion_event_id;
MotionEvent::ToolType primary_tool_type;
base::TimeTicks time; base::TimeTicks time;
float x; float x;
float y; float y;
......
...@@ -18,6 +18,7 @@ const float kTouchY = 14.2f; ...@@ -18,6 +18,7 @@ const float kTouchY = 14.2f;
GestureEventData CreateGesture(EventType type) { GestureEventData CreateGesture(EventType type) {
return GestureEventData(GestureEventDetails(type, 0, 0), return GestureEventData(GestureEventDetails(type, 0, 0),
0, 0,
MotionEvent::TOOL_TYPE_FINGER,
base::TimeTicks(), base::TimeTicks(),
kTouchX, kTouchX,
kTouchY, kTouchY,
...@@ -31,9 +32,10 @@ GestureEventData CreateGesture(EventType type) { ...@@ -31,9 +32,10 @@ GestureEventData CreateGesture(EventType type) {
bool GestureEquals(const GestureEventData& lhs, const GestureEventData& rhs) { bool GestureEquals(const GestureEventData& lhs, const GestureEventData& rhs) {
return lhs.type() == rhs.type() && return lhs.type() == rhs.type() &&
lhs.motion_event_id == rhs.motion_event_id && lhs.time == rhs.time && lhs.motion_event_id == rhs.motion_event_id &&
lhs.x == rhs.x && lhs.y == rhs.y && lhs.raw_x == rhs.raw_x && lhs.primary_tool_type == rhs.primary_tool_type &&
lhs.raw_y == rhs.raw_y; lhs.time == rhs.time && lhs.x == rhs.x && lhs.y == rhs.y &&
lhs.raw_x == rhs.raw_x && lhs.raw_y == rhs.raw_y;
} }
bool PacketEquals(const GestureEventDataPacket& lhs, bool PacketEquals(const GestureEventDataPacket& lhs,
......
...@@ -50,6 +50,7 @@ gfx::RectF GetBoundingBox(const MotionEvent& event) { ...@@ -50,6 +50,7 @@ gfx::RectF GetBoundingBox(const MotionEvent& event) {
GestureEventData CreateGesture(const GestureEventDetails& details, GestureEventData CreateGesture(const GestureEventDetails& details,
int motion_event_id, int motion_event_id,
MotionEvent::ToolType primary_tool_type,
base::TimeTicks time, base::TimeTicks time,
float x, float x,
float y, float y,
...@@ -59,6 +60,7 @@ GestureEventData CreateGesture(const GestureEventDetails& details, ...@@ -59,6 +60,7 @@ GestureEventData CreateGesture(const GestureEventDetails& details,
const gfx::RectF& bounding_box) { const gfx::RectF& bounding_box) {
return GestureEventData(details, return GestureEventData(details,
motion_event_id, motion_event_id,
primary_tool_type,
time, time,
x, x,
y, y,
...@@ -70,6 +72,7 @@ GestureEventData CreateGesture(const GestureEventDetails& details, ...@@ -70,6 +72,7 @@ GestureEventData CreateGesture(const GestureEventDetails& details,
GestureEventData CreateGesture(EventType type, GestureEventData CreateGesture(EventType type,
int motion_event_id, int motion_event_id,
MotionEvent::ToolType primary_tool_type,
base::TimeTicks time, base::TimeTicks time,
float x, float x,
float y, float y,
...@@ -79,6 +82,7 @@ GestureEventData CreateGesture(EventType type, ...@@ -79,6 +82,7 @@ GestureEventData CreateGesture(EventType type,
const gfx::RectF& bounding_box) { const gfx::RectF& bounding_box) {
return GestureEventData(GestureEventDetails(type, 0, 0), return GestureEventData(GestureEventDetails(type, 0, 0),
motion_event_id, motion_event_id,
primary_tool_type,
time, time,
x, x,
y, y,
...@@ -92,6 +96,7 @@ GestureEventData CreateGesture(const GestureEventDetails& details, ...@@ -92,6 +96,7 @@ GestureEventData CreateGesture(const GestureEventDetails& details,
const MotionEvent& event) { const MotionEvent& event) {
return GestureEventData(details, return GestureEventData(details,
event.GetId(), event.GetId(),
event.GetToolType(),
event.GetEventTime(), event.GetEventTime(),
event.GetX(), event.GetX(),
event.GetY(), event.GetY(),
...@@ -194,6 +199,7 @@ class GestureProvider::ScaleGestureListenerImpl ...@@ -194,6 +199,7 @@ class GestureProvider::ScaleGestureListenerImpl
pinch_event_sent_ = true; pinch_event_sent_ = true;
provider_->Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, provider_->Send(CreateGesture(ET_GESTURE_PINCH_BEGIN,
e.GetId(), e.GetId(),
e.GetToolType(),
detector.GetEventTime(), detector.GetEventTime(),
detector.GetFocusX(), detector.GetFocusX(),
detector.GetFocusY(), detector.GetFocusY(),
...@@ -227,6 +233,7 @@ class GestureProvider::ScaleGestureListenerImpl ...@@ -227,6 +233,7 @@ class GestureProvider::ScaleGestureListenerImpl
GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0);
provider_->Send(CreateGesture(pinch_details, provider_->Send(CreateGesture(pinch_details,
e.GetId(), e.GetId(),
e.GetToolType(),
detector.GetEventTime(), detector.GetEventTime(),
detector.GetFocusX(), detector.GetFocusX(),
detector.GetFocusY(), detector.GetFocusY(),
...@@ -368,6 +375,7 @@ class GestureProvider::GestureListenerImpl ...@@ -368,6 +375,7 @@ class GestureProvider::GestureListenerImpl
// used to determine which layer the scroll should affect. // used to determine which layer the scroll should affect.
provider_->Send(CreateGesture(scroll_details, provider_->Send(CreateGesture(scroll_details,
e2.GetId(), e2.GetId(),
e2.GetToolType(),
e2.GetEventTime(), e2.GetEventTime(),
e1.GetX(), e1.GetX(),
e1.GetY(), e1.GetY(),
...@@ -386,6 +394,7 @@ class GestureProvider::GestureListenerImpl ...@@ -386,6 +394,7 @@ class GestureProvider::GestureListenerImpl
ET_GESTURE_SCROLL_UPDATE, -distance_x, -distance_y); ET_GESTURE_SCROLL_UPDATE, -distance_x, -distance_y);
provider_->Send(CreateGesture(scroll_details, provider_->Send(CreateGesture(scroll_details,
e2.GetId(), e2.GetId(),
e2.GetToolType(),
e2.GetEventTime(), e2.GetEventTime(),
center.x(), center.x(),
center.y(), center.y(),
...@@ -432,6 +441,7 @@ class GestureProvider::GestureListenerImpl ...@@ -432,6 +441,7 @@ class GestureProvider::GestureListenerImpl
e1.GetTouchMajor()); e1.GetTouchMajor());
provider_->Send(CreateGesture(two_finger_tap_details, provider_->Send(CreateGesture(two_finger_tap_details,
e2.GetId(), e2.GetId(),
e2.GetToolType(),
e2.GetEventTime(), e2.GetEventTime(),
e1.GetX(), e1.GetX(),
e1.GetY(), e1.GetY(),
...@@ -685,12 +695,13 @@ void GestureProvider::Send(GestureEventData gesture) { ...@@ -685,12 +695,13 @@ void GestureProvider::Send(GestureEventData gesture) {
gesture.type() == ET_GESTURE_SHOW_PRESS || gesture.type() == ET_GESTURE_SHOW_PRESS ||
gesture.type() == ET_GESTURE_END); gesture.type() == ET_GESTURE_END);
// TODO(jdduke): Provide a way of skipping this clamping for stylus and/or if (gesture.primary_tool_type == MotionEvent::TOOL_TYPE_UNKNOWN ||
// mouse-based input, perhaps by exposing the source type on MotionEvent. gesture.primary_tool_type == MotionEvent::TOOL_TYPE_FINGER) {
gesture.details.set_bounding_box( gesture.details.set_bounding_box(
ClampBoundingBox(gesture.details.bounding_box_f(), ClampBoundingBox(gesture.details.bounding_box_f(),
min_gesture_bounds_length_, min_gesture_bounds_length_,
max_gesture_bounds_length_)); max_gesture_bounds_length_));
}
switch (gesture.type()) { switch (gesture.type()) {
case ET_GESTURE_LONG_PRESS: case ET_GESTURE_LONG_PRESS:
...@@ -768,6 +779,7 @@ void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { ...@@ -768,6 +779,7 @@ void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) {
const int action_index = event.GetActionIndex(); const int action_index = event.GetActionIndex();
Send(CreateGesture(ET_GESTURE_BEGIN, Send(CreateGesture(ET_GESTURE_BEGIN,
event.GetId(), event.GetId(),
event.GetToolType(),
event.GetEventTime(), event.GetEventTime(),
event.GetX(action_index), event.GetX(action_index),
event.GetY(action_index), event.GetY(action_index),
......
...@@ -49,6 +49,8 @@ class GESTURE_DETECTION_EXPORT GestureProvider { ...@@ -49,6 +49,8 @@ class GESTURE_DETECTION_EXPORT GestureProvider {
// The min and max size (both length and width, in dips) of the generated // The min and max size (both length and width, in dips) of the generated
// bounding box for all gesture types. This is useful for touch streams // bounding box for all gesture types. This is useful for touch streams
// that may report zero or unreasonably small or large touch sizes. // that may report zero or unreasonably small or large touch sizes.
// Note that these bounds are only applied for touch or unknown tool types;
// mouse and stylus-derived gestures will not be affected.
// Both values default to 0 (disabled). // Both values default to 0 (disabled).
float min_gesture_bounds_length; float min_gesture_bounds_length;
float max_gesture_bounds_length; float max_gesture_bounds_length;
......
...@@ -252,14 +252,10 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { ...@@ -252,14 +252,10 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient {
SetUpWithConfig(config); SetUpWithConfig(config);
} }
void SetMinGestureBoundsLength(float min_gesture_bound_length) { void SetMinMaxGestureBoundsLength(float min_gesture_bound_length,
float max_gesture_bound_length) {
GestureProvider::Config config = GetDefaultConfig(); GestureProvider::Config config = GetDefaultConfig();
config.min_gesture_bounds_length = min_gesture_bound_length; config.min_gesture_bounds_length = min_gesture_bound_length;
SetUpWithConfig(config);
}
void SetMaxGestureBoundsLength(float max_gesture_bound_length) {
GestureProvider::Config config = GetDefaultConfig();
config.max_gesture_bounds_length = max_gesture_bound_length; config.max_gesture_bounds_length = max_gesture_bound_length;
SetUpWithConfig(config); SetUpWithConfig(config);
} }
...@@ -284,12 +280,15 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { ...@@ -284,12 +280,15 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient {
MotionEvent::ACTION_MOVE, MotionEvent::ACTION_MOVE,
scroll_to_x, scroll_to_x,
scroll_to_y); scroll_to_y);
event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER);
event.set_id(++motion_event_id); event.set_id(++motion_event_id);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_TRUE(gesture_provider_->IsScrollInProgress()); EXPECT_TRUE(gesture_provider_->IsScrollInProgress());
EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id);
EXPECT_EQ(event.GetToolType(0),
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(ET_GESTURE_SCROLL_UPDATE, GetMostRecentGestureEventType()); EXPECT_EQ(ET_GESTURE_SCROLL_UPDATE, GetMostRecentGestureEventType());
EXPECT_EQ(BoundsForSingleMockTouchAtLocation(scroll_to_x, scroll_to_y), EXPECT_EQ(BoundsForSingleMockTouchAtLocation(scroll_to_x, scroll_to_y),
GetMostRecentGestureEvent().details.bounding_box()); GetMostRecentGestureEvent().details.bounding_box());
...@@ -304,6 +303,7 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { ...@@ -304,6 +303,7 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient {
event = ObtainMotionEvent( event = ObtainMotionEvent(
event_time + kOneSecond, end_action_type, scroll_to_x, scroll_to_y); event_time + kOneSecond, end_action_type, scroll_to_x, scroll_to_y);
event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER);
event.set_id(++motion_event_id); event.set_id(++motion_event_id);
gesture_provider_->OnTouchEvent(event); gesture_provider_->OnTouchEvent(event);
...@@ -311,6 +311,8 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient { ...@@ -311,6 +311,8 @@ class GestureProviderTest : public testing::Test, public GestureProviderClient {
EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_END)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_END));
EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType()); EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType());
EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id);
EXPECT_EQ(event.GetToolType(0),
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points()); EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
EXPECT_EQ(BoundsForSingleMockTouchAtLocation(scroll_to_x, scroll_to_y), EXPECT_EQ(BoundsForSingleMockTouchAtLocation(scroll_to_x, scroll_to_y),
GetMostRecentGestureEvent().details.bounding_box()); GetMostRecentGestureEvent().details.bounding_box());
...@@ -409,22 +411,28 @@ TEST_F(GestureProviderTest, GestureTap) { ...@@ -409,22 +411,28 @@ TEST_F(GestureProviderTest, GestureTap) {
MockMotionEvent event = MockMotionEvent event =
ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN); ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN);
event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER);
event.set_id(++motion_event_id); event.set_id(++motion_event_id);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType()); EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType());
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points()); EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
EXPECT_EQ(event.GetToolType(0),
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY), EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY),
GetMostRecentGestureEvent().details.bounding_box()); GetMostRecentGestureEvent().details.bounding_box());
event = ObtainMotionEvent(event_time + kOneMicrosecond, event = ObtainMotionEvent(event_time + kOneMicrosecond,
MotionEvent::ACTION_UP); MotionEvent::ACTION_UP);
event.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER);
event.set_id(++motion_event_id); event.set_id(++motion_event_id);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(ET_GESTURE_TAP, GetMostRecentGestureEventType()); EXPECT_EQ(ET_GESTURE_TAP, GetMostRecentGestureEventType());
// Ensure tap details have been set. // Ensure tap details have been set.
EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap_count()); EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap_count());
EXPECT_EQ(event.GetToolType(0),
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id); EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id);
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points()); EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY), EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY),
...@@ -2290,7 +2298,7 @@ TEST_F(GestureProviderTest, PinchZoomWithThreshold) { ...@@ -2290,7 +2298,7 @@ TEST_F(GestureProviderTest, PinchZoomWithThreshold) {
// Verify that the min gesture bound setting is honored. // Verify that the min gesture bound setting is honored.
TEST_F(GestureProviderTest, MinGestureBoundsLength) { TEST_F(GestureProviderTest, MinGestureBoundsLength) {
const float kMinGestureBoundsLength = 10.f * kMockTouchRadius; const float kMinGestureBoundsLength = 10.f * kMockTouchRadius;
SetMinGestureBoundsLength(kMinGestureBoundsLength); SetMinMaxGestureBoundsLength(kMinGestureBoundsLength, 0.f);
gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false); gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false);
base::TimeTicks event_time = base::TimeTicks::Now(); base::TimeTicks event_time = base::TimeTicks::Now();
...@@ -2316,7 +2324,7 @@ TEST_F(GestureProviderTest, MinGestureBoundsLength) { ...@@ -2316,7 +2324,7 @@ TEST_F(GestureProviderTest, MinGestureBoundsLength) {
TEST_F(GestureProviderTest, MaxGestureBoundsLength) { TEST_F(GestureProviderTest, MaxGestureBoundsLength) {
const float kMaxGestureBoundsLength = kMockTouchRadius / 10.f; const float kMaxGestureBoundsLength = kMockTouchRadius / 10.f;
SetMaxGestureBoundsLength(kMaxGestureBoundsLength); SetMinMaxGestureBoundsLength(0.f, kMaxGestureBoundsLength);
gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false); gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false);
base::TimeTicks event_time = base::TimeTicks::Now(); base::TimeTicks event_time = base::TimeTicks::Now();
...@@ -2363,4 +2371,63 @@ TEST_F(GestureProviderTest, ZeroRadiusBoundingBox) { ...@@ -2363,4 +2371,63 @@ TEST_F(GestureProviderTest, ZeroRadiusBoundingBox) {
GetMostRecentGestureEvent().details.bounding_box()); GetMostRecentGestureEvent().details.bounding_box());
} }
// Verify that the min/max gesture bound settings are not applied to stylus
// or mouse-derived MotionEvents.
TEST_F(GestureProviderTest, NoMinOrMaxGestureBoundsLengthWithStylusOrMouse) {
const float kMinGestureBoundsLength = 5.f * kMockTouchRadius;
const float kMaxGestureBoundsLength = 10.f * kMockTouchRadius;
SetMinMaxGestureBoundsLength(kMinGestureBoundsLength,
kMaxGestureBoundsLength);
gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false);
base::TimeTicks event_time = base::TimeTicks::Now();
MockMotionEvent event =
ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN);
event.SetTouchMajor(0);
event.SetToolType(0, MotionEvent::TOOL_TYPE_MOUSE);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType());
EXPECT_EQ(MotionEvent::TOOL_TYPE_MOUSE,
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(0.f, GetMostRecentGestureEvent().details.bounding_box_f().width());
EXPECT_EQ(0.f, GetMostRecentGestureEvent().details.bounding_box_f().height());
event =
ObtainMotionEvent(event_time + kOneMicrosecond, MotionEvent::ACTION_UP);
event.SetTouchMajor(1);
event.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(ET_GESTURE_TAP, GetMostRecentGestureEventType());
EXPECT_EQ(MotionEvent::TOOL_TYPE_STYLUS,
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(1.f, GetMostRecentGestureEvent().details.bounding_box_f().width());
EXPECT_EQ(1.f, GetMostRecentGestureEvent().details.bounding_box_f().height());
event = ObtainMotionEvent(event_time, MotionEvent::ACTION_DOWN);
event.SetTouchMajor(2.f * kMaxGestureBoundsLength);
event.SetToolType(0, MotionEvent::TOOL_TYPE_MOUSE);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(MotionEvent::TOOL_TYPE_MOUSE,
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType());
EXPECT_EQ(2.f * kMaxGestureBoundsLength,
GetMostRecentGestureEvent().details.bounding_box_f().width());
EXPECT_EQ(2.f * kMaxGestureBoundsLength,
GetMostRecentGestureEvent().details.bounding_box_f().height());
event =
ObtainMotionEvent(event_time + kOneMicrosecond, MotionEvent::ACTION_UP);
event.SetTouchMajor(2.f * kMaxGestureBoundsLength);
event.SetToolType(0, MotionEvent::TOOL_TYPE_ERASER);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_EQ(ET_GESTURE_TAP, GetMostRecentGestureEventType());
EXPECT_EQ(MotionEvent::TOOL_TYPE_ERASER,
GetMostRecentGestureEvent().primary_tool_type);
EXPECT_EQ(2.f * kMaxGestureBoundsLength,
GetMostRecentGestureEvent().details.bounding_box_f().width());
EXPECT_EQ(2.f * kMaxGestureBoundsLength,
GetMostRecentGestureEvent().details.bounding_box_f().height());
}
} // namespace ui } // namespace ui
...@@ -29,6 +29,7 @@ class GESTURE_DETECTION_EXPORT MotionEvent { ...@@ -29,6 +29,7 @@ class GESTURE_DETECTION_EXPORT MotionEvent {
TOOL_TYPE_FINGER, TOOL_TYPE_FINGER,
TOOL_TYPE_STYLUS, TOOL_TYPE_STYLUS,
TOOL_TYPE_MOUSE, TOOL_TYPE_MOUSE,
TOOL_TYPE_ERASER
}; };
enum ButtonType { enum ButtonType {
...@@ -83,6 +84,7 @@ class GESTURE_DETECTION_EXPORT MotionEvent { ...@@ -83,6 +84,7 @@ class GESTURE_DETECTION_EXPORT MotionEvent {
float GetRawOffsetY() const { return GetRawY() - GetY(); } float GetRawOffsetY() const { return GetRawY() - GetY(); }
float GetTouchMajor() const { return GetTouchMajor(0); } float GetTouchMajor() const { return GetTouchMajor(0); }
float GetPressure() const { return GetPressure(0); } float GetPressure() const { return GetPressure(0); }
ToolType GetToolType() const { return GetToolType(0); }
// O(N) search of pointers (use sparingly!). Returns -1 if |id| nonexistent. // O(N) search of pointers (use sparingly!). Returns -1 if |id| nonexistent.
int FindPointerIndexOfId(int id) const; int FindPointerIndexOfId(int id) const;
......
...@@ -17,9 +17,11 @@ COMPILE_ASSERT(ET_GESTURE_TYPE_END - ET_GESTURE_TYPE_START < 32, ...@@ -17,9 +17,11 @@ COMPILE_ASSERT(ET_GESTURE_TYPE_END - ET_GESTURE_TYPE_START < 32,
GestureEventData CreateGesture(EventType type, GestureEventData CreateGesture(EventType type,
int motion_event_id, int motion_event_id,
MotionEvent::ToolType primary_tool_type,
const GestureEventDataPacket& packet) { const GestureEventDataPacket& packet) {
return GestureEventData(GestureEventDetails(type, 0, 0), return GestureEventData(GestureEventDetails(type, 0, 0),
motion_event_id, motion_event_id,
primary_tool_type,
packet.timestamp(), packet.timestamp(),
packet.touch_location().x(), packet.touch_location().x(),
packet.touch_location().y(), packet.touch_location().y(),
...@@ -128,6 +130,8 @@ bool IsTouchStartEvent(GestureEventDataPacket::GestureSource gesture_source) { ...@@ -128,6 +130,8 @@ bool IsTouchStartEvent(GestureEventDataPacket::GestureSource gesture_source) {
TouchDispositionGestureFilter::TouchDispositionGestureFilter( TouchDispositionGestureFilter::TouchDispositionGestureFilter(
TouchDispositionGestureFilterClient* client) TouchDispositionGestureFilterClient* client)
: client_(client), : client_(client),
ending_event_motion_event_id_(0),
ending_event_primary_tool_type_(MotionEvent::TOOL_TYPE_UNKNOWN),
needs_tap_ending_event_(false), needs_tap_ending_event_(false),
needs_show_press_event_(false), needs_show_press_event_(false),
needs_fling_ending_event_(false), needs_fling_ending_event_(false),
...@@ -259,6 +263,7 @@ void TouchDispositionGestureFilter::SendGesture( ...@@ -259,6 +263,7 @@ void TouchDispositionGestureFilter::SendGesture(
case ET_GESTURE_TAP_DOWN: case ET_GESTURE_TAP_DOWN:
DCHECK(!needs_tap_ending_event_); DCHECK(!needs_tap_ending_event_);
ending_event_motion_event_id_ = event.motion_event_id; ending_event_motion_event_id_ = event.motion_event_id;
ending_event_primary_tool_type_ = event.primary_tool_type;
needs_show_press_event_ = true; needs_show_press_event_ = true;
needs_tap_ending_event_ = true; needs_tap_ending_event_ = true;
break; break;
...@@ -289,6 +294,7 @@ void TouchDispositionGestureFilter::SendGesture( ...@@ -289,6 +294,7 @@ void TouchDispositionGestureFilter::SendGesture(
CancelFlingIfNecessary(packet_being_sent); CancelFlingIfNecessary(packet_being_sent);
EndScrollIfNecessary(packet_being_sent); EndScrollIfNecessary(packet_being_sent);
ending_event_motion_event_id_ = event.motion_event_id; ending_event_motion_event_id_ = event.motion_event_id;
ending_event_primary_tool_type_ = event.primary_tool_type;
needs_scroll_ending_event_ = true; needs_scroll_ending_event_ = true;
break; break;
case ET_GESTURE_SCROLL_END: case ET_GESTURE_SCROLL_END:
...@@ -297,6 +303,7 @@ void TouchDispositionGestureFilter::SendGesture( ...@@ -297,6 +303,7 @@ void TouchDispositionGestureFilter::SendGesture(
case ET_SCROLL_FLING_START: case ET_SCROLL_FLING_START:
CancelFlingIfNecessary(packet_being_sent); CancelFlingIfNecessary(packet_being_sent);
ending_event_motion_event_id_ = event.motion_event_id; ending_event_motion_event_id_ = event.motion_event_id;
ending_event_primary_tool_type_ = event.primary_tool_type;
needs_fling_ending_event_ = true; needs_fling_ending_event_ = true;
needs_scroll_ending_event_ = false; needs_scroll_ending_event_ = false;
break; break;
...@@ -316,6 +323,7 @@ void TouchDispositionGestureFilter::CancelTapIfNecessary( ...@@ -316,6 +323,7 @@ void TouchDispositionGestureFilter::CancelTapIfNecessary(
SendGesture(CreateGesture(ET_GESTURE_TAP_CANCEL, SendGesture(CreateGesture(ET_GESTURE_TAP_CANCEL,
ending_event_motion_event_id_, ending_event_motion_event_id_,
ending_event_primary_tool_type_,
packet_being_sent), packet_being_sent),
packet_being_sent); packet_being_sent);
DCHECK(!needs_tap_ending_event_); DCHECK(!needs_tap_ending_event_);
...@@ -328,6 +336,7 @@ void TouchDispositionGestureFilter::CancelFlingIfNecessary( ...@@ -328,6 +336,7 @@ void TouchDispositionGestureFilter::CancelFlingIfNecessary(
SendGesture(CreateGesture(ET_SCROLL_FLING_CANCEL, SendGesture(CreateGesture(ET_SCROLL_FLING_CANCEL,
ending_event_motion_event_id_, ending_event_motion_event_id_,
ending_event_primary_tool_type_,
packet_being_sent), packet_being_sent),
packet_being_sent); packet_being_sent);
DCHECK(!needs_fling_ending_event_); DCHECK(!needs_fling_ending_event_);
...@@ -340,6 +349,7 @@ void TouchDispositionGestureFilter::EndScrollIfNecessary( ...@@ -340,6 +349,7 @@ void TouchDispositionGestureFilter::EndScrollIfNecessary(
SendGesture(CreateGesture(ET_GESTURE_SCROLL_END, SendGesture(CreateGesture(ET_GESTURE_SCROLL_END,
ending_event_motion_event_id_, ending_event_motion_event_id_,
ending_event_primary_tool_type_,
packet_being_sent), packet_being_sent),
packet_being_sent); packet_being_sent);
DCHECK(!needs_scroll_ending_event_); DCHECK(!needs_scroll_ending_event_);
......
...@@ -95,6 +95,7 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter { ...@@ -95,6 +95,7 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter {
// when necessary, e.g., GestureTapCancel when scrolling begins, or // when necessary, e.g., GestureTapCancel when scrolling begins, or
// GestureFlingCancel when a user taps following a GestureFlingStart. // GestureFlingCancel when a user taps following a GestureFlingStart.
int ending_event_motion_event_id_; int ending_event_motion_event_id_;
MotionEvent::ToolType ending_event_primary_tool_type_;
bool needs_tap_ending_event_; bool needs_tap_ending_event_;
bool needs_show_press_event_; bool needs_show_press_event_;
bool needs_fling_ending_event_; bool needs_fling_ending_event_;
......
...@@ -202,6 +202,7 @@ class TouchDispositionGestureFilterTest ...@@ -202,6 +202,7 @@ class TouchDispositionGestureFilterTest
GestureEventData CreateGesture(EventType type) { GestureEventData CreateGesture(EventType type) {
return GestureEventData(GestureEventDetails(type, 0, 0), return GestureEventData(GestureEventDetails(type, 0, 0),
0, 0,
MotionEvent::TOOL_TYPE_FINGER,
base::TimeTicks(), base::TimeTicks(),
touch_event_.GetX(0), touch_event_.GetX(0),
touch_event_.GetY(0), touch_event_.GetY(0),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment