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 | |
26 TouchExplorationController::TouchExplorationController( | 21 TouchExplorationController::TouchExplorationController( |
27 aura::Window* root_window) | 22 aura::Window* root_window) |
28 : root_window_(root_window), | 23 : root_window_(root_window), |
29 state_(NO_FINGERS_DOWN), | 24 state_(NO_FINGERS_DOWN), |
30 event_handler_for_testing_(NULL), | 25 event_handler_for_testing_(NULL), |
31 gesture_provider_(this), | |
32 prev_state_(NO_FINGERS_DOWN) { | 26 prev_state_(NO_FINGERS_DOWN) { |
33 CHECK(root_window); | 27 CHECK(root_window); |
34 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 28 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
35 } | 29 } |
36 | 30 |
37 | 31 |
38 TouchExplorationController::~TouchExplorationController() { | 32 TouchExplorationController::~TouchExplorationController() { |
39 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 33 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
40 } | 34 } |
41 | 35 |
42 void TouchExplorationController::CallTapTimerNowForTesting() { | 36 void TouchExplorationController::CallTapTimerNowForTesting() { |
43 DCHECK(tap_timer_.IsRunning()); | 37 DCHECK(tap_timer_.IsRunning()); |
44 tap_timer_.Stop(); | 38 tap_timer_.Stop(); |
45 OnTapTimerFired(); | 39 OnTapTimerFired(); |
46 } | 40 } |
47 | 41 |
48 void TouchExplorationController::SetEventHandlerForTesting( | 42 void TouchExplorationController::SetEventHandlerForTesting( |
49 ui::EventHandler* event_handler_for_testing) { | 43 ui::EventHandler* event_handler_for_testing) { |
50 event_handler_for_testing_ = event_handler_for_testing; | 44 event_handler_for_testing_ = event_handler_for_testing; |
51 } | 45 } |
52 | 46 |
53 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const { | 47 bool TouchExplorationController::IsInNoFingersDownStateForTesting() const { |
54 return state_ == NO_FINGERS_DOWN; | 48 return state_ == NO_FINGERS_DOWN; |
55 } | 49 } |
56 | 50 |
57 bool TouchExplorationController::IsInGestureInProgressStateForTesting() const { | |
58 return state_ == GESTURE_IN_PROGRESS; | |
59 } | |
60 | |
61 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 51 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
62 const ui::Event& event, | 52 const ui::Event& event, |
63 scoped_ptr<ui::Event>* rewritten_event) { | 53 scoped_ptr<ui::Event>* rewritten_event) { |
64 if (!event.IsTouchEvent()) { | 54 if (!event.IsTouchEvent()) { |
65 if (event.IsKeyEvent()) { | 55 if (event.IsKeyEvent()) { |
66 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); | 56 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); |
67 VLOG(0) << "\nKeyboard event: " << key_event.name() << "\n" | 57 VLOG(0) << "\nKeyboard event: " << key_event.name() << "\n" |
68 << " Key code: " << key_event.key_code() | 58 << " Key code: " << key_event.key_code() |
69 << ", Flags: " << key_event.flags() | 59 << ", Flags: " << key_event.flags() |
70 << ", Is char: " << key_event.is_char(); | 60 << ", Is char: " << key_event.is_char(); |
71 } | 61 } |
| 62 if(event.IsGestureEvent()){ |
| 63 VLOG(0) << "\n Gesture event " << event.name(); |
| 64 } |
72 return ui::EVENT_REWRITE_CONTINUE; | 65 return ui::EVENT_REWRITE_CONTINUE; |
73 } | 66 } |
74 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); | 67 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); |
75 | 68 |
76 // If the tap timer should have fired by now but hasn't, run it now and | 69 // If the tap timer should have fired by now but hasn't, run it now and |
77 // stop the timer. This is important so that behavior is consistent with | 70 // stop the timer. This is important so that behavior is consistent with |
78 // the timestamps of the events, and not dependent on the granularity of | 71 // the timestamps of the events, and not dependent on the granularity of |
79 // the timer. | 72 // the timer. |
80 if (tap_timer_.IsRunning() && | 73 if (tap_timer_.IsRunning() && |
81 touch_event.time_stamp() - initial_press_->time_stamp() > | 74 touch_event.time_stamp() - initial_press_->time_stamp() > |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 return InNoFingersDown(touch_event, rewritten_event); | 116 return InNoFingersDown(touch_event, rewritten_event); |
124 case SINGLE_TAP_PRESSED: | 117 case SINGLE_TAP_PRESSED: |
125 return InSingleTapPressed(touch_event, rewritten_event); | 118 return InSingleTapPressed(touch_event, rewritten_event); |
126 case SINGLE_TAP_RELEASED: | 119 case SINGLE_TAP_RELEASED: |
127 case TOUCH_EXPLORE_RELEASED: | 120 case TOUCH_EXPLORE_RELEASED: |
128 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); | 121 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); |
129 case DOUBLE_TAP_PRESSED: | 122 case DOUBLE_TAP_PRESSED: |
130 return InDoubleTapPressed(touch_event, rewritten_event); | 123 return InDoubleTapPressed(touch_event, rewritten_event); |
131 case TOUCH_EXPLORATION: | 124 case TOUCH_EXPLORATION: |
132 return InTouchExploration(touch_event, rewritten_event); | 125 return InTouchExploration(touch_event, rewritten_event); |
133 case GESTURE_IN_PROGRESS: | |
134 return InGestureInProgress(touch_event, rewritten_event); | |
135 case TOUCH_EXPLORE_SECOND_PRESS: | 126 case TOUCH_EXPLORE_SECOND_PRESS: |
136 return InTouchExploreSecondPress(touch_event, rewritten_event); | 127 return InTouchExploreSecondPress(touch_event, rewritten_event); |
137 case TWO_TO_ONE_FINGER: | 128 case TWO_TO_ONE_FINGER: |
138 return InTwoToOneFinger(touch_event, rewritten_event); | 129 return InTwoToOneFinger(touch_event, rewritten_event); |
139 case PASSTHROUGH: | 130 case PASSTHROUGH: |
140 return InPassthrough(touch_event, rewritten_event); | 131 return InPassthrough(touch_event, rewritten_event); |
141 case WAIT_FOR_RELEASE: | 132 case WAIT_FOR_RELEASE: |
142 return InWaitForRelease(touch_event, rewritten_event); | 133 return InWaitForRelease(touch_event, rewritten_event); |
143 } | 134 } |
144 NOTREACHED(); | 135 NOTREACHED(); |
145 return ui::EVENT_REWRITE_CONTINUE; | 136 return ui::EVENT_REWRITE_CONTINUE; |
146 } | 137 } |
147 | 138 |
148 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 139 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
149 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 140 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
150 NOTREACHED(); | 141 NOTREACHED(); |
151 return ui::EVENT_REWRITE_CONTINUE; | 142 return ui::EVENT_REWRITE_CONTINUE; |
152 } | 143 } |
153 | 144 |
154 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( | 145 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
155 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 146 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
156 const ui::EventType type = event.type(); | 147 const ui::EventType type = event.type(); |
157 if (type == ui::ET_TOUCH_PRESSED) { | 148 if (type == ui::ET_TOUCH_PRESSED) { |
158 initial_press_.reset(new TouchEvent(event)); | 149 initial_press_.reset(new TouchEvent(event)); |
159 last_unused_finger_event_.reset(new TouchEvent(event)); | 150 last_unused_finger_event_.reset(new TouchEvent(event)); |
160 tap_timer_.Start(FROM_HERE, | 151 tap_timer_.Start(FROM_HERE, |
161 gesture_detector_config_.double_tap_timeout, | 152 gesture_detector_config_.double_tap_timeout, |
162 this, | 153 this, |
163 &TouchExplorationController::OnTapTimerFired); | 154 &TouchExplorationController::OnTapTimerFired); |
164 gesture_provider_.OnTouchEvent(event); | |
165 gesture_provider_.OnTouchEventAck(false); | |
166 ProcessGestureEvents(); | |
167 state_ = SINGLE_TAP_PRESSED; | 155 state_ = SINGLE_TAP_PRESSED; |
168 VLOG_STATE(); | 156 VLOG_STATE(); |
169 return ui::EVENT_REWRITE_DISCARD; | 157 return ui::EVENT_REWRITE_DISCARD; |
170 } | 158 } |
171 NOTREACHED() << "Unexpected event type received."; | 159 NOTREACHED() << "Unexpected event type received."; |
172 return ui::EVENT_REWRITE_CONTINUE; | 160 return ui::EVENT_REWRITE_CONTINUE; |
173 } | 161 } |
174 | 162 |
175 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 163 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
176 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 164 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
(...skipping 10 matching lines...) Expand all Loading... |
187 event.touch_id(), | 175 event.touch_id(), |
188 event.time_stamp())); | 176 event.time_stamp())); |
189 (*rewritten_event)->set_flags(event.flags()); | 177 (*rewritten_event)->set_flags(event.flags()); |
190 return EVENT_REWRITE_REWRITTEN; | 178 return EVENT_REWRITE_REWRITTEN; |
191 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 179 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
192 DCHECK_EQ(0U, current_touch_ids_.size()); | 180 DCHECK_EQ(0U, current_touch_ids_.size()); |
193 state_ = SINGLE_TAP_RELEASED; | 181 state_ = SINGLE_TAP_RELEASED; |
194 VLOG_STATE(); | 182 VLOG_STATE(); |
195 return EVENT_REWRITE_DISCARD; | 183 return EVENT_REWRITE_DISCARD; |
196 } else if (type == ui::ET_TOUCH_MOVED) { | 184 } else if (type == ui::ET_TOUCH_MOVED) { |
197 float distance = (event.location() - initial_press_->location()).Length(); | 185 // If the user moves far enough from the initial touch location (outside |
198 // If the user does not move far enough from the original position, then the | 186 // the "slop" region, jump to the touch exploration mode early. |
199 // resulting movement should not be considered to be a deliberate gesture or | 187 // TODO(evy, lisayin): Add gesture recognition here instead - |
200 // touch exploration. | 188 // we should probably jump to gesture mode here if the velocity is |
201 if (distance <= gesture_detector_config_.touch_slop) | 189 // high enough, and touch exploration if the velocity is lower. |
202 return EVENT_REWRITE_DISCARD; | 190 float delta = (event.location() - initial_press_->location()).Length(); |
203 | 191 if (delta > gesture_detector_config_.touch_slop) { |
204 float delta_time = | 192 EnterTouchToMouseMode(); |
205 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); | 193 state_ = TOUCH_EXPLORATION; |
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; | |
217 VLOG_STATE(); | 194 VLOG_STATE(); |
218 return InGestureInProgress(event, rewritten_event); | 195 return InTouchExploration(event, rewritten_event); |
219 } | 196 } |
220 EnterTouchToMouseMode(); | 197 return EVENT_REWRITE_DISCARD; |
221 state_ = TOUCH_EXPLORATION; | |
222 VLOG_STATE(); | |
223 return InTouchExploration(event, rewritten_event); | |
224 } | 198 } |
225 NOTREACHED() << "Unexpected event type received."; | 199 NOTREACHED() << "Unexpected event type received."; |
226 return ui::EVENT_REWRITE_CONTINUE; | 200 return ui::EVENT_REWRITE_CONTINUE; |
227 } | 201 } |
228 | 202 |
229 ui::EventRewriteStatus | 203 ui::EventRewriteStatus |
230 TouchExplorationController::InSingleTapOrTouchExploreReleased( | 204 TouchExplorationController::InSingleTapOrTouchExploreReleased( |
231 const ui::TouchEvent& event, | 205 const ui::TouchEvent& event, |
232 scoped_ptr<ui::Event>* rewritten_event) { | 206 scoped_ptr<ui::Event>* rewritten_event) { |
233 const ui::EventType type = event.type(); | 207 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 | |
248 if (type == ui::ET_TOUCH_PRESSED) { | 208 if (type == ui::ET_TOUCH_PRESSED) { |
249 // This is the second tap in a double-tap (or double tap-hold). | 209 // This is the second tap in a double-tap (or double tap-hold). |
250 // Rewrite at location of last touch exploration. | 210 // 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 } |
251 rewritten_event->reset( | 215 rewritten_event->reset( |
252 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 216 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
253 last_touch_exploration_->location(), | 217 last_touch_exploration_->location(), |
254 event.touch_id(), | 218 event.touch_id(), |
255 event.time_stamp())); | 219 event.time_stamp())); |
256 (*rewritten_event)->set_flags(event.flags()); | 220 (*rewritten_event)->set_flags(event.flags()); |
257 state_ = DOUBLE_TAP_PRESSED; | 221 state_ = DOUBLE_TAP_PRESSED; |
258 VLOG_STATE(); | 222 VLOG_STATE(); |
259 return ui::EVENT_REWRITE_REWRITTEN; | 223 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; |
260 } | 231 } |
261 NOTREACHED() << "Unexpected event type received."; | 232 NOTREACHED() << "Unexpected event type received."; |
262 return ui::EVENT_REWRITE_CONTINUE; | 233 return ui::EVENT_REWRITE_CONTINUE; |
263 } | 234 } |
264 | 235 |
265 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed( | 236 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed( |
266 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 237 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
267 const ui::EventType type = event.type(); | 238 const ui::EventType type = event.type(); |
268 if (type == ui::ET_TOUCH_PRESSED) { | 239 if (type == ui::ET_TOUCH_PRESSED) { |
269 return ui::EVENT_REWRITE_DISCARD; | 240 return ui::EVENT_REWRITE_DISCARD; |
270 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 241 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
271 if (current_touch_ids_.size() != 0) | 242 if (current_touch_ids_.size() != 0) |
272 return EVENT_REWRITE_DISCARD; | 243 return EVENT_REWRITE_DISCARD; |
273 | 244 |
274 // Rewrite release at location of last touch exploration with the same | 245 // Rewrite release at location of last touch exploration with the same |
275 // id as the previous press. | 246 // id as the prevoius press. |
276 rewritten_event->reset( | 247 rewritten_event->reset( |
277 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 248 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
278 last_touch_exploration_->location(), | 249 last_touch_exploration_->location(), |
279 initial_press_->touch_id(), | 250 initial_press_->touch_id(), |
280 event.time_stamp())); | 251 event.time_stamp())); |
281 (*rewritten_event)->set_flags(event.flags()); | 252 (*rewritten_event)->set_flags(event.flags()); |
282 ResetToNoFingersDown(); | 253 ResetToNoFingersDown(); |
283 return ui::EVENT_REWRITE_REWRITTEN; | 254 return ui::EVENT_REWRITE_REWRITTEN; |
284 } else if (type == ui::ET_TOUCH_MOVED) { | 255 } else if (type == ui::ET_TOUCH_MOVED) { |
285 return ui::EVENT_REWRITE_DISCARD; | 256 return ui::EVENT_REWRITE_DISCARD; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 NOTREACHED() << "Unexpected event type received."; | 289 NOTREACHED() << "Unexpected event type received."; |
319 return ui::EVENT_REWRITE_CONTINUE; | 290 return ui::EVENT_REWRITE_CONTINUE; |
320 } | 291 } |
321 | 292 |
322 // Rewrite as a mouse-move event. | 293 // Rewrite as a mouse-move event. |
323 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); | 294 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); |
324 last_touch_exploration_.reset(new TouchEvent(event)); | 295 last_touch_exploration_.reset(new TouchEvent(event)); |
325 return ui::EVENT_REWRITE_REWRITTEN; | 296 return ui::EVENT_REWRITE_REWRITTEN; |
326 } | 297 } |
327 | 298 |
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 } | |
366 | 299 |
367 ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( | 300 ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger( |
368 const ui::TouchEvent& event, | 301 const ui::TouchEvent& event, |
369 scoped_ptr<ui::Event>* rewritten_event) { | 302 scoped_ptr<ui::Event>* rewritten_event) { |
370 // The user should only ever be in TWO_TO_ONE_FINGER with two fingers down. | 303 // The user should only ever be in TWO_TO_ONE_FINGER with two fingers down. |
371 // If the user added or removed a finger, the state is changed. | 304 // If the user added or removed a finger, the state is changed. |
372 ui::EventType type = event.type(); | 305 ui::EventType type = event.type(); |
373 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 306 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
374 DCHECK(current_touch_ids_.size() == 1); | 307 DCHECK(current_touch_ids_.size() == 1); |
375 // Stop passing through the second finger and go to the wait state. | 308 // 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... |
474 if (current_touch_ids_.size() != 1) | 407 if (current_touch_ids_.size() != 1) |
475 return EVENT_REWRITE_DISCARD; | 408 return EVENT_REWRITE_DISCARD; |
476 | 409 |
477 // Rewrite at location of last touch exploration. | 410 // Rewrite at location of last touch exploration. |
478 rewritten_event->reset( | 411 rewritten_event->reset( |
479 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 412 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
480 last_touch_exploration_->location(), | 413 last_touch_exploration_->location(), |
481 initial_press_->touch_id(), | 414 initial_press_->touch_id(), |
482 event.time_stamp())); | 415 event.time_stamp())); |
483 (*rewritten_event)->set_flags(event.flags()); | 416 (*rewritten_event)->set_flags(event.flags()); |
484 EnterTouchToMouseMode(); | |
485 state_ = TOUCH_EXPLORATION; | 417 state_ = TOUCH_EXPLORATION; |
486 VLOG_STATE(); | 418 VLOG_STATE(); |
487 return ui::EVENT_REWRITE_REWRITTEN; | 419 return ui::EVENT_REWRITE_REWRITTEN; |
488 } | 420 } |
489 NOTREACHED() << "Unexpected event type received."; | 421 NOTREACHED() << "Unexpected event type received."; |
490 return ui::EVENT_REWRITE_CONTINUE; | 422 return ui::EVENT_REWRITE_CONTINUE; |
491 } | 423 } |
492 | 424 |
493 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( | 425 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( |
494 const ui::TouchEvent& event, | 426 const ui::TouchEvent& event, |
495 scoped_ptr<ui::Event>* rewritten_event) { | 427 scoped_ptr<ui::Event>* rewritten_event) { |
496 ui::EventType type = event.type(); | 428 ui::EventType type = event.type(); |
497 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || | 429 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || |
498 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { | 430 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { |
499 NOTREACHED() << "Unexpected event type received."; | 431 NOTREACHED() << "Unexpected event type received."; |
500 return ui::EVENT_REWRITE_CONTINUE; | 432 return ui::EVENT_REWRITE_CONTINUE; |
501 } | 433 } |
502 if (current_touch_ids_.size() == 0) { | 434 if (current_touch_ids_.size() == 0) { |
503 state_ = NO_FINGERS_DOWN; | 435 state_ = NO_FINGERS_DOWN; |
504 VLOG_STATE(); | |
505 ResetToNoFingersDown(); | 436 ResetToNoFingersDown(); |
506 } | 437 } |
507 return EVENT_REWRITE_DISCARD; | 438 return EVENT_REWRITE_DISCARD; |
508 } | 439 } |
509 | 440 |
510 void TouchExplorationController::OnTapTimerFired() { | 441 void TouchExplorationController::OnTapTimerFired() { |
511 switch (state_) { | 442 switch (state_) { |
512 case SINGLE_TAP_RELEASED: | 443 case SINGLE_TAP_RELEASED: |
513 ResetToNoFingersDown(); | 444 ResetToNoFingersDown(); |
514 break; | 445 break; |
515 case TOUCH_EXPLORE_RELEASED: | 446 case TOUCH_EXPLORE_RELEASED: |
516 ResetToNoFingersDown(); | 447 ResetToNoFingersDown(); |
517 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 448 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
518 return; | 449 return; |
519 case SINGLE_TAP_PRESSED: | 450 case SINGLE_TAP_PRESSED: |
520 case GESTURE_IN_PROGRESS: | |
521 // Discard any pending gestures. | |
522 ignore_result(gesture_provider_.GetAndResetPendingGestures()); | |
523 EnterTouchToMouseMode(); | 451 EnterTouchToMouseMode(); |
524 state_ = TOUCH_EXPLORATION; | 452 state_ = TOUCH_EXPLORATION; |
525 VLOG_STATE(); | 453 VLOG_STATE(); |
526 break; | 454 break; |
527 default: | 455 default: |
528 return; | 456 return; |
529 } | 457 } |
530 scoped_ptr<ui::Event> mouse_move = | 458 |
531 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 459 scoped_ptr<ui::Event> mouse_move = CreateMouseMoveEvent( |
| 460 initial_press_->location(), initial_press_->flags()); |
532 DispatchEvent(mouse_move.get()); | 461 DispatchEvent(mouse_move.get()); |
533 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 462 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
534 } | 463 } |
535 | 464 |
536 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 465 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
537 if (event_handler_for_testing_) { | 466 if (event_handler_for_testing_) { |
538 event_handler_for_testing_->OnEvent(event); | 467 event_handler_for_testing_->OnEvent(event); |
539 return; | 468 return; |
540 } | 469 } |
541 ui::EventDispatchDetails result ALLOW_UNUSED = | 470 ui::EventDispatchDetails result ALLOW_UNUSED = |
542 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 471 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
543 } | 472 } |
544 | 473 |
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 DispatchEvent(new ui::KeyEvent( | |
593 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN, false)); | |
594 DispatchEvent(new ui::KeyEvent( | |
595 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false)); | |
596 DispatchEvent(new ui::KeyEvent( | |
597 ui::ET_KEY_PRESSED, direction, ui::EF_SHIFT_DOWN, false)); | |
598 | |
599 DispatchEvent(new ui::KeyEvent( | |
600 ui::ET_KEY_RELEASED, direction, ui::EF_SHIFT_DOWN, false)); | |
601 DispatchEvent(new ui::KeyEvent( | |
602 ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN, false)); | |
603 DispatchEvent(new ui::KeyEvent( | |
604 ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE, false)); | |
605 } | |
606 | |
607 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( | 474 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( |
608 const gfx::PointF& location, | 475 const gfx::PointF& location, |
609 int flags) { | 476 int flags) { |
610 return scoped_ptr<ui::Event>( | 477 return scoped_ptr<ui::Event>( |
611 new ui::MouseEvent( | 478 new ui::MouseEvent( |
612 ui::ET_MOUSE_MOVED, | 479 ui::ET_MOUSE_MOVED, |
613 location, | 480 location, |
614 location, | 481 location, |
615 flags | ui::EF_IS_SYNTHESIZED | ui::EF_TOUCH_ACCESSIBILITY, | 482 flags | ui::EF_IS_SYNTHESIZED | ui::EF_TOUCH_ACCESSIBILITY, |
616 0)); | 483 0)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 case SINGLE_TAP_PRESSED: | 542 case SINGLE_TAP_PRESSED: |
676 return "SINGLE_TAP_PRESSED"; | 543 return "SINGLE_TAP_PRESSED"; |
677 case SINGLE_TAP_RELEASED: | 544 case SINGLE_TAP_RELEASED: |
678 return "SINGLE_TAP_RELEASED"; | 545 return "SINGLE_TAP_RELEASED"; |
679 case TOUCH_EXPLORE_RELEASED: | 546 case TOUCH_EXPLORE_RELEASED: |
680 return "TOUCH_EXPLORE_RELEASED"; | 547 return "TOUCH_EXPLORE_RELEASED"; |
681 case DOUBLE_TAP_PRESSED: | 548 case DOUBLE_TAP_PRESSED: |
682 return "DOUBLE_TAP_PRESSED"; | 549 return "DOUBLE_TAP_PRESSED"; |
683 case TOUCH_EXPLORATION: | 550 case TOUCH_EXPLORATION: |
684 return "TOUCH_EXPLORATION"; | 551 return "TOUCH_EXPLORATION"; |
685 case GESTURE_IN_PROGRESS: | |
686 return "GESTURE_IN_PROGRESS"; | |
687 case TOUCH_EXPLORE_SECOND_PRESS: | 552 case TOUCH_EXPLORE_SECOND_PRESS: |
688 return "TOUCH_EXPLORE_SECOND_PRESS"; | 553 return "TOUCH_EXPLORE_SECOND_PRESS"; |
689 case TWO_TO_ONE_FINGER: | 554 case TWO_TO_ONE_FINGER: |
690 return "TWO_TO_ONE_FINGER"; | 555 return "TWO_TO_ONE_FINGER"; |
691 case PASSTHROUGH: | 556 case PASSTHROUGH: |
692 return "PASSTHROUGH"; | 557 return "PASSTHROUGH"; |
693 case WAIT_FOR_RELEASE: | 558 case WAIT_FOR_RELEASE: |
694 return "WAIT_FOR_RELEASE"; | 559 return "WAIT_FOR_RELEASE"; |
695 } | 560 } |
696 return "Not a state"; | 561 return "Not a state"; |
697 } | 562 } |
698 | 563 |
699 } // namespace ui | 564 } // namespace ui |
OLD | NEW |