Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/chromeos/touch_exploration_controller.h" | 5 #include "ui/chromeos/touch_exploration_controller.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "ui/aura/client/cursor_client.h" | 9 #include "ui/aura/client/cursor_client.h" |
| 10 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
| 11 #include "ui/aura/window_event_dispatcher.h" | 11 #include "ui/aura/window_event_dispatcher.h" |
| 12 #include "ui/aura/window_tree_host.h" | 12 #include "ui/aura/window_tree_host.h" |
| 13 #include "ui/events/event.h" | 13 #include "ui/events/event.h" |
| 14 #include "ui/events/event_processor.h" | 14 #include "ui/events/event_processor.h" |
| 15 #include "ui/events/event_utils.h" | 15 #include "ui/events/event_utils.h" |
| 16 #include "ui/gfx/geometry/rect.h" | 16 #include "ui/gfx/geometry/rect.h" |
| 17 | 17 |
| 18 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) | 18 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) |
| 19 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) | 19 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) |
| 20 | 20 |
| 21 namespace ui { | 21 namespace ui { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // Delay between adjustment sounds. | 25 // Delay between adjustment sounds. |
| 26 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); | 26 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
| 27 | 27 |
| 28 // Delay before corner passthrough activates. | |
| 29 const base::TimeDelta kCornerPassthroughDelay = | |
| 30 base::TimeDelta::FromMilliseconds(700); | |
| 31 | |
| 28 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | 32 // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
| 29 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | 33 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
| 30 } // namespace | 34 } // namespace |
| 31 | 35 |
| 32 TouchExplorationController::TouchExplorationController( | 36 TouchExplorationController::TouchExplorationController( |
| 33 aura::Window* root_window, | 37 aura::Window* root_window, |
| 34 TouchExplorationControllerDelegate* delegate) | 38 TouchExplorationControllerDelegate* delegate) |
| 35 : root_window_(root_window), | 39 : root_window_(root_window), |
| 36 delegate_(delegate), | 40 delegate_(delegate), |
| 37 state_(NO_FINGERS_DOWN), | 41 state_(NO_FINGERS_DOWN), |
| 38 gesture_provider_(this), | 42 gesture_provider_(this), |
| 39 prev_state_(NO_FINGERS_DOWN), | 43 prev_state_(NO_FINGERS_DOWN), |
| 40 VLOG_on_(true), | 44 VLOG_on_(true), |
| 41 tick_clock_(NULL) { | 45 tick_clock_(NULL), |
| 46 waiting_for_corner_passthrough_(false) { | |
| 42 CHECK(root_window); | 47 CHECK(root_window); |
| 43 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 48 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
| 44 } | 49 } |
| 45 | 50 |
| 46 TouchExplorationController::~TouchExplorationController() { | 51 TouchExplorationController::~TouchExplorationController() { |
| 47 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 52 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
| 48 } | 53 } |
| 49 | 54 |
| 50 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 55 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
| 51 const ui::Event& event, | 56 const ui::Event& event, |
| 52 scoped_ptr<ui::Event>* rewritten_event) { | 57 scoped_ptr<ui::Event>* rewritten_event) { |
| 53 if (!event.IsTouchEvent()) { | 58 if (!event.IsTouchEvent()) { |
| 54 return ui::EVENT_REWRITE_CONTINUE; | 59 return ui::EVENT_REWRITE_CONTINUE; |
| 55 } | 60 } |
| 56 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); | 61 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); |
| 57 | 62 |
| 58 // If the tap timer should have fired by now but hasn't, run it now and | 63 // If the tap timer should have fired by now but hasn't, run it now and |
| 59 // stop the timer. This is important so that behavior is consistent with | 64 // stop the timer. This is important so that behavior is consistent with |
| 60 // the timestamps of the events, and not dependent on the granularity of | 65 // the timestamps of the events, and not dependent on the granularity of |
| 61 // the timer. | 66 // the timer. |
| 62 if (tap_timer_.IsRunning() && | 67 if (tap_timer_.IsRunning() && |
| 63 touch_event.time_stamp() - initial_press_->time_stamp() > | 68 touch_event.time_stamp() - initial_press_->time_stamp() > |
| 64 gesture_detector_config_.double_tap_timeout) { | 69 gesture_detector_config_.double_tap_timeout) { |
| 65 tap_timer_.Stop(); | 70 tap_timer_.Stop(); |
| 66 OnTapTimerFired(); | 71 OnTapTimerFired(); |
| 67 // Note: this may change the state. We should now continue and process | 72 // Note: this may change the state. We should now continue and process |
| 68 // this event under this new state. | 73 // this event under this new state. |
| 69 } | 74 } |
| 70 | 75 |
| 76 if (long_press_timer_.IsRunning() && | |
| 77 event.time_stamp() - initial_press_->time_stamp() > | |
| 78 gesture_detector_config_.longpress_timeout) { | |
| 79 long_press_timer_.Stop(); | |
| 80 OnLongPressTimerFired(); | |
| 81 } | |
| 82 | |
| 71 const ui::EventType type = touch_event.type(); | 83 const ui::EventType type = touch_event.type(); |
| 72 const gfx::PointF& location = touch_event.location_f(); | 84 const gfx::PointF& location = touch_event.location_f(); |
| 73 const int touch_id = touch_event.touch_id(); | 85 const int touch_id = touch_event.touch_id(); |
| 74 | 86 |
| 75 // Always update touch ids and touch locations, so we can use those | 87 // Always update touch ids and touch locations, so we can use those |
| 76 // no matter what state we're in. | 88 // no matter what state we're in. |
| 77 if (type == ui::ET_TOUCH_PRESSED) { | 89 if (type == ui::ET_TOUCH_PRESSED) { |
| 90 // If the user enters the screen from the edge then send an earcon. | |
| 91 gfx::Point edges = touch_event.location(); | |
| 92 if (FindEdgesWithinBounds(edges, kLeavingScreenEdge) != NO_EDGE) | |
|
aboxhall
2014/08/06 18:10:45
Do we want to not play this if a user already has
lisayin
2014/08/06 20:37:35
Hmmm. Good point. I'll move it to InNoFingersDown.
| |
| 93 delegate_->PlayEnterScreenEarcon(); | |
| 78 current_touch_ids_.push_back(touch_id); | 94 current_touch_ids_.push_back(touch_id); |
| 79 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); | 95 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); |
| 80 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 96 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 81 // In order to avoid accidentally double tapping when moving off the edge of | 97 // In order to avoid accidentally double tapping when moving off the edge of |
| 82 // the screen, the state will be rewritten to NoFingersDown. | 98 // the screen, the state will be rewritten to NoFingersDown. |
| 83 TouchEvent touch_event = static_cast<const TouchEvent&>(event); | 99 TouchEvent touch_event = static_cast<const TouchEvent&>(event); |
| 84 if (FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != | 100 gfx::Point edges = touch_event.location(); |
| 85 NO_EDGE) { | 101 if (FindEdgesWithinBounds(edges, kLeavingScreenEdge) != NO_EDGE) { |
|
aboxhall
2014/08/06 18:10:45
Perhaps this needs to check for state as well: I i
lisayin
2014/08/06 20:37:35
I actually think it makes sense to notify the user
aboxhall
2014/08/06 21:03:12
I guess it could be handy knowing that you'll cons
lisayin
2014/08/06 21:48:22
So another thing that kind of keeps the sound from
| |
| 86 if (current_touch_ids_.size() == 0) { | 102 // Indicates to the user that they are leaving the screen. |
| 87 ResetToNoFingersDown(); | 103 if (VLOG_on_) |
| 88 } | 104 VLOG(0) << "Leaving the Screen"; |
| 105 delegate_->PlayExitScreenEarcon(); | |
| 106 if (current_touch_ids_.size() == 0) | |
| 107 ResetToNoFingersDown(); | |
| 89 } | 108 } |
| 90 | 109 |
| 91 std::vector<int>::iterator it = std::find( | 110 std::vector<int>::iterator it = std::find( |
| 92 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); | 111 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); |
| 93 | 112 |
| 94 // Can happen if touch exploration is enabled while fingers were down. | 113 // Can happen if touch exploration is enabled while fingers were down. |
| 95 if (it == current_touch_ids_.end()) | 114 if (it == current_touch_ids_.end()) |
| 96 return ui::EVENT_REWRITE_CONTINUE; | 115 return ui::EVENT_REWRITE_CONTINUE; |
| 97 | 116 |
| 98 current_touch_ids_.erase(it); | 117 current_touch_ids_.erase(it); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 121 case DOUBLE_TAP_PENDING: | 140 case DOUBLE_TAP_PENDING: |
| 122 return InDoubleTapPending(touch_event, rewritten_event); | 141 return InDoubleTapPending(touch_event, rewritten_event); |
| 123 case TOUCH_RELEASE_PENDING: | 142 case TOUCH_RELEASE_PENDING: |
| 124 return InTouchReleasePending(touch_event, rewritten_event); | 143 return InTouchReleasePending(touch_event, rewritten_event); |
| 125 case TOUCH_EXPLORATION: | 144 case TOUCH_EXPLORATION: |
| 126 return InTouchExploration(touch_event, rewritten_event); | 145 return InTouchExploration(touch_event, rewritten_event); |
| 127 case GESTURE_IN_PROGRESS: | 146 case GESTURE_IN_PROGRESS: |
| 128 return InGestureInProgress(touch_event, rewritten_event); | 147 return InGestureInProgress(touch_event, rewritten_event); |
| 129 case TOUCH_EXPLORE_SECOND_PRESS: | 148 case TOUCH_EXPLORE_SECOND_PRESS: |
| 130 return InTouchExploreSecondPress(touch_event, rewritten_event); | 149 return InTouchExploreSecondPress(touch_event, rewritten_event); |
| 150 case CORNER_PASSTHROUGH: | |
| 151 return InCornerPassthrough(touch_event, rewritten_event); | |
| 131 case SLIDE_GESTURE: | 152 case SLIDE_GESTURE: |
| 132 return InSlideGesture(touch_event, rewritten_event); | 153 return InSlideGesture(touch_event, rewritten_event); |
| 133 case ONE_FINGER_PASSTHROUGH: | 154 case ONE_FINGER_PASSTHROUGH: |
| 134 return InOneFingerPassthrough(touch_event, rewritten_event); | 155 return InOneFingerPassthrough(touch_event, rewritten_event); |
| 135 case WAIT_FOR_ONE_FINGER: | 156 case WAIT_FOR_ONE_FINGER: |
| 136 return InWaitForOneFinger(touch_event, rewritten_event); | 157 return InWaitForOneFinger(touch_event, rewritten_event); |
| 137 } | 158 } |
| 138 NOTREACHED(); | 159 NOTREACHED(); |
| 139 return ui::EVENT_REWRITE_CONTINUE; | 160 return ui::EVENT_REWRITE_CONTINUE; |
| 140 } | 161 } |
| 141 | 162 |
| 142 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 163 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
| 143 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 164 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
| 144 NOTREACHED(); | 165 NOTREACHED(); |
| 145 return ui::EVENT_REWRITE_CONTINUE; | 166 return ui::EVENT_REWRITE_CONTINUE; |
| 146 } | 167 } |
| 147 | 168 |
| 148 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( | 169 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
| 149 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 170 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
| 150 const ui::EventType type = event.type(); | 171 const ui::EventType type = event.type(); |
| 151 if (type == ui::ET_TOUCH_PRESSED) { | 172 if (type != ui::ET_TOUCH_PRESSED) { |
| 152 initial_press_.reset(new TouchEvent(event)); | 173 NOTREACHED() << "Unexpected event type received: " << event.name(); |
| 153 last_unused_finger_event_.reset(new TouchEvent(event)); | 174 return ui::EVENT_REWRITE_CONTINUE; |
| 154 StartTapTimer(); | |
| 155 gesture_provider_.OnTouchEvent(event); | |
| 156 gesture_provider_.OnTouchEventAck(false); | |
| 157 ProcessGestureEvents(); | |
| 158 state_ = SINGLE_TAP_PRESSED; | |
| 159 VLOG_STATE(); | |
| 160 return ui::EVENT_REWRITE_DISCARD; | |
| 161 } | 175 } |
| 162 NOTREACHED() << "Unexpected event type received: " << event.name(); | 176 int location = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
| 163 return ui::EVENT_REWRITE_CONTINUE; | 177 base::TimeDelta timeout; |
| 178 | |
| 179 // If the press was at a corner, the user might go into corner passthrough | |
| 180 // instead. | |
| 181 bool in_a_bottom_corner = | |
| 182 (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location); | |
| 183 if (in_a_bottom_corner) { | |
| 184 long_press_timer_.Start(FROM_HERE, | |
| 185 gesture_detector_config_.longpress_timeout, | |
| 186 this, | |
| 187 &TouchExplorationController::OnLongPressTimerFired); | |
| 188 waiting_for_corner_passthrough_ = true; | |
|
aboxhall
2014/08/06 18:10:45
Why not just use the long_press_timer_ (or corner_
lisayin
2014/08/06 20:37:35
I'm hoping to use this timer for evy's passthrough
| |
| 189 } else { | |
| 190 waiting_for_corner_passthrough_ = false; | |
| 191 } | |
| 192 tap_timer_.Start(FROM_HERE, | |
| 193 gesture_detector_config_.double_tap_timeout, | |
| 194 this, | |
| 195 &TouchExplorationController::OnTapTimerFired); | |
| 196 initial_press_.reset(new TouchEvent(event)); | |
| 197 last_unused_finger_event_.reset(new TouchEvent(event)); | |
| 198 gesture_provider_.OnTouchEvent(event); | |
| 199 gesture_provider_.OnTouchEventAck(false); | |
| 200 ProcessGestureEvents(); | |
| 201 state_ = SINGLE_TAP_PRESSED; | |
| 202 VLOG_STATE(); | |
| 203 return ui::EVENT_REWRITE_DISCARD; | |
| 164 } | 204 } |
| 165 | 205 |
| 166 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 206 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
| 167 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 207 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
| 168 const ui::EventType type = event.type(); | 208 const ui::EventType type = event.type(); |
| 169 | 209 |
| 210 int location = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); | |
| 211 bool in_a_bottom_corner = | |
| 212 (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER); | |
| 213 // If the event is from the initial press and the location is no longer in the | |
| 214 // corner, then we are not waiting for a corner passthrough anymore. | |
| 215 if (event.touch_id() == initial_press_->touch_id() && !in_a_bottom_corner) { | |
| 216 waiting_for_corner_passthrough_ = false; | |
| 217 if (long_press_timer_.IsRunning()) { | |
|
aboxhall
2014/08/06 18:10:44
If we're not going to use this for anything other
lisayin
2014/08/06 20:37:35
Done.
| |
| 218 long_press_timer_.Stop(); | |
| 219 if (event.time_stamp() - initial_press_->time_stamp() > | |
| 220 gesture_detector_config_.double_tap_timeout) { | |
| 221 OnTapTimerFired(); | |
|
aboxhall
2014/08/06 18:10:44
Why do this? Could you add a comment?
lisayin
2014/08/06 20:37:35
This is in case the finger moves out of the corner
aboxhall
2014/08/06 21:03:12
Ah, I see now. But won't the tap timer have been r
lisayin
2014/08/06 21:48:22
In TapTimerFired, if the long press timer is runni
aboxhall
2014/08/06 22:01:24
Oh, duh! Makes sense, thanks for the explanation :
| |
| 222 } | |
| 223 } | |
| 224 } | |
| 225 | |
| 170 if (type == ui::ET_TOUCH_PRESSED) { | 226 if (type == ui::ET_TOUCH_PRESSED) { |
| 171 // TODO (evy, lisayin) : add support for multifinger swipes. | 227 // TODO (evy, lisayin) : add support for multifinger swipes. |
| 172 // For now, we wait for there to be only one finger down again. | 228 // For now, we wait for there to be only one finger down again. |
| 173 state_ = WAIT_FOR_ONE_FINGER; | 229 state_ = WAIT_FOR_ONE_FINGER; |
| 174 return EVENT_REWRITE_DISCARD; | 230 return EVENT_REWRITE_DISCARD; |
| 175 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 231 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 176 if (current_touch_ids_.size() == 0 && | 232 if (current_touch_ids_.size() == 0 && |
| 177 event.touch_id() == initial_press_->touch_id()) { | 233 event.touch_id() == initial_press_->touch_id()) { |
| 178 state_ = SINGLE_TAP_RELEASED; | 234 state_ = SINGLE_TAP_RELEASED; |
| 179 VLOG_STATE(); | 235 VLOG_STATE(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 193 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); | 249 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); |
| 194 float velocity = distance / delta_time; | 250 float velocity = distance / delta_time; |
| 195 if (VLOG_on_) { | 251 if (VLOG_on_) { |
| 196 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance | 252 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance |
| 197 << "\n Velocity of click: " << velocity | 253 << "\n Velocity of click: " << velocity |
| 198 << "\n Minimum swipe velocity: " | 254 << "\n Minimum swipe velocity: " |
| 199 << gesture_detector_config_.minimum_swipe_velocity; | 255 << gesture_detector_config_.minimum_swipe_velocity; |
| 200 } | 256 } |
| 201 // Change to slide gesture if the slide occurred at the right edge. | 257 // Change to slide gesture if the slide occurred at the right edge. |
| 202 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); | 258 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
| 203 if (edge & RIGHT_EDGE) { | 259 if (edge & RIGHT_EDGE && edge != BOTTOM_RIGHT_CORNER) { |
| 204 state_ = SLIDE_GESTURE; | 260 state_ = SLIDE_GESTURE; |
| 205 VLOG_STATE(); | 261 VLOG_STATE(); |
| 206 return InSlideGesture(event, rewritten_event); | 262 return InSlideGesture(event, rewritten_event); |
| 207 } | 263 } |
| 208 | 264 |
| 209 // If the user moves fast enough from the initial touch location, start | 265 // If the user moves fast enough from the initial touch location, start |
| 210 // gesture detection. Otherwise, jump to the touch exploration mode early. | 266 // gesture detection. Otherwise, jump to the touch exploration mode early. |
| 211 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { | 267 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
| 212 state_ = GESTURE_IN_PROGRESS; | 268 state_ = GESTURE_IN_PROGRESS; |
| 213 VLOG_STATE(); | 269 VLOG_STATE(); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 gesture_provider_.OnTouchEvent(event); | 442 gesture_provider_.OnTouchEvent(event); |
| 387 gesture_provider_.OnTouchEventAck(false); | 443 gesture_provider_.OnTouchEventAck(false); |
| 388 if (current_touch_ids_.size() == 0) { | 444 if (current_touch_ids_.size() == 0) { |
| 389 ResetToNoFingersDown(); | 445 ResetToNoFingersDown(); |
| 390 } | 446 } |
| 391 } | 447 } |
| 392 ProcessGestureEvents(); | 448 ProcessGestureEvents(); |
| 393 return ui::EVENT_REWRITE_DISCARD; | 449 return ui::EVENT_REWRITE_DISCARD; |
| 394 } | 450 } |
| 395 | 451 |
| 452 ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough( | |
| 453 const ui::TouchEvent& event, | |
| 454 scoped_ptr<ui::Event>* rewritten_event) { | |
| 455 ui::EventType type = event.type(); | |
| 456 | |
| 457 // If the first finger has left the corner, then exit passthrough. | |
| 458 if (event.touch_id() == initial_press_->touch_id()) { | |
| 459 int edges = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); | |
| 460 bool in_a_bottom_corner = (edges == BOTTOM_LEFT_CORNER) || | |
| 461 (edges == BOTTOM_RIGHT_CORNER); | |
| 462 if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner) | |
| 463 return ui::EVENT_REWRITE_DISCARD; | |
| 464 | |
| 465 if (current_touch_ids_.size() == 0) { | |
| 466 ResetToNoFingersDown(); | |
| 467 return ui::EVENT_REWRITE_DISCARD; | |
| 468 } | |
| 469 | |
| 470 waiting_for_corner_passthrough_ = false; | |
| 471 state_ = WAIT_FOR_ONE_FINGER; | |
| 472 VLOG_STATE(); | |
| 473 return ui::EVENT_REWRITE_DISCARD; | |
| 474 } | |
| 475 | |
| 476 rewritten_event->reset(new ui::TouchEvent( | |
| 477 type, event.location(), event.touch_id(), event.time_stamp())); | |
| 478 (*rewritten_event)->set_flags(event.flags()); | |
| 479 | |
| 480 if (current_touch_ids_.size() == 0) | |
| 481 ResetToNoFingersDown(); | |
| 482 | |
| 483 return ui::EVENT_REWRITE_REWRITTEN; | |
| 484 } | |
| 485 | |
| 396 ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( | 486 ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( |
| 397 const ui::TouchEvent& event, | 487 const ui::TouchEvent& event, |
| 398 scoped_ptr<ui::Event>* rewritten_event) { | 488 scoped_ptr<ui::Event>* rewritten_event) { |
| 399 ui::EventType type = event.type(); | 489 ui::EventType type = event.type(); |
| 400 | 490 |
| 401 if (!(type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED || | 491 if (!(type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED || |
| 402 type == ui::ET_TOUCH_MOVED || type == ui::ET_TOUCH_PRESSED)) { | 492 type == ui::ET_TOUCH_MOVED || type == ui::ET_TOUCH_PRESSED)) { |
| 403 NOTREACHED() << "Unexpected event type received: " << event.name(); | 493 NOTREACHED() << "Unexpected event type received: " << event.name(); |
| 404 return ui::EVENT_REWRITE_CONTINUE; | 494 return ui::EVENT_REWRITE_CONTINUE; |
| 405 } | 495 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 VLOG_STATE(); | 551 VLOG_STATE(); |
| 462 return ui::EVENT_REWRITE_REWRITTEN; | 552 return ui::EVENT_REWRITE_REWRITTEN; |
| 463 } | 553 } |
| 464 NOTREACHED() << "Unexpected event type received: " << event.name(); | 554 NOTREACHED() << "Unexpected event type received: " << event.name(); |
| 465 return ui::EVENT_REWRITE_CONTINUE; | 555 return ui::EVENT_REWRITE_CONTINUE; |
| 466 } | 556 } |
| 467 | 557 |
| 468 ui::EventRewriteStatus TouchExplorationController::InWaitForOneFinger( | 558 ui::EventRewriteStatus TouchExplorationController::InWaitForOneFinger( |
| 469 const ui::TouchEvent& event, | 559 const ui::TouchEvent& event, |
| 470 scoped_ptr<ui::Event>* rewritten_event) { | 560 scoped_ptr<ui::Event>* rewritten_event) { |
| 561 waiting_for_corner_passthrough_ = false; | |
| 471 ui::EventType type = event.type(); | 562 ui::EventType type = event.type(); |
| 472 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || | 563 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || |
| 473 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { | 564 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { |
| 474 NOTREACHED() << "Unexpected event type received: " << event.name(); | 565 NOTREACHED() << "Unexpected event type received: " << event.name(); |
| 475 return ui::EVENT_REWRITE_CONTINUE; | 566 return ui::EVENT_REWRITE_CONTINUE; |
| 476 } | 567 } |
| 477 if (current_touch_ids_.size() == 1) { | 568 if (current_touch_ids_.size() == 1) { |
| 478 EnterTouchToMouseMode(); | 569 EnterTouchToMouseMode(); |
| 479 state_ = TOUCH_EXPLORATION; | 570 state_ = TOUCH_EXPLORATION; |
| 480 VLOG_STATE(); | 571 VLOG_STATE(); |
| 481 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); | 572 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); |
| 482 last_touch_exploration_.reset(new TouchEvent(event)); | 573 last_touch_exploration_.reset(new TouchEvent(event)); |
| 483 return ui::EVENT_REWRITE_REWRITTEN; | 574 return ui::EVENT_REWRITE_REWRITTEN; |
| 484 } | 575 } |
| 485 return EVENT_REWRITE_DISCARD; | 576 return EVENT_REWRITE_DISCARD; |
| 486 } | 577 } |
| 487 | 578 |
| 488 void TouchExplorationController::PlaySoundForTimer() { | 579 void TouchExplorationController::PlaySoundForTimer() { |
| 489 delegate_->PlayVolumeAdjustSound(); | 580 delegate_->PlayVolumeAdjustEarcon(); |
| 490 } | 581 } |
| 491 | 582 |
| 492 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | 583 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
| 493 const ui::TouchEvent& event, | 584 const ui::TouchEvent& event, |
| 494 scoped_ptr<ui::Event>* rewritten_event) { | 585 scoped_ptr<ui::Event>* rewritten_event) { |
| 495 // The timer should not fire when sliding. | 586 // The timer should not fire when sliding. |
| 496 if (tap_timer_.IsRunning()) | 587 if (tap_timer_.IsRunning()) |
| 497 tap_timer_.Stop(); | 588 tap_timer_.Stop(); |
| 498 | 589 |
| 499 ui::EventType type = event.type(); | 590 ui::EventType type = event.type(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 519 return EVENT_REWRITE_DISCARD; | 610 return EVENT_REWRITE_DISCARD; |
| 520 } | 611 } |
| 521 | 612 |
| 522 // This can occur if the user leaves the screen edge and then returns to it to | 613 // This can occur if the user leaves the screen edge and then returns to it to |
| 523 // continue adjusting the sound. | 614 // continue adjusting the sound. |
| 524 if (!sound_timer_.IsRunning()) { | 615 if (!sound_timer_.IsRunning()) { |
| 525 sound_timer_.Start(FROM_HERE, | 616 sound_timer_.Start(FROM_HERE, |
| 526 kSoundDelay, | 617 kSoundDelay, |
| 527 this, | 618 this, |
| 528 &ui::TouchExplorationController::PlaySoundForTimer); | 619 &ui::TouchExplorationController::PlaySoundForTimer); |
| 529 delegate_->PlayVolumeAdjustSound(); | 620 delegate_->PlayVolumeAdjustEarcon(); |
| 530 } | 621 } |
| 531 | 622 |
| 532 // There should not be more than one finger down. | 623 // There should not be more than one finger down. |
| 533 DCHECK(current_touch_ids_.size() <= 1); | 624 DCHECK(current_touch_ids_.size() <= 1); |
| 534 if (type == ui::ET_TOUCH_MOVED) { | 625 if (type == ui::ET_TOUCH_MOVED) { |
| 535 gesture_provider_.OnTouchEvent(event); | 626 gesture_provider_.OnTouchEvent(event); |
| 536 gesture_provider_.OnTouchEventAck(false); | 627 gesture_provider_.OnTouchEventAck(false); |
| 537 } | 628 } |
| 538 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 629 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 539 gesture_provider_.OnTouchEvent(event); | 630 gesture_provider_.OnTouchEvent(event); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 last_touch_exploration_->location(); | 673 last_touch_exploration_->location(); |
| 583 scoped_ptr<ui::TouchEvent> passthrough_press( | 674 scoped_ptr<ui::TouchEvent> passthrough_press( |
| 584 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 675 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
| 585 last_touch_exploration_->location(), | 676 last_touch_exploration_->location(), |
| 586 last_unused_finger_event_->touch_id(), | 677 last_unused_finger_event_->touch_id(), |
| 587 Now())); | 678 Now())); |
| 588 DispatchEvent(passthrough_press.get()); | 679 DispatchEvent(passthrough_press.get()); |
| 589 return; | 680 return; |
| 590 } | 681 } |
| 591 case SINGLE_TAP_PRESSED: | 682 case SINGLE_TAP_PRESSED: |
| 683 if (waiting_for_corner_passthrough_) | |
| 684 return; | |
| 592 case GESTURE_IN_PROGRESS: | 685 case GESTURE_IN_PROGRESS: |
| 593 // Discard any pending gestures. | 686 // Discard any pending gestures. |
| 594 delete gesture_provider_.GetAndResetPendingGestures(); | 687 delete gesture_provider_.GetAndResetPendingGestures(); |
| 595 state_ = TOUCH_EXPLORATION; | 688 state_ = TOUCH_EXPLORATION; |
| 596 VLOG_STATE(); | 689 VLOG_STATE(); |
| 597 break; | 690 break; |
| 598 default: | 691 default: |
| 599 return; | 692 return; |
| 600 } | 693 } |
| 601 EnterTouchToMouseMode(); | 694 EnterTouchToMouseMode(); |
| 602 scoped_ptr<ui::Event> mouse_move = | 695 scoped_ptr<ui::Event> mouse_move = |
| 603 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 696 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
| 604 DispatchEvent(mouse_move.get()); | 697 DispatchEvent(mouse_move.get()); |
| 605 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 698 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| 606 } | 699 } |
| 607 | 700 |
| 701 void TouchExplorationController::OnLongPressTimerFired() { | |
| 702 if (waiting_for_corner_passthrough_) { | |
|
aboxhall
2014/08/06 18:10:44
Invert this logic:
if (!waiting_for_corner_passthr
lisayin
2014/08/06 20:37:35
Done.
| |
| 703 if (sound_timer_.IsRunning()) | |
| 704 sound_timer_.Stop(); | |
| 705 delegate_->PlayPassthroughEarcon(); | |
| 706 delete gesture_provider_.GetAndResetPendingGestures(); | |
| 707 state_ = CORNER_PASSTHROUGH; | |
| 708 VLOG_STATE(); | |
| 709 return; | |
| 710 } | |
| 711 } | |
| 712 | |
| 608 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 713 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
| 609 ui::EventDispatchDetails result ALLOW_UNUSED = | 714 ui::EventDispatchDetails result ALLOW_UNUSED = |
| 610 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 715 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
| 611 } | 716 } |
| 612 | 717 |
| 613 void TouchExplorationController::OnGestureEvent( | 718 void TouchExplorationController::OnGestureEvent( |
| 614 ui::GestureEvent* gesture) { | 719 ui::GestureEvent* gesture) { |
| 615 CHECK(gesture->IsGestureEvent()); | 720 CHECK(gesture->IsGestureEvent()); |
| 616 ui::EventType type = gesture->type(); | 721 ui::EventType type = gesture->type(); |
| 617 if (VLOG_on_) | 722 if (VLOG_on_) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 639 } | 744 } |
| 640 } | 745 } |
| 641 } | 746 } |
| 642 | 747 |
| 643 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { | 748 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { |
| 644 ui::EventType type = gesture->type(); | 749 ui::EventType type = gesture->type(); |
| 645 if (!gesture->IsScrollGestureEvent()) | 750 if (!gesture->IsScrollGestureEvent()) |
| 646 return; | 751 return; |
| 647 | 752 |
| 648 if (type == ET_GESTURE_SCROLL_BEGIN) { | 753 if (type == ET_GESTURE_SCROLL_BEGIN) { |
| 649 delegate_->PlayVolumeAdjustSound(); | 754 delegate_->PlayVolumeAdjustEarcon(); |
| 650 } | 755 } |
| 651 | 756 |
| 652 if (type == ET_GESTURE_SCROLL_END) { | 757 if (type == ET_GESTURE_SCROLL_END) { |
| 653 if (sound_timer_.IsRunning()) | 758 if (sound_timer_.IsRunning()) |
| 654 sound_timer_.Stop(); | 759 sound_timer_.Stop(); |
| 655 delegate_->PlayVolumeAdjustSound(); | 760 delegate_->PlayVolumeAdjustEarcon(); |
| 656 } | 761 } |
| 657 | 762 |
| 658 // If the user is in the corner of the right side of the screen, the volume | 763 // 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 | 764 // 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 | 765 // 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 | 766 // their finger along the right side of the screen. Volume is relative to |
| 662 // where they are on the right side of the screen. | 767 // where they are on the right side of the screen. |
| 663 gfx::Point location = gesture->location(); | 768 gfx::Point location = gesture->location(); |
| 664 int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); | 769 int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); |
| 665 if (!(edge & RIGHT_EDGE)) | 770 if (!(edge & RIGHT_EDGE)) |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 void TouchExplorationController::EnterTouchToMouseMode() { | 897 void TouchExplorationController::EnterTouchToMouseMode() { |
| 793 aura::client::CursorClient* cursor_client = | 898 aura::client::CursorClient* cursor_client = |
| 794 aura::client::GetCursorClient(root_window_); | 899 aura::client::GetCursorClient(root_window_); |
| 795 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) | 900 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) |
| 796 cursor_client->EnableMouseEvents(); | 901 cursor_client->EnableMouseEvents(); |
| 797 if (cursor_client && cursor_client->IsCursorVisible()) | 902 if (cursor_client && cursor_client->IsCursorVisible()) |
| 798 cursor_client->HideCursor(); | 903 cursor_client->HideCursor(); |
| 799 } | 904 } |
| 800 | 905 |
| 801 void TouchExplorationController::ResetToNoFingersDown() { | 906 void TouchExplorationController::ResetToNoFingersDown() { |
| 907 waiting_for_corner_passthrough_ = false; | |
| 802 ProcessGestureEvents(); | 908 ProcessGestureEvents(); |
| 803 if (sound_timer_.IsRunning()) | 909 if (sound_timer_.IsRunning()) |
| 804 sound_timer_.Stop(); | 910 sound_timer_.Stop(); |
| 805 state_ = NO_FINGERS_DOWN; | 911 state_ = NO_FINGERS_DOWN; |
| 806 VLOG_STATE(); | 912 VLOG_STATE(); |
| 807 if (tap_timer_.IsRunning()) | 913 if (tap_timer_.IsRunning()) |
| 808 tap_timer_.Stop(); | 914 tap_timer_.Stop(); |
| 809 } | 915 } |
| 810 | 916 |
| 811 void TouchExplorationController::VlogState(const char* function_name) { | 917 void TouchExplorationController::VlogState(const char* function_name) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 862 case DOUBLE_TAP_PENDING: | 968 case DOUBLE_TAP_PENDING: |
| 863 return "DOUBLE_TAP_PENDING"; | 969 return "DOUBLE_TAP_PENDING"; |
| 864 case TOUCH_RELEASE_PENDING: | 970 case TOUCH_RELEASE_PENDING: |
| 865 return "TOUCH_RELEASE_PENDING"; | 971 return "TOUCH_RELEASE_PENDING"; |
| 866 case TOUCH_EXPLORATION: | 972 case TOUCH_EXPLORATION: |
| 867 return "TOUCH_EXPLORATION"; | 973 return "TOUCH_EXPLORATION"; |
| 868 case GESTURE_IN_PROGRESS: | 974 case GESTURE_IN_PROGRESS: |
| 869 return "GESTURE_IN_PROGRESS"; | 975 return "GESTURE_IN_PROGRESS"; |
| 870 case TOUCH_EXPLORE_SECOND_PRESS: | 976 case TOUCH_EXPLORE_SECOND_PRESS: |
| 871 return "TOUCH_EXPLORE_SECOND_PRESS"; | 977 return "TOUCH_EXPLORE_SECOND_PRESS"; |
| 978 case CORNER_PASSTHROUGH: | |
| 979 return "CORNER_PASSTHROUGH"; | |
| 872 case SLIDE_GESTURE: | 980 case SLIDE_GESTURE: |
| 873 return "SLIDE_GESTURE"; | 981 return "SLIDE_GESTURE"; |
| 874 case ONE_FINGER_PASSTHROUGH: | 982 case ONE_FINGER_PASSTHROUGH: |
| 875 return "ONE_FINGER_PASSTHROUGH"; | 983 return "ONE_FINGER_PASSTHROUGH"; |
| 876 case WAIT_FOR_ONE_FINGER: | 984 case WAIT_FOR_ONE_FINGER: |
| 877 return "WAIT_FOR_ONE_FINGER"; | 985 return "WAIT_FOR_ONE_FINGER"; |
| 878 } | 986 } |
| 879 return "Not a state"; | 987 return "Not a state"; |
| 880 } | 988 } |
| 881 | 989 |
| 882 } // namespace ui | 990 } // namespace ui |
| OLD | NEW |