Files.app: Override overflow specifying to use the original scroll bar.
[chromium-blink-merge.git] / ui / chromeos / touch_exploration_controller.h
blobe809bcd7b9378f0232a2137e4bd0f29e4f605f5a
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"
17 namespace aura {
18 class Window;
21 namespace ui {
23 class Event;
24 class EventHandler;
25 class GestureEvent;
26 class GestureProviderAura;
27 class TouchEvent;
29 // TouchExplorationController is used in tandem with "Spoken Feedback" to
30 // make the touch UI accessible. Gestures are mapped to accessiblity key
31 // shortcuts.
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.
45 // ** Long version **
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
58 // than 300 ms.
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
81 // to activate it.
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 {
102 public:
103 explicit TouchExplorationController(aura::Window* root_window);
104 virtual ~TouchExplorationController();
106 void CallTapTimerNowForTesting();
107 void CallTapTimerNowIfRunningForTesting();
108 void SetEventHandlerForTesting(ui::EventHandler* event_handler_for_testing);
109 bool IsInNoFingersDownStateForTesting() const;
110 bool IsInGestureInProgressStateForTesting() const;
111 // VLOGs should be suppressed in tests that generate a lot of logs,
112 // for example permutations of nine touch events.
113 void SuppressVLOGsForTesting(bool suppress);
115 private:
116 // Overridden from ui::EventRewriter
117 virtual ui::EventRewriteStatus RewriteEvent(
118 const ui::Event& event,
119 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE;
120 virtual ui::EventRewriteStatus NextDispatchEvent(
121 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE;
123 // Event handlers based on the current state - see State, below.
124 ui::EventRewriteStatus InNoFingersDown(
125 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
126 ui::EventRewriteStatus InSingleTapPressed(
127 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
128 ui::EventRewriteStatus InSingleTapOrTouchExploreReleased(
129 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
130 ui::EventRewriteStatus InDoubleTapPressed(
131 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
132 ui::EventRewriteStatus InTouchExploration(
133 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
134 ui::EventRewriteStatus InTwoToOneFinger(
135 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
136 ui::EventRewriteStatus InPassthrough(
137 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
138 ui::EventRewriteStatus InGestureInProgress(
139 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
140 ui::EventRewriteStatus InTouchExploreSecondPress(
141 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
142 ui::EventRewriteStatus InWaitForRelease(
143 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
145 // 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).
147 // 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.
149 void OnTapTimerFired();
151 // Dispatch a new event outside of the event rewriting flow.
152 void DispatchEvent(ui::Event* event);
154 // Overridden from GestureProviderAuraClient.
156 // The gesture provider keeps track of all the touch events after
157 // the user moves fast enough to trigger a gesture. After the user
158 // completes their gesture, this method will decide what keyboard
159 // input their gesture corresponded to.
160 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE;
162 // Process the gesture events that have been created.
163 void ProcessGestureEvents();
165 void OnSwipeEvent(ui::GestureEvent* swipe_gesture);
167 // Dispatches the keyboard short cut Shift+Search+<arrow key>
168 // outside the event rewritting flow.
169 void DispatchShiftSearchKeyEvent(const ui::KeyboardCode direction);
171 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location,
172 int flags);
174 void EnterTouchToMouseMode();
176 // Set the state to NO_FINGERS_DOWN and reset any other fields to their
177 // default value.
178 void ResetToNoFingersDown();
180 enum State {
181 // No fingers are down and no events are pending.
182 NO_FINGERS_DOWN,
184 // A single finger is down, but we're not yet sure if this is going
185 // to be touch exploration or something else.
186 SINGLE_TAP_PRESSED,
188 // 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
190 // second time. If the second tap doesn't occurs within the grace period,
191 // we dispatch a mouse move at the location of the first tap.
192 SINGLE_TAP_RELEASED,
194 // The user was in touch explore mode and released the finger.
195 // If another touch press occurs within the grace period, a single
196 // tap click occurs. This state differs from SINGLE_TAP_RELEASED
197 // In that if a second tap doesn't occur within the grace period,
198 // there is no mouse move dispatched.
199 TOUCH_EXPLORE_RELEASED,
201 // The user tapped once, and before the grace period expired, pressed
202 // one finger down to begin a double-tap, but has not released it yet.
203 DOUBLE_TAP_PRESSED,
205 // We're in touch exploration mode. Anything other than the first finger
206 // is ignored, and movements of the first finger are rewritten as mouse
207 // move events. This mode is entered if a single finger is pressed and
208 // after the grace period the user hasn't added a second finger or
209 // moved the finger outside of the slop region. We'll stay in this
210 // mode until all fingers are lifted.
211 TOUCH_EXPLORATION,
213 // If the user moves their finger faster than the threshold velocity after a
214 // single tap, the touch events that follow will be translated into gesture
215 // events. If the user successfully completes a gesture within the grace
216 // period, the gesture will be interpreted and used to control the UI via
217 // discrete actions - currently by synthesizing key events corresponding to
218 // each gesture Otherwise, the collected gestures are discarded and the
219 // state changes to touch_exploration.
220 GESTURE_IN_PROGRESS,
222 // The user was in touch exploration, but has placed down another finger.
223 // If the user releases the second finger, a touch press and release
224 // will go through at the last touch explore location. If the user
225 // releases the touch explore finger, the other finger will continue with
226 // touch explore. Any fingers pressed past the first two are ignored.
227 TOUCH_EXPLORE_SECOND_PRESS,
229 // The user placed two fingers down within the grace period.
230 // We're now in two to one finger mode until one of the fingers is
231 // lifted. The first finger is ignored and the events for the second
232 // finger are passed throuugh. If either finger is released, nothing
233 // happens until all fingers are up.
234 TWO_TO_ONE_FINGER,
236 // 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
238 // all fingers are released.
239 PASSTHROUGH,
241 // 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
243 // generally useful for developing new features, because it creates a
244 // simple way to handle a dead end in user flow.
245 WAIT_FOR_RELEASE,
248 void VlogState(const char* function_name);
250 void VlogEvent(const ui::TouchEvent& event, const char* function_name);
252 // Gets enum name from integer value.
253 const char* EnumStateToString(State state);
255 aura::Window* root_window_;
257 // A set of touch ids for fingers currently touching the screen.
258 std::vector<int> current_touch_ids_;
260 // Map of touch ids to their last known location.
261 std::map<int, gfx::PointF> touch_locations_;
263 // The current state.
264 State state_;
266 // A copy of the event from the initial touch press.
267 scoped_ptr<ui::TouchEvent> initial_press_;
269 // Stores the most recent event from a finger that is currently not
270 // sending events through, but might in the future (e.g. TwoToOneFinger
271 // to Passthrough state).
272 scoped_ptr<ui::TouchEvent> last_unused_finger_event_;
274 // The last synthesized mouse move event. When the user double-taps,
275 // we send the passed-through tap to the location of this event.
276 scoped_ptr<ui::TouchEvent> last_touch_exploration_;
278 // 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,
280 // the location and id of the touch release is from here.
281 scoped_ptr<ui::TouchEvent> last_two_to_one_;
283 // A timer to fire the mouse move event after the double-tap delay.
284 base::OneShotTimer<TouchExplorationController> tap_timer_;
286 // For testing only, an event handler to use for generated events
287 // outside of the normal event rewriting flow.
288 ui::EventHandler* event_handler_for_testing_;
290 // A default gesture detector config, so we can share the same
291 // timeout and pixel slop constants.
292 ui::GestureDetector::Config gesture_detector_config_;
294 // Gesture Handler to interpret the touch events.
295 ui::GestureProviderAura gesture_provider_;
297 // The previous state entered.
298 State prev_state_;
300 // A copy of the previous event passed.
301 scoped_ptr<ui::TouchEvent> prev_event_;
303 // This toggles whether VLOGS are turned on or not.
304 bool VLOG_on_;
306 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController);
309 } // namespace ui
311 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_