Chromium Code Reviews| Index: ui/chromeos/touch_exploration_controller.cc |
| diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc |
| index 0a63014062c19cbb9580426b5854b23c3a2008b7..233f544b8d6c0a5c735df55483c1083800b86279 100644 |
| --- a/ui/chromeos/touch_exploration_controller.cc |
| +++ b/ui/chromeos/touch_exploration_controller.cc |
| @@ -23,6 +23,10 @@ namespace { |
| // Delay between adjustment sounds. |
| const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
| +// Delay before corner passthrough activates. |
| +const base::TimeDelta kCornerPassthroughDelay = |
| + base::TimeDelta::FromMilliseconds(500); |
| + |
| // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
| const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
| } // namespace |
| @@ -36,7 +40,8 @@ TouchExplorationController::TouchExplorationController( |
| event_handler_for_testing_(NULL), |
| gesture_provider_(this), |
| prev_state_(NO_FINGERS_DOWN), |
| - VLOG_on_(true) { |
| + VLOG_on_(true), |
| + waiting_for_corner_passthrough_(false) { |
| CHECK(root_window); |
| root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
| } |
| @@ -132,6 +137,8 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
| return InTouchExploreSecondPress(touch_event, rewritten_event); |
| case TWO_TO_ONE_FINGER: |
| return InTwoToOneFinger(touch_event, rewritten_event); |
| + case CORNER_PASSTHROUGH: |
| + return InCornerPassthrough(touch_event, rewritten_event); |
| case PASSTHROUGH: |
| return InPassthrough(touch_event, rewritten_event); |
| case WAIT_FOR_RELEASE: |
| @@ -152,28 +159,60 @@ ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
| ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
| const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
| const ui::EventType type = event.type(); |
| - if (type == ui::ET_TOUCH_PRESSED) { |
| - initial_press_.reset(new TouchEvent(event)); |
| - last_unused_finger_event_.reset(new TouchEvent(event)); |
| - tap_timer_.Start(FROM_HERE, |
| - gesture_detector_config_.double_tap_timeout, |
| - this, |
| - &TouchExplorationController::OnTapTimerFired); |
| - gesture_provider_.OnTouchEvent(event); |
| - gesture_provider_.OnTouchEventAck(false); |
| - ProcessGestureEvents(); |
| - state_ = SINGLE_TAP_PRESSED; |
| - VLOG_STATE(); |
| - return ui::EVENT_REWRITE_DISCARD; |
| + if (type != ui::ET_TOUCH_PRESSED) { |
| + NOTREACHED() << "Unexpected event type received: " << event.name(); |
| + return ui::EVENT_REWRITE_CONTINUE; |
| } |
| - NOTREACHED() << "Unexpected event type received: " << event.name();; |
| - return ui::EVENT_REWRITE_CONTINUE; |
| + int location = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
| + base::TimeDelta timeout; |
| + |
| + // If the press was at a corner, the user might go into corner passthrough |
| + // instead. |
| + bool in_a_bottom_corner = |
| + (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location); |
| + if (in_a_bottom_corner) { |
| + VLOG(0) << "Location: " << location; |
| + timeout = kCornerPassthroughDelay; |
| + waiting_for_corner_passthrough_ = true; |
| + } else { |
| + timeout = gesture_detector_config_.double_tap_timeout; |
| + waiting_for_corner_passthrough_ = false; |
| + } |
| + |
| + initial_press_.reset(new TouchEvent(event)); |
| + last_unused_finger_event_.reset(new TouchEvent(event)); |
| + tap_timer_.Start( |
| + FROM_HERE, timeout, this, &TouchExplorationController::OnTapTimerFired); |
| + gesture_provider_.OnTouchEvent(event); |
| + gesture_provider_.OnTouchEventAck(false); |
| + ProcessGestureEvents(); |
| + state_ = SINGLE_TAP_PRESSED; |
| + VLOG_STATE(); |
| + return ui::EVENT_REWRITE_DISCARD; |
| } |
| ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
| const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
| const ui::EventType type = event.type(); |
| + int location = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
| + bool in_a_bottom_corner = |
| + (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER); |
| + // If the event is from the initial press and the location is no longer in the |
| + // corner, then we are not waiting for a corner passthrough anymore. |
| + if (event.touch_id() == initial_press_->touch_id() && in_a_bottom_corner) { |
|
aboxhall
2014/07/24 18:26:34
I think |in_a_bottom_corner| should be negated...
lisayin
2014/07/25 20:11:57
Opps...
|
| + waiting_for_corner_passthrough_ = false; |
| + // If the initial press was in a corner, then more than the double tap |
| + // timeout could have elapsed. |
| + if (tap_timer_.IsRunning() && |
| + event.time_stamp() - initial_press_->time_stamp() > |
| + gesture_detector_config_.double_tap_timeout) { |
| + tap_timer_.Stop(); |
| + OnTapTimerFired(); |
| + return EVENT_REWRITE_DISCARD; |
| + } |
| + } |
| + |
| if (type == ui::ET_TOUCH_PRESSED) { |
| // Adding a second finger within the timeout period switches to |
| // passing through every event from the second finger and none form the |
| @@ -402,7 +441,7 @@ ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( |
| // If a third finger is pressed, we are now going into passthrough mode |
| // and now need to dispatch the first finger into a press, as well as the |
| // recent press. |
| - if (current_touch_ids_.size() == 3){ |
| + if (current_touch_ids_.size() == 3) { |
| state_ = PASSTHROUGH; |
| scoped_ptr<ui::TouchEvent> first_finger_press; |
| first_finger_press.reset( |
| @@ -441,6 +480,33 @@ ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( |
| return ui::EVENT_REWRITE_CONTINUE; |
| } |
| +ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough( |
| + const ui::TouchEvent& event, |
| + scoped_ptr<ui::Event>* rewritten_event) { |
| + ui::EventType type = event.type(); |
| + if (current_touch_ids_.size() == 0) { |
| + ResetToNoFingersDown(); |
| + } |
| + |
| + if (event.touch_id() == initial_press_->touch_id()) { |
|
aboxhall
2014/07/24 18:26:34
Some comments explaining this block would be helpf
lisayin
2014/07/25 20:11:57
Done.
|
| + int edge = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
|
aboxhall
2014/07/24 18:26:34
suggestion: s/edge/edges/
lisayin
2014/07/25 20:11:57
Done.
|
| + bool in_a_bottom_corner = (edge == BOTTOM_LEFT_CORNER) || |
| + (edge == BOTTOM_RIGHT_CORNER); |
| + if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner) |
| + return ui::EVENT_REWRITE_DISCARD; |
| + |
| + waiting_for_corner_passthrough_ = false; |
| + state_ = WAIT_FOR_RELEASE; |
| + return ui::EVENT_REWRITE_DISCARD; |
| + } |
| + |
| + rewritten_event->reset(new ui::TouchEvent( |
| + type, event.location(), event.touch_id(), event.time_stamp())); |
| + (*rewritten_event)->set_flags(event.flags()); |
| + |
| + return ui::EVENT_REWRITE_REWRITTEN; |
| +} |
| + |
| ui::EventRewriteStatus TouchExplorationController::InPassthrough( |
| const ui::TouchEvent& event, |
| scoped_ptr<ui::Event>* rewritten_event) { |
| @@ -586,6 +652,14 @@ ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
| } |
| void TouchExplorationController::OnTapTimerFired() { |
| + if (waiting_for_corner_passthrough_) { |
| + delegate_->PlayEarCon(); |
| + delete gesture_provider_.GetAndResetPendingGestures(); |
| + state_ = CORNER_PASSTHROUGH; |
| + VLOG_STATE(); |
| + return; |
| + } |
| + |
| switch (state_) { |
| case SINGLE_TAP_RELEASED: |
| ResetToNoFingersDown(); |
| @@ -805,6 +879,7 @@ void TouchExplorationController::EnterTouchToMouseMode() { |
| } |
| void TouchExplorationController::ResetToNoFingersDown() { |
| + waiting_for_corner_passthrough_ = false; |
| ProcessGestureEvents(); |
| if (sound_timer_.IsRunning()) |
| sound_timer_.Stop(); |
| @@ -875,6 +950,8 @@ const char* TouchExplorationController::EnumStateToString(State state) { |
| return "TOUCH_EXPLORE_SECOND_PRESS"; |
| case TWO_TO_ONE_FINGER: |
| return "TWO_TO_ONE_FINGER"; |
| + case CORNER_PASSTHROUGH: |
| + return "CORNER_PASSTHROUGH"; |
| case PASSTHROUGH: |
| return "PASSTHROUGH"; |
| case WAIT_FOR_RELEASE: |