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

Side by Side 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, 5 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/chromeos/touch_exploration_controller.h" 5 #include "ui/chromeos/touch_exploration_controller.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "ui/aura/client/cursor_client.h" 9 #include "ui/aura/client/cursor_client.h"
10 #include "ui/aura/window.h" 10 #include "ui/aura/window.h"
11 #include "ui/aura/window_event_dispatcher.h" 11 #include "ui/aura/window_event_dispatcher.h"
12 #include "ui/aura/window_tree_host.h" 12 #include "ui/aura/window_tree_host.h"
13 #include "ui/events/event.h" 13 #include "ui/events/event.h"
14 #include "ui/events/event_processor.h" 14 #include "ui/events/event_processor.h"
15 15
16 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) 16 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__)
17 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) 17 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__)
18 18
19 namespace ui { 19 namespace ui {
20 20
21 namespace {
22 // In ChromeOS, VKEY_LWIN is synonymous for the search key.
23 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN;
24 } // namespace
25
21 TouchExplorationController::TouchExplorationController( 26 TouchExplorationController::TouchExplorationController(
22 aura::Window* root_window) 27 aura::Window* root_window)
23 : root_window_(root_window), 28 : root_window_(root_window),
24 state_(NO_FINGERS_DOWN), 29 state_(NO_FINGERS_DOWN),
25 event_handler_for_testing_(NULL), 30 event_handler_for_testing_(NULL),
31 gesture_provider_(this),
26 prev_state_(NO_FINGERS_DOWN) { 32 prev_state_(NO_FINGERS_DOWN) {
27 CHECK(root_window); 33 CHECK(root_window);
28 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); 34 root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
29 } 35 }
30 36
31 37
32 TouchExplorationController::~TouchExplorationController() { 38 TouchExplorationController::~TouchExplorationController() {
33 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); 39 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this);
34 } 40 }
35 41
36 void TouchExplorationController::CallTapTimerNowForTesting() { 42 void TouchExplorationController::CallTapTimerNowForTesting() {
37 DCHECK(tap_timer_.IsRunning()); 43 DCHECK(tap_timer_.IsRunning());
38 tap_timer_.Stop(); 44 tap_timer_.Stop();
39 OnTapTimerFired(); 45 OnTapTimerFired();
40 } 46 }
41 47
42 void TouchExplorationController::SetEventHandlerForTesting( 48 void TouchExplorationController::SetEventHandlerForTesting(
43 ui::EventHandler* event_handler_for_testing) { 49 ui::EventHandler* event_handler_for_testing) {
44 event_handler_for_testing_ = event_handler_for_testing; 50 event_handler_for_testing_ = event_handler_for_testing;
45 } 51 }
46 52
47 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const { 53 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const {
48 return state_ == NO_FINGERS_DOWN; 54 return state_ == NO_FINGERS_DOWN;
49 } 55 }
50 56
57 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.
58 return state_ == GESTURE_IN_PROGRESS;
59 }
60
51 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( 61 ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
52 const ui::Event& event, 62 const ui::Event& event,
53 scoped_ptr<ui::Event>* rewritten_event) { 63 scoped_ptr<ui::Event>* rewritten_event) {
54 if (!event.IsTouchEvent()) { 64 if (!event.IsTouchEvent()) {
55 if (event.IsKeyEvent()) { 65 if (event.IsKeyEvent()) {
56 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); 66 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event);
57 VLOG(0) << "\nKeyboard event: " << key_event.name() << "\n" 67 VLOG(0) << "\nKeyboard event: " << key_event.name() << "\n"
58 << " Key code: " << key_event.key_code() 68 << " Key code: " << key_event.key_code()
59 << ", Flags: " << key_event.flags() 69 << ", Flags: " << key_event.flags()
60 << ", Is char: " << key_event.is_char(); 70 << ", Is char: " << key_event.is_char();
61 } 71 }
62 if(event.IsGestureEvent()){
63 VLOG(0) << "\n Gesture event " << event.name();
64 }
65 return ui::EVENT_REWRITE_CONTINUE; 72 return ui::EVENT_REWRITE_CONTINUE;
66 } 73 }
67 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); 74 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event);
68 75
69 // If the tap timer should have fired by now but hasn't, run it now and 76 // If the tap timer should have fired by now but hasn't, run it now and
70 // stop the timer. This is important so that behavior is consistent with 77 // stop the timer. This is important so that behavior is consistent with
71 // the timestamps of the events, and not dependent on the granularity of 78 // the timestamps of the events, and not dependent on the granularity of
72 // the timer. 79 // the timer.
73 if (tap_timer_.IsRunning() && 80 if (tap_timer_.IsRunning() &&
74 touch_event.time_stamp() - initial_press_->time_stamp() > 81 touch_event.time_stamp() - initial_press_->time_stamp() >
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 return InNoFingersDown(touch_event, rewritten_event); 123 return InNoFingersDown(touch_event, rewritten_event);
117 case SINGLE_TAP_PRESSED: 124 case SINGLE_TAP_PRESSED:
118 return InSingleTapPressed(touch_event, rewritten_event); 125 return InSingleTapPressed(touch_event, rewritten_event);
119 case SINGLE_TAP_RELEASED: 126 case SINGLE_TAP_RELEASED:
120 case TOUCH_EXPLORE_RELEASED: 127 case TOUCH_EXPLORE_RELEASED:
121 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); 128 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event);
122 case DOUBLE_TAP_PRESSED: 129 case DOUBLE_TAP_PRESSED:
123 return InDoubleTapPressed(touch_event, rewritten_event); 130 return InDoubleTapPressed(touch_event, rewritten_event);
124 case TOUCH_EXPLORATION: 131 case TOUCH_EXPLORATION:
125 return InTouchExploration(touch_event, rewritten_event); 132 return InTouchExploration(touch_event, rewritten_event);
133 case GESTURE_IN_PROGRESS:
134 return InGestureInProgress(touch_event, rewritten_event);
126 case TOUCH_EXPLORE_SECOND_PRESS: 135 case TOUCH_EXPLORE_SECOND_PRESS:
127 return InTouchExploreSecondPress(touch_event, rewritten_event); 136 return InTouchExploreSecondPress(touch_event, rewritten_event);
128 case TWO_TO_ONE_FINGER: 137 case TWO_TO_ONE_FINGER:
129 return InTwoToOneFinger(touch_event, rewritten_event); 138 return InTwoToOneFinger(touch_event, rewritten_event);
130 case PASSTHROUGH: 139 case PASSTHROUGH:
131 return InPassthrough(touch_event, rewritten_event); 140 return InPassthrough(touch_event, rewritten_event);
132 case WAIT_FOR_RELEASE: 141 case WAIT_FOR_RELEASE:
133 return InWaitForRelease(touch_event, rewritten_event); 142 return InWaitForRelease(touch_event, rewritten_event);
134 } 143 }
135 NOTREACHED(); 144 NOTREACHED();
136 return ui::EVENT_REWRITE_CONTINUE; 145 return ui::EVENT_REWRITE_CONTINUE;
137 } 146 }
138 147
139 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( 148 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent(
140 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { 149 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) {
141 NOTREACHED(); 150 NOTREACHED();
142 return ui::EVENT_REWRITE_CONTINUE; 151 return ui::EVENT_REWRITE_CONTINUE;
143 } 152 }
144 153
145 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( 154 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown(
146 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { 155 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) {
147 const ui::EventType type = event.type(); 156 const ui::EventType type = event.type();
148 if (type == ui::ET_TOUCH_PRESSED) { 157 if (type == ui::ET_TOUCH_PRESSED) {
149 initial_press_.reset(new TouchEvent(event)); 158 initial_press_.reset(new TouchEvent(event));
150 last_unused_finger_event_.reset(new TouchEvent(event)); 159 last_unused_finger_event_.reset(new TouchEvent(event));
151 tap_timer_.Start(FROM_HERE, 160 tap_timer_.Start(FROM_HERE,
152 gesture_detector_config_.double_tap_timeout, 161 gesture_detector_config_.double_tap_timeout,
153 this, 162 this,
154 &TouchExplorationController::OnTapTimerFired); 163 &TouchExplorationController::OnTapTimerFired);
164 gesture_provider_.OnTouchEvent(event);
165 gesture_provider_.OnTouchEventAck(false);
155 state_ = SINGLE_TAP_PRESSED; 166 state_ = SINGLE_TAP_PRESSED;
156 VLOG_STATE(); 167 VLOG_STATE();
157 return ui::EVENT_REWRITE_DISCARD; 168 return ui::EVENT_REWRITE_DISCARD;
158 } 169 }
159 NOTREACHED() << "Unexpected event type received."; 170 NOTREACHED() << "Unexpected event type received.";
160 return ui::EVENT_REWRITE_CONTINUE; 171 return ui::EVENT_REWRITE_CONTINUE;
161 } 172 }
162 173
163 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( 174 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
164 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { 175 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) {
(...skipping 10 matching lines...) Expand all
175 event.touch_id(), 186 event.touch_id(),
176 event.time_stamp())); 187 event.time_stamp()));
177 (*rewritten_event)->set_flags(event.flags()); 188 (*rewritten_event)->set_flags(event.flags());
178 return EVENT_REWRITE_REWRITTEN; 189 return EVENT_REWRITE_REWRITTEN;
179 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 190 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
180 DCHECK_EQ(0U, current_touch_ids_.size()); 191 DCHECK_EQ(0U, current_touch_ids_.size());
181 state_ = SINGLE_TAP_RELEASED; 192 state_ = SINGLE_TAP_RELEASED;
182 VLOG_STATE(); 193 VLOG_STATE();
183 return EVENT_REWRITE_DISCARD; 194 return EVENT_REWRITE_DISCARD;
184 } else if (type == ui::ET_TOUCH_MOVED) { 195 } else if (type == ui::ET_TOUCH_MOVED) {
185 // If the user moves far enough from the initial touch location (outside 196 float delta_time =
186 // the "slop" region, jump to the touch exploration mode early. 197 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF();
187 // TODO(evy, lisayin): Add gesture recognition here instead - 198 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.
188 // we should probably jump to gesture mode here if the velocity is 199 (event.location() - initial_press_->location()).Length();
189 // high enough, and touch exploration if the velocity is lower. 200 float velocity = delta_distance / delta_time;
190 float delta = (event.location() - initial_press_->location()).Length(); 201 VLOG(0) << "\n Delta time: " << delta_time
191 if (delta > gesture_detector_config_.touch_slop) { 202 << "\n Delta distance: " << delta_distance
192 EnterTouchToMouseMode(); 203 << "\n Velocity of click: " << velocity
193 state_ = TOUCH_EXPLORATION; 204 << "\n Minimum swipe velocity: "
205 << gesture_detector_config_.minimum_swipe_velocity;
206 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.
207 return EVENT_REWRITE_DISCARD;
208
209 // 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.
210 // from the initial touch location, start gesture detection.
211 // Otherwise, if the user moves far enough from the initial touch location
212 // outside the "slop" region, jump to the touch exploration mode early.
213 if (velocity > gesture_detector_config_.minimum_swipe_velocity) {
214 state_ = GESTURE_IN_PROGRESS;
194 VLOG_STATE(); 215 VLOG_STATE();
195 return InTouchExploration(event, rewritten_event); 216 return InGestureInProgress(event, rewritten_event);
196 } 217 }
197 return EVENT_REWRITE_DISCARD; 218 EnterTouchToMouseMode();
219 state_ = TOUCH_EXPLORATION;
220 VLOG_STATE();
221 return InTouchExploration(event, rewritten_event);
198 } 222 }
199 NOTREACHED() << "Unexpected event type received."; 223 NOTREACHED() << "Unexpected event type received.";
200 return ui::EVENT_REWRITE_CONTINUE; 224 return ui::EVENT_REWRITE_CONTINUE;
201 } 225 }
202 226
203 ui::EventRewriteStatus 227 ui::EventRewriteStatus
204 TouchExplorationController::InSingleTapOrTouchExploreReleased( 228 TouchExplorationController::InSingleTapOrTouchExploreReleased(
205 const ui::TouchEvent& event, 229 const ui::TouchEvent& event,
206 scoped_ptr<ui::Event>* rewritten_event) { 230 scoped_ptr<ui::Event>* rewritten_event) {
207 const ui::EventType type = event.type(); 231 const ui::EventType type = event.type();
232 // If there is more than one finger down, then discard to wait until only one
233 // finger is or no fingers are down (should be replaced with wait_state).
234 if (current_touch_ids_.size() > 1) {
235 state_ = WAIT_FOR_RELEASE;
236 return ui::EVENT_REWRITE_DISCARD;
237 }
238 // If there is no touch exploration yet, discard.
239 if (last_touch_exploration_ == NULL || type == ui::ET_TOUCH_RELEASED) {
240 if (current_touch_ids_.size() == 0) {
241 ResetToNoFingersDown();
242 }
243 return ui::EVENT_REWRITE_DISCARD;
244 }
245
208 if (type == ui::ET_TOUCH_PRESSED) { 246 if (type == ui::ET_TOUCH_PRESSED) {
209 // This is the second tap in a double-tap (or double tap-hold). 247 // This is the second tap in a double-tap (or double tap-hold).
210 // Rewrite at location of last touch exploration. 248 // Rewrite at location of last touch exploration.
211 // If there is no touch exploration yet, discard instead.
212 if (!last_touch_exploration_) {
213 return ui::EVENT_REWRITE_DISCARD;
214 }
215 rewritten_event->reset( 249 rewritten_event->reset(
216 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, 250 new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
217 last_touch_exploration_->location(), 251 last_touch_exploration_->location(),
218 event.touch_id(), 252 event.touch_id(),
219 event.time_stamp())); 253 event.time_stamp()));
220 (*rewritten_event)->set_flags(event.flags()); 254 (*rewritten_event)->set_flags(event.flags());
221 state_ = DOUBLE_TAP_PRESSED; 255 state_ = DOUBLE_TAP_PRESSED;
222 VLOG_STATE(); 256 VLOG_STATE();
223 return ui::EVENT_REWRITE_REWRITTEN; 257 return ui::EVENT_REWRITE_REWRITTEN;
224 } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) {
225 // If the previous press was discarded, we need to also handle its
226 // release.
227 if (current_touch_ids_.size() == 0) {
228 ResetToNoFingersDown();
229 }
230 return ui::EVENT_REWRITE_DISCARD;
231 } 258 }
232 NOTREACHED() << "Unexpected event type received."; 259 NOTREACHED() << "Unexpected event type received.";
233 return ui::EVENT_REWRITE_CONTINUE; 260 return ui::EVENT_REWRITE_CONTINUE;
234 } 261 }
235 262
236 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed( 263 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed(
237 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { 264 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) {
238 const ui::EventType type = event.type(); 265 const ui::EventType type = event.type();
239 if (type == ui::ET_TOUCH_PRESSED) { 266 if (type == ui::ET_TOUCH_PRESSED) {
240 return ui::EVENT_REWRITE_DISCARD; 267 return ui::EVENT_REWRITE_DISCARD;
241 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 268 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
242 if (current_touch_ids_.size() != 0) 269 if (current_touch_ids_.size() != 0)
243 return EVENT_REWRITE_DISCARD; 270 return EVENT_REWRITE_DISCARD;
244 271
245 // Rewrite release at location of last touch exploration with the same 272 // Rewrite release at location of last touch exploration with the same
246 // id as the prevoius press. 273 // id as the previous press.
247 rewritten_event->reset( 274 rewritten_event->reset(
248 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 275 new ui::TouchEvent(ui::ET_TOUCH_RELEASED,
249 last_touch_exploration_->location(), 276 last_touch_exploration_->location(),
250 initial_press_->touch_id(), 277 initial_press_->touch_id(),
251 event.time_stamp())); 278 event.time_stamp()));
252 (*rewritten_event)->set_flags(event.flags()); 279 (*rewritten_event)->set_flags(event.flags());
253 ResetToNoFingersDown(); 280 ResetToNoFingersDown();
254 return ui::EVENT_REWRITE_REWRITTEN; 281 return ui::EVENT_REWRITE_REWRITTEN;
255 } else if (type == ui::ET_TOUCH_MOVED) { 282 } else if (type == ui::ET_TOUCH_MOVED) {
256 return ui::EVENT_REWRITE_DISCARD; 283 return ui::EVENT_REWRITE_DISCARD;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 NOTREACHED() << "Unexpected event type received."; 316 NOTREACHED() << "Unexpected event type received.";
290 return ui::EVENT_REWRITE_CONTINUE; 317 return ui::EVENT_REWRITE_CONTINUE;
291 } 318 }
292 319
293 // Rewrite as a mouse-move event. 320 // Rewrite as a mouse-move event.
294 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); 321 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags());
295 last_touch_exploration_.reset(new TouchEvent(event)); 322 last_touch_exploration_.reset(new TouchEvent(event));
296 return ui::EVENT_REWRITE_REWRITTEN; 323 return ui::EVENT_REWRITE_REWRITTEN;
297 } 324 }
298 325
326 ui::EventRewriteStatus TouchExplorationController::InGestureInProgress(
327 const ui::TouchEvent& event,
328 scoped_ptr<ui::Event>* rewritten_event) {
329 ui::EventType type = event.type();
330 if (type == ui::ET_TOUCH_PRESSED ||
331 event.touch_id() != initial_press_->touch_id()) {
332 // Should go to passthrough mode.
333 if (tap_timer_.IsRunning())
334 tap_timer_.Stop();
335 // Discard any pending gestures.
336 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 :)
337 gesture_provider_.GetAndResetPendingGestures());
338 state_ = TWO_TO_ONE_FINGER;
339 last_two_to_one_.reset(new TouchEvent(event));
340 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
341 event.location(),
342 event.touch_id(),
343 event.time_stamp()));
344 (*rewritten_event)->set_flags(event.flags());
345 return EVENT_REWRITE_REWRITTEN;
346 }
347 /*
348 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.
349 last_touch_exploration_.reset(initial_press_.get());
350 }*/
351 if (type == ui::ET_TOUCH_MOVED) {
352 gesture_provider_.OnTouchEvent(event);
353 gesture_provider_.OnTouchEventAck(false);
354 }
355 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
356 gesture_provider_.OnTouchEvent(event);
357 gesture_provider_.OnTouchEventAck(false);
358 if (current_touch_ids_.size() == 0)
359 ResetToNoFingersDown();
360 }
361 return ui::EVENT_REWRITE_DISCARD;
362 }
299 363
300 ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( 364 ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger(
301 const ui::TouchEvent& event, 365 const ui::TouchEvent& event,
302 scoped_ptr<ui::Event>* rewritten_event) { 366 scoped_ptr<ui::Event>* rewritten_event) {
303 // The user should only ever be in TWO_TO_ONE_FINGER with two fingers down. 367 // The user should only ever be in TWO_TO_ONE_FINGER with two fingers down.
304 // If the user added or removed a finger, the state is changed. 368 // If the user added or removed a finger, the state is changed.
305 ui::EventType type = event.type(); 369 ui::EventType type = event.type();
306 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 370 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
307 DCHECK(current_touch_ids_.size() == 1); 371 DCHECK(current_touch_ids_.size() == 1);
308 // Stop passing through the second finger and go to the wait state. 372 // Stop passing through the second finger and go to the wait state.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 if (current_touch_ids_.size() != 1) 471 if (current_touch_ids_.size() != 1)
408 return EVENT_REWRITE_DISCARD; 472 return EVENT_REWRITE_DISCARD;
409 473
410 // Rewrite at location of last touch exploration. 474 // Rewrite at location of last touch exploration.
411 rewritten_event->reset( 475 rewritten_event->reset(
412 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 476 new ui::TouchEvent(ui::ET_TOUCH_RELEASED,
413 last_touch_exploration_->location(), 477 last_touch_exploration_->location(),
414 initial_press_->touch_id(), 478 initial_press_->touch_id(),
415 event.time_stamp())); 479 event.time_stamp()));
416 (*rewritten_event)->set_flags(event.flags()); 480 (*rewritten_event)->set_flags(event.flags());
481 EnterTouchToMouseMode();
417 state_ = TOUCH_EXPLORATION; 482 state_ = TOUCH_EXPLORATION;
418 VLOG_STATE(); 483 VLOG_STATE();
419 return ui::EVENT_REWRITE_REWRITTEN; 484 return ui::EVENT_REWRITE_REWRITTEN;
420 } 485 }
421 NOTREACHED() << "Unexpected event type received."; 486 NOTREACHED() << "Unexpected event type received.";
422 return ui::EVENT_REWRITE_CONTINUE; 487 return ui::EVENT_REWRITE_CONTINUE;
423 } 488 }
424 489
425 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( 490 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease(
426 const ui::TouchEvent& event, 491 const ui::TouchEvent& event,
427 scoped_ptr<ui::Event>* rewritten_event) { 492 scoped_ptr<ui::Event>* rewritten_event) {
428 ui::EventType type = event.type(); 493 ui::EventType type = event.type();
429 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || 494 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED ||
430 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { 495 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) {
431 NOTREACHED() << "Unexpected event type received."; 496 NOTREACHED() << "Unexpected event type received.";
432 return ui::EVENT_REWRITE_CONTINUE; 497 return ui::EVENT_REWRITE_CONTINUE;
433 } 498 }
434 if (current_touch_ids_.size() == 0) { 499 if (current_touch_ids_.size() == 0) {
435 state_ = NO_FINGERS_DOWN; 500 state_ = NO_FINGERS_DOWN;
501 VLOG_STATE();
436 ResetToNoFingersDown(); 502 ResetToNoFingersDown();
437 } 503 }
438 return EVENT_REWRITE_DISCARD; 504 return EVENT_REWRITE_DISCARD;
439 } 505 }
440 506
441 void TouchExplorationController::OnTapTimerFired() { 507 void TouchExplorationController::OnTapTimerFired() {
442 switch (state_) { 508 switch (state_) {
443 case SINGLE_TAP_RELEASED: 509 case SINGLE_TAP_RELEASED:
444 ResetToNoFingersDown(); 510 ResetToNoFingersDown();
445 break; 511 break;
446 case TOUCH_EXPLORE_RELEASED: 512 case TOUCH_EXPLORE_RELEASED:
447 ResetToNoFingersDown(); 513 ResetToNoFingersDown();
448 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 514 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
449 return; 515 return;
450 case SINGLE_TAP_PRESSED: 516 case SINGLE_TAP_PRESSED:
517 case GESTURE_IN_PROGRESS: {
518 // Discard any pending gestures.
519 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.
520 gesture_provider_.GetAndResetPendingGestures());
451 EnterTouchToMouseMode(); 521 EnterTouchToMouseMode();
452 state_ = TOUCH_EXPLORATION; 522 state_ = TOUCH_EXPLORATION;
453 VLOG_STATE(); 523 VLOG_STATE();
454 break; 524 } break;
455 default: 525 default:
456 return; 526 return;
457 } 527 }
458 528 scoped_ptr<ui::Event> mouse_move =
459 scoped_ptr<ui::Event> mouse_move = CreateMouseMoveEvent( 529 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags());
460 initial_press_->location(), initial_press_->flags());
461 DispatchEvent(mouse_move.get()); 530 DispatchEvent(mouse_move.get());
462 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 531 last_touch_exploration_.reset(new TouchEvent(*initial_press_));
463 } 532 }
464 533
465 void TouchExplorationController::DispatchEvent(ui::Event* event) { 534 void TouchExplorationController::DispatchEvent(ui::Event* event) {
466 if (event_handler_for_testing_) { 535 if (event_handler_for_testing_) {
467 event_handler_for_testing_->OnEvent(event); 536 event_handler_for_testing_->OnEvent(event);
468 return; 537 return;
469 } 538 }
470 ui::EventDispatchDetails result ALLOW_UNUSED = 539 ui::EventDispatchDetails result ALLOW_UNUSED =
471 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); 540 root_window_->GetHost()->dispatcher()->OnEventFromSource(event);
472 } 541 }
473 542
543 void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) {
544 if (tap_timer_.IsRunning())
545 tap_timer_.Stop();
546
547 CHECK(gesture->IsGestureEvent());
548 VLOG(0) << " \n Gesture Triggered: " << gesture->name();
549
550 if (gesture->type() == ui::ET_GESTURE_SWIPE) {
551 OnSwipeEvent(gesture);
552 return;
553 }
554 // If the event processed was not a swipe gesture, then determine the next
555 // state by the number of fingers currently down.
556 if (current_touch_ids_.size() == 0) {
557 ResetToNoFingersDown();
558 } else if (current_touch_ids_.size() == 1) {
559 EnterTouchToMouseMode();
560 state_ = TOUCH_EXPLORATION;
561 }
562 }
563
564 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
565 // A swipe gesture contains details for the direction in which the swipe
566 // occurred.
567 GestureEventDetails event_details = swipe_gesture->details();
568 if (event_details.swipe_left()) {
569 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT);
570 return;
571 } else if (event_details.swipe_right()) {
572 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT);
573 return;
574 } else if (event_details.swipe_up()) {
575 DispatchShiftSearchKeyEvent(ui::VKEY_UP);
576 return;
577 } else if (event_details.swipe_down()) {
578 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN);
579 return;
580 }
581 }
582
583 void TouchExplorationController::DispatchShiftSearchKeyEvent(
584 const ui::KeyboardCode direction) {
585 // In order to activate the shortcut shift+search+<arrow key>
586 // three KeyPressed events must be dispatched in succession along
587 // with three KeyReleased events.
588 DispatchEvent(new ui::KeyEvent(
589 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false));
590 DispatchEvent(new ui::KeyEvent(
591 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false));
592 DispatchEvent(new ui::KeyEvent(
593 ui::ET_KEY_PRESSED, direction, ui::EF_SHIFT_DOWN, false));
594
595 DispatchEvent(new ui::KeyEvent(
596 ui::ET_KEY_RELEASED, direction, ui::EF_SHIFT_DOWN, false));
597 DispatchEvent(new ui::KeyEvent(
598 ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false));
599 DispatchEvent(new ui::KeyEvent(
600 ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE, false));
601 }
602
474 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( 603 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent(
475 const gfx::PointF& location, 604 const gfx::PointF& location,
476 int flags) { 605 int flags) {
477 return scoped_ptr<ui::Event>( 606 return scoped_ptr<ui::Event>(
478 new ui::MouseEvent( 607 new ui::MouseEvent(
479 ui::ET_MOUSE_MOVED, 608 ui::ET_MOUSE_MOVED,
480 location, 609 location,
481 location, 610 location,
482 flags | ui::EF_IS_SYNTHESIZED | ui::EF_TOUCH_ACCESSIBILITY, 611 flags | ui::EF_IS_SYNTHESIZED | ui::EF_TOUCH_ACCESSIBILITY,
483 0)); 612 0));
484 } 613 }
485 614
486 void TouchExplorationController::EnterTouchToMouseMode() { 615 void TouchExplorationController::EnterTouchToMouseMode() {
487 aura::client::CursorClient* cursor_client = 616 aura::client::CursorClient* cursor_client =
488 aura::client::GetCursorClient(root_window_); 617 aura::client::GetCursorClient(root_window_);
489 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) 618 if (cursor_client && !cursor_client->IsMouseEventsEnabled())
490 cursor_client->EnableMouseEvents(); 619 cursor_client->EnableMouseEvents();
491 if (cursor_client && cursor_client->IsCursorVisible()) 620 if (cursor_client && cursor_client->IsCursorVisible())
492 cursor_client->HideCursor(); 621 cursor_client->HideCursor();
493 } 622 }
494 623
495 void TouchExplorationController::ResetToNoFingersDown() { 624 void TouchExplorationController::ResetToNoFingersDown() {
625 // Process the gestures.
626 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.
627 gestures.reset(gesture_provider_.GetAndResetPendingGestures());
628 if (gestures != NULL) {
aboxhall 2014/07/02 16:45:57 if (gestures) should work I think...
lisayin 2014/07/02 17:19:44 Done.
629 for (ScopedVector<GestureEvent>::iterator i = gestures->begin();
630 i != gestures->end();
631 ++i) {
632 OnGestureEvent(*i);
633 }
634 }
496 state_ = NO_FINGERS_DOWN; 635 state_ = NO_FINGERS_DOWN;
497 VLOG_STATE(); 636 VLOG_STATE();
498 if (tap_timer_.IsRunning()) 637 if (tap_timer_.IsRunning())
499 tap_timer_.Stop(); 638 tap_timer_.Stop();
500 } 639 }
501 640
502 void TouchExplorationController::VlogState(const char* function_name) { 641 void TouchExplorationController::VlogState(const char* function_name) {
503 if (prev_state_ == state_) 642 if (prev_state_ == state_)
504 return; 643 return;
505 prev_state_ = state_; 644 prev_state_ = state_;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 case SINGLE_TAP_PRESSED: 681 case SINGLE_TAP_PRESSED:
543 return "SINGLE_TAP_PRESSED"; 682 return "SINGLE_TAP_PRESSED";
544 case SINGLE_TAP_RELEASED: 683 case SINGLE_TAP_RELEASED:
545 return "SINGLE_TAP_RELEASED"; 684 return "SINGLE_TAP_RELEASED";
546 case TOUCH_EXPLORE_RELEASED: 685 case TOUCH_EXPLORE_RELEASED:
547 return "TOUCH_EXPLORE_RELEASED"; 686 return "TOUCH_EXPLORE_RELEASED";
548 case DOUBLE_TAP_PRESSED: 687 case DOUBLE_TAP_PRESSED:
549 return "DOUBLE_TAP_PRESSED"; 688 return "DOUBLE_TAP_PRESSED";
550 case TOUCH_EXPLORATION: 689 case TOUCH_EXPLORATION:
551 return "TOUCH_EXPLORATION"; 690 return "TOUCH_EXPLORATION";
691 case GESTURE_IN_PROGRESS:
692 return "GESTURE_IN_PROGRESS";
552 case TOUCH_EXPLORE_SECOND_PRESS: 693 case TOUCH_EXPLORE_SECOND_PRESS:
553 return "TOUCH_EXPLORE_SECOND_PRESS"; 694 return "TOUCH_EXPLORE_SECOND_PRESS";
554 case TWO_TO_ONE_FINGER: 695 case TWO_TO_ONE_FINGER:
555 return "TWO_TO_ONE_FINGER"; 696 return "TWO_TO_ONE_FINGER";
556 case PASSTHROUGH: 697 case PASSTHROUGH:
557 return "PASSTHROUGH"; 698 return "PASSTHROUGH";
558 case WAIT_FOR_RELEASE: 699 case WAIT_FOR_RELEASE:
559 return "WAIT_FOR_RELEASE"; 700 return "WAIT_FOR_RELEASE";
560 } 701 }
561 return "Not a state"; 702 return "Not a state";
562 } 703 }
563 704
564 } // namespace ui 705 } // namespace ui
OLDNEW
« 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