1// Copyright (c) 2012 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_GESTURES_GESTURE_SEQUENCE_H_
6#define UI_EVENTS_GESTURES_GESTURE_SEQUENCE_H_
7
8#include "base/timer/timer.h"
9#include "ui/events/event_constants.h"
10#include "ui/events/gestures/gesture_point.h"
11#include "ui/events/gestures/gesture_recognizer.h"
12#include "ui/gfx/rect.h"
13
14namespace ui {
15class TouchEvent;
16class GestureEvent;
17
18// Gesture state.
19enum GestureState {
20  GS_NO_GESTURE,
21  GS_PENDING_SYNTHETIC_CLICK,
22  GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL,
23  GS_SCROLL,
24  GS_PINCH,
25  GS_PENDING_TWO_FINGER_TAP,
26  GS_PENDING_TWO_FINGER_TAP_NO_PINCH,
27  GS_PENDING_PINCH,
28  GS_PENDING_PINCH_NO_PINCH,
29};
30
31enum ScrollType {
32  ST_FREE,
33  ST_HORIZONTAL,
34  ST_VERTICAL,
35};
36
37// Delegates dispatch of gesture events for which the GestureSequence does not
38// have enough context to dispatch itself.
39class EVENTS_EXPORT GestureSequenceDelegate {
40 public:
41  virtual void DispatchPostponedGestureEvent(GestureEvent* event) = 0;
42
43 protected:
44  virtual ~GestureSequenceDelegate() {}
45};
46
47// A GestureSequence recognizes gestures from touch sequences.
48class EVENTS_EXPORT GestureSequence {
49 public:
50  // Maximum number of points in a single gesture.
51  static const int kMaxGesturePoints = 12;
52
53  explicit GestureSequence(GestureSequenceDelegate* delegate);
54  virtual ~GestureSequence();
55
56  typedef GestureRecognizer::Gestures Gestures;
57
58  // Invoked for each touch event that could contribute to the current gesture.
59  // Returns list of  zero or more GestureEvents identified after processing
60  // TouchEvent.
61  // Caller would be responsible for freeing up Gestures.
62  virtual Gestures* ProcessTouchEventForGesture(const TouchEvent& event,
63                                                EventResult status);
64  const GesturePoint* points() const { return points_; }
65  int point_count() const { return point_count_; }
66
67  const gfx::Point& last_touch_location() const { return last_touch_location_; }
68
69 protected:
70  virtual base::OneShotTimer<GestureSequence>* CreateTimer();
71  base::OneShotTimer<GestureSequence>* GetLongPressTimer();
72  base::OneShotTimer<GestureSequence>* GetShowPressTimer();
73
74 private:
75  // Recreates the axis-aligned bounding box that contains all the touch-points
76  // at their most recent position.
77  void RecreateBoundingBox();
78
79  void ResetVelocities();
80
81  GesturePoint& GesturePointForEvent(const TouchEvent& event);
82
83  // Do a linear scan through points_ to find the GesturePoint
84  // with id |point_id|.
85  GesturePoint* GetPointByPointId(int point_id);
86
87  bool IsSecondTouchDownCloseEnoughForTwoFingerTap();
88
89  // Creates a gesture event with the specified parameters. The function
90  // includes some common information (e.g. number of touch-points in the
91  // gesture etc.) in the gesture event as well.
92  GestureEvent* CreateGestureEvent(const GestureEventDetails& details,
93                                   const gfx::Point& location,
94                                   int flags,
95                                   base::Time timestamp,
96                                   unsigned int touch_id_bitmask);
97
98  // Functions to be called to add GestureEvents, after successful recognition.
99
100  // Tap gestures.
101  void AppendTapDownGestureEvent(const GesturePoint& point, Gestures* gestures);
102  void PrependTapCancelGestureEvent(const GesturePoint& point,
103                                   Gestures* gestures);
104  void AppendBeginGestureEvent(const GesturePoint& point, Gestures* gestures);
105  void AppendEndGestureEvent(const GesturePoint& point, Gestures* gestures);
106  void AppendClickGestureEvent(const GesturePoint& point,
107                               int tap_count,
108                               Gestures* gestures);
109  void AppendDoubleClickGestureEvent(const GesturePoint& point,
110                                     Gestures* gestures);
111  void AppendLongPressGestureEvent();
112  void AppendShowPressGestureEvent();
113  void AppendLongTapGestureEvent(const GesturePoint& point,
114                                 Gestures* gestures);
115
116  // Scroll gestures.
117  void AppendScrollGestureBegin(const GesturePoint& point,
118                                const gfx::Point& location,
119                                Gestures* gestures);
120  void AppendScrollGestureEnd(const GesturePoint& point,
121                              const gfx::Point& location,
122                              Gestures* gestures,
123                              float x_velocity,
124                              float y_velocity);
125  void AppendScrollGestureUpdate(GesturePoint& point,
126                                 Gestures* gestures);
127
128  // Pinch gestures.
129  void AppendPinchGestureBegin(const GesturePoint& p1,
130                               const GesturePoint& p2,
131                               Gestures* gestures);
132  void AppendPinchGestureEnd(const GesturePoint& p1,
133                             const GesturePoint& p2,
134                             float scale,
135                             Gestures* gestures);
136  void AppendPinchGestureUpdate(const GesturePoint& point,
137                                float scale,
138                                Gestures* gestures);
139  void AppendSwipeGesture(const GesturePoint& point,
140                          int swipe_x,
141                          int swipe_y,
142                          Gestures* gestures);
143  void AppendTwoFingerTapGestureEvent(Gestures* gestures);
144
145  void set_state(const GestureState state) { state_ = state; }
146
147  // Various GestureTransitionFunctions for a signature.
148  // There is, 1:many mapping from GestureTransitionFunction to Signature
149  // But a Signature have only one GestureTransitionFunction.
150  bool Click(const TouchEvent& event,
151             const GesturePoint& point,
152             Gestures* gestures);
153  bool ScrollStart(const TouchEvent& event,
154                   GesturePoint& point,
155                   Gestures* gestures);
156  void BreakRailScroll(const TouchEvent& event,
157                       GesturePoint& point,
158                       Gestures* gestures);
159  bool ScrollUpdate(const TouchEvent& event,
160                    GesturePoint& point,
161                    Gestures* gestures);
162  bool TouchDown(const TouchEvent& event,
163                 const GesturePoint& point,
164                 Gestures* gestures);
165  bool TwoFingerTouchDown(const TouchEvent& event,
166                          const GesturePoint& point,
167                          Gestures* gestures);
168  bool TwoFingerTouchMove(const TouchEvent& event,
169                          const GesturePoint& point,
170                          Gestures* gestures);
171  bool TwoFingerTouchReleased(const TouchEvent& event,
172                              const GesturePoint& point,
173                              Gestures* gestures);
174  bool ScrollEnd(const TouchEvent& event,
175                 GesturePoint& point,
176                 Gestures* gestures);
177  bool PinchStart(const TouchEvent& event,
178                  const GesturePoint& point,
179                  Gestures* gestures);
180  bool PinchUpdate(const TouchEvent& event,
181                   GesturePoint& point,
182                   Gestures* gestures);
183  bool PinchEnd(const TouchEvent& event,
184                const GesturePoint& point,
185                Gestures* gestures);
186  bool MaybeSwipe(const TouchEvent& event,
187                  const GesturePoint& point,
188                  Gestures* gestures);
189
190  void TwoFingerTapOrPinch(const TouchEvent& event,
191                           const GesturePoint& point,
192                           Gestures* gestures);
193
194  void StopTimersIfRequired(const TouchEvent& event);
195
196  // Current state of gesture recognizer.
197  GestureState state_;
198
199  // ui::EventFlags.
200  int flags_;
201
202  // We maintain the smallest axis-aligned rectangle that contains all the
203  // current touch-points. This box is updated after every touch-event.
204  gfx::Rect bounding_box_;
205
206  // The center of the bounding box used in the latest multi-finger scroll
207  // update gesture.
208  gfx::Point latest_multi_scroll_update_location_;
209
210  // The last scroll update prediction offset. This is removed from the scroll
211  // distance on the next update since the page has already been scrolled this
212  // distance.
213  gfx::Vector2dF last_scroll_prediction_offset_;
214
215  // For pinch, the 'distance' represents the diagonal distance of
216  // |bounding_box_|.
217
218  // The distance between the two points at PINCH_START.
219  float pinch_distance_start_;
220
221  // This distance is updated after each PINCH_UPDATE.
222  float pinch_distance_current_;
223
224  // This is the time when second touch down was received. Used for determining
225  // if a two finger double tap has happened.
226  base::TimeDelta second_touch_time_;
227
228  ScrollType scroll_type_;
229  scoped_ptr<base::OneShotTimer<GestureSequence> > long_press_timer_;
230  scoped_ptr<base::OneShotTimer<GestureSequence> > show_press_timer_;
231
232  GesturePoint points_[kMaxGesturePoints];
233  int point_count_;
234
235  // Location of the last touch event.
236  gfx::Point last_touch_location_;
237
238  GestureSequenceDelegate* delegate_;
239
240  DISALLOW_COPY_AND_ASSIGN(GestureSequence);
241};
242
243}  // namespace ui
244
245#endif  // UI_EVENTS_GESTURES_GESTURE_SEQUENCE_H_
246