diff options
author | evy@chromium.org <evy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-15 14:33:53 +0000 |
---|---|---|
committer | evy@chromium.org <evy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-15 14:33:53 +0000 |
commit | 4612f49c0433eb949f64f0f7f039cd7d55ed1036 (patch) | |
tree | ee783e9203f73490a3ee7caa6bd2a79bf374943b /ui | |
parent | 7e4902c8293f69d3f1e8579d7e2fe181eaff342f (diff) | |
download | chromium_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.cc | 54 | ||||
-rw-r--r-- | ui/chromeos/touch_exploration_controller.h | 12 | ||||
-rw-r--r-- | ui/chromeos/touch_exploration_controller_unittest.cc | 89 |
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]; |