OLD | NEW |
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 { |
| 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 Loading... |
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); |
| 166 ProcessGestureEvents(); |
155 state_ = SINGLE_TAP_PRESSED; | 167 state_ = SINGLE_TAP_PRESSED; |
156 VLOG_STATE(); | 168 VLOG_STATE(); |
157 return ui::EVENT_REWRITE_DISCARD; | 169 return ui::EVENT_REWRITE_DISCARD; |
158 } | 170 } |
159 NOTREACHED() << "Unexpected event type received."; | 171 NOTREACHED() << "Unexpected event type received."; |
160 return ui::EVENT_REWRITE_CONTINUE; | 172 return ui::EVENT_REWRITE_CONTINUE; |
161 } | 173 } |
162 | 174 |
163 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 175 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
164 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 176 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
(...skipping 10 matching lines...) Expand all Loading... |
175 event.touch_id(), | 187 event.touch_id(), |
176 event.time_stamp())); | 188 event.time_stamp())); |
177 (*rewritten_event)->set_flags(event.flags()); | 189 (*rewritten_event)->set_flags(event.flags()); |
178 return EVENT_REWRITE_REWRITTEN; | 190 return EVENT_REWRITE_REWRITTEN; |
179 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 191 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
180 DCHECK_EQ(0U, current_touch_ids_.size()); | 192 DCHECK_EQ(0U, current_touch_ids_.size()); |
181 state_ = SINGLE_TAP_RELEASED; | 193 state_ = SINGLE_TAP_RELEASED; |
182 VLOG_STATE(); | 194 VLOG_STATE(); |
183 return EVENT_REWRITE_DISCARD; | 195 return EVENT_REWRITE_DISCARD; |
184 } else if (type == ui::ET_TOUCH_MOVED) { | 196 } else if (type == ui::ET_TOUCH_MOVED) { |
185 // If the user moves far enough from the initial touch location (outside | 197 float distance = (event.location() - initial_press_->location()).Length(); |
186 // the "slop" region, jump to the touch exploration mode early. | 198 // If the user does not move far enough from the original position, then the |
187 // TODO(evy, lisayin): Add gesture recognition here instead - | 199 // resulting movement should not be considered to be a deliberate gesture or |
188 // we should probably jump to gesture mode here if the velocity is | 200 // touch exploration. |
189 // high enough, and touch exploration if the velocity is lower. | 201 if (distance <= gesture_detector_config_.touch_slop) |
190 float delta = (event.location() - initial_press_->location()).Length(); | 202 return EVENT_REWRITE_DISCARD; |
191 if (delta > gesture_detector_config_.touch_slop) { | 203 |
192 EnterTouchToMouseMode(); | 204 float delta_time = |
193 state_ = TOUCH_EXPLORATION; | 205 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); |
| 206 float velocity = distance / delta_time; |
| 207 VLOG(0) << "\n Delta time: " << delta_time |
| 208 << "\n Distance: " << distance |
| 209 << "\n Velocity of click: " << velocity |
| 210 << "\n Minimum swipe velocity: " |
| 211 << gesture_detector_config_.minimum_swipe_velocity; |
| 212 |
| 213 // If the user moves fast enough from the initial touch location, start |
| 214 // gesture detection. Otherwise, jump to the touch exploration mode early. |
| 215 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
| 216 state_ = GESTURE_IN_PROGRESS; |
194 VLOG_STATE(); | 217 VLOG_STATE(); |
195 return InTouchExploration(event, rewritten_event); | 218 return InGestureInProgress(event, rewritten_event); |
196 } | 219 } |
197 return EVENT_REWRITE_DISCARD; | 220 EnterTouchToMouseMode(); |
| 221 state_ = TOUCH_EXPLORATION; |
| 222 VLOG_STATE(); |
| 223 return InTouchExploration(event, rewritten_event); |
198 } | 224 } |
199 NOTREACHED() << "Unexpected event type received."; | 225 NOTREACHED() << "Unexpected event type received."; |
200 return ui::EVENT_REWRITE_CONTINUE; | 226 return ui::EVENT_REWRITE_CONTINUE; |
201 } | 227 } |
202 | 228 |
203 ui::EventRewriteStatus | 229 ui::EventRewriteStatus |
204 TouchExplorationController::InSingleTapOrTouchExploreReleased( | 230 TouchExplorationController::InSingleTapOrTouchExploreReleased( |
205 const ui::TouchEvent& event, | 231 const ui::TouchEvent& event, |
206 scoped_ptr<ui::Event>* rewritten_event) { | 232 scoped_ptr<ui::Event>* rewritten_event) { |
207 const ui::EventType type = event.type(); | 233 const ui::EventType type = event.type(); |
| 234 // If there is more than one finger down, then discard to wait until only one |
| 235 // finger is or no fingers are down. |
| 236 if (current_touch_ids_.size() > 1) { |
| 237 state_ = WAIT_FOR_RELEASE; |
| 238 return ui::EVENT_REWRITE_DISCARD; |
| 239 } |
| 240 // If there is no touch exploration yet, discard. |
| 241 if (!last_touch_exploration_ || type == ui::ET_TOUCH_RELEASED) { |
| 242 if (current_touch_ids_.size() == 0) { |
| 243 ResetToNoFingersDown(); |
| 244 } |
| 245 return ui::EVENT_REWRITE_DISCARD; |
| 246 } |
| 247 |
208 if (type == ui::ET_TOUCH_PRESSED) { | 248 if (type == ui::ET_TOUCH_PRESSED) { |
209 // This is the second tap in a double-tap (or double tap-hold). | 249 // This is the second tap in a double-tap (or double tap-hold). |
210 // Rewrite at location of last touch exploration. | 250 // 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( | 251 rewritten_event->reset( |
216 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 252 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
217 last_touch_exploration_->location(), | 253 last_touch_exploration_->location(), |
218 event.touch_id(), | 254 event.touch_id(), |
219 event.time_stamp())); | 255 event.time_stamp())); |
220 (*rewritten_event)->set_flags(event.flags()); | 256 (*rewritten_event)->set_flags(event.flags()); |
221 state_ = DOUBLE_TAP_PRESSED; | 257 state_ = DOUBLE_TAP_PRESSED; |
222 VLOG_STATE(); | 258 VLOG_STATE(); |
223 return ui::EVENT_REWRITE_REWRITTEN; | 259 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 } | 260 } |
232 NOTREACHED() << "Unexpected event type received."; | 261 NOTREACHED() << "Unexpected event type received."; |
233 return ui::EVENT_REWRITE_CONTINUE; | 262 return ui::EVENT_REWRITE_CONTINUE; |
234 } | 263 } |
235 | 264 |
236 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed( | 265 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed( |
237 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 266 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
238 const ui::EventType type = event.type(); | 267 const ui::EventType type = event.type(); |
239 if (type == ui::ET_TOUCH_PRESSED) { | 268 if (type == ui::ET_TOUCH_PRESSED) { |
240 return ui::EVENT_REWRITE_DISCARD; | 269 return ui::EVENT_REWRITE_DISCARD; |
241 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 270 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
242 if (current_touch_ids_.size() != 0) | 271 if (current_touch_ids_.size() != 0) |
243 return EVENT_REWRITE_DISCARD; | 272 return EVENT_REWRITE_DISCARD; |
244 | 273 |
245 // Rewrite release at location of last touch exploration with the same | 274 // Rewrite release at location of last touch exploration with the same |
246 // id as the prevoius press. | 275 // id as the previous press. |
247 rewritten_event->reset( | 276 rewritten_event->reset( |
248 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 277 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
249 last_touch_exploration_->location(), | 278 last_touch_exploration_->location(), |
250 initial_press_->touch_id(), | 279 initial_press_->touch_id(), |
251 event.time_stamp())); | 280 event.time_stamp())); |
252 (*rewritten_event)->set_flags(event.flags()); | 281 (*rewritten_event)->set_flags(event.flags()); |
253 ResetToNoFingersDown(); | 282 ResetToNoFingersDown(); |
254 return ui::EVENT_REWRITE_REWRITTEN; | 283 return ui::EVENT_REWRITE_REWRITTEN; |
255 } else if (type == ui::ET_TOUCH_MOVED) { | 284 } else if (type == ui::ET_TOUCH_MOVED) { |
256 return ui::EVENT_REWRITE_DISCARD; | 285 return ui::EVENT_REWRITE_DISCARD; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 NOTREACHED() << "Unexpected event type received."; | 318 NOTREACHED() << "Unexpected event type received."; |
290 return ui::EVENT_REWRITE_CONTINUE; | 319 return ui::EVENT_REWRITE_CONTINUE; |
291 } | 320 } |
292 | 321 |
293 // Rewrite as a mouse-move event. | 322 // Rewrite as a mouse-move event. |
294 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); | 323 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); |
295 last_touch_exploration_.reset(new TouchEvent(event)); | 324 last_touch_exploration_.reset(new TouchEvent(event)); |
296 return ui::EVENT_REWRITE_REWRITTEN; | 325 return ui::EVENT_REWRITE_REWRITTEN; |
297 } | 326 } |
298 | 327 |
| 328 ui::EventRewriteStatus TouchExplorationController::InGestureInProgress( |
| 329 const ui::TouchEvent& event, |
| 330 scoped_ptr<ui::Event>* rewritten_event) { |
| 331 ui::EventType type = event.type(); |
| 332 // If additional fingers are added before a swipe gesture has been registered, |
| 333 // then the state will no longer be GESTURE_IN_PROGRESS. |
| 334 if (type == ui::ET_TOUCH_PRESSED || |
| 335 event.touch_id() != initial_press_->touch_id()) { |
| 336 if (tap_timer_.IsRunning()) |
| 337 tap_timer_.Stop(); |
| 338 // Discard any pending gestures. |
| 339 ignore_result(gesture_provider_.GetAndResetPendingGestures()); |
| 340 state_ = TWO_TO_ONE_FINGER; |
| 341 last_two_to_one_.reset(new TouchEvent(event)); |
| 342 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
| 343 event.location(), |
| 344 event.touch_id(), |
| 345 event.time_stamp())); |
| 346 (*rewritten_event)->set_flags(event.flags()); |
| 347 return EVENT_REWRITE_REWRITTEN; |
| 348 } |
| 349 |
| 350 // There should not be more than one finger down. |
| 351 DCHECK(current_touch_ids_.size() <= 1); |
| 352 if (type == ui::ET_TOUCH_MOVED) { |
| 353 gesture_provider_.OnTouchEvent(event); |
| 354 gesture_provider_.OnTouchEventAck(false); |
| 355 } |
| 356 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 357 gesture_provider_.OnTouchEvent(event); |
| 358 gesture_provider_.OnTouchEventAck(false); |
| 359 if (current_touch_ids_.size() == 0) |
| 360 ResetToNoFingersDown(); |
| 361 } |
| 362 |
| 363 ProcessGestureEvents(); |
| 364 return ui::EVENT_REWRITE_DISCARD; |
| 365 } |
299 | 366 |
300 ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( | 367 ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( |
301 const ui::TouchEvent& event, | 368 const ui::TouchEvent& event, |
302 scoped_ptr<ui::Event>* rewritten_event) { | 369 scoped_ptr<ui::Event>* rewritten_event) { |
303 // The user should only ever be in TWO_TO_ONE_FINGER with two fingers down. | 370 // 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. | 371 // If the user added or removed a finger, the state is changed. |
305 ui::EventType type = event.type(); | 372 ui::EventType type = event.type(); |
306 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 373 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
307 DCHECK(current_touch_ids_.size() == 1); | 374 DCHECK(current_touch_ids_.size() == 1); |
308 // Stop passing through the second finger and go to the wait state. | 375 // Stop passing through the second finger and go to the wait state. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 if (current_touch_ids_.size() != 1) | 474 if (current_touch_ids_.size() != 1) |
408 return EVENT_REWRITE_DISCARD; | 475 return EVENT_REWRITE_DISCARD; |
409 | 476 |
410 // Rewrite at location of last touch exploration. | 477 // Rewrite at location of last touch exploration. |
411 rewritten_event->reset( | 478 rewritten_event->reset( |
412 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 479 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
413 last_touch_exploration_->location(), | 480 last_touch_exploration_->location(), |
414 initial_press_->touch_id(), | 481 initial_press_->touch_id(), |
415 event.time_stamp())); | 482 event.time_stamp())); |
416 (*rewritten_event)->set_flags(event.flags()); | 483 (*rewritten_event)->set_flags(event.flags()); |
| 484 EnterTouchToMouseMode(); |
417 state_ = TOUCH_EXPLORATION; | 485 state_ = TOUCH_EXPLORATION; |
418 VLOG_STATE(); | 486 VLOG_STATE(); |
419 return ui::EVENT_REWRITE_REWRITTEN; | 487 return ui::EVENT_REWRITE_REWRITTEN; |
420 } | 488 } |
421 NOTREACHED() << "Unexpected event type received."; | 489 NOTREACHED() << "Unexpected event type received."; |
422 return ui::EVENT_REWRITE_CONTINUE; | 490 return ui::EVENT_REWRITE_CONTINUE; |
423 } | 491 } |
424 | 492 |
425 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( | 493 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( |
426 const ui::TouchEvent& event, | 494 const ui::TouchEvent& event, |
427 scoped_ptr<ui::Event>* rewritten_event) { | 495 scoped_ptr<ui::Event>* rewritten_event) { |
428 ui::EventType type = event.type(); | 496 ui::EventType type = event.type(); |
429 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || | 497 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || |
430 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { | 498 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { |
431 NOTREACHED() << "Unexpected event type received."; | 499 NOTREACHED() << "Unexpected event type received."; |
432 return ui::EVENT_REWRITE_CONTINUE; | 500 return ui::EVENT_REWRITE_CONTINUE; |
433 } | 501 } |
434 if (current_touch_ids_.size() == 0) { | 502 if (current_touch_ids_.size() == 0) { |
435 state_ = NO_FINGERS_DOWN; | 503 state_ = NO_FINGERS_DOWN; |
| 504 VLOG_STATE(); |
436 ResetToNoFingersDown(); | 505 ResetToNoFingersDown(); |
437 } | 506 } |
438 return EVENT_REWRITE_DISCARD; | 507 return EVENT_REWRITE_DISCARD; |
439 } | 508 } |
440 | 509 |
441 void TouchExplorationController::OnTapTimerFired() { | 510 void TouchExplorationController::OnTapTimerFired() { |
442 switch (state_) { | 511 switch (state_) { |
443 case SINGLE_TAP_RELEASED: | 512 case SINGLE_TAP_RELEASED: |
444 ResetToNoFingersDown(); | 513 ResetToNoFingersDown(); |
445 break; | 514 break; |
446 case TOUCH_EXPLORE_RELEASED: | 515 case TOUCH_EXPLORE_RELEASED: |
447 ResetToNoFingersDown(); | 516 ResetToNoFingersDown(); |
448 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 517 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
449 return; | 518 return; |
450 case SINGLE_TAP_PRESSED: | 519 case SINGLE_TAP_PRESSED: |
| 520 case GESTURE_IN_PROGRESS: |
| 521 // Discard any pending gestures. |
| 522 ignore_result(gesture_provider_.GetAndResetPendingGestures()); |
451 EnterTouchToMouseMode(); | 523 EnterTouchToMouseMode(); |
452 state_ = TOUCH_EXPLORATION; | 524 state_ = TOUCH_EXPLORATION; |
453 VLOG_STATE(); | 525 VLOG_STATE(); |
454 break; | 526 break; |
455 default: | 527 default: |
456 return; | 528 return; |
457 } | 529 } |
458 | 530 scoped_ptr<ui::Event> mouse_move = |
459 scoped_ptr<ui::Event> mouse_move = CreateMouseMoveEvent( | 531 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
460 initial_press_->location(), initial_press_->flags()); | |
461 DispatchEvent(mouse_move.get()); | 532 DispatchEvent(mouse_move.get()); |
462 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 533 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
463 } | 534 } |
464 | 535 |
465 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 536 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
466 if (event_handler_for_testing_) { | 537 if (event_handler_for_testing_) { |
467 event_handler_for_testing_->OnEvent(event); | 538 event_handler_for_testing_->OnEvent(event); |
468 return; | 539 return; |
469 } | 540 } |
470 ui::EventDispatchDetails result ALLOW_UNUSED = | 541 ui::EventDispatchDetails result ALLOW_UNUSED = |
471 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 542 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
472 } | 543 } |
473 | 544 |
| 545 void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) { |
| 546 CHECK(gesture->IsGestureEvent()); |
| 547 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); |
| 548 if (gesture->type() == ui::ET_GESTURE_SWIPE) { |
| 549 if (tap_timer_.IsRunning()) |
| 550 tap_timer_.Stop(); |
| 551 OnSwipeEvent(gesture); |
| 552 return; |
| 553 } |
| 554 } |
| 555 |
| 556 void TouchExplorationController::ProcessGestureEvents() { |
| 557 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( |
| 558 gesture_provider_.GetAndResetPendingGestures()); |
| 559 if (gestures) { |
| 560 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); |
| 561 i != gestures->end(); |
| 562 ++i) { |
| 563 OnGestureEvent(*i); |
| 564 } |
| 565 } |
| 566 } |
| 567 |
| 568 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { |
| 569 // A swipe gesture contains details for the direction in which the swipe |
| 570 // occurred. |
| 571 GestureEventDetails event_details = swipe_gesture->details(); |
| 572 if (event_details.swipe_left()) { |
| 573 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); |
| 574 return; |
| 575 } else if (event_details.swipe_right()) { |
| 576 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT); |
| 577 return; |
| 578 } else if (event_details.swipe_up()) { |
| 579 DispatchShiftSearchKeyEvent(ui::VKEY_UP); |
| 580 return; |
| 581 } else if (event_details.swipe_down()) { |
| 582 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN); |
| 583 return; |
| 584 } |
| 585 } |
| 586 |
| 587 void TouchExplorationController::DispatchShiftSearchKeyEvent( |
| 588 const ui::KeyboardCode direction) { |
| 589 // In order to activate the shortcut shift+search+<arrow key> |
| 590 // three KeyPressed events must be dispatched in succession along |
| 591 // with three KeyReleased events. |
| 592 ui::KeyEvent shift_down = ui::KeyEvent( |
| 593 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false); |
| 594 ui::KeyEvent search_down = ui::KeyEvent( |
| 595 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false); |
| 596 ui::KeyEvent direction_down = |
| 597 ui::KeyEvent(ui::ET_KEY_PRESSED, direction, ui::EF_SHIFT_DOWN, false); |
| 598 |
| 599 ui::KeyEvent direction_up = |
| 600 ui::KeyEvent(ui::ET_KEY_RELEASED, direction, ui::EF_SHIFT_DOWN, false); |
| 601 ui::KeyEvent search_up = ui::KeyEvent( |
| 602 ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false); |
| 603 ui::KeyEvent shift_up = |
| 604 ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE, false); |
| 605 |
| 606 DispatchEvent(&shift_down); |
| 607 DispatchEvent(&search_down); |
| 608 DispatchEvent(&direction_down); |
| 609 DispatchEvent(&direction_up); |
| 610 DispatchEvent(&search_up); |
| 611 DispatchEvent(&shift_up); |
| 612 } |
| 613 |
474 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( | 614 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( |
475 const gfx::PointF& location, | 615 const gfx::PointF& location, |
476 int flags) { | 616 int flags) { |
477 return scoped_ptr<ui::Event>( | 617 return scoped_ptr<ui::Event>( |
478 new ui::MouseEvent( | 618 new ui::MouseEvent( |
479 ui::ET_MOUSE_MOVED, | 619 ui::ET_MOUSE_MOVED, |
480 location, | 620 location, |
481 location, | 621 location, |
482 flags | ui::EF_IS_SYNTHESIZED | ui::EF_TOUCH_ACCESSIBILITY, | 622 flags | ui::EF_IS_SYNTHESIZED | ui::EF_TOUCH_ACCESSIBILITY, |
483 0)); | 623 0)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 case SINGLE_TAP_PRESSED: | 682 case SINGLE_TAP_PRESSED: |
543 return "SINGLE_TAP_PRESSED"; | 683 return "SINGLE_TAP_PRESSED"; |
544 case SINGLE_TAP_RELEASED: | 684 case SINGLE_TAP_RELEASED: |
545 return "SINGLE_TAP_RELEASED"; | 685 return "SINGLE_TAP_RELEASED"; |
546 case TOUCH_EXPLORE_RELEASED: | 686 case TOUCH_EXPLORE_RELEASED: |
547 return "TOUCH_EXPLORE_RELEASED"; | 687 return "TOUCH_EXPLORE_RELEASED"; |
548 case DOUBLE_TAP_PRESSED: | 688 case DOUBLE_TAP_PRESSED: |
549 return "DOUBLE_TAP_PRESSED"; | 689 return "DOUBLE_TAP_PRESSED"; |
550 case TOUCH_EXPLORATION: | 690 case TOUCH_EXPLORATION: |
551 return "TOUCH_EXPLORATION"; | 691 return "TOUCH_EXPLORATION"; |
| 692 case GESTURE_IN_PROGRESS: |
| 693 return "GESTURE_IN_PROGRESS"; |
552 case TOUCH_EXPLORE_SECOND_PRESS: | 694 case TOUCH_EXPLORE_SECOND_PRESS: |
553 return "TOUCH_EXPLORE_SECOND_PRESS"; | 695 return "TOUCH_EXPLORE_SECOND_PRESS"; |
554 case TWO_TO_ONE_FINGER: | 696 case TWO_TO_ONE_FINGER: |
555 return "TWO_TO_ONE_FINGER"; | 697 return "TWO_TO_ONE_FINGER"; |
556 case PASSTHROUGH: | 698 case PASSTHROUGH: |
557 return "PASSTHROUGH"; | 699 return "PASSTHROUGH"; |
558 case WAIT_FOR_RELEASE: | 700 case WAIT_FOR_RELEASE: |
559 return "WAIT_FOR_RELEASE"; | 701 return "WAIT_FOR_RELEASE"; |
560 } | 702 } |
561 return "Not a state"; | 703 return "Not a state"; |
562 } | 704 } |
563 | 705 |
564 } // namespace ui | 706 } // namespace ui |
OLD | NEW |