Chromium Code Reviews| Index: ui/chromeos/touch_exploration_controller.h |
| diff --git a/ui/chromeos/touch_exploration_controller.h b/ui/chromeos/touch_exploration_controller.h |
| index d6fa8af0da7fd47ed933019d57ea2d1cece9efc0..083c79d5818f67fe1d332c2e81634c7b5a883c4d 100644 |
| --- a/ui/chromeos/touch_exploration_controller.h |
| +++ b/ui/chromeos/touch_exploration_controller.h |
| @@ -5,9 +5,11 @@ |
| #ifndef UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
| #define UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ |
| +#include "base/timer/timer.h" |
| #include "base/values.h" |
| #include "ui/chromeos/ui_chromeos_export.h" |
| #include "ui/events/event_rewriter.h" |
| +#include "ui/events/gesture_detection/gesture_detector.h" |
| #include "ui/gfx/geometry/point.h" |
| namespace aura { |
| @@ -17,17 +19,52 @@ class Window; |
| namespace ui { |
| class Event; |
| +class TouchEvent; |
| // TouchExplorationController is used in tandem with "Spoken Feedback" to |
| -// make the touch UI accessible. TouchExplorationController rewrites the |
| -// incoming touch events as follows: |
| -// - When one finger is touching the screen, touch events are converted to mouse |
| -// moves. This is the "Touch Exploration Mode". (The idea is that mouse moves |
| -// will be subsequently used by another component to move focus between UI |
| -// elements, and the elements will be read out to the user.) |
| -// - When more than one finger is touching the screen, touches from the |
| -// first (i.e. "oldest") finger are ignored, and the other touches go through |
| -// as is. |
| +// make the touch UI accessible. |
| +// |
| +// At a high-level, single-finger events are used for accessibility - |
| +// exploring the screen gets turned into mouse moves (which can then be |
| +// spoken by an accessibility service running), a double-tap simulates a |
| +// click, and gestures can be used to send high-level accessibility commands. |
| +// 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
|
| +// 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.
|
| +// running app will see a one-finger swipe. |
| +// |
| +// Here are the details of the implementation: |
| +// |
| +// When the first touch is pressed, a 300 ms grace period timer starts. |
| +// |
| +// If the user keeps their finger down for more than 300 ms and doesn't |
| +// 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.
|
| +// all movements are translated into synthesized mouse move events. |
| +// |
| +// 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.
|
| +// (without performing a gesture), they enter touch exploration mode earlier |
| +// than 300 ms. |
| +// |
| +// If the user taps and releases their finger, after 300 ms from the initial |
| +// touch, a single mouse move is fired. |
| +// |
| +// If the user double-taps, the second tap is passed through, allowing the |
| +// user to click - however, the double-tap location is changed to the location |
| +// of the last successful touch exploration - that allows the user to explore |
| +// anywhere on the screen, hear its description, then double-tap anywhere |
| +// to activate it. |
| +// |
| +// If the user adds a second finger during the grace period, they enter |
| +// passthrough mode. In this mode, the first finger is ignored but all |
| +// additional touch events are mostly passed through unmodified. So a |
| +// two-finger scroll gets passed through as a one-finger scroll. However, |
| +// 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.
|
| +// continues to pass through events, allowing the user to start a scroll |
| +// with two fingers but finish it with one. Sometimes this requires rewriting |
| +// the touch ids. |
| +// |
| +// Once either touch exploration or passthrough mode has been activated, |
| +// it remains in that mode until all fingers have been released. |
| +// |
| // The caller is expected to retain ownership of instances of this class and |
| // destroy them before |root_window| is destroyed. |
| class UI_CHROMEOS_EXPORT TouchExplorationController : |
| @@ -48,16 +85,85 @@ class UI_CHROMEOS_EXPORT TouchExplorationController : |
| virtual ui::EventRewriteStatus NextDispatchEvent( |
| const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE; |
| + // Event handlers based on the current state - see State, below. |
| + ui::EventRewriteStatus OnNoFingersDown( |
| + const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| + ui::EventRewriteStatus OnGracePeriod( |
| + const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| + ui::EventRewriteStatus OnTouchExploration( |
| + const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| + ui::EventRewriteStatus OnPassthroughMinusOne( |
| + const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| + ui::EventRewriteStatus OnSingleTapPending( |
| + const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| + ui::EventRewriteStatus OnDoubleTapPressed( |
| + const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event); |
| + |
| + // This timer is started every time we get the first press event, and |
| + // it fires after the double-click timeout elapses (300 ms by default). |
| + // If the user taps and releases within 300 ms and doesn't press again, |
| + // we treat that as a single mouse move (touch exploration) event. |
| + void OnTapTimerFired(); |
| + |
| + enum State { |
| + // No fingers are down and no events are pending. |
| + NO_FINGERS_DOWN, |
| + |
| + // A single finger is down, but we're not yet sure if this is going |
| + // to be touch exploration or something else. |
| + 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.
|
| + |
| + // 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.
|
| + // hasn't added a second finger or moved the finger too rapidly. |
| + // 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.
|
| + 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.
|
| + |
| + // 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.
|
| + // to wait until the end of the grace period before we will rewrite this |
| + // as touch exploration, in case it's actually the first tap of a mouse |
| + // move. |
| + SINGLE_TAP_PENDING, |
| + |
| + // The user tapped once, and before the grace period expired, pressed |
| + // one finger down to begin a double-tap, but has not released it yet. |
| + DOUBLE_TAP_PRESSED, |
| + |
| + // The user placed two or more fingers down within the grace period. |
| + // We're now in passthrough mode until all fingers are lifted. When |
| + // 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
|
| + // pass through all events unchanged. |
| + PASSTHROUGH_MINUS_ONE, |
| + }; |
| + |
| + aura::Window* root_window_; |
| + |
| // A set of touch ids for fingers currently touching the screen. |
| std::vector<int> touch_ids_; |
| // Map of touch ids to their last known location. |
| std::map<int, gfx::PointF> touch_locations_; |
| - // Initialized from RewriteEvent() and dispatched in NextDispatchEvent(). |
| - scoped_ptr<ui::Event> next_dispatch_event_; |
| + // 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?
|
| + // "passthrough minus one" mode, where we pass through two-finger gestures |
| + // as if they were one, and so on. |
| + std::map<int, int> touch_id_map_; |
| - aura::Window* root_window_; |
| + // The current state. |
| + State state_; |
| + |
| + // A copy of the event from the initial touch press. |
| + scoped_ptr<ui::TouchEvent> initial_press_; |
| + |
| + // The last location where we synthesized a mouse move event. |
| + // When the user double-taps, we send the passed-through tap here. |
| + gfx::PointF last_touch_exploration_location_; |
| + |
| + // A timer to fire the mouse move event after the double-tap delay. |
| + base::OneShotTimer<TouchExplorationController> tap_timer_; |
| + |
| + // A default gesture detector config, so we can share the same |
| + // timeout and pixel slop constants. |
| + ui::GestureDetector::Config gesture_detector_config_; |
| DISALLOW_COPY_AND_ASSIGN(TouchExplorationController); |
| }; |