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
3 // found in the LICENSE file.
5 #ifndef UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_
6 #define UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_
8 #include "base/timer/timer.h"
9 #include "base/values.h"
10 #include "ui/chromeos/ui_chromeos_export.h"
11 #include "ui/events/event.h"
12 #include "ui/events/event_rewriter.h"
13 #include "ui/events/gesture_detection/gesture_detector.h"
14 #include "ui/events/gestures/gesture_provider_aura.h"
15 #include "ui/gfx/geometry/point.h"
26 class GestureProviderAura
;
29 // TouchExplorationController is used in tandem with "Spoken Feedback" to
30 // make the touch UI accessible. Gestures are mapped to accessiblity key
33 // ** Short version **
35 // At a high-level, single-finger events are used for accessibility -
36 // 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
38 // 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
40 // 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
42 // 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.
47 // Here are the details of the implementation:
49 // When the first touch is pressed, a 300 ms grace period timer starts.
51 // 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),
53 // they enter touch exploration mode, and all movements are translated into
54 // synthesized mouse move events.
56 // Also, if the user moves their single finger outside a certain slop region
57 // (without performing a gesture), they enter touch exploration mode earlier
60 // If the user taps and releases their finger, after 300 ms from the initial
61 // touch, a single mouse move is fired.
63 // While in touch exploration mode, the user can perform a single tap
64 // if the user releases their finger and taps before 300 ms passes.
65 // This will result in a click on the last successful touch exploration
66 // location. This allows the user to perform a single tap
67 // anywhere to activate it.
69 // The user can perform swipe gestures in one of the four cardinal directions
70 // which will be interpreted and used to control the UI. The gesture will only
71 // be registered if the finger moves outside the slop and completed within the
72 // grace period. If additional fingers are added during the grace period, the
73 // state changes to passthrough. If the gesture fails to be completed within the
74 // grace period, the state changes to touch exploration mode. Once the state has
75 // changed, any gestures made during the grace period are discarded.
77 // If the user double-taps, the second tap is passed through, allowing the
78 // user to click - however, the double-tap location is changed to the location
79 // of the last successful touch exploration - that allows the user to explore
80 // anywhere on the screen, hear its description, then double-tap anywhere
83 // If the user enters touch exploration mode, they can click without lifting
84 // their touch exploration finger by tapping anywhere else on the screen with
85 // a second finger, while the touch exploration finger is still pressed.
87 // 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
89 // 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
91 // adds a third finger while in two to one finger mode, all fingers and touch
92 // events are passed through from then on.
94 // Once touch exploration mode has been activated,
95 // it remains in that mode until all fingers have been released.
97 // The caller is expected to retain ownership of instances of this class and
98 // destroy them before |root_window| is destroyed.
99 class UI_CHROMEOS_EXPORT TouchExplorationController
100 : public ui::EventRewriter
,
101 public ui::GestureProviderAuraClient
{
103 explicit TouchExplorationController(aura::Window
* root_window
);
104 virtual ~TouchExplorationController();
107 friend class TouchExplorationControllerTestApi
;
109 // Overridden from ui::EventRewriter
110 virtual ui::EventRewriteStatus
RewriteEvent(
111 const ui::Event
& event
,
112 scoped_ptr
<ui::Event
>* rewritten_event
) OVERRIDE
;
113 virtual ui::EventRewriteStatus
NextDispatchEvent(
114 const ui::Event
& last_event
, scoped_ptr
<ui::Event
>* new_event
) OVERRIDE
;
116 // Event handlers based on the current state - see State, below.
117 ui::EventRewriteStatus
InNoFingersDown(
118 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
119 ui::EventRewriteStatus
InSingleTapPressed(
120 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
121 ui::EventRewriteStatus
InSingleTapOrTouchExploreReleased(
122 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
123 ui::EventRewriteStatus
InDoubleTapPressed(
124 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
125 ui::EventRewriteStatus
InTouchExploration(
126 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
127 ui::EventRewriteStatus
InTwoToOneFinger(
128 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
129 ui::EventRewriteStatus
InPassthrough(
130 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
131 ui::EventRewriteStatus
InGestureInProgress(
132 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
133 ui::EventRewriteStatus
InTouchExploreSecondPress(
134 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
135 ui::EventRewriteStatus
InWaitForRelease(
136 const ui::TouchEvent
& event
, scoped_ptr
<ui::Event
>* rewritten_event
);
138 // 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).
140 // 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.
142 void OnTapTimerFired();
144 // Dispatch a new event outside of the event rewriting flow.
145 void DispatchEvent(ui::Event
* event
);
147 // Overridden from GestureProviderAuraClient.
149 // The gesture provider keeps track of all the touch events after
150 // the user moves fast enough to trigger a gesture. After the user
151 // completes their gesture, this method will decide what keyboard
152 // input their gesture corresponded to.
153 virtual void OnGestureEvent(ui::GestureEvent
* gesture
) OVERRIDE
;
155 // Process the gesture events that have been created.
156 void ProcessGestureEvents();
158 void OnSwipeEvent(ui::GestureEvent
* swipe_gesture
);
160 // Dispatches the keyboard short cut Shift+Search+<arrow key>
161 // outside the event rewritting flow.
162 void DispatchShiftSearchKeyEvent(const ui::KeyboardCode direction
);
164 scoped_ptr
<ui::Event
> CreateMouseMoveEvent(const gfx::PointF
& location
,
167 void EnterTouchToMouseMode();
169 // Set the state to NO_FINGERS_DOWN and reset any other fields to their
171 void ResetToNoFingersDown();
174 // No fingers are down and no events are pending.
177 // A single finger is down, but we're not yet sure if this is going
178 // to be touch exploration or something else.
181 // 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
183 // second time. If the second tap doesn't occurs within the grace period,
184 // we dispatch a mouse move at the location of the first tap.
187 // The user was in touch explore mode and released the finger.
188 // If another touch press occurs within the grace period, a single
189 // tap click occurs. This state differs from SINGLE_TAP_RELEASED
190 // In that if a second tap doesn't occur within the grace period,
191 // there is no mouse move dispatched.
192 TOUCH_EXPLORE_RELEASED
,
194 // The user tapped once, and before the grace period expired, pressed
195 // one finger down to begin a double-tap, but has not released it yet.
198 // We're in touch exploration mode. Anything other than the first finger
199 // is ignored, and movements of the first finger are rewritten as mouse
200 // move events. This mode is entered if a single finger is pressed and
201 // after the grace period the user hasn't added a second finger or
202 // moved the finger outside of the slop region. We'll stay in this
203 // mode until all fingers are lifted.
206 // If the user moves their finger faster than the threshold velocity after a
207 // single tap, the touch events that follow will be translated into gesture
208 // events. If the user successfully completes a gesture within the grace
209 // period, the gesture will be interpreted and used to control the UI via
210 // discrete actions - currently by synthesizing key events corresponding to
211 // each gesture Otherwise, the collected gestures are discarded and the
212 // state changes to touch_exploration.
215 // The user was in touch exploration, but has placed down another finger.
216 // If the user releases the second finger, a touch press and release
217 // will go through at the last touch explore location. If the user
218 // releases the touch explore finger, the other finger will continue with
219 // touch explore. Any fingers pressed past the first two are ignored.
220 TOUCH_EXPLORE_SECOND_PRESS
,
222 // The user placed two fingers down within the grace period.
223 // We're now in two to one finger mode until one of the fingers is
224 // lifted. The first finger is ignored and the events for the second
225 // finger are passed throuugh. If either finger is released, nothing
226 // happens until all fingers are up.
229 // 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
231 // all fingers are released.
234 // 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
236 // generally useful for developing new features, because it creates a
237 // simple way to handle a dead end in user flow.
241 void VlogState(const char* function_name
);
243 void VlogEvent(const ui::TouchEvent
& event
, const char* function_name
);
245 // Gets enum name from integer value.
246 const char* EnumStateToString(State state
);
248 aura::Window
* root_window_
;
250 // A set of touch ids for fingers currently touching the screen.
251 std::vector
<int> current_touch_ids_
;
253 // Map of touch ids to their last known location.
254 std::map
<int, gfx::PointF
> touch_locations_
;
256 // The current state.
259 // A copy of the event from the initial touch press.
260 scoped_ptr
<ui::TouchEvent
> initial_press_
;
262 // Stores the most recent event from a finger that is currently not
263 // sending events through, but might in the future (e.g. TwoToOneFinger
264 // to Passthrough state).
265 scoped_ptr
<ui::TouchEvent
> last_unused_finger_event_
;
267 // The last synthesized mouse move event. When the user double-taps,
268 // we send the passed-through tap to the location of this event.
269 scoped_ptr
<ui::TouchEvent
> last_touch_exploration_
;
271 // 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,
273 // the location and id of the touch release is from here.
274 scoped_ptr
<ui::TouchEvent
> last_two_to_one_
;
276 // A timer to fire the mouse move event after the double-tap delay.
277 base::OneShotTimer
<TouchExplorationController
> tap_timer_
;
279 // For testing only, an event handler to use for generated events
280 // outside of the normal event rewriting flow.
281 ui::EventHandler
* event_handler_for_testing_
;
283 // A default gesture detector config, so we can share the same
284 // timeout and pixel slop constants.
285 ui::GestureDetector::Config gesture_detector_config_
;
287 // Gesture Handler to interpret the touch events.
288 ui::GestureProviderAura gesture_provider_
;
290 // The previous state entered.
293 // A copy of the previous event passed.
294 scoped_ptr
<ui::TouchEvent
> prev_event_
;
296 // This toggles whether VLOGS are turned on or not.
299 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController
);
304 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_