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 #ifndef UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ | 5 #ifndef UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
6 #define UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ | 6 #define UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
7 | 7 |
8 #include "base/timer/timer.h" | 8 #include "base/timer/timer.h" |
9 #include "base/values.h" | 9 #include "base/values.h" |
10 #include "ui/chromeos/ui_chromeos_export.h" | 10 #include "ui/chromeos/ui_chromeos_export.h" |
11 #include "ui/events/event.h" | 11 #include "ui/events/event.h" |
12 #include "ui/events/event_rewriter.h" | 12 #include "ui/events/event_rewriter.h" |
13 #include "ui/events/gesture_detection/gesture_detector.h" | 13 #include "ui/events/gesture_detection/gesture_detector.h" |
14 #include "ui/events/gestures/gesture_provider_aura.h" | 14 #include "ui/events/gestures/gesture_provider_aura.h" |
15 #include "ui/gfx/geometry/point.h" | 15 #include "ui/gfx/geometry/point.h" |
16 | 16 |
17 namespace aura { | 17 namespace aura { |
18 class Window; | 18 class Window; |
19 } | 19 } |
20 | 20 |
21 namespace ui { | 21 namespace ui { |
22 | 22 |
23 class Event; | 23 class Event; |
24 class EventHandler; | 24 class EventHandler; |
25 class GestureEvent; | 25 class GestureEvent; |
26 class GestureProviderAura; | 26 class GestureProviderAura; |
27 class TouchEvent; | 27 class TouchEvent; |
28 | 28 |
| 29 // A delegate to handle commands in response to detected accessibility gesture |
| 30 // events. |
| 31 class TouchExplorationControllerDelegate { |
| 32 public: |
| 33 virtual ~TouchExplorationControllerDelegate() {} |
| 34 |
| 35 // This function should be called whenever the delegate wants to play a sound |
| 36 // when the volume adjusts. |
| 37 virtual void PlayVolumeAdjustSound() = 0; |
| 38 |
| 39 // Takes an int from 0.0 to 100.0 that indicates the percent the volume |
| 40 // should be set to. |
| 41 virtual void SetOutputLevel(int volume) = 0; |
| 42 }; |
| 43 |
29 // TouchExplorationController is used in tandem with "Spoken Feedback" to | 44 // TouchExplorationController is used in tandem with "Spoken Feedback" to |
30 // make the touch UI accessible. Gestures are mapped to accessiblity key | 45 // make the touch UI accessible. Gestures performed in the middle of the screen |
31 // shortcuts. | 46 // are mapped to accessiblity key shortcuts while gestures performed on the edge |
| 47 // of the screen can change settings. |
32 // | 48 // |
33 // ** Short version ** | 49 // ** Short version ** |
34 // | 50 // |
35 // At a high-level, single-finger events are used for accessibility - | 51 // At a high-level, single-finger events are used for accessibility - |
36 // exploring the screen gets turned into mouse moves (which can then be | 52 // exploring the screen gets turned into mouse moves (which can then be |
37 // spoken by an accessibility service running), a single tap while the user | 53 // spoken by an accessibility service running), a single tap while the user |
38 // is in touch exploration or a double-tap simulates a click, and gestures | 54 // is in touch exploration or a double-tap simulates a click, and gestures |
39 // can be used to send high-level accessibility commands. For example, a swipe | 55 // can be used to send high-level accessibility commands. For example, a swipe |
40 // right would correspond to the keyboard short cut shift+search+right. | 56 // right would correspond to the keyboard short cut shift+search+right. |
41 // When two or more fingers are pressed initially, from then on the events | 57 // When two or more fingers are pressed initially, from then on the events |
42 // are passed through, but with the initial finger removed - so if you swipe | 58 // are passed through, but with the initial finger removed - so if you swipe |
43 // down with two fingers, the running app will see a one-finger swipe. | 59 // down with two fingers, the running app will see a one-finger swipe. Slide |
| 60 // gestures performed on the edge of the screen can change settings |
| 61 // continuously. For example, sliding a finger along the right side of the |
| 62 // screen will change the volume. |
44 // | 63 // |
45 // ** Long version ** | 64 // ** Long version ** |
46 // | 65 // |
47 // Here are the details of the implementation: | 66 // Here are the details of the implementation: |
48 // | 67 // |
49 // When the first touch is pressed, a 300 ms grace period timer starts. | 68 // When the first touch is pressed, a 300 ms grace period timer starts. |
50 // | 69 // |
51 // If the user keeps their finger down for more than 300 ms and doesn't | 70 // If the user keeps their finger down for more than 300 ms and doesn't |
52 // perform a supported accessibility gesture in that time (e.g. swipe right), | 71 // perform a supported accessibility gesture in that time (e.g. swipe right), |
53 // they enter touch exploration mode, and all movements are translated into | 72 // they enter touch exploration mode, and all movements are translated into |
(...skipping 30 matching lines...) Expand all Loading... |
84 // their touch exploration finger by tapping anywhere else on the screen with | 103 // their touch exploration finger by tapping anywhere else on the screen with |
85 // a second finger, while the touch exploration finger is still pressed. | 104 // a second finger, while the touch exploration finger is still pressed. |
86 // | 105 // |
87 // If the user adds a second finger during the grace period, they enter | 106 // If the user adds a second finger during the grace period, they enter |
88 // two to one finger passthrough mode. In this mode, the first finger is | 107 // two to one finger passthrough mode. In this mode, the first finger is |
89 // ignored and the user can scroll or drag with the second finger. If either | 108 // ignored and the user can scroll or drag with the second finger. If either |
90 // finger is released, nothing happens until all fingers are up. If the user | 109 // finger is released, nothing happens until all fingers are up. If the user |
91 // adds a third finger while in two to one finger mode, all fingers and touch | 110 // adds a third finger while in two to one finger mode, all fingers and touch |
92 // events are passed through from then on. | 111 // events are passed through from then on. |
93 // | 112 // |
| 113 // If the user places a finger on the edge of the screen and moves their finger |
| 114 // past slop, a slide gesture is performed. The user can then slide one finger |
| 115 // along an edge of the screen and continuously control a setting. Once the user |
| 116 // enters this state, the boundaries that define an edge expand so that the user |
| 117 // can now adjust the setting within a slightly bigger width along the screen. |
| 118 // If the user exits this area without lifting their finger, they will not be |
| 119 // able to perform any actions, however if they keep their finger down and |
| 120 // return to the "hot edge," then they can still adjust the setting. In order to |
| 121 // perform other touch accessibility movements, the user must lift their finger. |
| 122 // If additional fingers are added while in this state, the user will transition |
| 123 // to passthrough. |
| 124 // |
| 125 // Currently, only the right edge is mapped to control the volume. Volume |
| 126 // control along the edge of the screen is directly proportional to where the |
| 127 // user's finger is located on the screen. The top right corner of the screen |
| 128 // automatically sets the volume to 100% and the bottome right corner of the |
| 129 // screen automatically sets the volume to 0% once the user has moved past slop. |
| 130 // |
94 // Once touch exploration mode has been activated, | 131 // Once touch exploration mode has been activated, |
95 // it remains in that mode until all fingers have been released. | 132 // it remains in that mode until all fingers have been released. |
96 // | 133 // |
97 // The caller is expected to retain ownership of instances of this class and | 134 // The caller is expected to retain ownership of instances of this class and |
98 // destroy them before |root_window| is destroyed. | 135 // destroy them before |root_window| is destroyed. |
99 class UI_CHROMEOS_EXPORT TouchExplorationController | 136 class UI_CHROMEOS_EXPORT TouchExplorationController |
100 : public ui::EventRewriter, | 137 : public ui::EventRewriter, |
101 public ui::GestureProviderAuraClient { | 138 public ui::GestureProviderAuraClient { |
102 public: | 139 public: |
103 explicit TouchExplorationController(aura::Window* root_window); | 140 explicit TouchExplorationController( |
| 141 aura::Window* root_window, |
| 142 ui::TouchExplorationControllerDelegate* delegate); |
104 virtual ~TouchExplorationController(); | 143 virtual ~TouchExplorationController(); |
105 | 144 |
106 private: | 145 private: |
107 friend class TouchExplorationControllerTestApi; | 146 friend class TouchExplorationControllerTestApi; |
108 | 147 |
109 // Overridden from ui::EventRewriter | 148 // Overridden from ui::EventRewriter |
110 virtual ui::EventRewriteStatus RewriteEvent( | 149 virtual ui::EventRewriteStatus RewriteEvent( |
111 const ui::Event& event, | 150 const ui::Event& event, |
112 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; | 151 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; |
113 virtual ui::EventRewriteStatus NextDispatchEvent( | 152 virtual ui::EventRewriteStatus NextDispatchEvent( |
(...skipping 13 matching lines...) Expand all Loading... |
127 ui::EventRewriteStatus InTwoToOneFinger( | 166 ui::EventRewriteStatus InTwoToOneFinger( |
128 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 167 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
129 ui::EventRewriteStatus InPassthrough( | 168 ui::EventRewriteStatus InPassthrough( |
130 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 169 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
131 ui::EventRewriteStatus InGestureInProgress( | 170 ui::EventRewriteStatus InGestureInProgress( |
132 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 171 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
133 ui::EventRewriteStatus InTouchExploreSecondPress( | 172 ui::EventRewriteStatus InTouchExploreSecondPress( |
134 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 173 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
135 ui::EventRewriteStatus InWaitForRelease( | 174 ui::EventRewriteStatus InWaitForRelease( |
136 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 175 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 176 ui::EventRewriteStatus InSlideGesture( |
| 177 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
137 | 178 |
138 // This timer is started every time we get the first press event, and | 179 // This timer is started every time we get the first press event, and |
139 // it fires after the double-click timeout elapses (300 ms by default). | 180 // it fires after the double-click timeout elapses (300 ms by default). |
140 // If the user taps and releases within 300 ms and doesn't press again, | 181 // If the user taps and releases within 300 ms and doesn't press again, |
141 // we treat that as a single mouse move (touch exploration) event. | 182 // we treat that as a single mouse move (touch exploration) event. |
142 void OnTapTimerFired(); | 183 void OnTapTimerFired(); |
143 | 184 |
144 // Dispatch a new event outside of the event rewriting flow. | 185 // Dispatch a new event outside of the event rewriting flow. |
145 void DispatchEvent(ui::Event* event); | 186 void DispatchEvent(ui::Event* event); |
146 | 187 |
147 // Overridden from GestureProviderAuraClient. | 188 // Overridden from GestureProviderAuraClient. |
148 // | 189 // |
149 // The gesture provider keeps track of all the touch events after | 190 // The gesture provider keeps track of all the touch events after |
150 // the user moves fast enough to trigger a gesture. After the user | 191 // the user moves fast enough to trigger a gesture. After the user |
151 // completes their gesture, this method will decide what keyboard | 192 // completes their gesture, this method will decide what keyboard |
152 // input their gesture corresponded to. | 193 // input their gesture corresponded to. |
153 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE; | 194 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE; |
154 | 195 |
155 // Process the gesture events that have been created. | 196 // Process the gesture events that have been created. |
156 void ProcessGestureEvents(); | 197 void ProcessGestureEvents(); |
157 | 198 |
158 void OnSwipeEvent(ui::GestureEvent* swipe_gesture); | 199 void OnSwipeEvent(ui::GestureEvent* swipe_gesture); |
159 | 200 |
| 201 void SideSlideControl(ui::GestureEvent* gesture); |
| 202 |
160 // Dispatches the keyboard short cut Shift+Search+<arrow key> | 203 // Dispatches the keyboard short cut Shift+Search+<arrow key> |
161 // outside the event rewritting flow. | 204 // outside the event rewritting flow. |
162 void DispatchShiftSearchKeyEvent(const ui::KeyboardCode direction); | 205 void DispatchShiftSearchKeyEvent(const ui::KeyboardCode direction); |
163 | 206 |
164 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, | 207 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, |
165 int flags); | 208 int flags); |
166 | 209 |
167 void EnterTouchToMouseMode(); | 210 void EnterTouchToMouseMode(); |
168 | 211 |
169 // Set the state to NO_FINGERS_DOWN and reset any other fields to their | 212 // Set the state to NO_FINGERS_DOWN and reset any other fields to their |
170 // default value. | 213 // default value. |
171 void ResetToNoFingersDown(); | 214 void ResetToNoFingersDown(); |
172 | 215 |
| 216 void PlaySoundForTimer(); |
| 217 |
| 218 // Some constants used in touch_exploration_controller: |
| 219 |
| 220 // Within this many dips of the screen edge, the release event generated will |
| 221 // reset the state to NoFingersDown. |
| 222 const float kLeavingScreenEdge = 6; |
| 223 |
| 224 // Swipe/scroll gestures within these bounds (in DIPs) will change preset |
| 225 // settings. |
| 226 const float kMaxDistanceFromEdge = 75; |
| 227 |
| 228 // After a slide gesture has been triggered, if the finger is still within |
| 229 // these bounds (in DIPs), the preset settings will still change. |
| 230 const float kSlopDistanceFromEdge = kMaxDistanceFromEdge + 40; |
| 231 |
173 enum State { | 232 enum State { |
174 // No fingers are down and no events are pending. | 233 // No fingers are down and no events are pending. |
175 NO_FINGERS_DOWN, | 234 NO_FINGERS_DOWN, |
176 | 235 |
177 // A single finger is down, but we're not yet sure if this is going | 236 // A single finger is down, but we're not yet sure if this is going |
178 // to be touch exploration or something else. | 237 // to be touch exploration or something else. |
179 SINGLE_TAP_PRESSED, | 238 SINGLE_TAP_PRESSED, |
180 | 239 |
181 // The user pressed and released a single finger - a tap - but we have | 240 // The user pressed and released a single finger - a tap - but we have |
182 // to wait until the end of the grace period to allow the user to tap the | 241 // to wait until the end of the grace period to allow the user to tap the |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 // If the user is in TWO_TO_ONE_FINGER with two fingers down and presses | 288 // If the user is in TWO_TO_ONE_FINGER with two fingers down and presses |
230 // a third finger, every finger and touch event is passed through until | 289 // a third finger, every finger and touch event is passed through until |
231 // all fingers are released. | 290 // all fingers are released. |
232 PASSTHROUGH, | 291 PASSTHROUGH, |
233 | 292 |
234 // If the user lifted a finger in TWO_TO_ONE_FINGER, they must release | 293 // If the user lifted a finger in TWO_TO_ONE_FINGER, they must release |
235 // all fingers before completing any more actions. This state is | 294 // all fingers before completing any more actions. This state is |
236 // generally useful for developing new features, because it creates a | 295 // generally useful for developing new features, because it creates a |
237 // simple way to handle a dead end in user flow. | 296 // simple way to handle a dead end in user flow. |
238 WAIT_FOR_RELEASE, | 297 WAIT_FOR_RELEASE, |
| 298 |
| 299 // If the user is within the given bounds from an edge of the screen, not |
| 300 // including corners, then the resulting movements will be interpreted as |
| 301 // slide gestures. |
| 302 SLIDE_GESTURE, |
239 }; | 303 }; |
240 | 304 |
| 305 enum ScreenLocation { |
| 306 // Hot "edges" of the screen are each represented by a respective bit. |
| 307 NO_EDGE = 0, |
| 308 RIGHT_EDGE = 1 << 0, |
| 309 TOP_EDGE = 1 << 1, |
| 310 LEFT_EDGE = 1 << 2, |
| 311 BOTTOM_EDGE = 1 << 3, |
| 312 }; |
| 313 |
| 314 // Given a point, if it is within the given bounds of an edge, returns the |
| 315 // edge. If it is within the given bounds of two edges, returns an int with |
| 316 // both bits that represent the respective edges turned on. Otherwise returns |
| 317 // SCREEN_CENTER. |
| 318 int FindEdgesWithinBounds(gfx::Point point, float bounds); |
| 319 |
241 void VlogState(const char* function_name); | 320 void VlogState(const char* function_name); |
242 | 321 |
243 void VlogEvent(const ui::TouchEvent& event, const char* function_name); | 322 void VlogEvent(const ui::TouchEvent& event, const char* function_name); |
244 | 323 |
245 // Gets enum name from integer value. | 324 // Gets enum name from integer value. |
246 const char* EnumStateToString(State state); | 325 const char* EnumStateToString(State state); |
247 | 326 |
248 aura::Window* root_window_; | 327 aura::Window* root_window_; |
249 | 328 |
| 329 // Handles volume control. Not owned. |
| 330 ui::TouchExplorationControllerDelegate* delegate_; |
| 331 |
250 // A set of touch ids for fingers currently touching the screen. | 332 // A set of touch ids for fingers currently touching the screen. |
251 std::vector<int> current_touch_ids_; | 333 std::vector<int> current_touch_ids_; |
252 | 334 |
253 // Map of touch ids to their last known location. | 335 // Map of touch ids to their last known location. |
254 std::map<int, gfx::PointF> touch_locations_; | 336 std::map<int, gfx::PointF> touch_locations_; |
255 | 337 |
256 // The current state. | 338 // The current state. |
257 State state_; | 339 State state_; |
258 | 340 |
259 // A copy of the event from the initial touch press. | 341 // A copy of the event from the initial touch press. |
260 scoped_ptr<ui::TouchEvent> initial_press_; | 342 scoped_ptr<ui::TouchEvent> initial_press_; |
261 | 343 |
262 // Stores the most recent event from a finger that is currently not | 344 // Stores the most recent event from a finger that is currently not |
263 // sending events through, but might in the future (e.g. TwoToOneFinger | 345 // sending events through, but might in the future (e.g. TwoToOneFinger |
264 // to Passthrough state). | 346 // to Passthrough state). |
265 scoped_ptr<ui::TouchEvent> last_unused_finger_event_; | 347 scoped_ptr<ui::TouchEvent> last_unused_finger_event_; |
266 | 348 |
267 // The last synthesized mouse move event. When the user double-taps, | 349 // The last synthesized mouse move event. When the user double-taps, |
268 // we send the passed-through tap to the location of this event. | 350 // we send the passed-through tap to the location of this event. |
269 scoped_ptr<ui::TouchEvent> last_touch_exploration_; | 351 scoped_ptr<ui::TouchEvent> last_touch_exploration_; |
270 | 352 |
271 // The last event from the finger that is being passed through in | 353 // The last event from the finger that is being passed through in |
272 // TWO_TO_ONE_FINGER. When the user lifts a finger during two to one, | 354 // TWO_TO_ONE_FINGER. When the user lifts a finger during two to one, |
273 // the location and id of the touch release is from here. | 355 // the location and id of the touch release is from here. |
274 scoped_ptr<ui::TouchEvent> last_two_to_one_; | 356 scoped_ptr<ui::TouchEvent> last_two_to_one_; |
275 | 357 |
276 // A timer to fire the mouse move event after the double-tap delay. | 358 // A timer to fire the mouse move event after the double-tap delay. |
277 base::OneShotTimer<TouchExplorationController> tap_timer_; | 359 base::OneShotTimer<TouchExplorationController> tap_timer_; |
278 | 360 |
| 361 // A timer to fire an indicating sound when sliding to change volume. |
| 362 base::RepeatingTimer<TouchExplorationController> sound_timer_; |
| 363 |
279 // For testing only, an event handler to use for generated events | 364 // For testing only, an event handler to use for generated events |
280 // outside of the normal event rewriting flow. | 365 // outside of the normal event rewriting flow. |
281 ui::EventHandler* event_handler_for_testing_; | 366 ui::EventHandler* event_handler_for_testing_; |
282 | 367 |
283 // A default gesture detector config, so we can share the same | 368 // A default gesture detector config, so we can share the same |
284 // timeout and pixel slop constants. | 369 // timeout and pixel slop constants. |
285 ui::GestureDetector::Config gesture_detector_config_; | 370 ui::GestureDetector::Config gesture_detector_config_; |
286 | 371 |
287 // Gesture Handler to interpret the touch events. | 372 // Gesture Handler to interpret the touch events. |
288 ui::GestureProviderAura gesture_provider_; | 373 ui::GestureProviderAura gesture_provider_; |
289 | 374 |
290 // The previous state entered. | 375 // The previous state entered. |
291 State prev_state_; | 376 State prev_state_; |
292 | 377 |
293 // A copy of the previous event passed. | 378 // A copy of the previous event passed. |
294 scoped_ptr<ui::TouchEvent> prev_event_; | 379 scoped_ptr<ui::TouchEvent> prev_event_; |
295 | 380 |
296 // This toggles whether VLOGS are turned on or not. | 381 // This toggles whether VLOGS are turned on or not. |
297 bool VLOG_on_; | 382 bool VLOG_on_; |
298 | 383 |
299 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); | 384 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); |
300 }; | 385 }; |
301 | 386 |
302 } // namespace ui | 387 } // namespace ui |
303 | 388 |
304 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ | 389 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
OLD | NEW |