summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorevy@chromium.org <evy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-15 14:33:53 +0000
committerevy@chromium.org <evy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-15 14:33:53 +0000
commit4612f49c0433eb949f64f0f7f039cd7d55ed1036 (patch)
treeee783e9203f73490a3ee7caa6bd2a79bf374943b /ui
parent7e4902c8293f69d3f1e8579d7e2fe181eaff342f (diff)
downloadchromium_src-4612f49c0433eb949f64f0f7f039cd7d55ed1036.zip
chromium_src-4612f49c0433eb949f64f0f7f039cd7d55ed1036.tar.gz
chromium_src-4612f49c0433eb949f64f0f7f039cd7d55ed1036.tar.bz2
Modified split tap in touch_exploration_controller.
Now if the user leaves a generous slop with either finger during split tap, the press is cancelled. TEST= TouchExplorationTest.SplitTapLeavesSlop BUG= 401222 Review URL: https://codereview.chromium.org/447903002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289845 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/chromeos/touch_exploration_controller.cc54
-rw-r--r--ui/chromeos/touch_exploration_controller.h12
-rw-r--r--ui/chromeos/touch_exploration_controller_unittest.cc89
3 files changed, 135 insertions, 20 deletions
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
index 8b91009..3aed357 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -173,12 +173,12 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
return InGestureInProgress(touch_event, rewritten_event);
case TOUCH_EXPLORE_SECOND_PRESS:
return InTouchExploreSecondPress(touch_event, rewritten_event);
- case CORNER_PASSTHROUGH:
- return InCornerPassthrough(touch_event, rewritten_event);
case SLIDE_GESTURE:
return InSlideGesture(touch_event, rewritten_event);
case ONE_FINGER_PASSTHROUGH:
return InOneFingerPassthrough(touch_event, rewritten_event);
+ case CORNER_PASSTHROUGH:
+ return InCornerPassthrough(touch_event, rewritten_event);
case WAIT_FOR_NO_FINGERS:
return InWaitForNoFingers(touch_event, rewritten_event);
case TWO_FINGER_TAP:
@@ -510,10 +510,47 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress(
ui::EventType type = event.type();
gfx::PointF location = event.location_f();
if (type == ui::ET_TOUCH_PRESSED) {
- return ui::EVENT_REWRITE_DISCARD;
+ // A third finger being pressed means that a split tap can no longer go
+ // through. The user enters the wait state, Since there has already been
+ // a press dispatched when split tap began, the touch needs to be
+ // cancelled.
+ rewritten_event->reset(
+ new ui::TouchEvent(ui::ET_TOUCH_CANCELLED,
+ last_touch_exploration_->location(),
+ initial_press_->touch_id(),
+ event.time_stamp()));
+ (*rewritten_event)->set_flags(event.flags());
+ SET_STATE(WAIT_FOR_NO_FINGERS);
+ return ui::EVENT_REWRITE_REWRITTEN;
} else if (type == ui::ET_TOUCH_MOVED) {
- // Currently this is a discard, but could be something like rotor
- // in the future.
+ // If the fingers have moved too far from their original locations,
+ // the user can no longer split tap.
+ ui::TouchEvent* original_touch;
+ if (event.touch_id() == last_touch_exploration_->touch_id())
+ original_touch = last_touch_exploration_.get();
+ else if (event.touch_id() == initial_press_->touch_id())
+ original_touch = initial_press_.get();
+ else {
+ NOTREACHED();
+ SET_STATE(WAIT_FOR_NO_FINGERS);
+ return ui::EVENT_REWRITE_DISCARD;
+ }
+ // Check the distance between the current finger location and the original
+ // location. The slop for this is a bit more generous since keeping two
+ // fingers in place is a bit harder. If the user has left the slop, the
+ // split tap press (which was previous dispatched) is lifted with a touch
+ // cancelled, and the user enters the wait state.
+ if ((event.location() - original_touch->location()).Length() >
+ GetSplitTapTouchSlop()) {
+ rewritten_event->reset(
+ new ui::TouchEvent(ui::ET_TOUCH_CANCELLED,
+ last_touch_exploration_->location(),
+ initial_press_->touch_id(),
+ event.time_stamp()));
+ (*rewritten_event)->set_flags(event.flags());
+ SET_STATE(WAIT_FOR_NO_FINGERS);
+ return ui::EVENT_REWRITE_REWRITTEN;
+ }
return ui::EVENT_REWRITE_DISCARD;
} else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
// If the touch exploration finger is lifted, there is no option to return
@@ -685,6 +722,7 @@ void TouchExplorationController::OnTapTimerFired() {
case GESTURE_IN_PROGRESS:
// If only one finger is down, go into touch exploration.
if (current_touch_ids_.size() == 1) {
+ EnterTouchToMouseMode();
SET_STATE(TOUCH_EXPLORATION);
break;
}
@@ -882,7 +920,7 @@ void TouchExplorationController::DispatchShiftSearchKeyEvent(
ui::KeyEvent third_key_up(ui::ET_KEY_RELEASED, third_key, ui::EF_SHIFT_DOWN);
ui::KeyEvent search_up(
ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN);
- ui::KeyEvent shift_up(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE);
+ ui ::KeyEvent shift_up(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE);
DispatchEvent(&shift_down);
DispatchEvent(&search_down);
@@ -1111,4 +1149,8 @@ void TouchExplorationController::InitializeSwipeGestureMaps() {
BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE);
}
+const float TouchExplorationController::GetSplitTapTouchSlop() {
+ return gesture_detector_config_.touch_slop * 3;
+}
+
} // namespace ui
diff --git a/ui/chromeos/touch_exploration_controller.h b/ui/chromeos/touch_exploration_controller.h
index cc030ec..c62237e 100644
--- a/ui/chromeos/touch_exploration_controller.h
+++ b/ui/chromeos/touch_exploration_controller.h
@@ -158,7 +158,7 @@ class TouchExplorationControllerDelegate {
// corners of the screen until an earcon sounds. After the earcon sounds, the
// user is in passthrough so all subsequent fingers placed on the screen will be
// passed through. Once the finger in the corner has been released, the state
-// will switch to wait for one finger.
+// will switch to wait for no fingers.
//
// The caller is expected to retain ownership of instances of this class and
// destroy them before |root_window| is destroyed.
@@ -278,6 +278,10 @@ class UI_CHROMEOS_EXPORT TouchExplorationController
// these bounds (in DIPs), the preset settings will still change.
const float kSlopDistanceFromEdge = kMaxDistanceFromEdge + 40;
+ // The split tap slop is a bit more generous since keeping two
+ // fingers in place is a bit harder.
+ const float GetSplitTapTouchSlop();
+
enum State {
// No fingers are down and no events are pending.
NO_FINGERS_DOWN,
@@ -329,8 +333,10 @@ class UI_CHROMEOS_EXPORT TouchExplorationController
// The user was in touch exploration, but has placed down another finger.
// If the user releases the second finger, a touch press and release
// will go through at the last touch explore location. If the user
- // releases the touch explore finger, the other finger will continue with
- // touch explore. Any fingers pressed past the first two are ignored.
+ // releases the touch explore finger, the touch press and release will
+ // still go through once the split tap finger is also lifted. If any
+ // fingers pressed past the first two, the touch press is cancelled and
+ // the user enters the wait state for the fingers to be removed.
TOUCH_EXPLORE_SECOND_PRESS,
// After the user double taps and holds with a single finger, all events
diff --git a/ui/chromeos/touch_exploration_controller_unittest.cc b/ui/chromeos/touch_exploration_controller_unittest.cc
index 2718c01..c43885e 100644
--- a/ui/chromeos/touch_exploration_controller_unittest.cc
+++ b/ui/chromeos/touch_exploration_controller_unittest.cc
@@ -1138,7 +1138,7 @@ TEST_F(TouchExplorationTest, SplitTapReleaseLongPress) {
released_time - pressed_time);
}
-TEST_F(TouchExplorationTest, SplitTapLongPressMultiFinger) {
+TEST_F(TouchExplorationTest, SplitTapMultiFinger) {
SwitchTouchExplorationMode(true);
gfx::Point initial_touch_location(11, 12);
gfx::Point second_touch_location(33, 34);
@@ -1162,14 +1162,14 @@ TEST_F(TouchExplorationTest, SplitTapLongPressMultiFinger) {
generator_->Dispatch(&split_tap_press);
simulated_clock_->Advance(gesture_detector_config_.longpress_timeout);
- // Placing a third finger on the screen should be discarded and not affect
- // the events passed through.
+ // Placing a third finger on the screen should cancel the initial press and
+ // enter the wait state.
ui::TouchEvent third_press(
ui::ET_TOUCH_PRESSED, third_touch_location, 2, Now());
generator_->Dispatch(&third_press);
- // When all three fingers are released, there should be only two captured
- // events: touch press and touch release. All fingers should then be up.
+ // When all three fingers are released, the only events captured should be a
+ // press and touch cancel. All fingers should then be up.
ui::TouchEvent touch_explore_release(
ui::ET_TOUCH_RELEASED, initial_touch_location, 0, Now());
generator_->Dispatch(&touch_explore_release);
@@ -1184,12 +1184,79 @@ TEST_F(TouchExplorationTest, SplitTapLongPressMultiFinger) {
ASSERT_EQ(2U, captured_events.size());
EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
EXPECT_EQ(initial_touch_location, captured_events[0]->location());
- base::TimeDelta pressed_time = captured_events[0]->time_stamp();
- EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type());
+ EXPECT_EQ(ui::ET_TOUCH_CANCELLED, captured_events[1]->type());
EXPECT_EQ(initial_touch_location, captured_events[1]->location());
- base::TimeDelta released_time = captured_events[1]->time_stamp();
- EXPECT_EQ(gesture_detector_config_.longpress_timeout,
- released_time - pressed_time);
+ EXPECT_TRUE(IsInNoFingersDownState());
+}
+
+
+TEST_F(TouchExplorationTest, SplitTapLeaveSlop) {
+ SwitchTouchExplorationMode(true);
+ gfx::Point first_touch_location(11, 12);
+ gfx::Point second_touch_location(33, 34);
+ gfx::Point first_move_location(
+ first_touch_location.x() + gesture_detector_config_.touch_slop * 3 + 1,
+ first_touch_location.y());
+ gfx::Point second_move_location(
+ second_touch_location.x() + gesture_detector_config_.touch_slop * 3 + 1,
+ second_touch_location.y());
+
+ // Tap and hold at one location, and get a mouse move event in touch explore.
+ EnterTouchExplorationModeAtLocation(first_touch_location);
+ ClearCapturedEvents();
+
+ // Now tap at a different location for split tap.
+ ui::TouchEvent split_tap_press(
+ ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now());
+ generator_->Dispatch(&split_tap_press);
+
+ // Move the first finger out of slop and release both fingers. The split
+ // tap should have been cancelled, so a touch press and touch cancel event
+ // should go through at the last touch exploration location (the first press).
+ ui::TouchEvent first_touch_move(
+ ui::ET_TOUCH_MOVED, first_move_location, 0, Now());
+ generator_->Dispatch(&first_touch_move);
+ ui::TouchEvent first_touch_release(
+ ui::ET_TOUCH_RELEASED, first_move_location, 0, Now());
+ generator_->Dispatch(&first_touch_release);
+ ui::TouchEvent second_touch_release(
+ ui::ET_TOUCH_RELEASED, second_touch_location, 1, Now());
+ generator_->Dispatch(&second_touch_release);
+
+ std::vector<ui::LocatedEvent*> captured_events = GetCapturedLocatedEvents();
+ ASSERT_EQ(2U, captured_events.size());
+ EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
+ EXPECT_EQ(first_touch_location, captured_events[0]->location());
+ EXPECT_EQ(ui::ET_TOUCH_CANCELLED, captured_events[1]->type());
+ EXPECT_EQ(first_touch_location, captured_events[1]->location());
+ EXPECT_TRUE(IsInNoFingersDownState());
+
+ // Now do the same, but moving the split tap finger out of slop
+ EnterTouchExplorationModeAtLocation(first_touch_location);
+ ClearCapturedEvents();
+ ui::TouchEvent split_tap_press2(
+ ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now());
+ generator_->Dispatch(&split_tap_press2);
+
+ // Move the second finger out of slop and release both fingers. The split
+ // tap should have been cancelled, so a touch press and touch cancel event
+ // should go through at the last touch exploration location (the first press).
+ ui::TouchEvent second_touch_move2(
+ ui::ET_TOUCH_MOVED, second_move_location, 1, Now());
+ generator_->Dispatch(&second_touch_move2);
+ ui::TouchEvent first_touch_release2(
+ ui::ET_TOUCH_RELEASED, first_touch_location, 0, Now());
+ generator_->Dispatch(&first_touch_release2);
+ ui::TouchEvent second_touch_release2(
+ ui::ET_TOUCH_RELEASED, second_move_location, 1, Now());
+ generator_->Dispatch(&second_touch_release2);
+
+ captured_events = GetCapturedLocatedEvents();
+ ASSERT_EQ(2U, captured_events.size());
+ EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
+ EXPECT_EQ(first_touch_location, captured_events[0]->location());
+ EXPECT_EQ(ui::ET_TOUCH_CANCELLED, captured_events[1]->type());
+ EXPECT_EQ(first_touch_location, captured_events[1]->location());
EXPECT_TRUE(IsInNoFingersDownState());
}
@@ -1253,7 +1320,7 @@ TEST_F(TouchExplorationTest, GestureSwipe) {
// There are gestures supported with up to four fingers.
for (int num_fingers = 1; num_fingers <= 4; num_fingers++) {
std::vector<gfx::Point> start_points;
- for(int j = 0; j < num_fingers; j++){
+ for (int j = 0; j < num_fingers; j++) {
start_points.push_back(gfx::Point(j * 10 + 100, j * 10 + 200));
}
gfx::Point* start_points_array = &start_points[0];