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 "base/time/default_tick_clock.h" | 9 #include "base/time/default_tick_clock.h" |
10 #include "ui/aura/client/cursor_client.h" | 10 #include "ui/aura/client/cursor_client.h" |
11 #include "ui/aura/window.h" | 11 #include "ui/aura/window.h" |
12 #include "ui/aura/window_event_dispatcher.h" | 12 #include "ui/aura/window_event_dispatcher.h" |
13 #include "ui/aura/window_tree_host.h" | 13 #include "ui/aura/window_tree_host.h" |
14 #include "ui/events/event.h" | 14 #include "ui/events/event.h" |
15 #include "ui/events/event_processor.h" | 15 #include "ui/events/event_processor.h" |
16 #include "ui/events/event_utils.h" | 16 #include "ui/events/event_utils.h" |
17 #include "ui/gfx/geometry/rect.h" | 17 #include "ui/gfx/geometry/rect.h" |
18 | 18 |
19 #define SET_STATE(state) SetState(state, __func__) | 19 #define SET_STATE(state) SetState(state, __func__) |
20 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) | 20 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) |
21 | 21 |
22 namespace ui { | 22 namespace ui { |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
26 // Delay between adjustment sounds. | 26 // Delay between adjustment sounds. |
27 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); | 27 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
28 | 28 |
| 29 // Delay before corner passthrough activates. |
| 30 const base::TimeDelta kCornerPassthroughDelay = |
| 31 base::TimeDelta::FromMilliseconds(700); |
| 32 |
29 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | 33 // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
30 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | 34 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
31 } // namespace | 35 } // namespace |
32 | 36 |
33 TouchExplorationController::TouchExplorationController( | 37 TouchExplorationController::TouchExplorationController( |
34 aura::Window* root_window, | 38 aura::Window* root_window, |
35 TouchExplorationControllerDelegate* delegate) | 39 TouchExplorationControllerDelegate* delegate) |
36 : root_window_(root_window), | 40 : root_window_(root_window), |
37 delegate_(delegate), | 41 delegate_(delegate), |
38 state_(NO_FINGERS_DOWN), | 42 state_(NO_FINGERS_DOWN), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 // the timer. | 74 // the timer. |
71 if (tap_timer_.IsRunning() && | 75 if (tap_timer_.IsRunning() && |
72 touch_event.time_stamp() - initial_press_->time_stamp() > | 76 touch_event.time_stamp() - initial_press_->time_stamp() > |
73 gesture_detector_config_.double_tap_timeout) { | 77 gesture_detector_config_.double_tap_timeout) { |
74 tap_timer_.Stop(); | 78 tap_timer_.Stop(); |
75 OnTapTimerFired(); | 79 OnTapTimerFired(); |
76 // Note: this may change the state. We should now continue and process | 80 // Note: this may change the state. We should now continue and process |
77 // this event under this new state. | 81 // this event under this new state. |
78 } | 82 } |
79 | 83 |
| 84 if (passthrough_timer_.IsRunning() && |
| 85 event.time_stamp() - initial_press_->time_stamp() > |
| 86 gesture_detector_config_.longpress_timeout) { |
| 87 passthrough_timer_.Stop(); |
| 88 OnPassthroughTimerFired(); |
| 89 } |
| 90 |
80 const ui::EventType type = touch_event.type(); | 91 const ui::EventType type = touch_event.type(); |
81 const gfx::PointF& location = touch_event.location_f(); | 92 const gfx::PointF& location = touch_event.location_f(); |
82 const int touch_id = touch_event.touch_id(); | 93 const int touch_id = touch_event.touch_id(); |
83 | 94 |
84 // Always update touch ids and touch locations, so we can use those | 95 // Always update touch ids and touch locations, so we can use those |
85 // no matter what state we're in. | 96 // no matter what state we're in. |
86 if (type == ui::ET_TOUCH_PRESSED) { | 97 if (type == ui::ET_TOUCH_PRESSED) { |
87 current_touch_ids_.push_back(touch_id); | 98 current_touch_ids_.push_back(touch_id); |
88 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); | 99 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); |
89 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 100 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
(...skipping 19 matching lines...) Expand all Loading... |
109 NOTREACHED() << "Unexpected event type received: " << event.name(); | 120 NOTREACHED() << "Unexpected event type received: " << event.name(); |
110 return ui::EVENT_REWRITE_CONTINUE; | 121 return ui::EVENT_REWRITE_CONTINUE; |
111 } | 122 } |
112 VLOG_EVENT(touch_event); | 123 VLOG_EVENT(touch_event); |
113 | 124 |
114 // In order to avoid accidentally double tapping when moving off the edge | 125 // In order to avoid accidentally double tapping when moving off the edge |
115 // of the screen, the state will be rewritten to NoFingersDown. | 126 // of the screen, the state will be rewritten to NoFingersDown. |
116 if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) && | 127 if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) && |
117 FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != | 128 FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != |
118 NO_EDGE) { | 129 NO_EDGE) { |
| 130 if (VLOG_on_) |
| 131 VLOG(0) << "Leaving screen"; |
| 132 |
| 133 // Indicates to the user that they are leaving the screen. |
| 134 delegate_->PlayExitScreenEarcon(); |
| 135 |
119 if (current_touch_ids_.size() == 0) { | 136 if (current_touch_ids_.size() == 0) { |
120 SET_STATE(NO_FINGERS_DOWN); | 137 SET_STATE(NO_FINGERS_DOWN); |
121 if (VLOG_on_) { | 138 if (VLOG_on_) { |
122 VLOG(0) << "Reset to no fingers in Rewrite event because the touch " | 139 VLOG(0) << "Reset to no fingers in Rewrite event because the touch " |
123 "release or cancel was on the edge of the screen."; | 140 "release or cancel was on the edge of the screen."; |
124 } | 141 } |
125 return ui::EVENT_REWRITE_DISCARD; | 142 return ui::EVENT_REWRITE_DISCARD; |
126 } | 143 } |
127 } | 144 } |
128 | 145 |
(...skipping 20 matching lines...) Expand all Loading... |
149 case DOUBLE_TAP_PENDING: | 166 case DOUBLE_TAP_PENDING: |
150 return InDoubleTapPending(touch_event, rewritten_event); | 167 return InDoubleTapPending(touch_event, rewritten_event); |
151 case TOUCH_RELEASE_PENDING: | 168 case TOUCH_RELEASE_PENDING: |
152 return InTouchReleasePending(touch_event, rewritten_event); | 169 return InTouchReleasePending(touch_event, rewritten_event); |
153 case TOUCH_EXPLORATION: | 170 case TOUCH_EXPLORATION: |
154 return InTouchExploration(touch_event, rewritten_event); | 171 return InTouchExploration(touch_event, rewritten_event); |
155 case GESTURE_IN_PROGRESS: | 172 case GESTURE_IN_PROGRESS: |
156 return InGestureInProgress(touch_event, rewritten_event); | 173 return InGestureInProgress(touch_event, rewritten_event); |
157 case TOUCH_EXPLORE_SECOND_PRESS: | 174 case TOUCH_EXPLORE_SECOND_PRESS: |
158 return InTouchExploreSecondPress(touch_event, rewritten_event); | 175 return InTouchExploreSecondPress(touch_event, rewritten_event); |
| 176 case CORNER_PASSTHROUGH: |
| 177 return InCornerPassthrough(touch_event, rewritten_event); |
159 case SLIDE_GESTURE: | 178 case SLIDE_GESTURE: |
160 return InSlideGesture(touch_event, rewritten_event); | 179 return InSlideGesture(touch_event, rewritten_event); |
161 case ONE_FINGER_PASSTHROUGH: | 180 case ONE_FINGER_PASSTHROUGH: |
162 return InOneFingerPassthrough(touch_event, rewritten_event); | 181 return InOneFingerPassthrough(touch_event, rewritten_event); |
163 case WAIT_FOR_NO_FINGERS: | 182 case WAIT_FOR_NO_FINGERS: |
164 return InWaitForNoFingers(touch_event, rewritten_event); | 183 return InWaitForNoFingers(touch_event, rewritten_event); |
165 case TWO_FINGER_TAP: | 184 case TWO_FINGER_TAP: |
166 return InTwoFingerTap(touch_event, rewritten_event); | 185 return InTwoFingerTap(touch_event, rewritten_event); |
167 } | 186 } |
168 NOTREACHED(); | 187 NOTREACHED(); |
169 return ui::EVENT_REWRITE_CONTINUE; | 188 return ui::EVENT_REWRITE_CONTINUE; |
170 } | 189 } |
171 | 190 |
172 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 191 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
173 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 192 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
174 NOTREACHED(); | 193 NOTREACHED(); |
175 return ui::EVENT_REWRITE_CONTINUE; | 194 return ui::EVENT_REWRITE_CONTINUE; |
176 } | 195 } |
177 | 196 |
178 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( | 197 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
179 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 198 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
180 ui::EventType type = event.type(); | 199 const ui::EventType type = event.type(); |
181 if (type == ui::ET_TOUCH_PRESSED) { | 200 if (type != ui::ET_TOUCH_PRESSED) { |
182 initial_press_.reset(new TouchEvent(event)); | 201 NOTREACHED() << "Unexpected event type received: " << event.name(); |
183 initial_presses_[event.touch_id()] = event.location(); | 202 return ui::EVENT_REWRITE_CONTINUE; |
184 last_unused_finger_event_.reset(new TouchEvent(event)); | |
185 StartTapTimer(); | |
186 SET_STATE(SINGLE_TAP_PRESSED); | |
187 return ui::EVENT_REWRITE_DISCARD; | |
188 } | 203 } |
189 NOTREACHED() << "Unexpected event type received: " << event.name(); | 204 |
190 return ui::EVENT_REWRITE_CONTINUE; | 205 // If the user enters the screen from the edge then send an earcon. |
| 206 int edge = FindEdgesWithinBounds(event.location(), kLeavingScreenEdge); |
| 207 if (edge != NO_EDGE) |
| 208 delegate_->PlayEnterScreenEarcon(); |
| 209 |
| 210 int location = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
| 211 // If the press was at a corner, the user might go into corner passthrough |
| 212 // instead. |
| 213 bool in_a_bottom_corner = |
| 214 (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location); |
| 215 if (in_a_bottom_corner) { |
| 216 passthrough_timer_.Start( |
| 217 FROM_HERE, |
| 218 gesture_detector_config_.longpress_timeout, |
| 219 this, |
| 220 &TouchExplorationController::OnPassthroughTimerFired); |
| 221 } |
| 222 initial_press_.reset(new TouchEvent(event)); |
| 223 initial_presses_[event.touch_id()] = event.location(); |
| 224 last_unused_finger_event_.reset(new TouchEvent(event)); |
| 225 StartTapTimer(); |
| 226 SET_STATE(SINGLE_TAP_PRESSED); |
| 227 return ui::EVENT_REWRITE_DISCARD; |
191 } | 228 } |
192 | 229 |
193 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 230 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
194 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 231 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
195 const ui::EventType type = event.type(); | 232 const ui::EventType type = event.type(); |
196 | 233 |
| 234 int location = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
| 235 bool in_a_bottom_corner = |
| 236 (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER); |
| 237 // If the event is from the initial press and the location is no longer in the |
| 238 // corner, then we are not waiting for a corner passthrough anymore. |
| 239 if (event.touch_id() == initial_press_->touch_id() && !in_a_bottom_corner) { |
| 240 if (passthrough_timer_.IsRunning()) { |
| 241 passthrough_timer_.Stop(); |
| 242 // Since the long press timer has been running, it is possible that the |
| 243 // tap timer has timed out before the long press timer has. If the tap |
| 244 // timer timeout has elapsed, then fire the tap timer. |
| 245 if (event.time_stamp() - initial_press_->time_stamp() > |
| 246 gesture_detector_config_.double_tap_timeout) { |
| 247 OnTapTimerFired(); |
| 248 } |
| 249 } |
| 250 } |
| 251 |
197 if (type == ui::ET_TOUCH_PRESSED) { | 252 if (type == ui::ET_TOUCH_PRESSED) { |
198 initial_presses_[event.touch_id()] = event.location(); | 253 initial_presses_[event.touch_id()] = event.location(); |
199 SET_STATE(TWO_FINGER_TAP); | 254 SET_STATE(TWO_FINGER_TAP); |
200 return EVENT_REWRITE_DISCARD; | 255 return EVENT_REWRITE_DISCARD; |
201 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 256 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 257 if (passthrough_timer_.IsRunning()) |
| 258 passthrough_timer_.Stop(); |
202 if (current_touch_ids_.size() == 0 && | 259 if (current_touch_ids_.size() == 0 && |
203 event.touch_id() == initial_press_->touch_id()) { | 260 event.touch_id() == initial_press_->touch_id()) { |
204 SET_STATE(SINGLE_TAP_RELEASED); | 261 SET_STATE(SINGLE_TAP_RELEASED); |
205 } else if (current_touch_ids_.size() == 0) { | 262 } else if (current_touch_ids_.size() == 0) { |
206 SET_STATE(NO_FINGERS_DOWN); | 263 SET_STATE(NO_FINGERS_DOWN); |
207 } | 264 } |
208 return EVENT_REWRITE_DISCARD; | 265 return EVENT_REWRITE_DISCARD; |
209 } else if (type == ui::ET_TOUCH_MOVED) { | 266 } else if (type == ui::ET_TOUCH_MOVED) { |
210 float distance = (event.location() - initial_press_->location()).Length(); | 267 float distance = (event.location() - initial_press_->location()).Length(); |
211 // If the user does not move far enough from the original position, then the | 268 // If the user does not move far enough from the original position, then the |
212 // resulting movement should not be considered to be a deliberate gesture or | 269 // resulting movement should not be considered to be a deliberate gesture or |
213 // touch exploration. | 270 // touch exploration. |
214 if (distance <= gesture_detector_config_.touch_slop) | 271 if (distance <= gesture_detector_config_.touch_slop) |
215 return EVENT_REWRITE_DISCARD; | 272 return EVENT_REWRITE_DISCARD; |
216 | 273 |
217 float delta_time = | 274 float delta_time = |
218 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); | 275 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); |
219 float velocity = distance / delta_time; | 276 float velocity = distance / delta_time; |
220 if (VLOG_on_) { | 277 if (VLOG_on_) { |
221 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance | 278 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance |
222 << "\n Velocity of click: " << velocity | 279 << "\n Velocity of click: " << velocity |
223 << "\n Minimum swipe velocity: " | 280 << "\n Minimum swipe velocity: " |
224 << gesture_detector_config_.minimum_swipe_velocity; | 281 << gesture_detector_config_.minimum_swipe_velocity; |
225 } | 282 } |
226 // Change to slide gesture if the slide occurred at the right edge. | 283 // Change to slide gesture if the slide occurred at the right edge. |
227 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); | 284 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
228 if (edge & RIGHT_EDGE) { | 285 if (edge & RIGHT_EDGE && edge != BOTTOM_RIGHT_CORNER) { |
229 SET_STATE(SLIDE_GESTURE); | 286 SET_STATE(SLIDE_GESTURE); |
230 return InSlideGesture(event, rewritten_event); | 287 return InSlideGesture(event, rewritten_event); |
231 } | 288 } |
232 | 289 |
233 // If the user moves fast enough from the initial touch location, start | 290 // If the user moves fast enough from the initial touch location, start |
234 // gesture detection. Otherwise, jump to the touch exploration mode early. | 291 // gesture detection. Otherwise, jump to the touch exploration mode early. |
235 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { | 292 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
236 SET_STATE(GESTURE_IN_PROGRESS); | 293 SET_STATE(GESTURE_IN_PROGRESS); |
237 return InGestureInProgress(event, rewritten_event); | 294 return InGestureInProgress(event, rewritten_event); |
238 } | 295 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 // The events were sent to the gesture provider in RewriteEvent already. | 444 // The events were sent to the gesture provider in RewriteEvent already. |
388 // If no gesture is registered before the tap timer times out, the state | 445 // If no gesture is registered before the tap timer times out, the state |
389 // will change to "wait for no fingers down" or "touch exploration" depending | 446 // will change to "wait for no fingers down" or "touch exploration" depending |
390 // on the number of fingers down, and this function will stop being called. | 447 // on the number of fingers down, and this function will stop being called. |
391 if (current_touch_ids_.size() == 0) { | 448 if (current_touch_ids_.size() == 0) { |
392 SET_STATE(NO_FINGERS_DOWN); | 449 SET_STATE(NO_FINGERS_DOWN); |
393 } | 450 } |
394 return ui::EVENT_REWRITE_DISCARD; | 451 return ui::EVENT_REWRITE_DISCARD; |
395 } | 452 } |
396 | 453 |
| 454 ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough( |
| 455 const ui::TouchEvent& event, |
| 456 scoped_ptr<ui::Event>* rewritten_event) { |
| 457 ui::EventType type = event.type(); |
| 458 |
| 459 // If the first finger has left the corner, then exit passthrough. |
| 460 if (event.touch_id() == initial_press_->touch_id()) { |
| 461 int edges = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
| 462 bool in_a_bottom_corner = (edges == BOTTOM_LEFT_CORNER) || |
| 463 (edges == BOTTOM_RIGHT_CORNER); |
| 464 if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner) |
| 465 return ui::EVENT_REWRITE_DISCARD; |
| 466 |
| 467 if (current_touch_ids_.size() == 0) { |
| 468 SET_STATE(NO_FINGERS_DOWN); |
| 469 return ui::EVENT_REWRITE_DISCARD; |
| 470 } |
| 471 SET_STATE(WAIT_FOR_NO_FINGERS); |
| 472 return ui::EVENT_REWRITE_DISCARD; |
| 473 } |
| 474 |
| 475 rewritten_event->reset(new ui::TouchEvent( |
| 476 type, event.location(), event.touch_id(), event.time_stamp())); |
| 477 (*rewritten_event)->set_flags(event.flags()); |
| 478 |
| 479 if (current_touch_ids_.size() == 0) |
| 480 SET_STATE(NO_FINGERS_DOWN); |
| 481 |
| 482 return ui::EVENT_REWRITE_REWRITTEN; |
| 483 } |
| 484 |
397 ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( | 485 ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( |
398 const ui::TouchEvent& event, | 486 const ui::TouchEvent& event, |
399 scoped_ptr<ui::Event>* rewritten_event) { | 487 scoped_ptr<ui::Event>* rewritten_event) { |
400 if (event.touch_id() != initial_press_->touch_id()) { | 488 if (event.touch_id() != initial_press_->touch_id()) { |
401 if (current_touch_ids_.size() == 0) { | 489 if (current_touch_ids_.size() == 0) { |
402 SET_STATE(NO_FINGERS_DOWN); | 490 SET_STATE(NO_FINGERS_DOWN); |
403 } | 491 } |
404 return ui::EVENT_REWRITE_DISCARD; | 492 return ui::EVENT_REWRITE_DISCARD; |
405 } | 493 } |
406 rewritten_event->reset( | 494 rewritten_event->reset( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 | 546 |
459 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( | 547 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( |
460 const ui::TouchEvent& event, | 548 const ui::TouchEvent& event, |
461 scoped_ptr<ui::Event>* rewritten_event) { | 549 scoped_ptr<ui::Event>* rewritten_event) { |
462 if (current_touch_ids_.size() == 0) | 550 if (current_touch_ids_.size() == 0) |
463 SET_STATE(NO_FINGERS_DOWN); | 551 SET_STATE(NO_FINGERS_DOWN); |
464 return EVENT_REWRITE_DISCARD; | 552 return EVENT_REWRITE_DISCARD; |
465 } | 553 } |
466 | 554 |
467 void TouchExplorationController::PlaySoundForTimer() { | 555 void TouchExplorationController::PlaySoundForTimer() { |
468 delegate_->PlayVolumeAdjustSound(); | 556 delegate_->PlayVolumeAdjustEarcon(); |
469 } | 557 } |
470 | 558 |
471 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | 559 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
472 const ui::TouchEvent& event, | 560 const ui::TouchEvent& event, |
473 scoped_ptr<ui::Event>* rewritten_event) { | 561 scoped_ptr<ui::Event>* rewritten_event) { |
474 // The timer should not fire when sliding. | 562 // The timer should not fire when sliding. |
475 tap_timer_.Stop(); | 563 tap_timer_.Stop(); |
476 | 564 |
477 ui::EventType type = event.type(); | 565 ui::EventType type = event.type(); |
478 // If additional fingers are added before a swipe gesture has been registered, | 566 // If additional fingers are added before a swipe gesture has been registered, |
(...skipping 19 matching lines...) Expand all Loading... |
498 return EVENT_REWRITE_DISCARD; | 586 return EVENT_REWRITE_DISCARD; |
499 } | 587 } |
500 | 588 |
501 // This can occur if the user leaves the screen edge and then returns to it to | 589 // This can occur if the user leaves the screen edge and then returns to it to |
502 // continue adjusting the sound. | 590 // continue adjusting the sound. |
503 if (!sound_timer_.IsRunning()) { | 591 if (!sound_timer_.IsRunning()) { |
504 sound_timer_.Start(FROM_HERE, | 592 sound_timer_.Start(FROM_HERE, |
505 kSoundDelay, | 593 kSoundDelay, |
506 this, | 594 this, |
507 &ui::TouchExplorationController::PlaySoundForTimer); | 595 &ui::TouchExplorationController::PlaySoundForTimer); |
508 delegate_->PlayVolumeAdjustSound(); | 596 delegate_->PlayVolumeAdjustEarcon(); |
509 } | 597 } |
510 | 598 |
511 if (current_touch_ids_.size() == 0) { | 599 if (current_touch_ids_.size() == 0) { |
512 SET_STATE(NO_FINGERS_DOWN); | 600 SET_STATE(NO_FINGERS_DOWN); |
513 } | 601 } |
514 return ui::EVENT_REWRITE_DISCARD; | 602 return ui::EVENT_REWRITE_DISCARD; |
515 } | 603 } |
516 | 604 |
517 ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( | 605 ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( |
518 const ui::TouchEvent& event, | 606 const ui::TouchEvent& event, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 last_touch_exploration_->location(); | 673 last_touch_exploration_->location(); |
586 scoped_ptr<ui::TouchEvent> passthrough_press( | 674 scoped_ptr<ui::TouchEvent> passthrough_press( |
587 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 675 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
588 last_touch_exploration_->location(), | 676 last_touch_exploration_->location(), |
589 last_unused_finger_event_->touch_id(), | 677 last_unused_finger_event_->touch_id(), |
590 Now())); | 678 Now())); |
591 DispatchEvent(passthrough_press.get()); | 679 DispatchEvent(passthrough_press.get()); |
592 return; | 680 return; |
593 } | 681 } |
594 case SINGLE_TAP_PRESSED: | 682 case SINGLE_TAP_PRESSED: |
595 EnterTouchToMouseMode(); | 683 if (passthrough_timer_.IsRunning()) |
596 SET_STATE(TOUCH_EXPLORATION); | 684 return; |
597 break; | |
598 case GESTURE_IN_PROGRESS: | 685 case GESTURE_IN_PROGRESS: |
599 // If only one finger is down, go into touch exploration. | 686 // If only one finger is down, go into touch exploration. |
600 if (current_touch_ids_.size() == 1) { | 687 if (current_touch_ids_.size() == 1) { |
601 EnterTouchToMouseMode(); | |
602 SET_STATE(TOUCH_EXPLORATION); | 688 SET_STATE(TOUCH_EXPLORATION); |
603 break; | 689 break; |
604 } | 690 } |
605 // Otherwise wait for all fingers to be lifted. | 691 // Otherwise wait for all fingers to be lifted. |
606 SET_STATE(WAIT_FOR_NO_FINGERS); | 692 SET_STATE(WAIT_FOR_NO_FINGERS); |
607 return; | 693 return; |
608 case TWO_FINGER_TAP: | 694 case TWO_FINGER_TAP: |
609 SET_STATE(WAIT_FOR_NO_FINGERS); | 695 SET_STATE(WAIT_FOR_NO_FINGERS); |
610 break; | 696 break; |
611 default: | 697 default: |
612 return; | 698 return; |
613 } | 699 } |
614 EnterTouchToMouseMode(); | 700 EnterTouchToMouseMode(); |
615 scoped_ptr<ui::Event> mouse_move = | 701 scoped_ptr<ui::Event> mouse_move = |
616 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 702 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
617 DispatchEvent(mouse_move.get()); | 703 DispatchEvent(mouse_move.get()); |
618 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 704 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
619 } | 705 } |
620 | 706 |
| 707 void TouchExplorationController::OnPassthroughTimerFired() { |
| 708 // The passthrough timer will only fire if if the user has held a finger in |
| 709 // one of the passthrough corners for the duration of the passthrough timeout. |
| 710 |
| 711 // Check that initial press isn't null. Also a check that if the initial |
| 712 // corner press was released, then it should not be in corner passthrough. |
| 713 if (!initial_press_ || |
| 714 touch_locations_.find(initial_press_->touch_id()) != |
| 715 touch_locations_.end()) { |
| 716 LOG(ERROR) << "No initial press or the initial press has been released."; |
| 717 } |
| 718 |
| 719 gfx::Point location = |
| 720 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]); |
| 721 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); |
| 722 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER) |
| 723 return; |
| 724 |
| 725 if (sound_timer_.IsRunning()) |
| 726 sound_timer_.Stop(); |
| 727 delegate_->PlayPassthroughEarcon(); |
| 728 SET_STATE(CORNER_PASSTHROUGH); |
| 729 return; |
| 730 } |
| 731 |
621 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 732 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
622 ui::EventDispatchDetails result ALLOW_UNUSED = | 733 ui::EventDispatchDetails result ALLOW_UNUSED = |
623 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 734 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
624 } | 735 } |
625 | 736 |
626 // This is an override for a function that is only called for timer-based events | 737 // This is an override for a function that is only called for timer-based events |
627 // like long press. Events that are created synchronously as a result of | 738 // like long press. Events that are created synchronously as a result of |
628 // certain touch events are added to the vector accessible via | 739 // certain touch events are added to the vector accessible via |
629 // GetAndResetPendingGestures(). We only care about swipes (which are created | 740 // GetAndResetPendingGestures(). We only care about swipes (which are created |
630 // synchronously), so we ignore this callback. | 741 // synchronously), so we ignore this callback. |
(...skipping 20 matching lines...) Expand all Loading... |
651 SideSlideControl(*i); | 762 SideSlideControl(*i); |
652 } | 763 } |
653 } | 764 } |
654 } | 765 } |
655 } | 766 } |
656 | 767 |
657 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { | 768 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { |
658 ui::EventType type = gesture->type(); | 769 ui::EventType type = gesture->type(); |
659 | 770 |
660 if (type == ET_GESTURE_SCROLL_BEGIN) { | 771 if (type == ET_GESTURE_SCROLL_BEGIN) { |
661 delegate_->PlayVolumeAdjustSound(); | 772 delegate_->PlayVolumeAdjustEarcon(); |
662 } | 773 } |
663 | 774 |
664 if (type == ET_GESTURE_SCROLL_END) { | 775 if (type == ET_GESTURE_SCROLL_END) { |
665 if (sound_timer_.IsRunning()) | 776 if (sound_timer_.IsRunning()) |
666 sound_timer_.Stop(); | 777 sound_timer_.Stop(); |
667 delegate_->PlayVolumeAdjustSound(); | 778 delegate_->PlayVolumeAdjustEarcon(); |
668 } | 779 } |
669 | 780 |
670 // If the user is in the corner of the right side of the screen, the volume | 781 // If the user is in the corner of the right side of the screen, the volume |
671 // will be automatically set to 100% or muted depending on which corner they | 782 // will be automatically set to 100% or muted depending on which corner they |
672 // are in. Otherwise, the user will be able to adjust the volume by sliding | 783 // are in. Otherwise, the user will be able to adjust the volume by sliding |
673 // their finger along the right side of the screen. Volume is relative to | 784 // their finger along the right side of the screen. Volume is relative to |
674 // where they are on the right side of the screen. | 785 // where they are on the right side of the screen. |
675 gfx::Point location = gesture->location(); | 786 gfx::Point location = gesture->location(); |
676 int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); | 787 int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); |
677 if (!(edge & RIGHT_EDGE)) | 788 if (!(edge & RIGHT_EDGE)) |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 // gesture provider still exists, it's reset to NULL until the user returns | 967 // gesture provider still exists, it's reset to NULL until the user returns |
857 // to NO_FINGERS_DOWN. | 968 // to NO_FINGERS_DOWN. |
858 switch (new_state) { | 969 switch (new_state) { |
859 case SINGLE_TAP_RELEASED: | 970 case SINGLE_TAP_RELEASED: |
860 case TOUCH_EXPLORE_RELEASED: | 971 case TOUCH_EXPLORE_RELEASED: |
861 case DOUBLE_TAP_PENDING: | 972 case DOUBLE_TAP_PENDING: |
862 case TOUCH_RELEASE_PENDING: | 973 case TOUCH_RELEASE_PENDING: |
863 case TOUCH_EXPLORATION: | 974 case TOUCH_EXPLORATION: |
864 case TOUCH_EXPLORE_SECOND_PRESS: | 975 case TOUCH_EXPLORE_SECOND_PRESS: |
865 case ONE_FINGER_PASSTHROUGH: | 976 case ONE_FINGER_PASSTHROUGH: |
| 977 case CORNER_PASSTHROUGH: |
866 case WAIT_FOR_NO_FINGERS: | 978 case WAIT_FOR_NO_FINGERS: |
867 if (gesture_provider_.get()) | 979 if (gesture_provider_.get()) |
868 gesture_provider_.reset(NULL); | 980 gesture_provider_.reset(NULL); |
869 break; | 981 break; |
870 case NO_FINGERS_DOWN: | 982 case NO_FINGERS_DOWN: |
871 gesture_provider_.reset(new GestureProviderAura(this)); | 983 gesture_provider_.reset(new GestureProviderAura(this)); |
872 if (sound_timer_.IsRunning()) | 984 if (sound_timer_.IsRunning()) |
873 sound_timer_.Stop(); | 985 sound_timer_.Stop(); |
874 tap_timer_.Stop(); | 986 tap_timer_.Stop(); |
875 break; | 987 break; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 case DOUBLE_TAP_PENDING: | 1047 case DOUBLE_TAP_PENDING: |
936 return "DOUBLE_TAP_PENDING"; | 1048 return "DOUBLE_TAP_PENDING"; |
937 case TOUCH_RELEASE_PENDING: | 1049 case TOUCH_RELEASE_PENDING: |
938 return "TOUCH_RELEASE_PENDING"; | 1050 return "TOUCH_RELEASE_PENDING"; |
939 case TOUCH_EXPLORATION: | 1051 case TOUCH_EXPLORATION: |
940 return "TOUCH_EXPLORATION"; | 1052 return "TOUCH_EXPLORATION"; |
941 case GESTURE_IN_PROGRESS: | 1053 case GESTURE_IN_PROGRESS: |
942 return "GESTURE_IN_PROGRESS"; | 1054 return "GESTURE_IN_PROGRESS"; |
943 case TOUCH_EXPLORE_SECOND_PRESS: | 1055 case TOUCH_EXPLORE_SECOND_PRESS: |
944 return "TOUCH_EXPLORE_SECOND_PRESS"; | 1056 return "TOUCH_EXPLORE_SECOND_PRESS"; |
| 1057 case CORNER_PASSTHROUGH: |
| 1058 return "CORNER_PASSTHROUGH"; |
945 case SLIDE_GESTURE: | 1059 case SLIDE_GESTURE: |
946 return "SLIDE_GESTURE"; | 1060 return "SLIDE_GESTURE"; |
947 case ONE_FINGER_PASSTHROUGH: | 1061 case ONE_FINGER_PASSTHROUGH: |
948 return "ONE_FINGER_PASSTHROUGH"; | 1062 return "ONE_FINGER_PASSTHROUGH"; |
949 case WAIT_FOR_NO_FINGERS: | 1063 case WAIT_FOR_NO_FINGERS: |
950 return "WAIT_FOR_NO_FINGERS"; | 1064 return "WAIT_FOR_NO_FINGERS"; |
951 case TWO_FINGER_TAP: | 1065 case TWO_FINGER_TAP: |
952 return "TWO_FINGER_TAP"; | 1066 return "TWO_FINGER_TAP"; |
953 } | 1067 } |
954 return "Not a state"; | 1068 return "Not a state"; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 left_swipe_gestures_[4] = | 1105 left_swipe_gestures_[4] = |
992 BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); | 1106 BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); |
993 right_swipe_gestures_[4] = | 1107 right_swipe_gestures_[4] = |
994 BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE); | 1108 BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE); |
995 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); | 1109 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); |
996 down_swipe_gestures_[4] = | 1110 down_swipe_gestures_[4] = |
997 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); | 1111 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); |
998 } | 1112 } |
999 | 1113 |
1000 } // namespace ui | 1114 } // namespace ui |
OLD | NEW |