| 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 |