Commit 2d3961fa authored by dmazzoni@chromium.org's avatar dmazzoni@chromium.org

Support double-tap to click in touch accessibility controller.

This refactors the touch accessibility controller to work like a state
machine, and implements support for double-tap to send a click to the
last location where the user did touch exploration previously. This also
means reimplementing existing touch interactions so that nothing is
passed through until the double-tap timeout passes or the user moves
outside the slop region.

BUG=377900

Review URL: https://codereview.chromium.org/296403011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275784 0039d316-1c4b-4281-b951-d872f2087c98
parent c01bd2b4
...@@ -55,7 +55,13 @@ IN_PROC_BROWSER_TEST_F(TouchExplorationTest, ToggleOnOff) { ...@@ -55,7 +55,13 @@ IN_PROC_BROWSER_TEST_F(TouchExplorationTest, ToggleOnOff) {
SwitchTouchExplorationMode(true); SwitchTouchExplorationMode(true);
aura::test::EventGenerator generator(root_window); aura::test::EventGenerator generator(root_window);
generator.set_current_location(gfx::Point(100, 200));
generator.PressTouchId(1); generator.PressTouchId(1);
// Since the touch exploration controller doesn't know if the user is
// double-tapping or not, touch exploration is only initiated if the
// user moves more than 8 pixels away from the initial location (the "slop"),
// or after 300 ms has elapsed.
generator.MoveTouchId(gfx::Point(109, 209), 1);
// Number of mouse events may be greater than 1 because of ET_MOUSE_ENTERED. // Number of mouse events may be greater than 1 because of ET_MOUSE_ENTERED.
EXPECT_GT(event_handler->num_mouse_events(), 0); EXPECT_GT(event_handler->num_mouse_events(), 0);
EXPECT_EQ(0, event_handler->num_touch_events()); EXPECT_EQ(0, event_handler->num_touch_events());
...@@ -68,7 +74,9 @@ IN_PROC_BROWSER_TEST_F(TouchExplorationTest, ToggleOnOff) { ...@@ -68,7 +74,9 @@ IN_PROC_BROWSER_TEST_F(TouchExplorationTest, ToggleOnOff) {
event_handler->Reset(); event_handler->Reset();
SwitchTouchExplorationMode(true); SwitchTouchExplorationMode(true);
generator.set_current_location(gfx::Point(500, 600));
generator.PressTouchId(2); generator.PressTouchId(2);
generator.MoveTouchId(gfx::Point(509, 609), 2);
EXPECT_GT(event_handler->num_mouse_events(), 0); EXPECT_GT(event_handler->num_mouse_events(), 0);
EXPECT_EQ(0, event_handler->num_touch_events()); EXPECT_EQ(0, event_handler->num_touch_events());
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/time/default_tick_clock.h"
#include "ui/aura/client/screen_position_client.h" #include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
...@@ -69,8 +70,9 @@ class TestTouchEvent : public ui::TouchEvent { ...@@ -69,8 +70,9 @@ class TestTouchEvent : public ui::TouchEvent {
TestTouchEvent(ui::EventType type, TestTouchEvent(ui::EventType type,
const gfx::Point& root_location, const gfx::Point& root_location,
int touch_id, int touch_id,
int flags) int flags,
: TouchEvent(type, root_location, flags, touch_id, ui::EventTimeForNow(), base::TimeDelta timestamp)
: TouchEvent(type, root_location, flags, touch_id, timestamp,
1.0f, 1.0f, 1.0f, 1.0f) { 1.0f, 1.0f, 1.0f, 1.0f) {
} }
...@@ -87,7 +89,8 @@ EventGenerator::EventGenerator(Window* root_window) ...@@ -87,7 +89,8 @@ EventGenerator::EventGenerator(Window* root_window)
current_host_(delegate_->GetHostAt(current_location_)), current_host_(delegate_->GetHostAt(current_location_)),
flags_(0), flags_(0),
grab_(false), grab_(false),
async_(false) { async_(false),
tick_clock_(new base::DefaultTickClock()) {
} }
EventGenerator::EventGenerator(Window* root_window, const gfx::Point& point) EventGenerator::EventGenerator(Window* root_window, const gfx::Point& point)
...@@ -96,7 +99,8 @@ EventGenerator::EventGenerator(Window* root_window, const gfx::Point& point) ...@@ -96,7 +99,8 @@ EventGenerator::EventGenerator(Window* root_window, const gfx::Point& point)
current_host_(delegate_->GetHostAt(current_location_)), current_host_(delegate_->GetHostAt(current_location_)),
flags_(0), flags_(0),
grab_(false), grab_(false),
async_(false) { async_(false),
tick_clock_(new base::DefaultTickClock()) {
} }
EventGenerator::EventGenerator(Window* root_window, Window* window) EventGenerator::EventGenerator(Window* root_window, Window* window)
...@@ -105,7 +109,8 @@ EventGenerator::EventGenerator(Window* root_window, Window* window) ...@@ -105,7 +109,8 @@ EventGenerator::EventGenerator(Window* root_window, Window* window)
current_host_(delegate_->GetHostAt(current_location_)), current_host_(delegate_->GetHostAt(current_location_)),
flags_(0), flags_(0),
grab_(false), grab_(false),
async_(false) { async_(false),
tick_clock_(new base::DefaultTickClock()) {
} }
EventGenerator::EventGenerator(EventGeneratorDelegate* delegate) EventGenerator::EventGenerator(EventGeneratorDelegate* delegate)
...@@ -113,7 +118,8 @@ EventGenerator::EventGenerator(EventGeneratorDelegate* delegate) ...@@ -113,7 +118,8 @@ EventGenerator::EventGenerator(EventGeneratorDelegate* delegate)
current_host_(delegate_->GetHostAt(current_location_)), current_host_(delegate_->GetHostAt(current_location_)),
flags_(0), flags_(0),
grab_(false), grab_(false),
async_(false) { async_(false),
tick_clock_(new base::DefaultTickClock()) {
} }
EventGenerator::~EventGenerator() { EventGenerator::~EventGenerator() {
...@@ -219,7 +225,8 @@ void EventGenerator::PressTouch() { ...@@ -219,7 +225,8 @@ void EventGenerator::PressTouch() {
void EventGenerator::PressTouchId(int touch_id) { void EventGenerator::PressTouchId(int touch_id) {
TestTouchEvent touchev( TestTouchEvent touchev(
ui::ET_TOUCH_PRESSED, GetLocationInCurrentRoot(), touch_id, flags_); ui::ET_TOUCH_PRESSED, GetLocationInCurrentRoot(), touch_id, flags_,
Now());
Dispatch(&touchev); Dispatch(&touchev);
} }
...@@ -230,7 +237,8 @@ void EventGenerator::MoveTouch(const gfx::Point& point) { ...@@ -230,7 +237,8 @@ void EventGenerator::MoveTouch(const gfx::Point& point) {
void EventGenerator::MoveTouchId(const gfx::Point& point, int touch_id) { void EventGenerator::MoveTouchId(const gfx::Point& point, int touch_id) {
current_location_ = point; current_location_ = point;
TestTouchEvent touchev( TestTouchEvent touchev(
ui::ET_TOUCH_MOVED, GetLocationInCurrentRoot(), touch_id, flags_); ui::ET_TOUCH_MOVED, GetLocationInCurrentRoot(), touch_id, flags_,
Now());
Dispatch(&touchev); Dispatch(&touchev);
if (!grab_) if (!grab_)
...@@ -243,7 +251,8 @@ void EventGenerator::ReleaseTouch() { ...@@ -243,7 +251,8 @@ void EventGenerator::ReleaseTouch() {
void EventGenerator::ReleaseTouchId(int touch_id) { void EventGenerator::ReleaseTouchId(int touch_id) {
TestTouchEvent touchev( TestTouchEvent touchev(
ui::ET_TOUCH_RELEASED, GetLocationInCurrentRoot(), touch_id, flags_); ui::ET_TOUCH_RELEASED, GetLocationInCurrentRoot(), touch_id, flags_,
Now());
Dispatch(&touchev); Dispatch(&touchev);
} }
...@@ -263,7 +272,7 @@ void EventGenerator::GestureEdgeSwipe() { ...@@ -263,7 +272,7 @@ void EventGenerator::GestureEdgeSwipe() {
0, 0,
0, 0,
0, 0,
ui::EventTimeForNow(), Now(),
ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE, 0, 0), ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE, 0, 0),
0); 0);
Dispatch(&gesture); Dispatch(&gesture);
...@@ -274,7 +283,7 @@ void EventGenerator::GestureTapAt(const gfx::Point& location) { ...@@ -274,7 +283,7 @@ void EventGenerator::GestureTapAt(const gfx::Point& location) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
location, location,
kTouchId, kTouchId,
ui::EventTimeForNow()); Now());
Dispatch(&press); Dispatch(&press);
ui::TouchEvent release( ui::TouchEvent release(
...@@ -288,7 +297,7 @@ void EventGenerator::GestureTapDownAndUp(const gfx::Point& location) { ...@@ -288,7 +297,7 @@ void EventGenerator::GestureTapDownAndUp(const gfx::Point& location) {
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
location, location,
kTouchId, kTouchId,
ui::EventTimeForNow()); Now());
Dispatch(&press); Dispatch(&press);
ui::TouchEvent release( ui::TouchEvent release(
...@@ -312,7 +321,7 @@ void EventGenerator::GestureScrollSequenceWithCallback( ...@@ -312,7 +321,7 @@ void EventGenerator::GestureScrollSequenceWithCallback(
int steps, int steps,
const ScrollStepCallback& callback) { const ScrollStepCallback& callback) {
const int kTouchId = 5; const int kTouchId = 5;
base::TimeDelta timestamp = ui::EventTimeForNow(); base::TimeDelta timestamp = Now();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, start, kTouchId, timestamp); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, start, kTouchId, timestamp);
Dispatch(&press); Dispatch(&press);
...@@ -367,7 +376,7 @@ void EventGenerator::GestureMultiFingerScrollWithDelays( ...@@ -367,7 +376,7 @@ void EventGenerator::GestureMultiFingerScrollWithDelays(
points[i] = start[i]; points[i] = start[i];
} }
base::TimeDelta press_time_first = ui::EventTimeForNow(); base::TimeDelta press_time_first = Now();
base::TimeDelta press_time[kMaxTouchPoints]; base::TimeDelta press_time[kMaxTouchPoints];
bool pressed[kMaxTouchPoints]; bool pressed[kMaxTouchPoints];
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
...@@ -417,8 +426,7 @@ void EventGenerator::ScrollSequence(const gfx::Point& start, ...@@ -417,8 +426,7 @@ void EventGenerator::ScrollSequence(const gfx::Point& start,
float y_offset, float y_offset,
int steps, int steps,
int num_fingers) { int num_fingers) {
base::TimeDelta timestamp = base::TimeDelta::FromInternalValue( base::TimeDelta timestamp = Now();
base::TimeTicks::Now().ToInternalValue());
ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL,
start, start,
timestamp, timestamp,
...@@ -457,7 +465,7 @@ void EventGenerator::ScrollSequence(const gfx::Point& start, ...@@ -457,7 +465,7 @@ void EventGenerator::ScrollSequence(const gfx::Point& start,
const std::vector<gfx::Point>& offsets, const std::vector<gfx::Point>& offsets,
int num_fingers) { int num_fingers) {
int steps = offsets.size(); int steps = offsets.size();
base::TimeDelta timestamp = ui::EventTimeForNow(); base::TimeDelta timestamp = Now();
ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL,
start, start,
timestamp, timestamp,
...@@ -501,6 +509,17 @@ void EventGenerator::Dispatch(ui::Event* event) { ...@@ -501,6 +509,17 @@ void EventGenerator::Dispatch(ui::Event* event) {
DoDispatchEvent(event, async_); DoDispatchEvent(event, async_);
} }
void EventGenerator::SetTickClock(scoped_ptr<base::TickClock> tick_clock) {
tick_clock_ = tick_clock.Pass();
}
base::TimeDelta EventGenerator::Now() {
// This is the same as what EventTimeForNow() does, but here we do it
// with a tick clock that can be replaced with a simulated clock for tests.
return base::TimeDelta::FromInternalValue(
tick_clock_->NowTicks().ToInternalValue());
}
void EventGenerator::DispatchKeyEvent(bool is_press, void EventGenerator::DispatchKeyEvent(bool is_press,
ui::KeyboardCode key_code, ui::KeyboardCode key_code,
int flags) { int flags) {
...@@ -638,6 +657,5 @@ void EventGenerator::DispatchNextPendingEvent() { ...@@ -638,6 +657,5 @@ void EventGenerator::DispatchNextPendingEvent() {
} }
} }
} // namespace test } // namespace test
} // namespace aura } // namespace aura
...@@ -11,12 +11,13 @@ ...@@ -11,12 +11,13 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/point.h" #include "ui/gfx/point.h"
namespace base { namespace base {
class TimeDelta; class TickClock;
} }
namespace ui { namespace ui {
...@@ -317,6 +318,12 @@ class EventGenerator { ...@@ -317,6 +318,12 @@ class EventGenerator {
current_host_ = host; current_host_ = host;
} }
// Specify an alternative tick clock to be used for simulating time in tests.
void SetTickClock(scoped_ptr<base::TickClock> tick_clock);
// Get the current time from the tick clock.
base::TimeDelta Now();
private: private:
// Dispatch a key event to the WindowEventDispatcher. // Dispatch a key event to the WindowEventDispatcher.
void DispatchKeyEvent(bool is_press, ui::KeyboardCode key_code, int flags); void DispatchKeyEvent(bool is_press, ui::KeyboardCode key_code, int flags);
...@@ -346,6 +353,7 @@ class EventGenerator { ...@@ -346,6 +353,7 @@ class EventGenerator {
std::list<ui::Event*> pending_events_; std::list<ui::Event*> pending_events_;
// Set to true to cause events to be posted asynchronously. // Set to true to cause events to be posted asynchronously.
bool async_; bool async_;
scoped_ptr<base::TickClock> tick_clock_;
DISALLOW_COPY_AND_ASSIGN(EventGenerator); DISALLOW_COPY_AND_ASSIGN(EventGenerator);
}; };
......
This diff is collapsed.
...@@ -5,9 +5,11 @@ ...@@ -5,9 +5,11 @@
#ifndef UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ #ifndef UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_
#define UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_ #define UI_CHROMEOS_TOUCH_EXPLORATION_CONTROLLER_H_
#include "base/timer/timer.h"
#include "base/values.h" #include "base/values.h"
#include "ui/chromeos/ui_chromeos_export.h" #include "ui/chromeos/ui_chromeos_export.h"
#include "ui/events/event_rewriter.h" #include "ui/events/event_rewriter.h"
#include "ui/events/gesture_detection/gesture_detector.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
namespace aura { namespace aura {
...@@ -17,17 +19,58 @@ class Window; ...@@ -17,17 +19,58 @@ class Window;
namespace ui { namespace ui {
class Event; class Event;
class EventHandler;
class TouchEvent;
// TouchExplorationController is used in tandem with "Spoken Feedback" to // TouchExplorationController is used in tandem with "Spoken Feedback" to
// make the touch UI accessible. TouchExplorationController rewrites the // make the touch UI accessible.
// incoming touch events as follows: //
// - When one finger is touching the screen, touch events are converted to mouse // ** Short version **
// 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 // At a high-level, single-finger events are used for accessibility -
// elements, and the elements will be read out to the user.) // exploring the screen gets turned into mouse moves (which can then be
// - When more than one finger is touching the screen, touches from the // spoken by an accessibility service running), a double-tap simulates a
// first (i.e. "oldest") finger are ignored, and the other touches go through // click, and gestures can be used to send high-level accessibility commands.
// as is. // When two or more fingers are pressed initially, from then on the events
// are passed through, but with the initial finger removed - so if you swipe
// down with two fingers, the running app will see a one-finger swipe.
//
// ** Long version **
//
// 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 supported accessibility gesture in that time (e.g. swipe right),
// they enter touch exploration mode, and all movements are translated into
// synthesized mouse move events.
//
// Also, if the user moves their single finger outside a certain slop region
// (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 fingers
// continue 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 // The caller is expected to retain ownership of instances of this class and
// destroy them before |root_window| is destroyed. // destroy them before |root_window| is destroyed.
class UI_CHROMEOS_EXPORT TouchExplorationController : class UI_CHROMEOS_EXPORT TouchExplorationController :
...@@ -36,28 +79,120 @@ class UI_CHROMEOS_EXPORT TouchExplorationController : ...@@ -36,28 +79,120 @@ class UI_CHROMEOS_EXPORT TouchExplorationController :
explicit TouchExplorationController(aura::Window* root_window); explicit TouchExplorationController(aura::Window* root_window);
virtual ~TouchExplorationController(); virtual ~TouchExplorationController();
private: void CallTapTimerNowForTesting();
scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location, void SetEventHandlerForTesting(ui::EventHandler* event_handler_for_testing);
int flags); bool IsInNoFingersDownStateForTesting() const;
void EnterTouchToMouseMode();
private:
// Overridden from ui::EventRewriter // Overridden from ui::EventRewriter
virtual ui::EventRewriteStatus RewriteEvent( virtual ui::EventRewriteStatus RewriteEvent(
const ui::Event& event, scoped_ptr<ui::Event>* rewritten_event) OVERRIDE; const ui::Event& event, scoped_ptr<ui::Event>* rewritten_event) OVERRIDE;
virtual ui::EventRewriteStatus NextDispatchEvent( virtual ui::EventRewriteStatus NextDispatchEvent(
const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE; const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) OVERRIDE;
// Event handlers based on the current state - see State, below.
ui::EventRewriteStatus InNoFingersDown(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus InSingleTapPressed(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus InSingleTapReleased(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus InDoubleTapPressed(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus InTouchExploration(
const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus InPassthroughMinusOne(
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();
// Dispatch a new event outside of the event rewriting flow.
void DispatchEvent(ui::Event* event);
scoped_ptr<ui::Event> CreateMouseMoveEvent(const gfx::PointF& location,
int flags);
void EnterTouchToMouseMode();
// Set the state to NO_FINGERS_DOWN and reset any other fields to their
// default value.
void ResetToNoFingersDown();
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.
SINGLE_TAP_PRESSED,
// The user pressed and released a single finger - a tap - but we have
// to wait until the end of the grace period to allow the user to tap the
// second time. If the second tap doesn't occurs within the grace period,
// we dispatch a mouse move at the location of the first tap.
SINGLE_TAP_RELEASED,
// 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,
// We're in touch exploration mode. Anything other than the first finger
// is ignored, and movements of the first finger are rewritten as mouse
// move events. This mode is entered if a single finger is pressed and
// after the grace period the user hasn't added a second finger or
// moved the finger outside of the slop region. We'll stay in this
// mode until all fingers are lifted.
TOUCH_EXPLORATION,
// The user placed two or more fingers down within the grace period.
// We're now in passthrough mode until all fingers are lifted. Initially
// the first finger is ignored and other fingers are passed through
// as-is. If a finger other than the initial one is the first to be
// released, we rewrite the first finger with the touch id of the finger
// that was released, from now on. The motivation for this is that if
// the user starts a scroll with 2 fingers, they can release either one
// and continue the scrolling.
PASSTHROUGH_MINUS_ONE,
};
aura::Window* root_window_;
// A set of touch ids for fingers currently touching the screen. // A set of touch ids for fingers currently touching the screen.
std::vector<int> touch_ids_; std::vector<int> current_touch_ids_;
// Map of touch ids to their last known location. // Map of touch ids to their last known location.
std::map<int, gfx::PointF> touch_locations_; std::map<int, gfx::PointF> touch_locations_;
// Initialized from RewriteEvent() and dispatched in NextDispatchEvent(). // The touch id that any events on the initial finger should be rewritten
scoped_ptr<ui::Event> next_dispatch_event_; // as in passthrough-minus-one mode. If kTouchIdUnassigned, events on the
// initial finger are discarded. If kTouchIdNone, the initial finger
// has been released and no more rewriting will be done.
int initial_touch_id_passthrough_mapping_;
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_;
// For testing only, an event handler to use for generated events
// outside of the normal event rewriting flow.
ui::EventHandler* event_handler_for_testing_;
// 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); DISALLOW_COPY_AND_ASSIGN(TouchExplorationController);
}; };
......
...@@ -218,6 +218,7 @@ ...@@ -218,6 +218,7 @@
'../chromeos/chromeos.gyp:chromeos', '../chromeos/chromeos.gyp:chromeos',
'aura/aura.gyp:aura_test_support', 'aura/aura.gyp:aura_test_support',
'chromeos/ui_chromeos.gyp:ui_chromeos', 'chromeos/ui_chromeos.gyp:ui_chromeos',
'events/events.gyp:gesture_detection',
], ],
'sources': [ 'sources': [
'chromeos/touch_exploration_controller_unittest.cc' 'chromeos/touch_exploration_controller_unittest.cc'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment