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

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

Issue 385073009: Side Slide Gestures for Accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added Tests for Slide Gestures Created 6 years, 5 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 #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
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698