Index: ui/chromeos/touch_exploration_controller.cc |
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc |
index 3670f1e948f213908d1884d9f844eacf35916a5c..dfab0d4ae1e5cb977011833fe221239f38a68ef8 100644 |
--- a/ui/chromeos/touch_exploration_controller.cc |
+++ b/ui/chromeos/touch_exploration_controller.cc |
@@ -27,6 +27,10 @@ const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
// In ChromeOS, VKEY_LWIN is synonymous for the search key. |
const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
+ |
+// Delay to indicate that a two finger tap has occured. |
+const base::TimeDelta kTwoFingerTap = base::TimeDelta::FromMilliseconds(50); |
+ |
} // namespace |
TouchExplorationController::TouchExplorationController( |
@@ -134,6 +138,8 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
return InOneFingerPassthrough(touch_event, rewritten_event); |
case WAIT_FOR_ONE_FINGER: |
return InWaitForOneFinger(touch_event, rewritten_event); |
+ case TWO_FINGER_TAP: |
+ return InTwoFingerTap(touch_event, rewritten_event); |
} |
NOTREACHED(); |
return ui::EVENT_REWRITE_CONTINUE; |
@@ -148,19 +154,20 @@ 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)); |
- StartTapTimer(); |
- 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; |
+ initial_press_.reset(new TouchEvent(event)); |
+ initial_presses_[event.touch_id()] = event.location(); |
+ last_unused_finger_event_.reset(new TouchEvent(event)); |
+ StartTapTimer(); |
+ gesture_provider_.OnTouchEvent(event); |
+ gesture_provider_.OnTouchEventAck(false); |
+ ProcessGestureEvents(); |
+ state_ = SINGLE_TAP_PRESSED; |
+ VLOG_STATE(); |
+ return ui::EVENT_REWRITE_DISCARD; |
} |
ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
@@ -168,7 +175,12 @@ ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
const ui::EventType type = event.type(); |
if (type == ui::ET_TOUCH_PRESSED) { |
- // TODO (evy, lisayin) : add support for multifinger swipes. |
+ initial_presses_[event.touch_id()] = event.location(); |
+ if ((event.time_stamp() - initial_press_->time_stamp()) < kTwoFingerTap) { |
+ state_ = TWO_FINGER_TAP; |
+ VLOG_STATE(); |
+ return EVENT_REWRITE_DISCARD; |
+ } |
// For now, we wait for there to be only one finger down again. |
state_ = WAIT_FOR_ONE_FINGER; |
return EVENT_REWRITE_DISCARD; |
@@ -549,6 +561,47 @@ ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
return ui::EVENT_REWRITE_DISCARD; |
} |
+ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( |
+ const ui::TouchEvent& event, |
+ scoped_ptr<ui::Event>* rewritten_event) { |
+ ui::EventType type = event.type(); |
+ if (type == ui::ET_TOUCH_PRESSED) { |
+ // TODO(evy): Process three finger gestures here. |
+ state_ = WAIT_FOR_ONE_FINGER; |
+ VLOG_STATE(); |
+ return ui::EVENT_REWRITE_DISCARD; |
+ } |
+ |
+ if (type == ui::ET_TOUCH_MOVED) { |
+ // Determine if it was a swipe. |
+ gfx::Point original_location = initial_presses_[event.touch_id()]; |
+ float distance = (event.location() - original_location).Length(); |
+ // If the user moves too far from the original position, consider the |
+ // movement a swipe. |
+ // TODO(evy, lisayin): Add multifinger swipe processing. |
+ if (distance > gesture_detector_config_.touch_slop) { |
+ state_ = WAIT_FOR_ONE_FINGER; |
+ } |
+ return ui::EVENT_REWRITE_DISCARD; |
+ } |
+ |
+ if (current_touch_ids_.size() != 0) |
+ return ui::EVENT_REWRITE_DISCARD; |
+ |
+ if (type == ui::ET_TOUCH_RELEASED) { |
+ ui::KeyEvent control_down( |
+ ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN); |
+ ui::KeyEvent control_up(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ui::EF_NONE); |
+ |
+ DispatchEvent(&control_down); |
James Cook
2014/08/08 18:06:30
I'm not that familiar with a11y -- maybe a comment
lisayin
2014/08/08 19:06:15
Done.
|
+ DispatchEvent(&control_up); |
+ |
+ ResetToNoFingersDown(); |
+ return ui::EVENT_REWRITE_DISCARD; |
+ } |
+ return ui::EVENT_REWRITE_DISCARD; |
+} |
+ |
base::TimeDelta TouchExplorationController::Now() { |
if (tick_clock_) { |
// This is the same as what EventTimeForNow() does, but here we do it |
@@ -595,6 +648,10 @@ void TouchExplorationController::OnTapTimerFired() { |
state_ = TOUCH_EXPLORATION; |
VLOG_STATE(); |
break; |
+ case TWO_FINGER_TAP: |
+ state_ = WAIT_FOR_ONE_FINGER; |
+ VLOG_STATE(); |
+ break; |
default: |
return; |
} |
@@ -800,6 +857,7 @@ void TouchExplorationController::EnterTouchToMouseMode() { |
void TouchExplorationController::ResetToNoFingersDown() { |
ProcessGestureEvents(); |
+ initial_presses_.clear(); |
James Cook
2014/08/08 18:06:30
Hooray for clearing out data structures!
lisayin
2014/08/08 19:06:15
:)
|
if (sound_timer_.IsRunning()) |
sound_timer_.Stop(); |
state_ = NO_FINGERS_DOWN; |
@@ -875,6 +933,8 @@ const char* TouchExplorationController::EnumStateToString(State state) { |
return "ONE_FINGER_PASSTHROUGH"; |
case WAIT_FOR_ONE_FINGER: |
return "WAIT_FOR_ONE_FINGER"; |
+ case TWO_FINGER_TAP: |
+ return "TWO_FINGER_TAP"; |
} |
return "Not a state"; |
} |