| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/chromeos/touch_exploration_controller.h" | 5 #include "ui/chromeos/touch_exploration_controller.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/time/default_tick_clock.h" |
| 9 #include "ui/aura/client/cursor_client.h" | 10 #include "ui/aura/client/cursor_client.h" |
| 10 #include "ui/aura/window.h" | 11 #include "ui/aura/window.h" |
| 11 #include "ui/aura/window_event_dispatcher.h" | 12 #include "ui/aura/window_event_dispatcher.h" |
| 12 #include "ui/aura/window_tree_host.h" | 13 #include "ui/aura/window_tree_host.h" |
| 13 #include "ui/events/event.h" | 14 #include "ui/events/event.h" |
| 14 #include "ui/events/event_processor.h" | 15 #include "ui/events/event_processor.h" |
| 15 #include "ui/events/event_utils.h" | 16 #include "ui/events/event_utils.h" |
| 16 #include "ui/gfx/geometry/rect.h" | 17 #include "ui/gfx/geometry/rect.h" |
| 17 | 18 |
| 18 #define VLOG_STATE() if (VLOG_IS_ON(0)) VlogState(__func__) | 19 #define SET_STATE(state) SetState(state, __func__) |
| 19 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) | 20 #define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) |
| 20 | 21 |
| 21 namespace ui { | 22 namespace ui { |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // Delay between adjustment sounds. | 26 // Delay between adjustment sounds. |
| 26 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); | 27 const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); |
| 27 | 28 |
| 28 // In ChromeOS, VKEY_LWIN is synonymous for the search key. | 29 // In ChromeOS, VKEY_LWIN is synonymous for the search key. |
| 29 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; | 30 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; |
| 30 } // namespace | 31 } // namespace |
| 31 | 32 |
| 32 TouchExplorationController::TouchExplorationController( | 33 TouchExplorationController::TouchExplorationController( |
| 33 aura::Window* root_window, | 34 aura::Window* root_window, |
| 34 TouchExplorationControllerDelegate* delegate) | 35 TouchExplorationControllerDelegate* delegate) |
| 35 : root_window_(root_window), | 36 : root_window_(root_window), |
| 36 delegate_(delegate), | 37 delegate_(delegate), |
| 37 state_(NO_FINGERS_DOWN), | 38 state_(NO_FINGERS_DOWN), |
| 38 gesture_provider_(this), | 39 gesture_provider_(new GestureProviderAura(this)), |
| 39 prev_state_(NO_FINGERS_DOWN), | 40 prev_state_(NO_FINGERS_DOWN), |
| 40 VLOG_on_(true), | 41 VLOG_on_(true), |
| 41 tick_clock_(NULL) { | 42 tick_clock_(NULL) { |
| 42 CHECK(root_window); | 43 CHECK(root_window); |
| 43 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 44 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
| 45 InitializeSwipeGestureMaps(); |
| 44 } | 46 } |
| 45 | 47 |
| 46 TouchExplorationController::~TouchExplorationController() { | 48 TouchExplorationController::~TouchExplorationController() { |
| 47 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 49 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
| 48 } | 50 } |
| 49 | 51 |
| 50 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 52 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
| 51 const ui::Event& event, | 53 const ui::Event& event, |
| 52 scoped_ptr<ui::Event>* rewritten_event) { | 54 scoped_ptr<ui::Event>* rewritten_event) { |
| 53 if (!event.IsTouchEvent()) { | 55 if (!event.IsTouchEvent()) { |
| 56 if (event.IsKeyEvent()) { |
| 57 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); |
| 58 VLOG(0) << "\nKeyboard event: " << key_event.name() |
| 59 << "\n Key code: " << key_event.key_code() |
| 60 << ", Flags: " << key_event.flags() |
| 61 << ", Is char: " << key_event.is_char(); |
| 62 } |
| 54 return ui::EVENT_REWRITE_CONTINUE; | 63 return ui::EVENT_REWRITE_CONTINUE; |
| 55 } | 64 } |
| 56 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); | 65 const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); |
| 57 | 66 |
| 58 // If the tap timer should have fired by now but hasn't, run it now and | 67 // 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 | 68 // 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 | 69 // the timestamps of the events, and not dependent on the granularity of |
| 61 // the timer. | 70 // the timer. |
| 62 if (tap_timer_.IsRunning() && | 71 if (tap_timer_.IsRunning() && |
| 63 touch_event.time_stamp() - initial_press_->time_stamp() > | 72 touch_event.time_stamp() - initial_press_->time_stamp() > |
| 64 gesture_detector_config_.double_tap_timeout) { | 73 gesture_detector_config_.double_tap_timeout) { |
| 65 tap_timer_.Stop(); | 74 tap_timer_.Stop(); |
| 66 OnTapTimerFired(); | 75 OnTapTimerFired(); |
| 67 // 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 |
| 68 // this event under this new state. | 77 // this event under this new state. |
| 69 } | 78 } |
| 70 | 79 |
| 71 const ui::EventType type = touch_event.type(); | 80 const ui::EventType type = touch_event.type(); |
| 72 const gfx::PointF& location = touch_event.location_f(); | 81 const gfx::PointF& location = touch_event.location_f(); |
| 73 const int touch_id = touch_event.touch_id(); | 82 const int touch_id = touch_event.touch_id(); |
| 74 | 83 |
| 75 // Always update touch ids and touch locations, so we can use those | 84 // Always update touch ids and touch locations, so we can use those |
| 76 // no matter what state we're in. | 85 // no matter what state we're in. |
| 77 if (type == ui::ET_TOUCH_PRESSED) { | 86 if (type == ui::ET_TOUCH_PRESSED) { |
| 78 current_touch_ids_.push_back(touch_id); | 87 current_touch_ids_.push_back(touch_id); |
| 79 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); | 88 touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); |
| 80 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 89 } 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 | |
| 82 // the screen, the state will be rewritten to NoFingersDown. | |
| 83 TouchEvent touch_event = static_cast<const TouchEvent&>(event); | |
| 84 if (FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != | |
| 85 NO_EDGE) { | |
| 86 if (current_touch_ids_.size() == 0) { | |
| 87 ResetToNoFingersDown(); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 std::vector<int>::iterator it = std::find( | 90 std::vector<int>::iterator it = std::find( |
| 92 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); | 91 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); |
| 93 | 92 |
| 94 // Can happen if touch exploration is enabled while fingers were down. | 93 // Can happen if touch exploration is enabled while fingers were down. |
| 95 if (it == current_touch_ids_.end()) | 94 if (it == current_touch_ids_.end()) |
| 96 return ui::EVENT_REWRITE_CONTINUE; | 95 return ui::EVENT_REWRITE_CONTINUE; |
| 97 | 96 |
| 98 current_touch_ids_.erase(it); | 97 current_touch_ids_.erase(it); |
| 99 touch_locations_.erase(touch_id); | 98 touch_locations_.erase(touch_id); |
| 100 } else if (type == ui::ET_TOUCH_MOVED) { | 99 } else if (type == ui::ET_TOUCH_MOVED) { |
| 101 std::vector<int>::iterator it = std::find( | 100 std::vector<int>::iterator it = std::find( |
| 102 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); | 101 current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); |
| 103 | 102 |
| 104 // Can happen if touch exploration is enabled while fingers were down. | 103 // Can happen if touch exploration is enabled while fingers were down. |
| 105 if (it == current_touch_ids_.end()) | 104 if (it == current_touch_ids_.end()) |
| 106 return ui::EVENT_REWRITE_CONTINUE; | 105 return ui::EVENT_REWRITE_CONTINUE; |
| 107 | 106 |
| 108 touch_locations_[*it] = location; | 107 touch_locations_[*it] = location; |
| 108 } else { |
| 109 NOTREACHED() << "Unexpected event type received: " << event.name(); |
| 110 return ui::EVENT_REWRITE_CONTINUE; |
| 109 } | 111 } |
| 110 VLOG_STATE(); | |
| 111 VLOG_EVENT(touch_event); | 112 VLOG_EVENT(touch_event); |
| 113 |
| 114 // In order to avoid accidentally double tapping when moving off the edge |
| 115 // of the screen, the state will be rewritten to NoFingersDown. |
| 116 if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) && |
| 117 FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != |
| 118 NO_EDGE) { |
| 119 if (current_touch_ids_.size() == 0) { |
| 120 SET_STATE(NO_FINGERS_DOWN); |
| 121 if (VLOG_on_) { |
| 122 VLOG(0) << "Reset to no fingers in Rewrite event because the touch " |
| 123 "release or cancel was on the edge of the screen."; |
| 124 } |
| 125 return ui::EVENT_REWRITE_DISCARD; |
| 126 } |
| 127 } |
| 128 |
| 129 // If the user is in a gesture state, or if there is a possiblity that the |
| 130 // user will enter it in the future, we send the event to the gesture |
| 131 // provider so it can keep track of the state of the fingers. When the user |
| 132 // leaves one of these states, SET_STATE will set the gesture provider to |
| 133 // NULL. |
| 134 if (gesture_provider_.get()) { |
| 135 gesture_provider_->OnTouchEvent(touch_event); |
| 136 gesture_provider_->OnTouchEventAck(false); |
| 137 ProcessGestureEvents(); |
| 138 } |
| 139 |
| 112 // The rest of the processing depends on what state we're in. | 140 // The rest of the processing depends on what state we're in. |
| 113 switch(state_) { | 141 switch (state_) { |
| 114 case NO_FINGERS_DOWN: | 142 case NO_FINGERS_DOWN: |
| 115 return InNoFingersDown(touch_event, rewritten_event); | 143 return InNoFingersDown(touch_event, rewritten_event); |
| 116 case SINGLE_TAP_PRESSED: | 144 case SINGLE_TAP_PRESSED: |
| 117 return InSingleTapPressed(touch_event, rewritten_event); | 145 return InSingleTapPressed(touch_event, rewritten_event); |
| 118 case SINGLE_TAP_RELEASED: | 146 case SINGLE_TAP_RELEASED: |
| 119 case TOUCH_EXPLORE_RELEASED: | 147 case TOUCH_EXPLORE_RELEASED: |
| 120 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); | 148 return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); |
| 121 case DOUBLE_TAP_PENDING: | 149 case DOUBLE_TAP_PENDING: |
| 122 return InDoubleTapPending(touch_event, rewritten_event); | 150 return InDoubleTapPending(touch_event, rewritten_event); |
| 123 case TOUCH_RELEASE_PENDING: | 151 case TOUCH_RELEASE_PENDING: |
| 124 return InTouchReleasePending(touch_event, rewritten_event); | 152 return InTouchReleasePending(touch_event, rewritten_event); |
| 125 case TOUCH_EXPLORATION: | 153 case TOUCH_EXPLORATION: |
| 126 return InTouchExploration(touch_event, rewritten_event); | 154 return InTouchExploration(touch_event, rewritten_event); |
| 127 case GESTURE_IN_PROGRESS: | 155 case GESTURE_IN_PROGRESS: |
| 128 return InGestureInProgress(touch_event, rewritten_event); | 156 return InGestureInProgress(touch_event, rewritten_event); |
| 129 case TOUCH_EXPLORE_SECOND_PRESS: | 157 case TOUCH_EXPLORE_SECOND_PRESS: |
| 130 return InTouchExploreSecondPress(touch_event, rewritten_event); | 158 return InTouchExploreSecondPress(touch_event, rewritten_event); |
| 131 case SLIDE_GESTURE: | 159 case SLIDE_GESTURE: |
| 132 return InSlideGesture(touch_event, rewritten_event); | 160 return InSlideGesture(touch_event, rewritten_event); |
| 133 case ONE_FINGER_PASSTHROUGH: | 161 case ONE_FINGER_PASSTHROUGH: |
| 134 return InOneFingerPassthrough(touch_event, rewritten_event); | 162 return InOneFingerPassthrough(touch_event, rewritten_event); |
| 135 case WAIT_FOR_ONE_FINGER: | 163 case WAIT_FOR_NO_FINGERS: |
| 136 return InWaitForOneFinger(touch_event, rewritten_event); | 164 return InWaitForNoFingers(touch_event, rewritten_event); |
| 137 case TWO_FINGER_TAP: | 165 case TWO_FINGER_TAP: |
| 138 return InTwoFingerTap(touch_event, rewritten_event); | 166 return InTwoFingerTap(touch_event, rewritten_event); |
| 139 } | 167 } |
| 140 NOTREACHED(); | 168 NOTREACHED(); |
| 141 return ui::EVENT_REWRITE_CONTINUE; | 169 return ui::EVENT_REWRITE_CONTINUE; |
| 142 } | 170 } |
| 143 | 171 |
| 144 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( | 172 ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( |
| 145 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { | 173 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { |
| 146 NOTREACHED(); | 174 NOTREACHED(); |
| 147 return ui::EVENT_REWRITE_CONTINUE; | 175 return ui::EVENT_REWRITE_CONTINUE; |
| 148 } | 176 } |
| 149 | 177 |
| 150 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( | 178 ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( |
| 151 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 179 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
| 152 const ui::EventType type = event.type(); | 180 ui::EventType type = event.type(); |
| 153 if (type != ui::ET_TOUCH_PRESSED) { | 181 if (type == ui::ET_TOUCH_PRESSED) { |
| 154 NOTREACHED() << "Unexpected event type received: " << event.name(); | 182 initial_press_.reset(new TouchEvent(event)); |
| 155 return ui::EVENT_REWRITE_CONTINUE; | 183 initial_presses_[event.touch_id()] = event.location(); |
| 184 last_unused_finger_event_.reset(new TouchEvent(event)); |
| 185 StartTapTimer(); |
| 186 SET_STATE(SINGLE_TAP_PRESSED); |
| 187 return ui::EVENT_REWRITE_DISCARD; |
| 156 } | 188 } |
| 157 initial_press_.reset(new TouchEvent(event)); | 189 NOTREACHED() << "Unexpected event type received: " << event.name(); |
| 158 initial_presses_[event.touch_id()] = event.location(); | 190 return ui::EVENT_REWRITE_CONTINUE; |
| 159 last_unused_finger_event_.reset(new TouchEvent(event)); | |
| 160 StartTapTimer(); | |
| 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 } | 191 } |
| 168 | 192 |
| 169 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( | 193 ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
| 170 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { | 194 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { |
| 171 const ui::EventType type = event.type(); | 195 const ui::EventType type = event.type(); |
| 172 | 196 |
| 173 if (type == ui::ET_TOUCH_PRESSED) { | 197 if (type == ui::ET_TOUCH_PRESSED) { |
| 174 initial_presses_[event.touch_id()] = event.location(); | 198 initial_presses_[event.touch_id()] = event.location(); |
| 175 state_ = TWO_FINGER_TAP; | 199 SET_STATE(TWO_FINGER_TAP); |
| 176 VLOG_STATE(); | |
| 177 return EVENT_REWRITE_DISCARD; | 200 return EVENT_REWRITE_DISCARD; |
| 178 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 201 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 179 if (current_touch_ids_.size() == 0 && | 202 if (current_touch_ids_.size() == 0 && |
| 180 event.touch_id() == initial_press_->touch_id()) { | 203 event.touch_id() == initial_press_->touch_id()) { |
| 181 state_ = SINGLE_TAP_RELEASED; | 204 SET_STATE(SINGLE_TAP_RELEASED); |
| 182 VLOG_STATE(); | |
| 183 } else if (current_touch_ids_.size() == 0) { | 205 } else if (current_touch_ids_.size() == 0) { |
| 184 ResetToNoFingersDown(); | 206 SET_STATE(NO_FINGERS_DOWN); |
| 185 } | 207 } |
| 186 return EVENT_REWRITE_DISCARD; | 208 return EVENT_REWRITE_DISCARD; |
| 187 } else if (type == ui::ET_TOUCH_MOVED) { | 209 } else if (type == ui::ET_TOUCH_MOVED) { |
| 188 float distance = (event.location() - initial_press_->location()).Length(); | 210 float distance = (event.location() - initial_press_->location()).Length(); |
| 189 // If the user does not move far enough from the original position, then the | 211 // If the user does not move far enough from the original position, then the |
| 190 // resulting movement should not be considered to be a deliberate gesture or | 212 // resulting movement should not be considered to be a deliberate gesture or |
| 191 // touch exploration. | 213 // touch exploration. |
| 192 if (distance <= gesture_detector_config_.touch_slop) | 214 if (distance <= gesture_detector_config_.touch_slop) |
| 193 return EVENT_REWRITE_DISCARD; | 215 return EVENT_REWRITE_DISCARD; |
| 194 | 216 |
| 195 float delta_time = | 217 float delta_time = |
| 196 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); | 218 (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); |
| 197 float velocity = distance / delta_time; | 219 float velocity = distance / delta_time; |
| 198 if (VLOG_on_) { | 220 if (VLOG_on_) { |
| 199 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance | 221 VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance |
| 200 << "\n Velocity of click: " << velocity | 222 << "\n Velocity of click: " << velocity |
| 201 << "\n Minimum swipe velocity: " | 223 << "\n Minimum swipe velocity: " |
| 202 << gesture_detector_config_.minimum_swipe_velocity; | 224 << gesture_detector_config_.minimum_swipe_velocity; |
| 203 } | 225 } |
| 204 // Change to slide gesture if the slide occurred at the right edge. | 226 // Change to slide gesture if the slide occurred at the right edge. |
| 205 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); | 227 int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); |
| 206 if (edge & RIGHT_EDGE) { | 228 if (edge & RIGHT_EDGE) { |
| 207 state_ = SLIDE_GESTURE; | 229 SET_STATE(SLIDE_GESTURE); |
| 208 VLOG_STATE(); | |
| 209 return InSlideGesture(event, rewritten_event); | 230 return InSlideGesture(event, rewritten_event); |
| 210 } | 231 } |
| 211 | 232 |
| 212 // If the user moves fast enough from the initial touch location, start | 233 // If the user moves fast enough from the initial touch location, start |
| 213 // gesture detection. Otherwise, jump to the touch exploration mode early. | 234 // gesture detection. Otherwise, jump to the touch exploration mode early. |
| 214 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { | 235 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
| 215 state_ = GESTURE_IN_PROGRESS; | 236 SET_STATE(GESTURE_IN_PROGRESS); |
| 216 VLOG_STATE(); | |
| 217 return InGestureInProgress(event, rewritten_event); | 237 return InGestureInProgress(event, rewritten_event); |
| 218 } | 238 } |
| 219 EnterTouchToMouseMode(); | 239 EnterTouchToMouseMode(); |
| 220 state_ = TOUCH_EXPLORATION; | 240 SET_STATE(TOUCH_EXPLORATION); |
| 221 VLOG_STATE(); | |
| 222 return InTouchExploration(event, rewritten_event); | 241 return InTouchExploration(event, rewritten_event); |
| 223 } | 242 } |
| 224 NOTREACHED() << "Unexpected event type received: " << event.name(); | 243 NOTREACHED(); |
| 225 return ui::EVENT_REWRITE_CONTINUE; | 244 return ui::EVENT_REWRITE_CONTINUE; |
| 226 } | 245 } |
| 227 | 246 |
| 228 ui::EventRewriteStatus | 247 ui::EventRewriteStatus |
| 229 TouchExplorationController::InSingleTapOrTouchExploreReleased( | 248 TouchExplorationController::InSingleTapOrTouchExploreReleased( |
| 230 const ui::TouchEvent& event, | 249 const ui::TouchEvent& event, |
| 231 scoped_ptr<ui::Event>* rewritten_event) { | 250 scoped_ptr<ui::Event>* rewritten_event) { |
| 232 const ui::EventType type = event.type(); | 251 const ui::EventType type = event.type(); |
| 233 // If there is more than one finger down, then discard to wait until only one | 252 // If there is more than one finger down, then discard to wait until no |
| 234 // finger is or no fingers are down. | 253 // fingers are down. |
| 235 if (current_touch_ids_.size() > 1) { | 254 if (current_touch_ids_.size() > 1) { |
| 236 state_ = WAIT_FOR_ONE_FINGER; | 255 SET_STATE(WAIT_FOR_NO_FINGERS); |
| 237 return ui::EVENT_REWRITE_DISCARD; | 256 return ui::EVENT_REWRITE_DISCARD; |
| 238 } | 257 } |
| 239 if (type == ui::ET_TOUCH_PRESSED) { | 258 if (type == ui::ET_TOUCH_PRESSED) { |
| 240 // If there is no touch exploration yet, we can't send a click, so discard. | 259 // If there is no touch exploration yet, we can't send a click, so discard. |
| 241 if (!last_touch_exploration_) { | 260 if (!last_touch_exploration_) { |
| 242 tap_timer_.Stop(); | 261 tap_timer_.Stop(); |
| 243 return ui::EVENT_REWRITE_DISCARD; | 262 return ui::EVENT_REWRITE_DISCARD; |
| 244 } | 263 } |
| 245 // This is the second tap in a double-tap (or double tap-hold). | 264 // This is the second tap in a double-tap (or double tap-hold). |
| 246 // We set the tap timer. If it fires before the user lifts their finger, | 265 // We set the tap timer. If it fires before the user lifts their finger, |
| 247 // one-finger passthrough begins. Otherwise, there is a touch press and | 266 // one-finger passthrough begins. Otherwise, there is a touch press and |
| 248 // release at the location of the last touch exploration. | 267 // release at the location of the last touch exploration. |
| 249 state_ = DOUBLE_TAP_PENDING; | 268 SET_STATE(DOUBLE_TAP_PENDING); |
| 250 VLOG_STATE(); | 269 // The old tap timer (from the initial click) is stopped if it is still |
| 270 // going, and the new one is set. |
| 271 tap_timer_.Stop(); |
| 251 StartTapTimer(); | 272 StartTapTimer(); |
| 252 // This will update as the finger moves before a possible passthrough, and | 273 // This will update as the finger moves before a possible passthrough, and |
| 253 // will determine the offset. | 274 // will determine the offset. |
| 254 last_unused_finger_event_.reset(new ui::TouchEvent(event)); | 275 last_unused_finger_event_.reset(new ui::TouchEvent(event)); |
| 255 return ui::EVENT_REWRITE_DISCARD; | 276 return ui::EVENT_REWRITE_DISCARD; |
| 256 } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) { | 277 } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) { |
| 257 // If the previous press was discarded, we need to also handle its | 278 // If the previous press was discarded, we need to also handle its |
| 258 // release. | 279 // release. |
| 259 if (current_touch_ids_.size() == 0) { | 280 if (current_touch_ids_.size() == 0) { |
| 260 ResetToNoFingersDown(); | 281 SET_STATE(NO_FINGERS_DOWN); |
| 261 } | 282 } |
| 262 return ui::EVENT_REWRITE_DISCARD; | 283 return ui::EVENT_REWRITE_DISCARD; |
| 263 } else if (type == ui::ET_TOUCH_MOVED) { | 284 } else if (type == ui::ET_TOUCH_MOVED) { |
| 264 return ui::EVENT_REWRITE_DISCARD; | 285 return ui::EVENT_REWRITE_DISCARD; |
| 265 } | 286 } |
| 266 NOTREACHED() << "Unexpected event type received: " << event.name(); | 287 NOTREACHED(); |
| 267 return ui::EVENT_REWRITE_CONTINUE; | 288 return ui::EVENT_REWRITE_CONTINUE; |
| 268 } | 289 } |
| 269 | 290 |
| 270 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending( | 291 ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending( |
| 271 const ui::TouchEvent& event, | 292 const ui::TouchEvent& event, |
| 272 scoped_ptr<ui::Event>* rewritten_event) { | 293 scoped_ptr<ui::Event>* rewritten_event) { |
| 273 const ui::EventType type = event.type(); | 294 const ui::EventType type = event.type(); |
| 274 if (type == ui::ET_TOUCH_PRESSED) { | 295 if (type == ui::ET_TOUCH_PRESSED) { |
| 275 return ui::EVENT_REWRITE_DISCARD; | 296 return ui::EVENT_REWRITE_DISCARD; |
| 276 } else if (type == ui::ET_TOUCH_MOVED) { | 297 } else if (type == ui::ET_TOUCH_MOVED) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 292 initial_press_->touch_id(), | 313 initial_press_->touch_id(), |
| 293 event.time_stamp())); | 314 event.time_stamp())); |
| 294 DispatchEvent(touch_press.get()); | 315 DispatchEvent(touch_press.get()); |
| 295 | 316 |
| 296 rewritten_event->reset( | 317 rewritten_event->reset( |
| 297 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 318 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
| 298 last_touch_exploration_->location(), | 319 last_touch_exploration_->location(), |
| 299 initial_press_->touch_id(), | 320 initial_press_->touch_id(), |
| 300 event.time_stamp())); | 321 event.time_stamp())); |
| 301 (*rewritten_event)->set_flags(event.flags()); | 322 (*rewritten_event)->set_flags(event.flags()); |
| 302 ResetToNoFingersDown(); | 323 SET_STATE(NO_FINGERS_DOWN); |
| 303 return ui::EVENT_REWRITE_REWRITTEN; | 324 return ui::EVENT_REWRITE_REWRITTEN; |
| 304 } | 325 } |
| 305 NOTREACHED() << "Unexpected event type received: " << event.name(); | 326 NOTREACHED(); |
| 306 return ui::EVENT_REWRITE_CONTINUE; | 327 return ui::EVENT_REWRITE_CONTINUE; |
| 307 } | 328 } |
| 308 | 329 |
| 309 ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( | 330 ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( |
| 310 const ui::TouchEvent& event, | 331 const ui::TouchEvent& event, |
| 311 scoped_ptr<ui::Event>* rewritten_event) { | 332 scoped_ptr<ui::Event>* rewritten_event) { |
| 312 const ui::EventType type = event.type(); | 333 const ui::EventType type = event.type(); |
| 313 if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { | 334 if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { |
| 314 return ui::EVENT_REWRITE_DISCARD; | 335 return ui::EVENT_REWRITE_DISCARD; |
| 315 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 336 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 316 if (current_touch_ids_.size() != 0) | 337 if (current_touch_ids_.size() != 0) |
| 317 return EVENT_REWRITE_DISCARD; | 338 return EVENT_REWRITE_DISCARD; |
| 318 | 339 |
| 319 rewritten_event->reset( | 340 rewritten_event->reset( |
| 320 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 341 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
| 321 last_touch_exploration_->location(), | 342 last_touch_exploration_->location(), |
| 322 initial_press_->touch_id(), | 343 initial_press_->touch_id(), |
| 323 event.time_stamp())); | 344 event.time_stamp())); |
| 324 (*rewritten_event)->set_flags(event.flags()); | 345 (*rewritten_event)->set_flags(event.flags()); |
| 325 ResetToNoFingersDown(); | 346 SET_STATE(NO_FINGERS_DOWN); |
| 326 return ui::EVENT_REWRITE_REWRITTEN; | 347 return ui::EVENT_REWRITE_REWRITTEN; |
| 327 } | 348 } |
| 328 NOTREACHED() << "Unexpected event type received: " << event.name(); | 349 NOTREACHED(); |
| 329 return ui::EVENT_REWRITE_CONTINUE; | 350 return ui::EVENT_REWRITE_CONTINUE; |
| 330 } | 351 } |
| 331 | 352 |
| 332 ui::EventRewriteStatus TouchExplorationController::InTouchExploration( | 353 ui::EventRewriteStatus TouchExplorationController::InTouchExploration( |
| 333 const ui::TouchEvent& event, | 354 const ui::TouchEvent& event, |
| 334 scoped_ptr<ui::Event>* rewritten_event) { | 355 scoped_ptr<ui::Event>* rewritten_event) { |
| 335 const ui::EventType type = event.type(); | 356 const ui::EventType type = event.type(); |
| 336 if (type == ui::ET_TOUCH_PRESSED) { | 357 if (type == ui::ET_TOUCH_PRESSED) { |
| 337 // Handle split-tap. | 358 // Handle split-tap. |
| 338 initial_press_.reset(new TouchEvent(event)); | 359 initial_press_.reset(new TouchEvent(event)); |
| 339 if (tap_timer_.IsRunning()) | 360 tap_timer_.Stop(); |
| 340 tap_timer_.Stop(); | |
| 341 rewritten_event->reset( | 361 rewritten_event->reset( |
| 342 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 362 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
| 343 last_touch_exploration_->location(), | 363 last_touch_exploration_->location(), |
| 344 event.touch_id(), | 364 event.touch_id(), |
| 345 event.time_stamp())); | 365 event.time_stamp())); |
| 346 (*rewritten_event)->set_flags(event.flags()); | 366 (*rewritten_event)->set_flags(event.flags()); |
| 347 state_ = TOUCH_EXPLORE_SECOND_PRESS; | 367 SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); |
| 348 VLOG_STATE(); | |
| 349 return ui::EVENT_REWRITE_REWRITTEN; | 368 return ui::EVENT_REWRITE_REWRITTEN; |
| 350 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 369 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 351 initial_press_.reset(new TouchEvent(event)); | 370 initial_press_.reset(new TouchEvent(event)); |
| 352 StartTapTimer(); | 371 StartTapTimer(); |
| 353 state_ = TOUCH_EXPLORE_RELEASED; | 372 SET_STATE(TOUCH_EXPLORE_RELEASED); |
| 354 VLOG_STATE(); | |
| 355 } else if (type != ui::ET_TOUCH_MOVED) { | 373 } else if (type != ui::ET_TOUCH_MOVED) { |
| 356 NOTREACHED() << "Unexpected event type received: " << event.name(); | 374 NOTREACHED(); |
| 357 return ui::EVENT_REWRITE_CONTINUE; | 375 return ui::EVENT_REWRITE_CONTINUE; |
| 358 } | 376 } |
| 359 | 377 |
| 360 // Rewrite as a mouse-move event. | 378 // Rewrite as a mouse-move event. |
| 361 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); | 379 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); |
| 362 last_touch_exploration_.reset(new TouchEvent(event)); | 380 last_touch_exploration_.reset(new TouchEvent(event)); |
| 363 return ui::EVENT_REWRITE_REWRITTEN; | 381 return ui::EVENT_REWRITE_REWRITTEN; |
| 364 } | 382 } |
| 365 | 383 |
| 366 ui::EventRewriteStatus TouchExplorationController::InGestureInProgress( | 384 ui::EventRewriteStatus TouchExplorationController::InGestureInProgress( |
| 367 const ui::TouchEvent& event, | 385 const ui::TouchEvent& event, |
| 368 scoped_ptr<ui::Event>* rewritten_event) { | 386 scoped_ptr<ui::Event>* rewritten_event) { |
| 369 ui::EventType type = event.type(); | 387 // The events were sent to the gesture provider in RewriteEvent already. |
| 370 // If additional fingers are added before a swipe gesture has been | 388 // If no gesture is registered before the tap timer times out, the state |
| 371 // registered, then the state will no longer be GESTURE_IN_PROGRESS. | 389 // will change to "wait for no fingers down" or "touch exploration" depending |
| 372 if (type == ui::ET_TOUCH_PRESSED || | 390 // on the number of fingers down, and this function will stop being called. |
| 373 event.touch_id() != initial_press_->touch_id()) { | 391 if (current_touch_ids_.size() == 0) { |
| 374 if (tap_timer_.IsRunning()) | 392 SET_STATE(NO_FINGERS_DOWN); |
| 375 tap_timer_.Stop(); | |
| 376 // Discard any pending gestures. | |
| 377 delete gesture_provider_.GetAndResetPendingGestures(); | |
| 378 state_ = WAIT_FOR_ONE_FINGER; | |
| 379 return EVENT_REWRITE_DISCARD; | |
| 380 } | 393 } |
| 381 | |
| 382 // There should not be more than one finger down. | |
| 383 DCHECK(current_touch_ids_.size() <= 1); | |
| 384 if (type == ui::ET_TOUCH_MOVED) { | |
| 385 gesture_provider_.OnTouchEvent(event); | |
| 386 gesture_provider_.OnTouchEventAck(false); | |
| 387 } | |
| 388 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | |
| 389 gesture_provider_.OnTouchEvent(event); | |
| 390 gesture_provider_.OnTouchEventAck(false); | |
| 391 if (current_touch_ids_.size() == 0) { | |
| 392 ResetToNoFingersDown(); | |
| 393 } | |
| 394 } | |
| 395 ProcessGestureEvents(); | |
| 396 return ui::EVENT_REWRITE_DISCARD; | 394 return ui::EVENT_REWRITE_DISCARD; |
| 397 } | 395 } |
| 398 | 396 |
| 399 ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( | 397 ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( |
| 400 const ui::TouchEvent& event, | 398 const ui::TouchEvent& event, |
| 401 scoped_ptr<ui::Event>* rewritten_event) { | 399 scoped_ptr<ui::Event>* rewritten_event) { |
| 402 ui::EventType type = event.type(); | |
| 403 | |
| 404 if (!(type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED || | |
| 405 type == ui::ET_TOUCH_MOVED || type == ui::ET_TOUCH_PRESSED)) { | |
| 406 NOTREACHED() << "Unexpected event type received: " << event.name(); | |
| 407 return ui::EVENT_REWRITE_CONTINUE; | |
| 408 } | |
| 409 if (event.touch_id() != initial_press_->touch_id()) { | 400 if (event.touch_id() != initial_press_->touch_id()) { |
| 410 if (current_touch_ids_.size() == 0) { | 401 if (current_touch_ids_.size() == 0) { |
| 411 ResetToNoFingersDown(); | 402 SET_STATE(NO_FINGERS_DOWN); |
| 412 } | 403 } |
| 413 return ui::EVENT_REWRITE_DISCARD; | 404 return ui::EVENT_REWRITE_DISCARD; |
| 414 } | 405 } |
| 415 rewritten_event->reset( | 406 rewritten_event->reset( |
| 416 new ui::TouchEvent(event.type(), | 407 new ui::TouchEvent(event.type(), |
| 417 event.location() - passthrough_offset_, | 408 event.location() - passthrough_offset_, |
| 418 event.touch_id(), | 409 event.touch_id(), |
| 419 event.time_stamp())); | 410 event.time_stamp())); |
| 420 | 411 |
| 421 (*rewritten_event)->set_flags(event.flags()); | 412 (*rewritten_event)->set_flags(event.flags()); |
| 422 if (current_touch_ids_.size() == 0) { | 413 if (current_touch_ids_.size() == 0) { |
| 423 ResetToNoFingersDown(); | 414 SET_STATE(NO_FINGERS_DOWN); |
| 424 } | 415 } |
| 425 | |
| 426 return ui::EVENT_REWRITE_REWRITTEN; | 416 return ui::EVENT_REWRITE_REWRITTEN; |
| 427 } | 417 } |
| 428 | 418 |
| 429 ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress( | 419 ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress( |
| 430 const ui::TouchEvent& event, | 420 const ui::TouchEvent& event, |
| 431 scoped_ptr<ui::Event>* rewritten_event) { | 421 scoped_ptr<ui::Event>* rewritten_event) { |
| 432 ui::EventType type = event.type(); | 422 ui::EventType type = event.type(); |
| 433 gfx::PointF location = event.location_f(); | 423 gfx::PointF location = event.location_f(); |
| 434 if (type == ui::ET_TOUCH_PRESSED) { | 424 if (type == ui::ET_TOUCH_PRESSED) { |
| 435 return ui::EVENT_REWRITE_DISCARD; | 425 return ui::EVENT_REWRITE_DISCARD; |
| 436 } else if (type == ui::ET_TOUCH_MOVED) { | 426 } else if (type == ui::ET_TOUCH_MOVED) { |
| 437 // Currently this is a discard, but could be something like rotor | 427 // Currently this is a discard, but could be something like rotor |
| 438 // in the future. | 428 // in the future. |
| 439 return ui::EVENT_REWRITE_DISCARD; | 429 return ui::EVENT_REWRITE_DISCARD; |
| 440 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 430 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 441 // If the touch exploration finger is lifted, there is no option to return | 431 // If the touch exploration finger is lifted, there is no option to return |
| 442 // to touch explore anymore. The remaining finger acts as a pending | 432 // to touch explore anymore. The remaining finger acts as a pending |
| 443 // tap or long tap for the last touch explore location. | 433 // tap or long tap for the last touch explore location. |
| 444 if (event.touch_id() == last_touch_exploration_->touch_id()){ | 434 if (event.touch_id() == last_touch_exploration_->touch_id()){ |
| 445 state_ = TOUCH_RELEASE_PENDING; | 435 SET_STATE(TOUCH_RELEASE_PENDING); |
| 446 VLOG_STATE(); | |
| 447 return EVENT_REWRITE_DISCARD; | 436 return EVENT_REWRITE_DISCARD; |
| 448 } | 437 } |
| 449 | 438 |
| 450 // Continue to release the touch only if the touch explore finger is the | 439 // Continue to release the touch only if the touch explore finger is the |
| 451 // only finger remaining. | 440 // only finger remaining. |
| 452 if (current_touch_ids_.size() != 1) | 441 if (current_touch_ids_.size() != 1) |
| 453 return EVENT_REWRITE_DISCARD; | 442 return EVENT_REWRITE_DISCARD; |
| 454 | 443 |
| 455 // Rewrite at location of last touch exploration. | 444 // Rewrite at location of last touch exploration. |
| 456 rewritten_event->reset( | 445 rewritten_event->reset( |
| 457 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, | 446 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, |
| 458 last_touch_exploration_->location(), | 447 last_touch_exploration_->location(), |
| 459 initial_press_->touch_id(), | 448 initial_press_->touch_id(), |
| 460 event.time_stamp())); | 449 event.time_stamp())); |
| 461 (*rewritten_event)->set_flags(event.flags()); | 450 (*rewritten_event)->set_flags(event.flags()); |
| 462 state_ = TOUCH_EXPLORATION; | 451 SET_STATE(TOUCH_EXPLORATION); |
| 463 EnterTouchToMouseMode(); | 452 EnterTouchToMouseMode(); |
| 464 VLOG_STATE(); | |
| 465 return ui::EVENT_REWRITE_REWRITTEN; | 453 return ui::EVENT_REWRITE_REWRITTEN; |
| 466 } | 454 } |
| 467 NOTREACHED() << "Unexpected event type received: " << event.name(); | 455 NOTREACHED(); |
| 468 return ui::EVENT_REWRITE_CONTINUE; | 456 return ui::EVENT_REWRITE_CONTINUE; |
| 469 } | 457 } |
| 470 | 458 |
| 471 ui::EventRewriteStatus TouchExplorationController::InWaitForOneFinger( | 459 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( |
| 472 const ui::TouchEvent& event, | 460 const ui::TouchEvent& event, |
| 473 scoped_ptr<ui::Event>* rewritten_event) { | 461 scoped_ptr<ui::Event>* rewritten_event) { |
| 474 ui::EventType type = event.type(); | 462 if (current_touch_ids_.size() == 0) |
| 475 if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED || | 463 SET_STATE(NO_FINGERS_DOWN); |
| 476 type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) { | |
| 477 NOTREACHED() << "Unexpected event type received: " << event.name(); | |
| 478 return ui::EVENT_REWRITE_CONTINUE; | |
| 479 } | |
| 480 if (current_touch_ids_.size() == 1) { | |
| 481 EnterTouchToMouseMode(); | |
| 482 state_ = TOUCH_EXPLORATION; | |
| 483 VLOG_STATE(); | |
| 484 *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); | |
| 485 last_touch_exploration_.reset(new TouchEvent(event)); | |
| 486 return ui::EVENT_REWRITE_REWRITTEN; | |
| 487 } | |
| 488 return EVENT_REWRITE_DISCARD; | 464 return EVENT_REWRITE_DISCARD; |
| 489 } | 465 } |
| 490 | 466 |
| 491 void TouchExplorationController::PlaySoundForTimer() { | 467 void TouchExplorationController::PlaySoundForTimer() { |
| 492 delegate_->PlayVolumeAdjustSound(); | 468 delegate_->PlayVolumeAdjustSound(); |
| 493 } | 469 } |
| 494 | 470 |
| 495 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | 471 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
| 496 const ui::TouchEvent& event, | 472 const ui::TouchEvent& event, |
| 497 scoped_ptr<ui::Event>* rewritten_event) { | 473 scoped_ptr<ui::Event>* rewritten_event) { |
| 498 // The timer should not fire when sliding. | 474 // The timer should not fire when sliding. |
| 499 if (tap_timer_.IsRunning()) | 475 tap_timer_.Stop(); |
| 500 tap_timer_.Stop(); | |
| 501 | 476 |
| 502 ui::EventType type = event.type(); | 477 ui::EventType type = event.type(); |
| 503 // If additional fingers are added before a swipe gesture has been registered, | 478 // If additional fingers are added before a swipe gesture has been registered, |
| 504 // then wait until all fingers have been lifted. | 479 // then wait until all fingers have been lifted. |
| 505 if (type == ui::ET_TOUCH_PRESSED || | 480 if (type == ui::ET_TOUCH_PRESSED || |
| 506 event.touch_id() != initial_press_->touch_id()) { | 481 event.touch_id() != initial_press_->touch_id()) { |
| 507 if (sound_timer_.IsRunning()) | 482 if (sound_timer_.IsRunning()) |
| 508 sound_timer_.Stop(); | 483 sound_timer_.Stop(); |
| 509 // Discard any pending gestures. | 484 SET_STATE(WAIT_FOR_NO_FINGERS); |
| 510 delete gesture_provider_.GetAndResetPendingGestures(); | |
| 511 state_ = WAIT_FOR_ONE_FINGER; | |
| 512 return EVENT_REWRITE_DISCARD; | 485 return EVENT_REWRITE_DISCARD; |
| 513 } | 486 } |
| 514 | 487 |
| 488 // There should not be more than one finger down. |
| 489 DCHECK(current_touch_ids_.size() <= 1); |
| 490 |
| 515 // Allows user to return to the edge to adjust the sound if they have left the | 491 // Allows user to return to the edge to adjust the sound if they have left the |
| 516 // boundaries. | 492 // boundaries. |
| 517 int edge = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); | 493 int edge = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); |
| 518 if (!(edge & RIGHT_EDGE) && (type != ui::ET_TOUCH_RELEASED)) { | 494 if (!(edge & RIGHT_EDGE) && (type != ui::ET_TOUCH_RELEASED)) { |
| 519 if (sound_timer_.IsRunning()) { | 495 if (sound_timer_.IsRunning()) { |
| 520 sound_timer_.Stop(); | 496 sound_timer_.Stop(); |
| 521 } | 497 } |
| 522 return EVENT_REWRITE_DISCARD; | 498 return EVENT_REWRITE_DISCARD; |
| 523 } | 499 } |
| 524 | 500 |
| 525 // This can occur if the user leaves the screen edge and then returns to it to | 501 // This can occur if the user leaves the screen edge and then returns to it to |
| 526 // continue adjusting the sound. | 502 // continue adjusting the sound. |
| 527 if (!sound_timer_.IsRunning()) { | 503 if (!sound_timer_.IsRunning()) { |
| 528 sound_timer_.Start(FROM_HERE, | 504 sound_timer_.Start(FROM_HERE, |
| 529 kSoundDelay, | 505 kSoundDelay, |
| 530 this, | 506 this, |
| 531 &ui::TouchExplorationController::PlaySoundForTimer); | 507 &ui::TouchExplorationController::PlaySoundForTimer); |
| 532 delegate_->PlayVolumeAdjustSound(); | 508 delegate_->PlayVolumeAdjustSound(); |
| 533 } | 509 } |
| 534 | 510 |
| 535 // There should not be more than one finger down. | 511 if (current_touch_ids_.size() == 0) { |
| 536 DCHECK(current_touch_ids_.size() <= 1); | 512 SET_STATE(NO_FINGERS_DOWN); |
| 537 if (type == ui::ET_TOUCH_MOVED) { | |
| 538 gesture_provider_.OnTouchEvent(event); | |
| 539 gesture_provider_.OnTouchEventAck(false); | |
| 540 } | 513 } |
| 541 if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | |
| 542 gesture_provider_.OnTouchEvent(event); | |
| 543 gesture_provider_.OnTouchEventAck(false); | |
| 544 delete gesture_provider_.GetAndResetPendingGestures(); | |
| 545 if (current_touch_ids_.size() == 0) { | |
| 546 ResetToNoFingersDown(); | |
| 547 } | |
| 548 return ui::EVENT_REWRITE_DISCARD; | |
| 549 } | |
| 550 | |
| 551 ProcessGestureEvents(); | |
| 552 return ui::EVENT_REWRITE_DISCARD; | 514 return ui::EVENT_REWRITE_DISCARD; |
| 553 } | 515 } |
| 554 | 516 |
| 555 ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( | 517 ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( |
| 556 const ui::TouchEvent& event, | 518 const ui::TouchEvent& event, |
| 557 scoped_ptr<ui::Event>* rewritten_event) { | 519 scoped_ptr<ui::Event>* rewritten_event) { |
| 558 ui::EventType type = event.type(); | 520 ui::EventType type = event.type(); |
| 559 if (type == ui::ET_TOUCH_PRESSED) { | 521 if (type == ui::ET_TOUCH_PRESSED) { |
| 560 // TODO(evy): Process three finger gestures here. | 522 // This is now a three finger gesture. |
| 561 state_ = WAIT_FOR_ONE_FINGER; | 523 SET_STATE(GESTURE_IN_PROGRESS); |
| 562 VLOG_STATE(); | |
| 563 return ui::EVENT_REWRITE_DISCARD; | 524 return ui::EVENT_REWRITE_DISCARD; |
| 564 } | 525 } |
| 565 | 526 |
| 566 if (type == ui::ET_TOUCH_MOVED) { | 527 if (type == ui::ET_TOUCH_MOVED) { |
| 567 // Determine if it was a swipe. | 528 // Determine if it was a swipe. |
| 568 gfx::Point original_location = initial_presses_[event.touch_id()]; | 529 gfx::Point original_location = initial_presses_[event.touch_id()]; |
| 569 float distance = (event.location() - original_location).Length(); | 530 float distance = (event.location() - original_location).Length(); |
| 570 // If the user moves too far from the original position, consider the | 531 // If the user moves too far from the original position, consider the |
| 571 // movement a swipe. | 532 // movement a swipe. |
| 572 // TODO(evy, lisayin): Add multifinger swipe processing. | |
| 573 if (distance > gesture_detector_config_.touch_slop) { | 533 if (distance > gesture_detector_config_.touch_slop) { |
| 574 state_ = WAIT_FOR_ONE_FINGER; | 534 SET_STATE(GESTURE_IN_PROGRESS); |
| 575 } | 535 } |
| 576 return ui::EVENT_REWRITE_DISCARD; | 536 return ui::EVENT_REWRITE_DISCARD; |
| 577 } | 537 } |
| 578 | 538 |
| 579 if (current_touch_ids_.size() != 0) | 539 if (current_touch_ids_.size() != 0) |
| 580 return ui::EVENT_REWRITE_DISCARD; | 540 return ui::EVENT_REWRITE_DISCARD; |
| 581 | 541 |
| 582 if (type == ui::ET_TOUCH_RELEASED) { | 542 if (type == ui::ET_TOUCH_RELEASED) { |
| 583 // In ChromeVox, pressing control will stop ChromeVox from speaking. | 543 // In ChromeVox, pressing control will stop ChromeVox from speaking. |
| 584 ui::KeyEvent control_down( | 544 ui::KeyEvent control_down( |
| 585 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN); | 545 ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN); |
| 586 ui::KeyEvent control_up(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ui::EF_NONE); | 546 ui::KeyEvent control_up(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ui::EF_NONE); |
| 587 | 547 |
| 588 DispatchEvent(&control_down); | 548 DispatchEvent(&control_down); |
| 589 DispatchEvent(&control_up); | 549 DispatchEvent(&control_up); |
| 590 | 550 SET_STATE(NO_FINGERS_DOWN); |
| 591 ResetToNoFingersDown(); | |
| 592 return ui::EVENT_REWRITE_DISCARD; | 551 return ui::EVENT_REWRITE_DISCARD; |
| 593 } | 552 } |
| 594 return ui::EVENT_REWRITE_DISCARD; | 553 return ui::EVENT_REWRITE_DISCARD; |
| 595 } | 554 } |
| 596 | 555 |
| 597 base::TimeDelta TouchExplorationController::Now() { | 556 base::TimeDelta TouchExplorationController::Now() { |
| 598 if (tick_clock_) { | 557 if (tick_clock_) { |
| 599 // This is the same as what EventTimeForNow() does, but here we do it | 558 // This is the same as what EventTimeForNow() does, but here we do it |
| 600 // with a clock that can be replaced with a simulated clock for tests. | 559 // with a clock that can be replaced with a simulated clock for tests. |
| 601 return base::TimeDelta::FromInternalValue( | 560 return base::TimeDelta::FromInternalValue( |
| 602 tick_clock_->NowTicks().ToInternalValue()); | 561 tick_clock_->NowTicks().ToInternalValue()); |
| 603 } | 562 } |
| 604 return ui::EventTimeForNow(); | 563 return ui::EventTimeForNow(); |
| 605 } | 564 } |
| 606 | 565 |
| 607 void TouchExplorationController::StartTapTimer() { | 566 void TouchExplorationController::StartTapTimer() { |
| 608 tap_timer_.Start(FROM_HERE, | 567 tap_timer_.Start(FROM_HERE, |
| 609 gesture_detector_config_.double_tap_timeout, | 568 gesture_detector_config_.double_tap_timeout, |
| 610 this, | 569 this, |
| 611 &TouchExplorationController::OnTapTimerFired); | 570 &TouchExplorationController::OnTapTimerFired); |
| 612 } | 571 } |
| 613 | 572 |
| 614 void TouchExplorationController::OnTapTimerFired() { | 573 void TouchExplorationController::OnTapTimerFired() { |
| 615 switch (state_) { | 574 switch (state_) { |
| 616 case SINGLE_TAP_RELEASED: | 575 case SINGLE_TAP_RELEASED: |
| 617 ResetToNoFingersDown(); | 576 SET_STATE(NO_FINGERS_DOWN); |
| 618 break; | 577 break; |
| 619 case TOUCH_EXPLORE_RELEASED: | 578 case TOUCH_EXPLORE_RELEASED: |
| 620 ResetToNoFingersDown(); | 579 SET_STATE(NO_FINGERS_DOWN); |
| 621 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 580 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| 622 return; | 581 return; |
| 623 case DOUBLE_TAP_PENDING: { | 582 case DOUBLE_TAP_PENDING: { |
| 624 state_ = ONE_FINGER_PASSTHROUGH; | 583 SET_STATE(ONE_FINGER_PASSTHROUGH); |
| 625 VLOG_STATE(); | |
| 626 passthrough_offset_ = last_unused_finger_event_->location() - | 584 passthrough_offset_ = last_unused_finger_event_->location() - |
| 627 last_touch_exploration_->location(); | 585 last_touch_exploration_->location(); |
| 628 scoped_ptr<ui::TouchEvent> passthrough_press( | 586 scoped_ptr<ui::TouchEvent> passthrough_press( |
| 629 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, | 587 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, |
| 630 last_touch_exploration_->location(), | 588 last_touch_exploration_->location(), |
| 631 last_unused_finger_event_->touch_id(), | 589 last_unused_finger_event_->touch_id(), |
| 632 Now())); | 590 Now())); |
| 633 DispatchEvent(passthrough_press.get()); | 591 DispatchEvent(passthrough_press.get()); |
| 634 return; | 592 return; |
| 635 } | 593 } |
| 636 case SINGLE_TAP_PRESSED: | 594 case SINGLE_TAP_PRESSED: |
| 595 EnterTouchToMouseMode(); |
| 596 SET_STATE(TOUCH_EXPLORATION); |
| 597 break; |
| 637 case GESTURE_IN_PROGRESS: | 598 case GESTURE_IN_PROGRESS: |
| 638 // Discard any pending gestures. | 599 // If only one finger is down, go into touch exploration. |
| 639 delete gesture_provider_.GetAndResetPendingGestures(); | 600 if (current_touch_ids_.size() == 1) { |
| 640 state_ = TOUCH_EXPLORATION; | 601 EnterTouchToMouseMode(); |
| 641 VLOG_STATE(); | 602 SET_STATE(TOUCH_EXPLORATION); |
| 642 break; | 603 break; |
| 604 } |
| 605 // Otherwise wait for all fingers to be lifted. |
| 606 SET_STATE(WAIT_FOR_NO_FINGERS); |
| 607 return; |
| 643 case TWO_FINGER_TAP: | 608 case TWO_FINGER_TAP: |
| 644 state_ = WAIT_FOR_ONE_FINGER; | 609 SET_STATE(WAIT_FOR_NO_FINGERS); |
| 645 VLOG_STATE(); | |
| 646 break; | 610 break; |
| 647 default: | 611 default: |
| 648 return; | 612 return; |
| 649 } | 613 } |
| 650 EnterTouchToMouseMode(); | 614 EnterTouchToMouseMode(); |
| 651 scoped_ptr<ui::Event> mouse_move = | 615 scoped_ptr<ui::Event> mouse_move = |
| 652 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); | 616 CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); |
| 653 DispatchEvent(mouse_move.get()); | 617 DispatchEvent(mouse_move.get()); |
| 654 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 618 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| 655 } | 619 } |
| 656 | 620 |
| 657 void TouchExplorationController::DispatchEvent(ui::Event* event) { | 621 void TouchExplorationController::DispatchEvent(ui::Event* event) { |
| 658 ui::EventDispatchDetails result ALLOW_UNUSED = | 622 ui::EventDispatchDetails result ALLOW_UNUSED = |
| 659 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); | 623 root_window_->GetHost()->dispatcher()->OnEventFromSource(event); |
| 660 } | 624 } |
| 661 | 625 |
| 662 void TouchExplorationController::OnGestureEvent( | 626 // This is an override for a function that is only called for timer-based events |
| 663 ui::GestureEvent* gesture) { | 627 // like long press. Events that are created synchronously as a result of |
| 664 CHECK(gesture->IsGestureEvent()); | 628 // certain touch events are added to the vector accessible via |
| 665 ui::EventType type = gesture->type(); | 629 // GetAndResetPendingGestures(). We only care about swipes (which are created |
| 666 if (VLOG_on_) | 630 // synchronously), so we ignore this callback. |
| 667 VLOG(0) << " \n Gesture Triggered: " << gesture->name(); | 631 void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) { |
| 668 if (type == ui::ET_GESTURE_SWIPE && state_ != SLIDE_GESTURE) { | |
| 669 if (VLOG_on_) | |
| 670 VLOG(0) << "Swipe!"; | |
| 671 delete gesture_provider_.GetAndResetPendingGestures(); | |
| 672 OnSwipeEvent(gesture); | |
| 673 return; | |
| 674 } | |
| 675 } | 632 } |
| 676 | 633 |
| 677 void TouchExplorationController::ProcessGestureEvents() { | 634 void TouchExplorationController::ProcessGestureEvents() { |
| 678 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( | 635 scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( |
| 679 gesture_provider_.GetAndResetPendingGestures()); | 636 gesture_provider_->GetAndResetPendingGestures()); |
| 680 if (gestures) { | 637 if (gestures) { |
| 681 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); | 638 for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); |
| 682 i != gestures->end(); | 639 i != gestures->end(); |
| 683 ++i) { | 640 ++i) { |
| 684 if (state_ == SLIDE_GESTURE) | 641 if ((*i)->type() == ui::ET_GESTURE_SWIPE && |
| 642 state_ == GESTURE_IN_PROGRESS) { |
| 643 OnSwipeEvent(*i); |
| 644 // The tap timer to leave gesture state is ended, and we now wait for |
| 645 // all fingers to be released. |
| 646 tap_timer_.Stop(); |
| 647 SET_STATE(WAIT_FOR_NO_FINGERS); |
| 648 return; |
| 649 } |
| 650 if (state_ == SLIDE_GESTURE && (*i)->IsScrollGestureEvent()) { |
| 685 SideSlideControl(*i); | 651 SideSlideControl(*i); |
| 686 else | 652 } |
| 687 OnGestureEvent(*i); | |
| 688 } | 653 } |
| 689 } | 654 } |
| 690 } | 655 } |
| 691 | 656 |
| 692 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { | 657 void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { |
| 693 ui::EventType type = gesture->type(); | 658 ui::EventType type = gesture->type(); |
| 694 if (!gesture->IsScrollGestureEvent()) | |
| 695 return; | |
| 696 | 659 |
| 697 if (type == ET_GESTURE_SCROLL_BEGIN) { | 660 if (type == ET_GESTURE_SCROLL_BEGIN) { |
| 698 delegate_->PlayVolumeAdjustSound(); | 661 delegate_->PlayVolumeAdjustSound(); |
| 699 } | 662 } |
| 700 | 663 |
| 701 if (type == ET_GESTURE_SCROLL_END) { | 664 if (type == ET_GESTURE_SCROLL_END) { |
| 702 if (sound_timer_.IsRunning()) | 665 if (sound_timer_.IsRunning()) |
| 703 sound_timer_.Stop(); | 666 sound_timer_.Stop(); |
| 704 delegate_->PlayVolumeAdjustSound(); | 667 delegate_->PlayVolumeAdjustSound(); |
| 705 } | 668 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 730 float ratio = (location.y() - kMaxDistanceFromEdge) / volume_adjust_height; | 693 float ratio = (location.y() - kMaxDistanceFromEdge) / volume_adjust_height; |
| 731 float volume = 100 - 100 * ratio; | 694 float volume = 100 - 100 * ratio; |
| 732 if (VLOG_on_) { | 695 if (VLOG_on_) { |
| 733 VLOG(0) << "\n Volume = " << volume | 696 VLOG(0) << "\n Volume = " << volume |
| 734 << "\n Location = " << location.ToString() | 697 << "\n Location = " << location.ToString() |
| 735 << "\n Bounds = " << root_window_->bounds().right(); | 698 << "\n Bounds = " << root_window_->bounds().right(); |
| 736 } | 699 } |
| 737 delegate_->SetOutputLevel(int(volume)); | 700 delegate_->SetOutputLevel(int(volume)); |
| 738 } | 701 } |
| 739 | 702 |
| 740 | |
| 741 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { | 703 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { |
| 742 // A swipe gesture contains details for the direction in which the swipe | 704 // A swipe gesture contains details for the direction in which the swipe |
| 743 // occurred. | 705 // occurred. TODO(evy) : Research which swipe results users most want and |
| 706 // remap these swipes to the best events. Hopefully in the near future |
| 707 // there will also be a menu for users to pick custom mappings. |
| 744 GestureEventDetails event_details = swipe_gesture->details(); | 708 GestureEventDetails event_details = swipe_gesture->details(); |
| 745 if (event_details.swipe_left()) { | 709 int num_fingers = event_details.touch_points(); |
| 746 DispatchShiftSearchKeyEvent(ui::VKEY_LEFT); | 710 if(VLOG_on_) |
| 711 VLOG(0) << "\nSwipe with " << num_fingers << " fingers."; |
| 712 |
| 713 if (num_fingers > 4) |
| 747 return; | 714 return; |
| 748 } else if (event_details.swipe_right()) { | 715 |
| 749 DispatchShiftSearchKeyEvent(ui::VKEY_RIGHT); | 716 if (event_details.swipe_left() && |
| 750 return; | 717 !left_swipe_gestures_[num_fingers].is_null()) { |
| 751 } else if (event_details.swipe_up()) { | 718 left_swipe_gestures_[num_fingers].Run(); |
| 752 DispatchShiftSearchKeyEvent(ui::VKEY_UP); | 719 } else if (event_details.swipe_right() && |
| 753 return; | 720 !right_swipe_gestures_[num_fingers].is_null()) { |
| 754 } else if (event_details.swipe_down()) { | 721 right_swipe_gestures_[num_fingers].Run(); |
| 755 DispatchShiftSearchKeyEvent(ui::VKEY_DOWN); | 722 } else if (event_details.swipe_up() && |
| 756 return; | 723 !up_swipe_gestures_[num_fingers].is_null()) { |
| 724 up_swipe_gestures_[num_fingers].Run(); |
| 725 } else if (event_details.swipe_down() && |
| 726 !down_swipe_gestures_[num_fingers].is_null()) { |
| 727 down_swipe_gestures_[num_fingers].Run(); |
| 757 } | 728 } |
| 758 } | 729 } |
| 759 | 730 |
| 760 int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point, | 731 int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point, |
| 761 float bounds) { | 732 float bounds) { |
| 762 // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be | 733 // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be |
| 763 // converted. | 734 // converted. |
| 764 root_window_->GetHost()->ConvertPointFromNativeScreen(&point); | 735 root_window_->GetHost()->ConvertPointFromNativeScreen(&point); |
| 765 gfx::Rect window = root_window_->GetBoundsInScreen(); | 736 gfx::Rect window = root_window_->GetBoundsInScreen(); |
| 766 | 737 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 779 if (point.x() > right_edge_limit) | 750 if (point.x() > right_edge_limit) |
| 780 result |= RIGHT_EDGE; | 751 result |= RIGHT_EDGE; |
| 781 if (point.y() < top_edge_limit) | 752 if (point.y() < top_edge_limit) |
| 782 result |= TOP_EDGE; | 753 result |= TOP_EDGE; |
| 783 if (point.y() > bottom_edge_limit) | 754 if (point.y() > bottom_edge_limit) |
| 784 result |= BOTTOM_EDGE; | 755 result |= BOTTOM_EDGE; |
| 785 return result; | 756 return result; |
| 786 } | 757 } |
| 787 | 758 |
| 788 void TouchExplorationController::DispatchShiftSearchKeyEvent( | 759 void TouchExplorationController::DispatchShiftSearchKeyEvent( |
| 789 const ui::KeyboardCode direction) { | 760 const ui::KeyboardCode third_key) { |
| 790 // In order to activate the shortcut shift+search+<arrow key> | 761 // In order to activate the shortcut shift+search+<arrow key> |
| 791 // three KeyPressed events must be dispatched in succession along | 762 // three KeyPressed events must be dispatched in succession along |
| 792 // with three KeyReleased events. | 763 // with three KeyReleased events. |
| 793 ui::KeyEvent shift_down = ui::KeyEvent( | 764 |
| 765 ui::KeyEvent shift_down( |
| 794 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN); | 766 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN); |
| 795 ui::KeyEvent search_down = ui::KeyEvent( | 767 ui::KeyEvent search_down( |
| 796 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); | 768 ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); |
| 797 ui::KeyEvent direction_down = | 769 ui::KeyEvent third_key_down(ui::ET_KEY_PRESSED, third_key, ui::EF_SHIFT_DOWN); |
| 798 ui::KeyEvent(ui::ET_KEY_PRESSED, direction, ui::EF_SHIFT_DOWN); | |
| 799 | 770 |
| 800 ui::KeyEvent direction_up = | 771 ui::KeyEvent third_key_up(ui::ET_KEY_RELEASED, third_key, ui::EF_SHIFT_DOWN); |
| 801 ui::KeyEvent(ui::ET_KEY_RELEASED, direction, ui::EF_SHIFT_DOWN); | 772 ui::KeyEvent search_up( |
| 802 ui::KeyEvent search_up = ui::KeyEvent( | |
| 803 ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); | 773 ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); |
| 804 ui::KeyEvent shift_up = | 774 ui::KeyEvent shift_up(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE); |
| 805 ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE); | |
| 806 | 775 |
| 807 DispatchEvent(&shift_down); | 776 DispatchEvent(&shift_down); |
| 808 DispatchEvent(&search_down); | 777 DispatchEvent(&search_down); |
| 809 DispatchEvent(&direction_down); | 778 DispatchEvent(&third_key_down); |
| 810 DispatchEvent(&direction_up); | 779 DispatchEvent(&third_key_up); |
| 811 DispatchEvent(&search_up); | 780 DispatchEvent(&search_up); |
| 812 DispatchEvent(&shift_up); | 781 DispatchEvent(&shift_up); |
| 813 } | 782 } |
| 814 | 783 |
| 784 base::Closure TouchExplorationController::BindShiftSearchKeyEvent( |
| 785 const ui::KeyboardCode third_key) { |
| 786 return base::Bind(&TouchExplorationController::DispatchShiftSearchKeyEvent, |
| 787 base::Unretained(this), |
| 788 third_key); |
| 789 } |
| 790 |
| 791 void TouchExplorationController::DispatchKeyWithFlags( |
| 792 const ui::KeyboardCode key, |
| 793 int flags) { |
| 794 ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags); |
| 795 ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags); |
| 796 DispatchEvent(&key_down); |
| 797 DispatchEvent(&key_up); |
| 798 if(VLOG_on_) { |
| 799 VLOG(0) << "\nKey down: key code : " << key_down.key_code() |
| 800 << ", flags: " << key_down.flags() |
| 801 << "\nKey up: key code : " << key_up.key_code() |
| 802 << ", flags: " << key_up.flags(); |
| 803 } |
| 804 } |
| 805 |
| 806 base::Closure TouchExplorationController::BindKeyEventWithFlags( |
| 807 const ui::KeyboardCode key, |
| 808 int flags) { |
| 809 return base::Bind(&TouchExplorationController::DispatchKeyWithFlags, |
| 810 base::Unretained(this), |
| 811 key, |
| 812 flags); |
| 813 } |
| 814 |
| 815 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( | 815 scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( |
| 816 const gfx::PointF& location, | 816 const gfx::PointF& location, |
| 817 int flags) { | 817 int flags) { |
| 818 // The "synthesized" flag should be set on all events that don't have a | 818 // The "synthesized" flag should be set on all events that don't have a |
| 819 // backing native event. | 819 // backing native event. |
| 820 flags |= ui::EF_IS_SYNTHESIZED; | 820 flags |= ui::EF_IS_SYNTHESIZED; |
| 821 | 821 |
| 822 // This flag is used to identify mouse move events that were generated from | 822 // This flag is used to identify mouse move events that were generated from |
| 823 // touch exploration in Chrome code. | 823 // touch exploration in Chrome code. |
| 824 flags |= ui::EF_TOUCH_ACCESSIBILITY; | 824 flags |= ui::EF_TOUCH_ACCESSIBILITY; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 840 | 840 |
| 841 void TouchExplorationController::EnterTouchToMouseMode() { | 841 void TouchExplorationController::EnterTouchToMouseMode() { |
| 842 aura::client::CursorClient* cursor_client = | 842 aura::client::CursorClient* cursor_client = |
| 843 aura::client::GetCursorClient(root_window_); | 843 aura::client::GetCursorClient(root_window_); |
| 844 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) | 844 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) |
| 845 cursor_client->EnableMouseEvents(); | 845 cursor_client->EnableMouseEvents(); |
| 846 if (cursor_client && cursor_client->IsCursorVisible()) | 846 if (cursor_client && cursor_client->IsCursorVisible()) |
| 847 cursor_client->HideCursor(); | 847 cursor_client->HideCursor(); |
| 848 } | 848 } |
| 849 | 849 |
| 850 void TouchExplorationController::ResetToNoFingersDown() { | 850 void TouchExplorationController::SetState(State new_state, |
| 851 ProcessGestureEvents(); | 851 const char* function_name) { |
| 852 initial_presses_.clear(); | 852 state_ = new_state; |
| 853 if (sound_timer_.IsRunning()) | 853 VlogState(function_name); |
| 854 sound_timer_.Stop(); | 854 // These are the states the user can be in that will never result in a |
| 855 state_ = NO_FINGERS_DOWN; | 855 // gesture before the user returns to NO_FINGERS_DOWN. Therefore, if the |
| 856 VLOG_STATE(); | 856 // gesture provider still exists, it's reset to NULL until the user returns |
| 857 if (tap_timer_.IsRunning()) | 857 // to NO_FINGERS_DOWN. |
| 858 tap_timer_.Stop(); | 858 switch (new_state) { |
| 859 case SINGLE_TAP_RELEASED: |
| 860 case TOUCH_EXPLORE_RELEASED: |
| 861 case DOUBLE_TAP_PENDING: |
| 862 case TOUCH_RELEASE_PENDING: |
| 863 case TOUCH_EXPLORATION: |
| 864 case TOUCH_EXPLORE_SECOND_PRESS: |
| 865 case ONE_FINGER_PASSTHROUGH: |
| 866 case WAIT_FOR_NO_FINGERS: |
| 867 if (gesture_provider_.get()) |
| 868 gesture_provider_.reset(NULL); |
| 869 break; |
| 870 case NO_FINGERS_DOWN: |
| 871 gesture_provider_.reset(new GestureProviderAura(this)); |
| 872 if (sound_timer_.IsRunning()) |
| 873 sound_timer_.Stop(); |
| 874 tap_timer_.Stop(); |
| 875 break; |
| 876 case SINGLE_TAP_PRESSED: |
| 877 case GESTURE_IN_PROGRESS: |
| 878 case SLIDE_GESTURE: |
| 879 case TWO_FINGER_TAP: |
| 880 break; |
| 881 } |
| 859 } | 882 } |
| 860 | 883 |
| 861 void TouchExplorationController::VlogState(const char* function_name) { | 884 void TouchExplorationController::VlogState(const char* function_name) { |
| 862 if (!VLOG_on_) | 885 if (!VLOG_on_) |
| 863 return; | 886 return; |
| 864 if (prev_state_ == state_) | 887 if (prev_state_ == state_) |
| 865 return; | 888 return; |
| 866 prev_state_ = state_; | 889 prev_state_ = state_; |
| 867 const char* state_string = EnumStateToString(state_); | 890 const char* state_string = EnumStateToString(state_); |
| 868 VLOG(0) << "\n Function name: " << function_name | 891 VLOG(0) << "\n Function name: " << function_name |
| 869 << "\n State: " << state_string; | 892 << "\n State: " << state_string; |
| 870 } | 893 } |
| 871 | 894 |
| 872 void TouchExplorationController::VlogEvent(const ui::TouchEvent& touch_event, | 895 void TouchExplorationController::VlogEvent(const ui::TouchEvent& touch_event, |
| 873 const char* function_name) { | 896 const char* function_name) { |
| 874 if (!VLOG_on_) | 897 if (!VLOG_on_) |
| 875 return; | 898 return; |
| 876 | 899 |
| 877 CHECK(touch_event.IsTouchEvent()); | |
| 878 if (prev_event_ != NULL && | 900 if (prev_event_ != NULL && |
| 879 prev_event_->type() == touch_event.type() && | 901 prev_event_->type() == touch_event.type() && |
| 880 prev_event_->touch_id() == touch_event.touch_id()){ | 902 prev_event_->touch_id() == touch_event.touch_id()){ |
| 881 return; | 903 return; |
| 882 } | 904 } |
| 883 // The above statement prevents events of the same type and id from being | 905 // The above statement prevents events of the same type and id from being |
| 884 // printed in a row. However, if two fingers are down, they would both be | 906 // printed in a row. However, if two fingers are down, they would both be |
| 885 // moving and alternating printing move events unless we check for this. | 907 // moving and alternating printing move events unless we check for this. |
| 886 if (prev_event_ != NULL && | 908 if (prev_event_ != NULL && |
| 887 prev_event_->type() == ET_TOUCH_MOVED && | 909 prev_event_->type() == ET_TOUCH_MOVED && |
| 888 touch_event.type() == ET_TOUCH_MOVED){ | 910 touch_event.type() == ET_TOUCH_MOVED){ |
| 889 return; | 911 return; |
| 890 } | 912 } |
| 913 |
| 891 const std::string& type = touch_event.name(); | 914 const std::string& type = touch_event.name(); |
| 892 const gfx::PointF& location = touch_event.location_f(); | 915 const gfx::PointF& location = touch_event.location_f(); |
| 893 const int touch_id = touch_event.touch_id(); | 916 const int touch_id = touch_event.touch_id(); |
| 894 | 917 |
| 895 VLOG(0) << "\n Function name: " << function_name | 918 VLOG(0) << "\n Function name: " << function_name |
| 896 << "\n Event Type: " << type | 919 << "\n Event Type: " << type |
| 897 << "\n Location: " << location.ToString() | 920 << "\n Location: " << location.ToString() |
| 898 << "\n Touch ID: " << touch_id; | 921 << "\n Touch ID: " << touch_id; |
| 899 prev_event_.reset(new TouchEvent(touch_event)); | 922 prev_event_.reset(new TouchEvent(touch_event)); |
| 900 } | 923 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 916 case TOUCH_EXPLORATION: | 939 case TOUCH_EXPLORATION: |
| 917 return "TOUCH_EXPLORATION"; | 940 return "TOUCH_EXPLORATION"; |
| 918 case GESTURE_IN_PROGRESS: | 941 case GESTURE_IN_PROGRESS: |
| 919 return "GESTURE_IN_PROGRESS"; | 942 return "GESTURE_IN_PROGRESS"; |
| 920 case TOUCH_EXPLORE_SECOND_PRESS: | 943 case TOUCH_EXPLORE_SECOND_PRESS: |
| 921 return "TOUCH_EXPLORE_SECOND_PRESS"; | 944 return "TOUCH_EXPLORE_SECOND_PRESS"; |
| 922 case SLIDE_GESTURE: | 945 case SLIDE_GESTURE: |
| 923 return "SLIDE_GESTURE"; | 946 return "SLIDE_GESTURE"; |
| 924 case ONE_FINGER_PASSTHROUGH: | 947 case ONE_FINGER_PASSTHROUGH: |
| 925 return "ONE_FINGER_PASSTHROUGH"; | 948 return "ONE_FINGER_PASSTHROUGH"; |
| 926 case WAIT_FOR_ONE_FINGER: | 949 case WAIT_FOR_NO_FINGERS: |
| 927 return "WAIT_FOR_ONE_FINGER"; | 950 return "WAIT_FOR_NO_FINGERS"; |
| 928 case TWO_FINGER_TAP: | 951 case TWO_FINGER_TAP: |
| 929 return "TWO_FINGER_TAP"; | 952 return "TWO_FINGER_TAP"; |
| 930 } | 953 } |
| 931 return "Not a state"; | 954 return "Not a state"; |
| 932 } | 955 } |
| 933 | 956 |
| 957 // TODO(evy, lisayin) : Just call abstracted methods on the delegate (e.g. |
| 958 // Swipe(Direction direction, int num_fingers)), and add the DispatchXYZ |
| 959 // methods to the delegate. Avoid the middle step of dispatching keys at all, |
| 960 // and simply have ChromeVox/ChromeOS complete the required action. |
| 961 |
| 962 void TouchExplorationController::InitializeSwipeGestureMaps() { |
| 963 // Gestures with one finger are used for navigation. |
| 964 left_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_LEFT); |
| 965 right_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_RIGHT); |
| 966 up_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_UP); |
| 967 down_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_DOWN); |
| 968 |
| 969 // Gestures with two fingers. |
| 970 left_swipe_gestures_[2] = |
| 971 BindKeyEventWithFlags(ui::VKEY_BROWSER_BACK, ui::EF_NONE); |
| 972 right_swipe_gestures_[2] = |
| 973 BindKeyEventWithFlags(ui::VKEY_BROWSER_FORWARD, ui::EF_NONE); |
| 974 // Jump to top. |
| 975 up_swipe_gestures_[2] = BindShiftSearchKeyEvent(ui::VKEY_A); |
| 976 // Read from here. |
| 977 down_swipe_gestures_[2] = BindShiftSearchKeyEvent(ui::VKEY_R); |
| 978 |
| 979 // Gestures with three fingers switch tabs left/right and scroll up/down. |
| 980 left_swipe_gestures_[3] = BindKeyEventWithFlags( |
| 981 ui::VKEY_TAB, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); |
| 982 right_swipe_gestures_[3] = |
| 983 BindKeyEventWithFlags(ui::VKEY_TAB, ui::EF_CONTROL_DOWN); |
| 984 up_swipe_gestures_[3] = BindKeyEventWithFlags(ui::VKEY_NEXT, ui::EF_NONE); |
| 985 down_swipe_gestures_[3] = BindKeyEventWithFlags(ui::VKEY_PRIOR, ui::EF_NONE); |
| 986 |
| 987 // Gestures with four fingers should probably eventually be used for rare |
| 988 // needs that are hard to access through menus. |
| 989 // Note that brightness levels are here because they can be important for low |
| 990 // vision users. However, none of these mappings are permanent. |
| 991 left_swipe_gestures_[4] = |
| 992 BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); |
| 993 right_swipe_gestures_[4] = |
| 994 BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE); |
| 995 up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); |
| 996 down_swipe_gestures_[4] = |
| 997 BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); |
| 998 } |
| 999 |
| 934 } // namespace ui | 1000 } // namespace ui |
| OLD | NEW |