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