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 |