Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Unified Diff: ui/chromeos/touch_exploration_controller.cc

Issue 330763007: Swipe Gestures for Accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gesture-vlogs
Patch Set: Nit Changes Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/chromeos/touch_exploration_controller.h ('k') | ui/chromeos/touch_exploration_controller_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/chromeos/touch_exploration_controller.cc
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
index 1a77b971aa9b0c7ad59f56d2004267541b4592dc..6670218404a30d7d0904ad0b6c0979855d5b4b68 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -18,11 +18,17 @@
namespace ui {
+namespace {
+// In ChromeOS, VKEY_LWIN is synonymous for the search key.
+const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN;
+} // namespace
+
TouchExplorationController::TouchExplorationController(
aura::Window* root_window)
: root_window_(root_window),
state_(NO_FINGERS_DOWN),
event_handler_for_testing_(NULL),
+ gesture_provider_(this),
prev_state_(NO_FINGERS_DOWN) {
CHECK(root_window);
root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
@@ -48,6 +54,10 @@ bool TouchExplorationController::IsInNoFingersDownStateForTesting() const {
return state_ == NO_FINGERS_DOWN;
}
+bool TouchExplorationController::IsInGestureInProgressStateForTesting() const {
aboxhall 2014/07/02 16:45:57 suggestion: should we just have a GetStateForTesti
lisayin 2014/07/02 17:09:50 The state enum is private so I don't think that we
aboxhall 2014/07/02 18:00:13 Ahh, that makes sense, thanks.
+ return state_ == GESTURE_IN_PROGRESS;
+}
+
ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
const ui::Event& event,
scoped_ptr<ui::Event>* rewritten_event) {
@@ -59,9 +69,6 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
<< ", Flags: " << key_event.flags()
<< ", Is char: " << key_event.is_char();
}
- if(event.IsGestureEvent()){
- VLOG(0) << "\n Gesture event " << event.name();
- }
return ui::EVENT_REWRITE_CONTINUE;
}
const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event);
@@ -123,6 +130,8 @@ ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
return InDoubleTapPressed(touch_event, rewritten_event);
case TOUCH_EXPLORATION:
return InTouchExploration(touch_event, rewritten_event);
+ case GESTURE_IN_PROGRESS:
+ return InGestureInProgress(touch_event, rewritten_event);
case TOUCH_EXPLORE_SECOND_PRESS:
return InTouchExploreSecondPress(touch_event, rewritten_event);
case TWO_TO_ONE_FINGER:
@@ -152,6 +161,8 @@ ui::EventRewriteStatus TouchExplorationController::InNoFingersDown(
gesture_detector_config_.double_tap_timeout,
this,
&TouchExplorationController::OnTapTimerFired);
+ gesture_provider_.OnTouchEvent(event);
+ gesture_provider_.OnTouchEventAck(false);
state_ = SINGLE_TAP_PRESSED;
VLOG_STATE();
return ui::EVENT_REWRITE_DISCARD;
@@ -182,19 +193,32 @@ ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
VLOG_STATE();
return EVENT_REWRITE_DISCARD;
} else if (type == ui::ET_TOUCH_MOVED) {
- // If the user moves far enough from the initial touch location (outside
- // the "slop" region, jump to the touch exploration mode early.
- // TODO(evy, lisayin): Add gesture recognition here instead -
- // we should probably jump to gesture mode here if the velocity is
- // high enough, and touch exploration if the velocity is lower.
- float delta = (event.location() - initial_press_->location()).Length();
- if (delta > gesture_detector_config_.touch_slop) {
- EnterTouchToMouseMode();
- state_ = TOUCH_EXPLORATION;
+ float delta_time =
+ (event.time_stamp() - initial_press_->time_stamp()).InSecondsF();
+ float delta_distance =
aboxhall 2014/07/02 16:45:57 nit: I think this should just be 'distance'
lisayin 2014/07/02 17:19:43 Done.
+ (event.location() - initial_press_->location()).Length();
+ float velocity = delta_distance / delta_time;
+ VLOG(0) << "\n Delta time: " << delta_time
+ << "\n Delta distance: " << delta_distance
+ << "\n Velocity of click: " << velocity
+ << "\n Minimum swipe velocity: "
+ << gesture_detector_config_.minimum_swipe_velocity;
+ if (delta_distance <= gesture_detector_config_.touch_slop)
aboxhall 2014/07/02 16:45:57 Presumably we don't need to compute delta_time and
lisayin 2014/07/02 17:19:43 Done.
+ return EVENT_REWRITE_DISCARD;
+
+ // If the user moves fast enough and far enough
aboxhall 2014/07/02 16:45:57 Re-flow this comment (I think tab should do it) A
lisayin 2014/07/02 17:19:43 Done.
+ // from the initial touch location, start gesture detection.
+ // Otherwise, if the user moves far enough from the initial touch location
+ // outside the "slop" region, jump to the touch exploration mode early.
+ if (velocity > gesture_detector_config_.minimum_swipe_velocity) {
+ state_ = GESTURE_IN_PROGRESS;
VLOG_STATE();
- return InTouchExploration(event, rewritten_event);
+ return InGestureInProgress(event, rewritten_event);
}
- return EVENT_REWRITE_DISCARD;
+ EnterTouchToMouseMode();
+ state_ = TOUCH_EXPLORATION;
+ VLOG_STATE();
+ return InTouchExploration(event, rewritten_event);
}
NOTREACHED() << "Unexpected event type received.";
return ui::EVENT_REWRITE_CONTINUE;
@@ -205,13 +229,23 @@ TouchExplorationController::InSingleTapOrTouchExploreReleased(
const ui::TouchEvent& event,
scoped_ptr<ui::Event>* rewritten_event) {
const ui::EventType type = event.type();
+ // If there is more than one finger down, then discard to wait until only one
+ // finger is or no fingers are down (should be replaced with wait_state).
+ if (current_touch_ids_.size() > 1) {
+ state_ = WAIT_FOR_RELEASE;
+ return ui::EVENT_REWRITE_DISCARD;
+ }
+ // If there is no touch exploration yet, discard.
+ if (last_touch_exploration_ == NULL || type == ui::ET_TOUCH_RELEASED) {
+ if (current_touch_ids_.size() == 0) {
+ ResetToNoFingersDown();
+ }
+ return ui::EVENT_REWRITE_DISCARD;
+ }
+
if (type == ui::ET_TOUCH_PRESSED) {
// This is the second tap in a double-tap (or double tap-hold).
// Rewrite at location of last touch exploration.
- // If there is no touch exploration yet, discard instead.
- if (!last_touch_exploration_) {
- return ui::EVENT_REWRITE_DISCARD;
- }
rewritten_event->reset(
new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
last_touch_exploration_->location(),
@@ -221,13 +255,6 @@ TouchExplorationController::InSingleTapOrTouchExploreReleased(
state_ = DOUBLE_TAP_PRESSED;
VLOG_STATE();
return ui::EVENT_REWRITE_REWRITTEN;
- } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) {
- // If the previous press was discarded, we need to also handle its
- // release.
- if (current_touch_ids_.size() == 0) {
- ResetToNoFingersDown();
- }
- return ui::EVENT_REWRITE_DISCARD;
}
NOTREACHED() << "Unexpected event type received.";
return ui::EVENT_REWRITE_CONTINUE;
@@ -243,7 +270,7 @@ ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed(
return EVENT_REWRITE_DISCARD;
// Rewrite release at location of last touch exploration with the same
- // id as the prevoius press.
+ // id as the previous press.
rewritten_event->reset(
new ui::TouchEvent(ui::ET_TOUCH_RELEASED,
last_touch_exploration_->location(),
@@ -296,6 +323,43 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploration(
return ui::EVENT_REWRITE_REWRITTEN;
}
+ui::EventRewriteStatus TouchExplorationController::InGestureInProgress(
+ const ui::TouchEvent& event,
+ scoped_ptr<ui::Event>* rewritten_event) {
+ ui::EventType type = event.type();
+ if (type == ui::ET_TOUCH_PRESSED ||
+ event.touch_id() != initial_press_->touch_id()) {
+ // Should go to passthrough mode.
+ if (tap_timer_.IsRunning())
+ tap_timer_.Stop();
+ // Discard any pending gestures.
+ scoped_ptr<ScopedVector<ui::GestureEvent> > gestures(
aboxhall 2014/07/02 16:45:58 Since you're not using |gestures|, you can use ign
lisayin 2014/07/02 17:09:50 Will I still need to cast the return from GetAndRe
aboxhall 2014/07/02 18:00:13 I see you figured this out :)
+ gesture_provider_.GetAndResetPendingGestures());
+ state_ = TWO_TO_ONE_FINGER;
+ last_two_to_one_.reset(new TouchEvent(event));
+ rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
+ event.location(),
+ event.touch_id(),
+ event.time_stamp()));
+ (*rewritten_event)->set_flags(event.flags());
+ return EVENT_REWRITE_REWRITTEN;
+ }
+ /*
+ if (last_touch_exploration_ == NULL) {
aboxhall 2014/07/02 16:45:57 Should this be uncommented or removed?
lisayin 2014/07/02 17:19:44 Done.
+ last_touch_exploration_.reset(initial_press_.get());
+ }*/
+ if (type == ui::ET_TOUCH_MOVED) {
+ gesture_provider_.OnTouchEvent(event);
+ gesture_provider_.OnTouchEventAck(false);
+ }
+ if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
+ gesture_provider_.OnTouchEvent(event);
+ gesture_provider_.OnTouchEventAck(false);
+ if (current_touch_ids_.size() == 0)
+ ResetToNoFingersDown();
+ }
+ return ui::EVENT_REWRITE_DISCARD;
+}
ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger(
const ui::TouchEvent& event,
@@ -414,6 +478,7 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress(
initial_press_->touch_id(),
event.time_stamp()));
(*rewritten_event)->set_flags(event.flags());
+ EnterTouchToMouseMode();
state_ = TOUCH_EXPLORATION;
VLOG_STATE();
return ui::EVENT_REWRITE_REWRITTEN;
@@ -433,6 +498,7 @@ ui::EventRewriteStatus TouchExplorationController::InWaitForRelease(
}
if (current_touch_ids_.size() == 0) {
state_ = NO_FINGERS_DOWN;
+ VLOG_STATE();
ResetToNoFingersDown();
}
return EVENT_REWRITE_DISCARD;
@@ -448,19 +514,22 @@ void TouchExplorationController::OnTapTimerFired() {
last_touch_exploration_.reset(new TouchEvent(*initial_press_));
return;
case SINGLE_TAP_PRESSED:
+ case GESTURE_IN_PROGRESS: {
+ // Discard any pending gestures.
+ scoped_ptr<ScopedVector<ui::GestureEvent> > gestures(
aboxhall 2014/07/02 16:45:57 Similarly, you can use ignore_result() here.
lisayin 2014/07/02 17:19:43 Done.
+ gesture_provider_.GetAndResetPendingGestures());
EnterTouchToMouseMode();
state_ = TOUCH_EXPLORATION;
VLOG_STATE();
- break;
+ } break;
default:
return;
}
-
- scoped_ptr<ui::Event> mouse_move = CreateMouseMoveEvent(
- initial_press_->location(), initial_press_->flags());
+ scoped_ptr<ui::Event> mouse_move =
+ CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags());
DispatchEvent(mouse_move.get());
last_touch_exploration_.reset(new TouchEvent(*initial_press_));
-}
+ }
void TouchExplorationController::DispatchEvent(ui::Event* event) {
if (event_handler_for_testing_) {
@@ -471,6 +540,66 @@ void TouchExplorationController::DispatchEvent(ui::Event* event) {
root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
}
+void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) {
+ if (tap_timer_.IsRunning())
+ tap_timer_.Stop();
+
+ CHECK(gesture->IsGestureEvent());
+ VLOG(0) << " \n Gesture Triggered: " << gesture->name();
+
+ if (gesture->type() == ui::ET_GESTURE_SWIPE) {
+ OnSwipeEvent(gesture);
+ return;
+ }
+ // If the event processed was not a swipe gesture, then determine the next
+ // state by the number of fingers currently down.
+ if (current_touch_ids_.size() == 0) {
+ ResetToNoFingersDown();
+ } else if (current_touch_ids_.size() == 1) {
+ EnterTouchToMouseMode();
+ state_ = TOUCH_EXPLORATION;
+ }
+}
+
+void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
+ // A swipe gesture contains details for the direction in which the swipe
+ // occurred.
+ GestureEventDetails event_details = swipe_gesture->details();
+ if (event_details.swipe_left()) {
+ DispatchShiftSearchKeyEvent(ui::VKEY_LEFT);
+ return;
+ } else if (event_details.swipe_right()) {
+ DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT);
+ return;
+ } else if (event_details.swipe_up()) {
+ DispatchShiftSearchKeyEvent(ui::VKEY_UP);
+ return;
+ } else if (event_details.swipe_down()) {
+ DispatchShiftSearchKeyEvent(ui::VKEY_DOWN);
+ return;
+ }
+}
+
+void TouchExplorationController::DispatchShiftSearchKeyEvent(
+ const ui::KeyboardCode direction) {
+ // In order to activate the shortcut shift+search+<arrow key>
+ // three KeyPressed events must be dispatched in succession along
+ // with three KeyReleased events.
+ DispatchEvent(new ui::KeyEvent(
+ ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false));
+ DispatchEvent(new ui::KeyEvent(
+ ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false));
+ DispatchEvent(new ui::KeyEvent(
+ ui::ET_KEY_PRESSED, direction, ui::EF_SHIFT_DOWN, false));
+
+ DispatchEvent(new ui::KeyEvent(
+ ui::ET_KEY_RELEASED, direction, ui::EF_SHIFT_DOWN, false));
+ DispatchEvent(new ui::KeyEvent(
+ ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false));
+ DispatchEvent(new ui::KeyEvent(
+ ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE, false));
+}
+
scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent(
const gfx::PointF& location,
int flags) {
@@ -493,6 +622,16 @@ void TouchExplorationController::EnterTouchToMouseMode() {
}
void TouchExplorationController::ResetToNoFingersDown() {
+ // Process the gestures.
+ scoped_ptr<ScopedVector<ui::GestureEvent> > gestures;
aboxhall 2014/07/02 16:45:57 You can initialise gestures with GetAndResetPendin
lisayin 2014/07/02 17:19:43 Done.
+ gestures.reset(gesture_provider_.GetAndResetPendingGestures());
+ if (gestures != NULL) {
aboxhall 2014/07/02 16:45:57 if (gestures) should work I think...
lisayin 2014/07/02 17:19:44 Done.
+ for (ScopedVector<GestureEvent>::iterator i = gestures->begin();
+ i != gestures->end();
+ ++i) {
+ OnGestureEvent(*i);
+ }
+ }
state_ = NO_FINGERS_DOWN;
VLOG_STATE();
if (tap_timer_.IsRunning())
@@ -549,6 +688,8 @@ const char* TouchExplorationController::EnumStateToString(State state) {
return "DOUBLE_TAP_PRESSED";
case TOUCH_EXPLORATION:
return "TOUCH_EXPLORATION";
+ case GESTURE_IN_PROGRESS:
+ return "GESTURE_IN_PROGRESS";
case TOUCH_EXPLORE_SECOND_PRESS:
return "TOUCH_EXPLORE_SECOND_PRESS";
case TWO_TO_ONE_FINGER:
« no previous file with comments | « ui/chromeos/touch_exploration_controller.h ('k') | ui/chromeos/touch_exploration_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698