Chromium Code Reviews| 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/gfx/geometry/point.h" | 15 #include "ui/gfx/geometry/point.h" |
| 15 | 16 |
| 16 namespace aura { | 17 namespace aura { |
| 17 class Window; | 18 class Window; |
| 18 } | 19 } |
| 19 | 20 |
| 20 namespace ui { | 21 namespace ui { |
| 21 | 22 |
| 22 class Event; | 23 class Event; |
| 23 class EventHandler; | 24 class EventHandler; |
| 25 class GestureEvent; | |
| 26 class GestureProviderAura; | |
| 24 class TouchEvent; | 27 class TouchEvent; |
| 25 | 28 |
| 26 // TouchExplorationController is used in tandem with "Spoken Feedback" to | 29 // TouchExplorationController is used in tandem with "Spoken Feedback" to |
| 27 // make the touch UI accessible. | 30 // make the touch UI accessible. Gestures are mapped to accessible key |
|
tdresser
2014/06/26 13:31:49
Should "accessible" be "accessibility"?
| |
| 31 // shortcuts. | |
| 28 // | 32 // |
| 29 // ** Short version ** | 33 // ** Short version ** |
| 30 // | 34 // |
| 31 // At a high-level, single-finger events are used for accessibility - | 35 // At a high-level, single-finger events are used for accessibility - |
| 32 // exploring the screen gets turned into mouse moves (which can then be | 36 // exploring the screen gets turned into mouse moves (which can then be |
| 33 // spoken by an accessibility service running), a single tap while the user | 37 // spoken by an accessibility service running), a single tap while the user |
| 34 // is in touch exploration or a double-tap simulates a click, and gestures | 38 // is in touch exploration or a double-tap simulates a click, and gestures |
| 35 // can be used to send high-level accessibility commands. | 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. | |
| 36 // When two or more fingers are pressed initially, from then on the events | 41 // When two or more fingers are pressed initially, from then on the events |
| 37 // are passed through, but with the initial finger removed - so if you swipe | 42 // are passed through, but with the initial finger removed - so if you swipe |
| 38 // down with two fingers, the running app will see a one-finger swipe. | 43 // down with two fingers, the running app will see a one-finger swipe. |
| 39 // | 44 // |
| 40 // ** Long version ** | 45 // ** Long version ** |
| 41 // | 46 // |
| 42 // Here are the details of the implementation: | 47 // Here are the details of the implementation: |
| 43 // | 48 // |
| 44 // When the first touch is pressed, a 300 ms grace period timer starts. | 49 // When the first touch is pressed, a 300 ms grace period timer starts. |
| 45 // | 50 // |
| 46 // If the user keeps their finger down for more than 300 ms and doesn't | 51 // If the user keeps their finger down for more than 300 ms and doesn't |
| 47 // perform a supported accessibility gesture in that time (e.g. swipe right), | 52 // perform a supported accessibility gesture in that time (e.g. swipe right), |
| 48 // they enter touch exploration mode, and all movements are translated into | 53 // they enter touch exploration mode, and all movements are translated into |
| 49 // synthesized mouse move events. | 54 // synthesized mouse move events. |
| 50 // | 55 // |
| 51 // Also, if the user moves their single finger outside a certain slop region | 56 // Also, if the user moves their single finger outside a certain slop region |
| 52 // (without performing a gesture), they enter touch exploration mode earlier | 57 // (without performing a gesture), they enter touch exploration mode earlier |
| 53 // than 300 ms. | 58 // than 300 ms. |
| 54 // | 59 // |
| 55 // If the user taps and releases their finger, after 300 ms from the initial | 60 // If the user taps and releases their finger, after 300 ms from the initial |
| 56 // touch, a single mouse move is fired. | 61 // touch, a single mouse move is fired. |
| 57 // | 62 // |
| 58 // While in touch exploration mode, the user can perform a single tap | 63 // While in touch exploration mode, the user can perform a single tap |
| 59 // if the user releases their finger and taps before 300 ms passes. | 64 // if the user releases their finger and taps before 300 ms passes. |
| 60 // This will result in a click on the last successful touch exploration | 65 // This will result in a click on the last successful touch exploration |
| 61 // location. This allows the user to perform a single tap | 66 // location. This allows the user to perform a single tap |
| 62 // anywhere to activate it. | 67 // anywhere to activate it. |
| 63 // | 68 // |
| 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 the gesture fails to be completed within the grace period, | |
| 73 // the state changes to touch exploration mode and any gestures made during the | |
| 74 // grace period are discarded. | |
| 75 // | |
| 64 // If the user double-taps, the second tap is passed through, allowing the | 76 // If the user double-taps, the second tap is passed through, allowing the |
| 65 // user to click - however, the double-tap location is changed to the location | 77 // user to click - however, the double-tap location is changed to the location |
| 66 // of the last successful touch exploration - that allows the user to explore | 78 // of the last successful touch exploration - that allows the user to explore |
| 67 // anywhere on the screen, hear its description, then double-tap anywhere | 79 // anywhere on the screen, hear its description, then double-tap anywhere |
| 68 // to activate it. | 80 // to activate it. |
| 69 // | 81 // |
| 70 // If the user enters touch exploration mode, they can click without lifting | 82 // If the user enters touch exploration mode, they can click without lifting |
| 71 // their touch exploration finger by tapping anywhere else on the screen with | 83 // their touch exploration finger by tapping anywhere else on the screen with |
| 72 // a second finger, while the touch exploration finger is still pressed. | 84 // a second finger, while the touch exploration finger is still pressed. |
| 73 // | 85 // |
| 74 // If the user adds a second finger during the grace period, they enter | 86 // If the user adds a second finger during the grace period, they enter |
| 75 // passthrough mode. In this mode, the first finger is ignored but all | 87 // passthrough mode. In this mode, the first finger is ignored but all |
| 76 // additional touch events are mostly passed through unmodified. So a | 88 // additional touch events are mostly passed through unmodified. So a |
| 77 // two-finger scroll gets passed through as a one-finger scroll. However, | 89 // two-finger scroll gets passed through as a one-finger scroll. However, |
| 78 // once in passthrough mode, if one finger is released, the remaining fingers | 90 // once in passthrough mode, if one finger is released, the remaining fingers |
| 79 // continue to pass through events, allowing the user to start a scroll | 91 // continue to pass through events, allowing the user to start a scroll |
| 80 // with two fingers but finish it with one. Sometimes this requires rewriting | 92 // with two fingers but finish it with one. Sometimes this requires rewriting |
| 81 // the touch ids. | 93 // the touch ids. |
| 82 // | 94 // |
| 83 // Once either touch exploration or passthrough mode has been activated, | 95 // Once either touch exploration or passthrough mode has been activated, |
| 84 // it remains in that mode until all fingers have been released. | 96 // it remains in that mode until all fingers have been released. |
| 85 // | 97 // |
| 86 // The caller is expected to retain ownership of instances of this class and | 98 // The caller is expected to retain ownership of instances of this class and |
| 87 // destroy them before |root_window| is destroyed. | 99 // destroy them before |root_window| is destroyed. |
| 88 class UI_CHROMEOS_EXPORT TouchExplorationController : | 100 class UI_CHROMEOS_EXPORT TouchExplorationController |
| 89 public ui::EventRewriter { | 101 : public ui::EventRewriter, |
| 102 public ui::GestureProviderAuraClient { | |
| 90 public: | 103 public: |
| 91 explicit TouchExplorationController(aura::Window* root_window); | 104 explicit TouchExplorationController(aura::Window* root_window); |
| 92 virtual ~TouchExplorationController(); | 105 virtual ~TouchExplorationController(); |
| 93 | 106 |
| 94 void CallTapTimerNowForTesting(); | 107 void CallTapTimerNowForTesting(); |
| 95 void SetEventHandlerForTesting(ui::EventHandler* event_handler_for_testing); | 108 void SetEventHandlerForTesting(ui::EventHandler* event_handler_for_testing); |
| 96 bool IsInNoFingersDownStateForTesting() const; | 109 bool IsInNoFingersDownStateForTesting() const; |
| 110 bool IsInGestureInProgressStateForTesting() const; | |
| 97 | 111 |
| 98 private: | 112 private: |
| 99 // Overridden from ui::EventRewriter | 113 // Overridden from ui::EventRewriter |
| 100 virtual ui::EventRewriteStatus RewriteEvent( | 114 virtual ui::EventRewriteStatus RewriteEvent( |
| 101 const ui::Event& event, | 115 const ui::Event& event, |
| 102 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; | 116 scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; |
| 103 virtual ui::EventRewriteStatus NextDispatchEvent( | 117 virtual ui::EventRewriteStatus NextDispatchEvent( |
| 104 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE; | 118 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE; |
| 105 | 119 |
| 106 // Event handlers based on the current state - see State, below. | 120 // Event handlers based on the current state - see State, below. |
| 107 ui::EventRewriteStatus InNoFingersDown( | 121 ui::EventRewriteStatus InNoFingersDown( |
| 108 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 122 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 109 ui::EventRewriteStatus InSingleTapPressed( | 123 ui::EventRewriteStatus InSingleTapPressed( |
| 110 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 124 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 111 ui::EventRewriteStatus InSingleTapOrTouchExploreReleased( | 125 ui::EventRewriteStatus InSingleTapOrTouchExploreReleased( |
| 112 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 126 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 113 ui::EventRewriteStatus InDoubleTapPressed( | 127 ui::EventRewriteStatus InDoubleTapPressed( |
| 114 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 128 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 115 ui::EventRewriteStatus InTouchExploration( | 129 ui::EventRewriteStatus InTouchExploration( |
| 116 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 130 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 131 ui::EventRewriteStatus InGestureInProgress( | |
| 132 const ui::TouchEvent& event, | |
| 133 scoped_ptr<ui::Event>* rewritten_event); | |
| 117 ui::EventRewriteStatus InPassthroughMinusOne( | 134 ui::EventRewriteStatus InPassthroughMinusOne( |
| 118 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 135 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 119 ui::EventRewriteStatus InTouchExploreSecondPress( | 136 ui::EventRewriteStatus InTouchExploreSecondPress( |
| 120 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | 137 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| 138 | |
| 121 // This timer is started every time we get the first press event, and | 139 // This timer is started every time we get the first press event, and |
| 122 // it fires after the double-click timeout elapses (300 ms by default). | 140 // it fires after the double-click timeout elapses (300 ms by default). |
| 123 // If the user taps and releases within 300 ms and doesn't press again, | 141 // If the user taps and releases within 300 ms and doesn't press again, |
| 124 // we treat that as a single mouse move (touch exploration) event. | 142 // we treat that as a single mouse move (touch exploration) event. |
| 125 void OnTapTimerFired(); | 143 void OnTapTimerFired(); |
| 126 | 144 |
| 127 // Dispatch a new event outside of the event rewriting flow. | 145 // Dispatch a new event outside of the event rewriting flow. |
| 128 void DispatchEvent(ui::Event* event); | 146 void DispatchEvent(ui::Event* event); |
| 129 | 147 |
| 148 // Overridden from GestureProviderAuraClient. | |
| 149 // | |
| 150 // The gesture provider keeps track of all the touch events after | |
| 151 // the user moves fast enough to trigger a gesture. After the user | |
| 152 // completes their gesture, this method will decide what keyboard | |
| 153 // input their gesture corresponded to. | |
| 154 void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE; | |
| 155 | |
| 156 void OnSwipeEvent(ui::GestureEvent* swipe_gesture); | |
| 157 | |
| 158 // Dispatches the keyboard short cut Shift+Search+<arrow key> | |
| 159 // outside the event rewritting flow. | |
| 160 void DispatchShiftSearchKeyEvent(const ui::KeyboardCode direction); | |
| 161 | |
| 130 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, | 162 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, |
| 131 int flags); | 163 int flags); |
| 132 | 164 |
| 133 void EnterTouchToMouseMode(); | 165 void EnterTouchToMouseMode(); |
| 134 | 166 |
| 135 // Set the state to NO_FINGERS_DOWN and reset any other fields to their | 167 // Set the state to NO_FINGERS_DOWN and reset any other fields to their |
| 136 // default value. | 168 // default value. |
| 137 void ResetToNoFingersDown(); | 169 void ResetToNoFingersDown(); |
| 138 | 170 |
| 139 enum State { | 171 enum State { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 162 DOUBLE_TAP_PRESSED, | 194 DOUBLE_TAP_PRESSED, |
| 163 | 195 |
| 164 // We're in touch exploration mode. Anything other than the first finger | 196 // We're in touch exploration mode. Anything other than the first finger |
| 165 // is ignored, and movements of the first finger are rewritten as mouse | 197 // is ignored, and movements of the first finger are rewritten as mouse |
| 166 // move events. This mode is entered if a single finger is pressed and | 198 // move events. This mode is entered if a single finger is pressed and |
| 167 // after the grace period the user hasn't added a second finger or | 199 // after the grace period the user hasn't added a second finger or |
| 168 // moved the finger outside of the slop region. We'll stay in this | 200 // moved the finger outside of the slop region. We'll stay in this |
| 169 // mode until all fingers are lifted. | 201 // mode until all fingers are lifted. |
| 170 TOUCH_EXPLORATION, | 202 TOUCH_EXPLORATION, |
| 171 | 203 |
| 204 // If the user moves their finger faster than the threshold velocity after a | |
| 205 // single tap, the touch events that follow will be translated into gesture | |
| 206 // events. If the user successfully completes a gesture within the grace | |
| 207 // period, the gesture will be interpreted and used to control the UI via | |
| 208 // discrete actions - currently by synthesizing key events corresponding to | |
| 209 // each gesture Otherwise, the collected gestures are discarded and the | |
| 210 // state changes to touch_exploration. | |
| 211 GESTURE_IN_PROGRESS, | |
| 212 | |
| 172 // The user placed two or more fingers down within the grace period. | 213 // The user placed two or more fingers down within the grace period. |
| 173 // We're now in passthrough mode until all fingers are lifted. Initially | 214 // We're now in passthrough mode until all fingers are lifted. Initially |
| 174 // the first finger is ignored and other fingers are passed through | 215 // the first finger is ignored and other fingers are passed through |
| 175 // as-is. If a finger other than the initial one is the first to be | 216 // as-is. If a finger other than the initial one is the first to be |
| 176 // released, we rewrite the first finger with the touch id of the finger | 217 // released, we rewrite the first finger with the touch id of the finger |
| 177 // that was released, from now on. The motivation for this is that if | 218 // that was released, from now on. The motivation for this is that if |
| 178 // the user starts a scroll with 2 fingers, they can release either one | 219 // the user starts a scroll with 2 fingers, they can release either one |
| 179 // and continue the scrolling. | 220 // and continue the scrolling. |
| 180 PASSTHROUGH_MINUS_ONE, | 221 PASSTHROUGH_MINUS_ONE, |
| 181 | 222 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 base::OneShotTimer<TouchExplorationController> tap_timer_; | 265 base::OneShotTimer<TouchExplorationController> tap_timer_; |
| 225 | 266 |
| 226 // For testing only, an event handler to use for generated events | 267 // For testing only, an event handler to use for generated events |
| 227 // outside of the normal event rewriting flow. | 268 // outside of the normal event rewriting flow. |
| 228 ui::EventHandler* event_handler_for_testing_; | 269 ui::EventHandler* event_handler_for_testing_; |
| 229 | 270 |
| 230 // A default gesture detector config, so we can share the same | 271 // A default gesture detector config, so we can share the same |
| 231 // timeout and pixel slop constants. | 272 // timeout and pixel slop constants. |
| 232 ui::GestureDetector::Config gesture_detector_config_; | 273 ui::GestureDetector::Config gesture_detector_config_; |
| 233 | 274 |
| 275 // Gesture Handler to interpret the touch events. | |
| 276 ui::GestureProviderAura gesture_provider_; | |
| 277 | |
| 234 // The previous state entered. | 278 // The previous state entered. |
| 235 State prev_state_; | 279 State prev_state_; |
| 236 | 280 |
| 237 // A copy of the previous event passed. | 281 // A copy of the previous event passed. |
| 238 scoped_ptr<ui::TouchEvent> prev_event_; | 282 scoped_ptr<ui::TouchEvent> prev_event_; |
| 239 | 283 |
| 240 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); | 284 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); |
| 241 }; | 285 }; |
| 242 | 286 |
| 243 } // namespace ui | 287 } // namespace ui |
| 244 | 288 |
| 245 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ | 289 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
| OLD | NEW |