Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: ui/chromeos/touch_exploration_controller.cc

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

Powered by Google App Engine
This is Rietveld 408576698