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/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
8 #include "ui/aura/client/cursor_client.h" | 8 #include "ui/aura/client/cursor_client.h" |
9 #include "ui/aura/window.h" | 9 #include "ui/aura/window.h" |
10 #include "ui/aura/window_event_dispatcher.h" | 10 #include "ui/aura/window_event_dispatcher.h" |
11 #include "ui/aura/window_tree_host.h" | 11 #include "ui/aura/window_tree_host.h" |
12 #include "ui/events/event.h" | 12 #include "ui/events/event.h" |
13 #include "ui/events/event_processor.h" | 13 #include "ui/events/event_processor.h" |
14 #include "ui/gfx/geometry/rect.h" | 14 #include "ui/gfx/geometry/rect.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 { | 21 namespace { |
22 | 22 |
23 // Delay between adjustment sounds. | 23 // Delay between adjustment sounds. |
24 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); | 24 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
25 | 25 |
| 26 // Delay before corner passthrough activates. |
| 27 const base::TimeDelta kCornerPassthroughDelay = |
| 28 base::TimeDelta::FromMilliseconds(700); |
| 29 |
26 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | 30 // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
27 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | 31 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
28 } // namespace | 32 } // namespace |
29 | 33 |
30 TouchExplorationController::TouchExplorationController( | 34 TouchExplorationController::TouchExplorationController( |
31 aura::Window* root_window, | 35 aura::Window* root_window, |
32 TouchExplorationControllerDelegate* delegate) | 36 TouchExplorationControllerDelegate* delegate) |
33 : root_window_(root_window), | 37 : root_window_(root_window), |
34 delegate_(delegate), | 38 delegate_(delegate), |
35 state_(NO_FINGERS_DOWN), | 39 state_(NO_FINGERS_DOWN), |
36 gesture_provider_(this), | 40 gesture_provider_(this), |
37 prev_state_(NO_FINGERS_DOWN), | 41 prev_state_(NO_FINGERS_DOWN), |
38 VLOG_on_(true) { | 42 VLOG_on_(true), |
| 43 waiting_for_corner_passthrough_(false) { |
39 CHECK(root_window); | 44 CHECK(root_window); |
40 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 45 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
41 } | 46 } |
42 | 47 |
43 TouchExplorationController::~TouchExplorationController() { | 48 TouchExplorationController::~TouchExplorationController() { |
44 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 49 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
45 } | 50 } |
46 | 51 |
47 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 52 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
48 const ui::Event& event, | 53 const ui::Event& event, |
(...skipping 16 matching lines...) Expand all Loading... |
65 // the timer. | 70 // the timer. |
66 if (tap_timer_.IsRunning() && | 71 if (tap_timer_.IsRunning() && |
67 touch_event.time_stamp() - initial_press_->time_stamp() > | 72 touch_event.time_stamp() - initial_press_->time_stamp() > |
68 gesture_detector_config_.double_tap_timeout) { | 73 gesture_detector_config_.double_tap_timeout) { |
69 tap_timer_.Stop(); | 74 tap_timer_.Stop(); |
70 OnTapTimerFired(); | 75 OnTapTimerFired(); |
71 // Note: this may change the state. We should now continue and process | 76 // Note: this may change the state. We should now continue and process |
72 // this event under this new state. | 77 // this event under this new state. |
73 } | 78 } |
74 | 79 |
| 80 if (long_press_timer_.IsRunning() && |
| 81 event.time_stamp() - initial_press_->time_stamp() > |
| 82 gesture_detector_config_.longpress_timeout) { |
| 83 long_press_timer_.Stop(); |
| 84 OnLongPressTimerFired(); |
| 85 } |
| 86 |
75 const ui::EventType type = touch_event.type(); | 87 const ui::EventType type = touch_event.type(); |
76 const gfx::PointF& location = touch_event.location_f(); | 88 const gfx::PointF& location = touch_event.location_f(); |
77 const int touch_id = touch_event.touch_id(); | 89 const int touch_id = touch_event.touch_id(); |
78 | 90 |
79 // Always update touch ids and touch locations, so we can use those | 91 // Always update touch ids and touch locations, so we can use those |
80 // no matter what state we're in. | 92 // no matter what state we're in. |
81 if (type == ui::ET_TOUCH_PRESSED) { | 93 if (type == ui::ET_TOUCH_PRESSED) { |
| 94 // If the user enters the screen then send an earcon. |
| 95 gfx::Point edges = touch_event.location(); |
| 96 if (FindEdgesWithinBounds(edges, kLeavingScreenEdge) != NO_EDGE) { |
| 97 if (VLOG_on_) |
| 98 VLOG(0) << "Entering the screen"; |
| 99 delegate_->PlayEnterScreenEarcon(); |
| 100 } |
82 current_touch_ids_.push_back(touch_id); | 101 current_touch_ids_.push_back(touch_id); |
83 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); | 102 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); |
84 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 103 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
85 // In order to avoid accidentally double tapping when moving off the edge of | 104 // In order to avoid accidentally double tapping when moving off the edge of |
86 // the screen, the state will be rewritten to NoFingersDown. | 105 // the screen, the state will be rewritten to NoFingersDown. |
87 TouchEvent touch_event = static_cast<const TouchEvent&>(event); | 106 TouchEvent touch_event = static_cast<const TouchEvent&>(event); |
88 if (FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != | 107 gfx::Point edges = touch_event.location(); |
89 NO_EDGE) { | 108 if (FindEdgesWithinBounds(edges, kLeavingScreenEdge) != NO_EDGE) { |
| 109 if (VLOG_on_) |
| 110 VLOG(0) << "Leaving screen"; |
| 111 // Indicates to the user that they are leaving the screen. |
| 112 delegate_->PlayExitScreenEarcon(); |
90 if (current_touch_ids_.size() == 0) | 113 if (current_touch_ids_.size() == 0) |
91 ResetToNoFingersDown(); | 114 ResetToNoFingersDown(); |
92 } | 115 } |
93 | 116 |
94 std::vector<int>::iterator it = std::find( | 117 std::vector<int>::iterator it = std::find( |
95 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); | 118 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); |
96 | 119 |
97 // Can happen if touch exploration is enabled while fingers were down. | 120 // Can happen if touch exploration is enabled while fingers were down. |
98 if (it == current_touch_ids_.end()) | 121 if (it == current_touch_ids_.end()) |
99 return ui::EVENT_REWRITE_CONTINUE; | 122 return ui::EVENT_REWRITE_CONTINUE; |
(...skipping 24 matching lines...) Expand all Loading... |
124 case DOUBLE_TAP_PRESSED: | 147 case DOUBLE_TAP_PRESSED: |
125 return InDoubleTapPressed(touch_event, rewritten_event); | 148 return InDoubleTapPressed(touch_event, rewritten_event); |
126 case TOUCH_EXPLORATION: | 149 case TOUCH_EXPLORATION: |
127 return InTouchExploration(touch_event, rewritten_event); | 150 return InTouchExploration(touch_event, rewritten_event); |
128 case GESTURE_IN_PROGRESS: | 151 case GESTURE_IN_PROGRESS: |
129 return InGestureInProgress(touch_event, rewritten_event); | 152 return InGestureInProgress(touch_event, rewritten_event); |
130 case TOUCH_EXPLORE_SECOND_PRESS: | 153 case TOUCH_EXPLORE_SECOND_PRESS: |
131 return InTouchExploreSecondPress(touch_event, rewritten_event); | 154 return InTouchExploreSecondPress(touch_event, rewritten_event); |
132 case TWO_TO_ONE_FINGER: | 155 case TWO_TO_ONE_FINGER: |
133 return InTwoToOneFinger(touch_event, rewritten_event); | 156 return InTwoToOneFinger(touch_event, rewritten_event); |
| 157 case CORNER_PASSTHROUGH: |
| 158 return InCornerPassthrough(touch_event, rewritten_event); |
134 case PASSTHROUGH: | 159 case PASSTHROUGH: |
135 return InPassthrough(touch_event, rewritten_event); | 160 return InPassthrough(touch_event, rewritten_event); |
136 case WAIT_FOR_RELEASE: | 161 case WAIT_FOR_RELEASE: |
137 return InWaitForRelease(touch_event, rewritten_event); | 162 return InWaitForRelease(touch_event, rewritten_event); |
138 case SLIDE_GESTURE: | 163 case SLIDE_GESTURE: |
139 return InSlideGesture(touch_event, rewritten_event); | 164 return InSlideGesture(touch_event, rewritten_event); |
140 } | 165 } |
141 NOTREACHED(); | 166 NOTREACHED(); |
142 return ui::EVENT_REWRITE_CONTINUE; | 167 return ui::EVENT_REWRITE_CONTINUE; |
143 } | 168 } |
144 | 169 |
145 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 170 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
146 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 171 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
147 NOTREACHED(); | 172 NOTREACHED(); |
148 return ui::EVENT_REWRITE_CONTINUE; | 173 return ui::EVENT_REWRITE_CONTINUE; |
149 } | 174 } |
150 | 175 |
151 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( | 176 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
152 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 177 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
153 const ui::EventType type = event.type(); | 178 const ui::EventType type = event.type(); |
154 if (type == ui::ET_TOUCH_PRESSED) { | 179 if (type != ui::ET_TOUCH_PRESSED) { |
155 initial_press_.reset(new TouchEvent(event)); | 180 NOTREACHED() << "Unexpected event type received: " << event.name(); |
156 last_unused_finger_event_.reset(new TouchEvent(event)); | 181 return ui::EVENT_REWRITE_CONTINUE; |
157 tap_timer_.Start(FROM_HERE, | |
158 gesture_detector_config_.double_tap_timeout, | |
159 this, | |
160 &TouchExplorationController::OnTapTimerFired); | |
161 gesture_provider_.OnTouchEvent(event); | |
162 gesture_provider_.OnTouchEventAck(false); | |
163 ProcessGestureEvents(); | |
164 state_ = SINGLE_TAP_PRESSED; | |
165 VLOG_STATE(); | |
166 return ui::EVENT_REWRITE_DISCARD; | |
167 } | 182 } |
168 NOTREACHED() << "Unexpected event type received: " << event.name();; | 183 int location = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
169 return ui::EVENT_REWRITE_CONTINUE; | 184 base::TimeDelta timeout; |
| 185 |
| 186 // If the press was at a corner, the user might go into corner passthrough |
| 187 // instead. |
| 188 bool in_a_bottom_corner = |
| 189 (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location); |
| 190 if (in_a_bottom_corner) { |
| 191 if (VLOG_on_) |
| 192 VLOG(0) << "Location: " << location; |
| 193 long_press_timer_.Start(FROM_HERE, |
| 194 gesture_detector_config_.longpress_timeout, |
| 195 this, |
| 196 &TouchExplorationController::OnLongPressTimerFired); |
| 197 waiting_for_corner_passthrough_ = true; |
| 198 } else { |
| 199 waiting_for_corner_passthrough_ = false; |
| 200 } |
| 201 tap_timer_.Start(FROM_HERE, |
| 202 gesture_detector_config_.double_tap_timeout, |
| 203 this, |
| 204 &TouchExplorationController::OnTapTimerFired); |
| 205 initial_press_.reset(new TouchEvent(event)); |
| 206 last_unused_finger_event_.reset(new TouchEvent(event)); |
| 207 gesture_provider_.OnTouchEvent(event); |
| 208 gesture_provider_.OnTouchEventAck(false); |
| 209 ProcessGestureEvents(); |
| 210 state_ = SINGLE_TAP_PRESSED; |
| 211 VLOG_STATE(); |
| 212 return ui::EVENT_REWRITE_DISCARD; |
170 } | 213 } |
171 | 214 |
172 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 215 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
173 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 216 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
174 const ui::EventType type = event.type(); | 217 const ui::EventType type = event.type(); |
175 | 218 |
| 219 int location = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
| 220 bool in_a_bottom_corner = |
| 221 (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER); |
| 222 // If the event is from the initial press and the location is no longer in the |
| 223 // corner, then we are not waiting for a corner passthrough anymore. |
| 224 if (event.touch_id() == initial_press_->touch_id() && !in_a_bottom_corner) { |
| 225 waiting_for_corner_passthrough_ = false; |
| 226 if (long_press_timer_.IsRunning()) { |
| 227 long_press_timer_.Stop(); |
| 228 if (event.time_stamp() - initial_press_->time_stamp() > |
| 229 gesture_detector_config_.double_tap_timeout) { |
| 230 OnTapTimerFired(); |
| 231 } |
| 232 } |
| 233 } |
| 234 |
176 if (type == ui::ET_TOUCH_PRESSED) { | 235 if (type == ui::ET_TOUCH_PRESSED) { |
| 236 waiting_for_corner_passthrough_ = false; |
177 // Adding a second finger within the timeout period switches to | 237 // Adding a second finger within the timeout period switches to |
178 // passing through every event from the second finger and none form the | 238 // passing through every event from the second finger and none form the |
179 // first. The event from the first finger is still saved in initial_press_. | 239 // first. The event from the first finger is still saved in initial_press_. |
180 state_ = TWO_TO_ONE_FINGER; | 240 state_ = TWO_TO_ONE_FINGER; |
181 last_two_to_one_.reset(new TouchEvent(event)); | 241 last_two_to_one_.reset(new TouchEvent(event)); |
182 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 242 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
183 event.location(), | 243 event.location(), |
184 event.touch_id(), | 244 event.touch_id(), |
185 event.time_stamp())); | 245 event.time_stamp())); |
186 (*rewritten_event)->set_flags(event.flags()); | 246 (*rewritten_event)->set_flags(event.flags()); |
187 return EVENT_REWRITE_REWRITTEN; | 247 return EVENT_REWRITE_REWRITTEN; |
188 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 248 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 249 waiting_for_corner_passthrough_ = false; |
189 DCHECK_EQ(0U, current_touch_ids_.size()); | 250 DCHECK_EQ(0U, current_touch_ids_.size()); |
190 state_ = SINGLE_TAP_RELEASED; | 251 state_ = SINGLE_TAP_RELEASED; |
191 VLOG_STATE(); | 252 VLOG_STATE(); |
192 return EVENT_REWRITE_DISCARD; | 253 return EVENT_REWRITE_DISCARD; |
193 } else if (type == ui::ET_TOUCH_MOVED) { | 254 } else if (type == ui::ET_TOUCH_MOVED) { |
194 float distance = (event.location() - initial_press_->location()).Length(); | 255 float distance = (event.location() - initial_press_->location()).Length(); |
195 // If the user does not move far enough from the original position, then the | 256 // If the user does not move far enough from the original position, then the |
196 // resulting movement should not be considered to be a deliberate gesture or | 257 // resulting movement should not be considered to be a deliberate gesture or |
197 // touch exploration. | 258 // touch exploration. |
198 if (distance <= gesture_detector_config_.touch_slop) | 259 if (distance <= gesture_detector_config_.touch_slop) |
199 return EVENT_REWRITE_DISCARD; | 260 return EVENT_REWRITE_DISCARD; |
200 | 261 |
201 float delta_time = | 262 float delta_time = |
202 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); | 263 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); |
203 float velocity = distance / delta_time; | 264 float velocity = distance / delta_time; |
204 VLOG(0) << "\n Delta time: " << delta_time | 265 if (VLOG_on_) { |
205 << "\n Distance: " << distance | 266 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance |
206 << "\n Velocity of click: " << velocity | 267 << "\n Velocity of click: " << velocity |
207 << "\n Minimum swipe velocity: " | 268 << "\n Minimum swipe velocity: " |
208 << gesture_detector_config_.minimum_swipe_velocity; | 269 << gesture_detector_config_.minimum_swipe_velocity; |
209 | 270 } |
210 // Change to slide gesture if the slide occurred at the right edge. | 271 // Change to slide gesture if the slide occurred at the right edge. |
211 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); | 272 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
212 if (edge & RIGHT_EDGE) { | 273 if (edge & RIGHT_EDGE && edge != BOTTOM_RIGHT_CORNER) { |
213 state_ = SLIDE_GESTURE; | 274 state_ = SLIDE_GESTURE; |
214 VLOG_STATE(); | 275 VLOG_STATE(); |
215 return InSlideGesture(event, rewritten_event); | 276 return InSlideGesture(event, rewritten_event); |
216 } | 277 } |
217 | 278 |
218 // If the user moves fast enough from the initial touch location, start | 279 // If the user moves fast enough from the initial touch location, start |
219 // gesture detection. Otherwise, jump to the touch exploration mode early. | 280 // gesture detection. Otherwise, jump to the touch exploration mode early. |
220 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { | 281 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
221 state_ = GESTURE_IN_PROGRESS; | 282 state_ = GESTURE_IN_PROGRESS; |
222 VLOG_STATE(); | 283 VLOG_STATE(); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 event.time_stamp())); | 452 event.time_stamp())); |
392 (*rewritten_event)->set_flags(event.flags()); | 453 (*rewritten_event)->set_flags(event.flags()); |
393 state_ = WAIT_FOR_RELEASE; | 454 state_ = WAIT_FOR_RELEASE; |
394 return ui::EVENT_REWRITE_REWRITTEN; | 455 return ui::EVENT_REWRITE_REWRITTEN; |
395 } | 456 } |
396 } else if (type == ui::ET_TOUCH_PRESSED) { | 457 } else if (type == ui::ET_TOUCH_PRESSED) { |
397 DCHECK(current_touch_ids_.size() == 3); | 458 DCHECK(current_touch_ids_.size() == 3); |
398 // If a third finger is pressed, we are now going into passthrough mode | 459 // If a third finger is pressed, we are now going into passthrough mode |
399 // and now need to dispatch the first finger into a press, as well as the | 460 // and now need to dispatch the first finger into a press, as well as the |
400 // recent press. | 461 // recent press. |
401 if (current_touch_ids_.size() == 3){ | 462 if (current_touch_ids_.size() == 3) { |
402 state_ = PASSTHROUGH; | 463 state_ = PASSTHROUGH; |
403 scoped_ptr<ui::TouchEvent> first_finger_press; | 464 scoped_ptr<ui::TouchEvent> first_finger_press; |
404 first_finger_press.reset( | 465 first_finger_press.reset( |
405 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 466 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
406 last_unused_finger_event_->location(), | 467 last_unused_finger_event_->location(), |
407 last_unused_finger_event_->touch_id(), | 468 last_unused_finger_event_->touch_id(), |
408 event.time_stamp())); | 469 event.time_stamp())); |
409 DispatchEvent(first_finger_press.get()); | 470 DispatchEvent(first_finger_press.get()); |
410 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 471 rewritten_event->reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
411 event.location(), | 472 event.location(), |
(...skipping 18 matching lines...) Expand all Loading... |
430 event.touch_id(), | 491 event.touch_id(), |
431 event.time_stamp())); | 492 event.time_stamp())); |
432 (*rewritten_event)->set_flags(event.flags()); | 493 (*rewritten_event)->set_flags(event.flags()); |
433 return ui::EVENT_REWRITE_REWRITTEN; | 494 return ui::EVENT_REWRITE_REWRITTEN; |
434 } | 495 } |
435 } | 496 } |
436 NOTREACHED() << "Unexpected event type received: " << event.name(); | 497 NOTREACHED() << "Unexpected event type received: " << event.name(); |
437 return ui::EVENT_REWRITE_CONTINUE; | 498 return ui::EVENT_REWRITE_CONTINUE; |
438 } | 499 } |
439 | 500 |
| 501 ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough( |
| 502 const ui::TouchEvent& event, |
| 503 scoped_ptr<ui::Event>* rewritten_event) { |
| 504 ui::EventType type = event.type(); |
| 505 |
| 506 // If the first finger has left the corner, then exit passthrough. |
| 507 if (event.touch_id() == initial_press_->touch_id()) { |
| 508 int edges = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
| 509 bool in_a_bottom_corner = (edges == BOTTOM_LEFT_CORNER) || |
| 510 (edges == BOTTOM_RIGHT_CORNER); |
| 511 if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner) |
| 512 return ui::EVENT_REWRITE_DISCARD; |
| 513 |
| 514 if (current_touch_ids_.size() == 0) { |
| 515 ResetToNoFingersDown(); |
| 516 return ui::EVENT_REWRITE_DISCARD; |
| 517 } |
| 518 |
| 519 waiting_for_corner_passthrough_ = false; |
| 520 state_ = WAIT_FOR_RELEASE; |
| 521 VLOG_STATE(); |
| 522 return ui::EVENT_REWRITE_DISCARD; |
| 523 } |
| 524 |
| 525 rewritten_event->reset(new ui::TouchEvent( |
| 526 type, event.location(), event.touch_id(), event.time_stamp())); |
| 527 (*rewritten_event)->set_flags(event.flags()); |
| 528 |
| 529 if (current_touch_ids_.size() == 0) |
| 530 ResetToNoFingersDown(); |
| 531 |
| 532 return ui::EVENT_REWRITE_REWRITTEN; |
| 533 } |
| 534 |
440 ui::EventRewriteStatus TouchExplorationController::InPassthrough( | 535 ui::EventRewriteStatus TouchExplorationController::InPassthrough( |
441 const ui::TouchEvent& event, | 536 const ui::TouchEvent& event, |
442 scoped_ptr<ui::Event>* rewritten_event) { | 537 scoped_ptr<ui::Event>* rewritten_event) { |
443 ui::EventType type = event.type(); | 538 ui::EventType type = event.type(); |
444 | 539 |
445 if (!(type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED || | 540 if (!(type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED || |
446 type == ui::ET_TOUCH_MOVED || type == ui::ET_TOUCH_PRESSED)) { | 541 type == ui::ET_TOUCH_MOVED || type == ui::ET_TOUCH_PRESSED)) { |
447 NOTREACHED() << "Unexpected event type received: " << event.name(); | 542 NOTREACHED() << "Unexpected event type received: " << event.name(); |
448 return ui::EVENT_REWRITE_CONTINUE; | 543 return ui::EVENT_REWRITE_CONTINUE; |
449 } | 544 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 VLOG_STATE(); | 592 VLOG_STATE(); |
498 return ui::EVENT_REWRITE_REWRITTEN; | 593 return ui::EVENT_REWRITE_REWRITTEN; |
499 } | 594 } |
500 NOTREACHED() << "Unexpected event type received: " << event.name(); | 595 NOTREACHED() << "Unexpected event type received: " << event.name(); |
501 return ui::EVENT_REWRITE_CONTINUE; | 596 return ui::EVENT_REWRITE_CONTINUE; |
502 } | 597 } |
503 | 598 |
504 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( | 599 ui::EventRewriteStatus TouchExplorationController::InWaitForRelease( |
505 const ui::TouchEvent& event, | 600 const ui::TouchEvent& event, |
506 scoped_ptr<ui::Event>* rewritten_event) { | 601 scoped_ptr<ui::Event>* rewritten_event) { |
| 602 waiting_for_corner_passthrough_ = false; |
507 ui::EventType type = event.type(); | 603 ui::EventType type = event.type(); |
508 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || | 604 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || |
509 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { | 605 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { |
510 NOTREACHED() << "Unexpected event type received: " << event.name(); | 606 NOTREACHED() << "Unexpected event type received: " << event.name(); |
511 return ui::EVENT_REWRITE_CONTINUE; | 607 return ui::EVENT_REWRITE_CONTINUE; |
512 } | 608 } |
513 if (current_touch_ids_.size() == 0) { | 609 if (current_touch_ids_.size() == 0) { |
514 state_ = NO_FINGERS_DOWN; | 610 state_ = NO_FINGERS_DOWN; |
515 VLOG_STATE(); | 611 VLOG_STATE(); |
516 ResetToNoFingersDown(); | 612 ResetToNoFingersDown(); |
517 } | 613 } |
518 return EVENT_REWRITE_DISCARD; | 614 return EVENT_REWRITE_DISCARD; |
519 } | 615 } |
520 | 616 |
521 void TouchExplorationController::PlaySoundForTimer() { | 617 void TouchExplorationController::PlaySoundForTimer() { |
522 delegate_->PlayVolumeAdjustSound(); | 618 delegate_->PlayVolumeAdjustEarcon(); |
523 } | 619 } |
524 | 620 |
525 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | 621 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
526 const ui::TouchEvent& event, | 622 const ui::TouchEvent& event, |
527 scoped_ptr<ui::Event>* rewritten_event) { | 623 scoped_ptr<ui::Event>* rewritten_event) { |
528 // The timer should not fire when sliding. | 624 // The timer should not fire when sliding. |
529 if (tap_timer_.IsRunning()) | 625 if (tap_timer_.IsRunning()) |
530 tap_timer_.Stop(); | 626 tap_timer_.Stop(); |
531 | 627 |
532 ui::EventType type = event.type(); | 628 ui::EventType type = event.type(); |
(...skipping 19 matching lines...) Expand all Loading... |
552 return EVENT_REWRITE_DISCARD; | 648 return EVENT_REWRITE_DISCARD; |
553 } | 649 } |
554 | 650 |
555 // This can occur if the user leaves the screen edge and then returns to it to | 651 // This can occur if the user leaves the screen edge and then returns to it to |
556 // continue adjusting the sound. | 652 // continue adjusting the sound. |
557 if (!sound_timer_.IsRunning()) { | 653 if (!sound_timer_.IsRunning()) { |
558 sound_timer_.Start(FROM_HERE, | 654 sound_timer_.Start(FROM_HERE, |
559 kSoundDelay, | 655 kSoundDelay, |
560 this, | 656 this, |
561 &ui::TouchExplorationController::PlaySoundForTimer); | 657 &ui::TouchExplorationController::PlaySoundForTimer); |
562 delegate_->PlayVolumeAdjustSound(); | 658 delegate_->PlayVolumeAdjustEarcon(); |
563 } | 659 } |
564 | 660 |
565 // There should not be more than one finger down. | 661 // There should not be more than one finger down. |
566 DCHECK(current_touch_ids_.size() <= 1); | 662 DCHECK(current_touch_ids_.size() <= 1); |
567 if (type == ui::ET_TOUCH_MOVED) { | 663 if (type == ui::ET_TOUCH_MOVED) { |
568 gesture_provider_.OnTouchEvent(event); | 664 gesture_provider_.OnTouchEvent(event); |
569 gesture_provider_.OnTouchEventAck(false); | 665 gesture_provider_.OnTouchEventAck(false); |
570 } | 666 } |
571 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 667 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
572 gesture_provider_.OnTouchEvent(event); | 668 gesture_provider_.OnTouchEvent(event); |
(...skipping 11 matching lines...) Expand all Loading... |
584 void TouchExplorationController::OnTapTimerFired() { | 680 void TouchExplorationController::OnTapTimerFired() { |
585 switch (state_) { | 681 switch (state_) { |
586 case SINGLE_TAP_RELEASED: | 682 case SINGLE_TAP_RELEASED: |
587 ResetToNoFingersDown(); | 683 ResetToNoFingersDown(); |
588 break; | 684 break; |
589 case TOUCH_EXPLORE_RELEASED: | 685 case TOUCH_EXPLORE_RELEASED: |
590 ResetToNoFingersDown(); | 686 ResetToNoFingersDown(); |
591 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 687 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
592 return; | 688 return; |
593 case SINGLE_TAP_PRESSED: | 689 case SINGLE_TAP_PRESSED: |
| 690 if (waiting_for_corner_passthrough_) |
| 691 return; |
594 case GESTURE_IN_PROGRESS: | 692 case GESTURE_IN_PROGRESS: |
595 // Discard any pending gestures. | 693 // Discard any pending gestures. |
596 delete gesture_provider_.GetAndResetPendingGestures(); | 694 delete gesture_provider_.GetAndResetPendingGestures(); |
597 state_ = TOUCH_EXPLORATION; | 695 state_ = TOUCH_EXPLORATION; |
598 VLOG_STATE(); | 696 VLOG_STATE(); |
599 break; | 697 break; |
600 default: | 698 default: |
601 return; | 699 return; |
602 } | 700 } |
603 EnterTouchToMouseMode(); | 701 EnterTouchToMouseMode(); |
604 scoped_ptr<ui::Event> mouse_move = | 702 scoped_ptr<ui::Event> mouse_move = |
605 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 703 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
606 DispatchEvent(mouse_move.get()); | 704 DispatchEvent(mouse_move.get()); |
607 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 705 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
608 } | 706 } |
609 | 707 |
| 708 void TouchExplorationController::OnLongPressTimerFired() { |
| 709 if (waiting_for_corner_passthrough_) { |
| 710 if (sound_timer_.IsRunning()) |
| 711 sound_timer_.Stop(); |
| 712 delegate_->PlayPassthroughEarcon(); |
| 713 delete gesture_provider_.GetAndResetPendingGestures(); |
| 714 state_ = CORNER_PASSTHROUGH; |
| 715 VLOG_STATE(); |
| 716 return; |
| 717 } |
| 718 } |
| 719 |
610 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 720 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
611 ui::EventDispatchDetails result ALLOW_UNUSED = | 721 ui::EventDispatchDetails result ALLOW_UNUSED = |
612 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 722 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
613 } | 723 } |
614 | 724 |
615 void TouchExplorationController::OnGestureEvent( | 725 void TouchExplorationController::OnGestureEvent( |
616 ui::GestureEvent* gesture) { | 726 ui::GestureEvent* gesture) { |
617 CHECK(gesture->IsGestureEvent()); | 727 CHECK(gesture->IsGestureEvent()); |
618 ui::EventType type = gesture->type(); | 728 ui::EventType type = gesture->type(); |
619 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); | 729 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); |
(...skipping 19 matching lines...) Expand all Loading... |
639 } | 749 } |
640 } | 750 } |
641 } | 751 } |
642 | 752 |
643 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { | 753 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { |
644 ui::EventType type = gesture->type(); | 754 ui::EventType type = gesture->type(); |
645 if (!gesture->IsScrollGestureEvent()) | 755 if (!gesture->IsScrollGestureEvent()) |
646 return; | 756 return; |
647 | 757 |
648 if (type == ET_GESTURE_SCROLL_BEGIN) { | 758 if (type == ET_GESTURE_SCROLL_BEGIN) { |
649 delegate_->PlayVolumeAdjustSound(); | 759 delegate_->PlayVolumeAdjustEarcon(); |
650 } | 760 } |
651 | 761 |
652 if (type == ET_GESTURE_SCROLL_END) { | 762 if (type == ET_GESTURE_SCROLL_END) { |
653 if (sound_timer_.IsRunning()) | 763 if (sound_timer_.IsRunning()) |
654 sound_timer_.Stop(); | 764 sound_timer_.Stop(); |
655 delegate_->PlayVolumeAdjustSound(); | 765 delegate_->PlayVolumeAdjustEarcon(); |
656 } | 766 } |
657 | 767 |
658 // If the user is in the corner of the right side of the screen, the volume | 768 // If the user is in the corner of the right side of the screen, the volume |
659 // will be automatically set to 100% or muted depending on which corner they | 769 // will be automatically set to 100% or muted depending on which corner they |
660 // are in. Otherwise, the user will be able to adjust the volume by sliding | 770 // are in. Otherwise, the user will be able to adjust the volume by sliding |
661 // their finger along the right side of the screen. Volume is relative to | 771 // their finger along the right side of the screen. Volume is relative to |
662 // where they are on the right side of the screen. | 772 // where they are on the right side of the screen. |
663 gfx::Point location = gesture->location(); | 773 gfx::Point location = gesture->location(); |
664 int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); | 774 int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); |
665 if (!(edge & RIGHT_EDGE)) | 775 if (!(edge & RIGHT_EDGE)) |
666 return; | 776 return; |
667 | 777 |
668 if (edge & TOP_EDGE) { | 778 if (edge & TOP_EDGE) { |
669 delegate_->SetOutputLevel(100); | 779 delegate_->SetOutputLevel(100); |
670 return; | 780 return; |
671 } | 781 } |
672 if (edge & BOTTOM_EDGE) { | 782 if (edge & BOTTOM_EDGE) { |
673 delegate_->SetOutputLevel(0); | 783 delegate_->SetOutputLevel(0); |
674 return; | 784 return; |
675 } | 785 } |
676 | 786 |
677 location = gesture->location(); | 787 location = gesture->location(); |
678 root_window_->GetHost()->ConvertPointFromNativeScreen(&location); | 788 root_window_->GetHost()->ConvertPointFromNativeScreen(&location); |
679 float volume_adjust_height = | 789 float volume_adjust_height = |
680 root_window_->bounds().height() - 2 * kMaxDistanceFromEdge; | 790 root_window_->bounds().height() - 2 * kMaxDistanceFromEdge; |
681 float ratio = (location.y() - kMaxDistanceFromEdge) / volume_adjust_height; | 791 float ratio = (location.y() - kMaxDistanceFromEdge) / volume_adjust_height; |
682 float volume = 100 - 100 * ratio; | 792 float volume = 100 - 100 * ratio; |
683 VLOG(0) << "\n Volume = " << volume << "\n Location = " << location.ToString() | 793 if (VLOG_on_) { |
684 << "\n Bounds = " << root_window_->bounds().right(); | 794 VLOG(0) << "\n Volume = " << volume |
685 | 795 << "\n Location = " << location.ToString() |
| 796 << "\n Bounds = " << root_window_->bounds().right(); |
| 797 } |
686 delegate_->SetOutputLevel(int(volume)); | 798 delegate_->SetOutputLevel(int(volume)); |
687 } | 799 } |
688 | 800 |
689 | 801 |
690 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { | 802 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { |
691 // A swipe gesture contains details for the direction in which the swipe | 803 // A swipe gesture contains details for the direction in which the swipe |
692 // occurred. | 804 // occurred. |
693 GestureEventDetails event_details = swipe_gesture->details(); | 805 GestureEventDetails event_details = swipe_gesture->details(); |
694 if (event_details.swipe_left()) { | 806 if (event_details.swipe_left()) { |
695 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); | 807 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 void TouchExplorationController::EnterTouchToMouseMode() { | 902 void TouchExplorationController::EnterTouchToMouseMode() { |
791 aura::client::CursorClient* cursor_client = | 903 aura::client::CursorClient* cursor_client = |
792 aura::client::GetCursorClient(root_window_); | 904 aura::client::GetCursorClient(root_window_); |
793 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) | 905 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) |
794 cursor_client->EnableMouseEvents(); | 906 cursor_client->EnableMouseEvents(); |
795 if (cursor_client && cursor_client->IsCursorVisible()) | 907 if (cursor_client && cursor_client->IsCursorVisible()) |
796 cursor_client->HideCursor(); | 908 cursor_client->HideCursor(); |
797 } | 909 } |
798 | 910 |
799 void TouchExplorationController::ResetToNoFingersDown() { | 911 void TouchExplorationController::ResetToNoFingersDown() { |
| 912 waiting_for_corner_passthrough_ = false; |
800 ProcessGestureEvents(); | 913 ProcessGestureEvents(); |
801 if (sound_timer_.IsRunning()) | 914 if (sound_timer_.IsRunning()) |
802 sound_timer_.Stop(); | 915 sound_timer_.Stop(); |
803 state_ = NO_FINGERS_DOWN; | 916 state_ = NO_FINGERS_DOWN; |
804 VLOG_STATE(); | 917 VLOG_STATE(); |
805 if (tap_timer_.IsRunning()) | 918 if (tap_timer_.IsRunning()) |
806 tap_timer_.Stop(); | 919 tap_timer_.Stop(); |
807 } | 920 } |
808 | 921 |
809 void TouchExplorationController::VlogState(const char* function_name) { | 922 void TouchExplorationController::VlogState(const char* function_name) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 case DOUBLE_TAP_PRESSED: | 973 case DOUBLE_TAP_PRESSED: |
861 return "DOUBLE_TAP_PRESSED"; | 974 return "DOUBLE_TAP_PRESSED"; |
862 case TOUCH_EXPLORATION: | 975 case TOUCH_EXPLORATION: |
863 return "TOUCH_EXPLORATION"; | 976 return "TOUCH_EXPLORATION"; |
864 case GESTURE_IN_PROGRESS: | 977 case GESTURE_IN_PROGRESS: |
865 return "GESTURE_IN_PROGRESS"; | 978 return "GESTURE_IN_PROGRESS"; |
866 case TOUCH_EXPLORE_SECOND_PRESS: | 979 case TOUCH_EXPLORE_SECOND_PRESS: |
867 return "TOUCH_EXPLORE_SECOND_PRESS"; | 980 return "TOUCH_EXPLORE_SECOND_PRESS"; |
868 case TWO_TO_ONE_FINGER: | 981 case TWO_TO_ONE_FINGER: |
869 return "TWO_TO_ONE_FINGER"; | 982 return "TWO_TO_ONE_FINGER"; |
| 983 case CORNER_PASSTHROUGH: |
| 984 return "CORNER_PASSTHROUGH"; |
870 case PASSTHROUGH: | 985 case PASSTHROUGH: |
871 return "PASSTHROUGH"; | 986 return "PASSTHROUGH"; |
872 case WAIT_FOR_RELEASE: | 987 case WAIT_FOR_RELEASE: |
873 return "WAIT_FOR_RELEASE"; | 988 return "WAIT_FOR_RELEASE"; |
874 case SLIDE_GESTURE: | 989 case SLIDE_GESTURE: |
875 return "SLIDE_GESTURE"; | 990 return "SLIDE_GESTURE"; |
876 } | 991 } |
877 return "Not a state"; | 992 return "Not a state"; |
878 } | 993 } |
879 | 994 |
880 } // namespace ui | 995 } // namespace ui |
OLD | NEW |