Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: ui/chromeos/touch_exploration_controller.h

Issue 296403011: Support double-tap to click in touch accessibility controller. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
};

Powered by Google App Engine
This is Rietveld 408576698