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/values.h" | 9 #include "base/values.h" |
| 9 #include "ui/chromeos/ui_chromeos_export.h" | 10 #include "ui/chromeos/ui_chromeos_export.h" |
| 10 #include "ui/events/event_rewriter.h" | 11 #include "ui/events/event_rewriter.h" |
| 12 #include "ui/events/gesture_detection/gesture_detector.h" | |
| 11 #include "ui/gfx/geometry/point.h" | 13 #include "ui/gfx/geometry/point.h" |
| 12 | 14 |
| 13 namespace aura { | 15 namespace aura { |
| 14 class Window; | 16 class Window; |
| 15 } | 17 } |
| 16 | 18 |
| 17 namespace ui { | 19 namespace ui { |
| 18 | 20 |
| 19 class Event; | 21 class Event; |
| 22 class TouchEvent; | |
| 20 | 23 |
| 21 // TouchExplorationController is used in tandem with "Spoken Feedback" to | 24 // TouchExplorationController is used in tandem with "Spoken Feedback" to |
| 22 // make the touch UI accessible. TouchExplorationController rewrites the | 25 // make the touch UI accessible. |
| 23 // incoming touch events as follows: | 26 // |
| 24 // - When one finger is touching the screen, touch events are converted to mouse | 27 // At a high-level, single-finger events are used for accessibility - |
| 25 // moves. This is the "Touch Exploration Mode". (The idea is that mouse moves | 28 // exploring the screen gets turned into mouse moves (which can then be |
| 26 // will be subsequently used by another component to move focus between UI | 29 // spoken by an accessibility service running), a double-tap simulates a |
| 27 // elements, and the elements will be read out to the user.) | 30 // click, and gestures can be used to send high-level accessibility commands. |
| 28 // - When more than one finger is touching the screen, touches from the | 31 // Whenever two or more fingers are pressed, the events are passed through |
|
mfomitchev
2014/05/28 17:47:45
This doesn't seem entirely accurate - the minus on
dmazzoni
2014/06/04 22:46:27
I tried to clarify, and I also tried to make it mo
| |
| 29 // first (i.e. "oldest") finger are ignored, and the other touches go through | 32 // withone finger removed - so if you swipe down with two fingers, the |
|
mfomitchev
2014/05/28 17:47:45
"withone" - missing space
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 30 // as is. | 33 // running app will see a one-finger swipe. |
| 34 // | |
| 35 // Here are the details of the implementation: | |
| 36 // | |
| 37 // When the first touch is pressed, a 300 ms grace period timer starts. | |
| 38 // | |
| 39 // If the user keeps their finger down for more than 300 ms and doesn't | |
| 40 // perform a gesture in that time, they enter touch exploration mode, and | |
|
mfomitchev
2014/05/28 17:47:45
I'd say smth like "supported accessibility gesture
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 41 // all movements are translated into synthesized mouse move events. | |
| 42 // | |
| 43 // Also, if the user moves their single finger outside a certain slop region | |
|
mfomitchev
2014/05/28 17:47:45
This won't be accurate once we support swipe gestu
dmazzoni
2014/06/04 22:46:27
True, but let's update the comment then.
| |
| 44 // (without performing a gesture), they enter touch exploration mode earlier | |
| 45 // than 300 ms. | |
| 46 // | |
| 47 // If the user taps and releases their finger, after 300 ms from the initial | |
| 48 // touch, a single mouse move is fired. | |
| 49 // | |
| 50 // If the user double-taps, the second tap is passed through, allowing the | |
| 51 // user to click - however, the double-tap location is changed to the location | |
| 52 // of the last successful touch exploration - that allows the user to explore | |
| 53 // anywhere on the screen, hear its description, then double-tap anywhere | |
| 54 // to activate it. | |
| 55 // | |
| 56 // If the user adds a second finger during the grace period, they enter | |
| 57 // passthrough mode. In this mode, the first finger is ignored but all | |
| 58 // additional touch events are mostly passed through unmodified. So a | |
| 59 // two-finger scroll gets passed through as a one-finger scroll. However, | |
| 60 // once in passthrough mode, if one finger is released, the remaining finger | |
|
mfomitchev
2014/05/28 17:47:45
"remaining fingers continue"
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 61 // continues to pass through events, allowing the user to start a scroll | |
| 62 // with two fingers but finish it with one. Sometimes this requires rewriting | |
| 63 // the touch ids. | |
| 64 // | |
| 65 // Once either touch exploration or passthrough mode has been activated, | |
| 66 // it remains in that mode until all fingers have been released. | |
| 67 // | |
| 31 // The caller is expected to retain ownership of instances of this class and | 68 // The caller is expected to retain ownership of instances of this class and |
| 32 // destroy them before |root_window| is destroyed. | 69 // destroy them before |root_window| is destroyed. |
| 33 class UI_CHROMEOS_EXPORT TouchExplorationController : | 70 class UI_CHROMEOS_EXPORT TouchExplorationController : |
| 34 public ui::EventRewriter { | 71 public ui::EventRewriter { |
| 35 public: | 72 public: |
| 36 explicit TouchExplorationController(aura::Window* root_window); | 73 explicit TouchExplorationController(aura::Window* root_window); |
| 37 virtual ~TouchExplorationController(); | 74 virtual ~TouchExplorationController(); |
| 38 | 75 |
| 39 private: | 76 private: |
| 40 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, | 77 scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, |
| 41 int flags); | 78 int flags); |
| 42 | 79 |
| 43 void EnterTouchToMouseMode(); | 80 void EnterTouchToMouseMode(); |
| 44 | 81 |
| 45 // Overridden from ui::EventRewriter | 82 // Overridden from ui::EventRewriter |
| 46 virtual ui::EventRewriteStatus RewriteEvent( | 83 virtual ui::EventRewriteStatus RewriteEvent( |
| 47 const ui::Event& event, scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; | 84 const ui::Event& event, scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; |
| 48 virtual ui::EventRewriteStatus NextDispatchEvent( | 85 virtual ui::EventRewriteStatus NextDispatchEvent( |
| 49 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE; | 86 const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE; |
| 50 | 87 |
| 88 // Event handlers based on the current state - see State, below. | |
| 89 ui::EventRewriteStatus OnNoFingersDown( | |
| 90 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | |
| 91 ui::EventRewriteStatus OnGracePeriod( | |
| 92 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | |
| 93 ui::EventRewriteStatus OnTouchExploration( | |
| 94 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | |
| 95 ui::EventRewriteStatus OnPassthroughMinusOne( | |
| 96 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | |
| 97 ui::EventRewriteStatus OnSingleTapPending( | |
| 98 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | |
| 99 ui::EventRewriteStatus OnDoubleTapPressed( | |
| 100 const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); | |
| 101 | |
| 102 // This timer is started every time we get the first press event, and | |
| 103 // it fires after the double-click timeout elapses (300 ms by default). | |
| 104 // If the user taps and releases within 300 ms and doesn't press again, | |
| 105 // we treat that as a single mouse move (touch exploration) event. | |
| 106 void OnTapTimerFired(); | |
| 107 | |
| 108 enum State { | |
| 109 // No fingers are down and no events are pending. | |
| 110 NO_FINGERS_DOWN, | |
| 111 | |
| 112 // A single finger is down, but we're not yet sure if this is going | |
| 113 // to be touch exploration or something else. | |
| 114 GRACE_PERIOD, | |
|
mfomitchev
2014/05/28 17:47:45
IMHO the naming is a bit confusing, since GRACE_PE
dmazzoni
2014/06/04 22:46:27
I like that, thanks.
| |
| 115 | |
| 116 // A single finger is down and after the grace period the user | |
|
mfomitchev
2014/05/28 17:47:45
You could have multiple fingers down in this mode,
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 117 // hasn't added a second finger or moved the finger too rapidly. | |
| 118 // We're now in touch exploration mode until this finger is lifted. | |
|
mfomitchev
2014/05/28 17:47:45
"until all fingers are lifted"
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 119 TOUCH_EXPLORATION, | |
|
mfomitchev
2014/05/28 17:47:45
I'd move this down next to PASSTHROUGH_MINUS_ONE -
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 120 | |
| 121 // The user pressed and released a single finger - a tap - but we have | |
|
mfomitchev
2014/05/28 17:47:45
This sounds a bit confusing IMHO. I'd say like "..
dmazzoni
2014/06/04 22:46:27
Done.
| |
| 122 // to wait until the end of the grace period before we will rewrite this | |
| 123 // as touch exploration, in case it's actually the first tap of a mouse | |
| 124 // move. | |
| 125 SINGLE_TAP_PENDING, | |
| 126 | |
| 127 // The user tapped once, and before the grace period expired, pressed | |
| 128 // one finger down to begin a double-tap, but has not released it yet. | |
| 129 DOUBLE_TAP_PRESSED, | |
| 130 | |
| 131 // The user placed two or more fingers down within the grace period. | |
| 132 // We're now in passthrough mode until all fingers are lifted. When | |
| 133 // two ore more fingers are down, we subtract one finger but otherwise | |
|
mfomitchev
2014/05/28 17:47:45
Doesn't seem like this is entirely accurate - base
dmazzoni
2014/06/04 22:46:27
Fixed.
FWIW, we may need to tweak this -the mouse
| |
| 134 // pass through all events unchanged. | |
| 135 PASSTHROUGH_MINUS_ONE, | |
| 136 }; | |
| 137 | |
| 138 aura::Window* root_window_; | |
| 139 | |
| 51 // A set of touch ids for fingers currently touching the screen. | 140 // A set of touch ids for fingers currently touching the screen. |
| 52 std::vector<int> touch_ids_; | 141 std::vector<int> touch_ids_; |
| 53 | 142 |
| 54 // Map of touch ids to their last known location. | 143 // Map of touch ids to their last known location. |
| 55 std::map<int, gfx::PointF> touch_locations_; | 144 std::map<int, gfx::PointF> touch_locations_; |
| 56 | 145 |
| 57 // Initialized from RewriteEvent() and dispatched in NextDispatchEvent(). | 146 // A map from the actual touch ids to the rewritten touch ids when in |
|
mfomitchev
2014/05/28 17:47:45
Hmm.. why change touch ids?
| |
| 58 scoped_ptr<ui::Event> next_dispatch_event_; | 147 // "passthrough minus one" mode, where we pass through two-finger gestures |
| 148 // as if they were one, and so on. | |
| 149 std::map<int, int> touch_id_map_; | |
| 59 | 150 |
| 60 aura::Window* root_window_; | 151 // The current state. |
| 152 State state_; | |
| 153 | |
| 154 // A copy of the event from the initial touch press. | |
| 155 scoped_ptr<ui::TouchEvent> initial_press_; | |
| 156 | |
| 157 // The last location where we synthesized a mouse move event. | |
| 158 // When the user double-taps, we send the passed-through tap here. | |
| 159 gfx::PointF last_touch_exploration_location_; | |
| 160 | |
| 161 // A timer to fire the mouse move event after the double-tap delay. | |
| 162 base::OneShotTimer<TouchExplorationController> tap_timer_; | |
| 163 | |
| 164 // A default gesture detector config, so we can share the same | |
| 165 // timeout and pixel slop constants. | |
| 166 ui::GestureDetector::Config gesture_detector_config_; | |
| 61 | 167 |
| 62 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); | 168 DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); |
| 63 }; | 169 }; |
| 64 | 170 |
| 65 } // namespace ui | 171 } // namespace ui |
| 66 | 172 |
| 67 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ | 173 #endif // UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
| OLD | NEW |