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