gesture_detector.h revision 116680a4aac90f2aa7413d9095a592090648e557
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
3// found in the LICENSE file.
4
5#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_DETECTOR_H_
6#define UI_EVENTS_GESTURE_DETECTION_GESTURE_DETECTOR_H_
7
8#include "base/logging.h"
9#include "base/memory/scoped_ptr.h"
10#include "ui/events/gesture_detection/gesture_detection_export.h"
11#include "ui/events/gesture_detection/velocity_tracker_state.h"
12
13namespace ui {
14
15class MotionEvent;
16
17// Port of GestureDetector.java from Android
18// * platform/frameworks/base/core/java/android/view/GestureDetector.java
19// * Change-Id: Ib470735ec929b0b358fca4597e92dc81084e675f
20// * Please update the Change-Id as upstream Android changes are pulled.
21class GestureDetector {
22 public:
23  struct GESTURE_DETECTION_EXPORT Config {
24    Config();
25    ~Config();
26
27    base::TimeDelta longpress_timeout;
28    base::TimeDelta showpress_timeout;
29    base::TimeDelta double_tap_timeout;
30
31    // The minimum duration between the first tap's up event and the second
32    // tap's down event for an interaction to be considered a double-tap.
33    base::TimeDelta double_tap_min_time;
34
35    // Distance a touch can wander before a scroll will occur (in dips).
36    float touch_slop;
37
38    // Distance the first touch can wander before it is no longer considered a
39    // double tap (in dips).
40    float double_tap_slop;
41
42    // Minimum velocity to initiate a fling (in dips/second).
43    float minimum_fling_velocity;
44
45    // Maximum velocity of an initiated fling (in dips/second).
46    float maximum_fling_velocity;
47
48    // Whether |OnSwipe| should be called after a secondary touch is released
49    // while a logical swipe gesture is active. Defaults to false.
50    bool swipe_enabled;
51
52    // Minimum velocity to initiate a swipe (in dips/second).
53    float minimum_swipe_velocity;
54
55    // Maximum angle of the swipe from its dominant component axis, between
56    // (0, 45] degrees. The closer this is to 0, the closer the dominant
57    // direction of the swipe must be to up, down left or right.
58    float maximum_swipe_deviation_angle;
59
60    // Whether |OnTwoFingerTap| should be called for two finger tap
61    // gestures. Defaults to false.
62    bool two_finger_tap_enabled;
63
64    // Maximum distance between pointers for a two finger tap.
65    float two_finger_tap_max_separation;
66
67    // Maximum time the second pointer can be active for a two finger tap.
68    base::TimeDelta two_finger_tap_timeout;
69  };
70
71  class GestureListener {
72   public:
73    virtual ~GestureListener() {}
74    virtual bool OnDown(const MotionEvent& e) = 0;
75    virtual void OnShowPress(const MotionEvent& e) = 0;
76    virtual bool OnSingleTapUp(const MotionEvent& e) = 0;
77    virtual void OnLongPress(const MotionEvent& e) = 0;
78    virtual bool OnScroll(const MotionEvent& e1,
79                          const MotionEvent& e2,
80                          float distance_x,
81                          float distance_y) = 0;
82    virtual bool OnFling(const MotionEvent& e1,
83                         const MotionEvent& e2,
84                         float velocity_x,
85                         float velocity_y) = 0;
86    // Added for Chromium (Aura).
87    virtual bool OnSwipe(const MotionEvent& e1,
88                         const MotionEvent& e2,
89                         float velocity_x,
90                         float velocity_y) = 0;
91    virtual bool OnTwoFingerTap(const MotionEvent& e1,
92                                const MotionEvent& e2) = 0;
93  };
94
95  class DoubleTapListener {
96   public:
97    virtual ~DoubleTapListener() {}
98    virtual bool OnSingleTapConfirmed(const MotionEvent& e) = 0;
99    virtual bool OnDoubleTap(const MotionEvent& e) = 0;
100    virtual bool OnDoubleTapEvent(const MotionEvent& e) = 0;
101  };
102
103  // A convenience class to extend when you only want to listen for a subset
104  // of all the gestures. This implements all methods in the
105  // |GestureListener| and |DoubleTapListener| but does
106  // nothing and returns false for all applicable methods.
107  class SimpleGestureListener : public GestureListener,
108                                public DoubleTapListener {
109   public:
110    // GestureListener implementation.
111    virtual bool OnDown(const MotionEvent& e) OVERRIDE;
112    virtual void OnShowPress(const MotionEvent& e) OVERRIDE;
113    virtual bool OnSingleTapUp(const MotionEvent& e) OVERRIDE;
114    virtual void OnLongPress(const MotionEvent& e) OVERRIDE;
115    virtual bool OnScroll(const MotionEvent& e1,
116                          const MotionEvent& e2,
117                          float distance_x,
118                          float distance_y) OVERRIDE;
119    virtual bool OnFling(const MotionEvent& e1,
120                         const MotionEvent& e2,
121                         float velocity_x,
122                         float velocity_y) OVERRIDE;
123    virtual bool OnSwipe(const MotionEvent& e1,
124                         const MotionEvent& e2,
125                         float velocity_x,
126                         float velocity_y) OVERRIDE;
127    virtual bool OnTwoFingerTap(const MotionEvent& e1,
128                                const MotionEvent& e2) OVERRIDE;
129
130    // DoubleTapListener implementation.
131    virtual bool OnSingleTapConfirmed(const MotionEvent& e) OVERRIDE;
132    virtual bool OnDoubleTap(const MotionEvent& e) OVERRIDE;
133    virtual bool OnDoubleTapEvent(const MotionEvent& e) OVERRIDE;
134  };
135
136  GestureDetector(const Config& config,
137                  GestureListener* listener,
138                  DoubleTapListener* optional_double_tap_listener);
139  ~GestureDetector();
140
141  bool OnTouchEvent(const MotionEvent& ev);
142
143  // Setting a valid |double_tap_listener| will enable double-tap detection,
144  // wherein calls to |OnSimpleTapConfirmed| are delayed by the tap timeout.
145  // Note: The listener must never be changed while |is_double_tapping| is true.
146  void SetDoubleTapListener(DoubleTapListener* double_tap_listener);
147
148  bool has_doubletap_listener() const { return double_tap_listener_ != NULL; }
149
150  bool is_double_tapping() const { return is_double_tapping_; }
151
152  void set_longpress_enabled(bool enabled) { longpress_enabled_ = enabled; }
153
154 private:
155  void Init(const Config& config);
156  void OnShowPressTimeout();
157  void OnLongPressTimeout();
158  void OnTapTimeout();
159  void Cancel();
160  void CancelTaps();
161  bool IsConsideredDoubleTap(const MotionEvent& first_down,
162                             const MotionEvent& first_up,
163                             const MotionEvent& second_down) const;
164  bool HandleSwipeIfNeeded(const MotionEvent& up, float vx, float vy);
165
166  class TimeoutGestureHandler;
167  scoped_ptr<TimeoutGestureHandler> timeout_handler_;
168  GestureListener* const listener_;
169  DoubleTapListener* double_tap_listener_;
170
171  float touch_slop_square_;
172  float double_tap_touch_slop_square_;
173  float double_tap_slop_square_;
174  float two_finger_tap_distance_square_;
175  float min_fling_velocity_;
176  float max_fling_velocity_;
177  float min_swipe_velocity_;
178  float min_swipe_direction_component_ratio_;
179  base::TimeDelta double_tap_timeout_;
180  base::TimeDelta two_finger_tap_timeout_;
181  base::TimeDelta double_tap_min_time_;
182
183  bool still_down_;
184  bool defer_confirm_single_tap_;
185  bool always_in_tap_region_;
186  bool always_in_bigger_tap_region_;
187  bool two_finger_tap_allowed_for_gesture_;
188
189  scoped_ptr<MotionEvent> current_down_event_;
190  scoped_ptr<MotionEvent> previous_up_event_;
191  scoped_ptr<MotionEvent> secondary_pointer_down_event_;
192
193  // True when the user is still touching for the second tap (down, move, and
194  // up events). Can only be true if there is a double tap listener attached.
195  bool is_double_tapping_;
196
197  float last_focus_x_;
198  float last_focus_y_;
199  float down_focus_x_;
200  float down_focus_y_;
201
202  bool longpress_enabled_;
203  bool swipe_enabled_;
204  bool two_finger_tap_enabled_;
205
206  // Determines speed during touch scrolling.
207  VelocityTrackerState velocity_tracker_;
208
209  DISALLOW_COPY_AND_ASSIGN(GestureDetector);
210};
211
212}  // namespace ui
213
214#endif  // UI_EVENTS_GESTURE_DETECTION_GESTURE_DETECTOR_H_
215