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

Side by Side Diff: views/touchui/gesture_recognizer.cc

Issue 8364039: Initial views touchui GestureRecognizer support (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Added switch support in place of map::find() Created 9 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 #include "views/touchui/gesture_recognizer.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "views/events/event.h"
10
11 namespace {
12 // TODO(Gajen): Make these configurable in sync with this CL http://code.google.
13 // com/p/chromium/issues/detail?id=100773.
14 const double kMaximumTouchDownDurationInSecondsForClick = 0.8;
15 const double kMinimumTouchDownDurationInSecondsForClick = 0.01;
16 const double kMaximumSecondsBetweenDoubleClick = 0.7;
17 const int kMaximumTouchMoveInPixelsForClick = 20;
18 const float kMinFlickSpeedSquared = 550.f * 550.f;
19
20 } // namespace
21
22 namespace views {
23
24 ////////////////////////////////////////////////////////////////////////////////
25 // GestureRecognizer Public:
26
27 GestureRecognizer::GestureRecognizer()
28 : first_touch_time_(0.0),
29 state_(GestureRecognizer::GS_NO_GESTURE),
30 last_touch_time_(0.0),
31 last_click_time_(0.0),
32 x_velocity_(0.0),
33 y_velocity_(0.0),
34 flags_(0) {
35 }
36
37 GestureRecognizer::~GestureRecognizer() {
38 }
39
40 GestureRecognizer* GestureRecognizer::GetInstance() {
41 return Singleton<GestureRecognizer>::get();
42 }
43
44 GestureRecognizer::Gestures* GestureRecognizer::ProcessTouchEventForGesture(
45 const TouchEvent& event,
46 ui::TouchStatus status) {
47 if (status != ui::TOUCH_STATUS_UNKNOWN)
48 return false; // The event was consumed by a touch sequence.
49
50 flags_ = event.flags();
sadrul 2011/11/18 19:01:50 It looks like flags_ isn't used anywhere else. Rem
Gajen 2011/11/21 15:56:50 Done.
51 scoped_ptr<Gestures> gestures(new Gestures());
52 UpdateValues(event);
53 switch (Signature(state_, event.identity(), event.type(), false)) {
54 case 0x00000003:
55 TouchDown(event, gestures.get());
56 break;
57 case 0x00020009:
58 NoGesture(event, gestures.get());
59 break;
60 case 0x00020001:
61 Click(event, gestures.get());
62 break;
63 case 0x00020005:
64 case 0x00020007:
65 InClickOrScroll(event, gestures.get());
66 break;
67 case 0x00040005:
68 InScroll(event, gestures.get());
69 break;
70 case 0x00040001:
71 case 0x00040009:
72 ScrollEnd(event, gestures.get());
73 break;
74 }
75 return gestures.release();
76 }
77
78 void GestureRecognizer::Reset() {
79 first_touch_time_ = 0.0;
80 state_ = GestureRecognizer::GS_NO_GESTURE;
81 last_touch_time_ = 0.0;
82 last_touch_position_.SetPoint(0, 0);
83 x_velocity_ = 0.0;
84 y_velocity_ = 0.0;
85 }
86
87 ////////////////////////////////////////////////////////////////////////////////
88 // GestureRecognizer Private:
89
90 // static
91 GestureRecognizer::TouchState GestureRecognizer::TouchEventTypeToTouchState(
92 ui::EventType type) {
93 switch (type) {
94 case ui::ET_TOUCH_RELEASED: return TS_RELEASED;
95 case ui::ET_TOUCH_PRESSED: return TS_PRESSED;
96 case ui::ET_TOUCH_MOVED: return TS_MOVED;
97 case ui::ET_TOUCH_STATIONARY: return TS_STATIONARY;
98 case ui::ET_TOUCH_CANCELLED: return TS_CANCELLED;
99 default:
100 VLOG(1) << "Unknown Touch Event type";
101 }
102 return TS_UNKNOWN;
103 }
104
105 // Builds a signature. Signatures are assembled by joining together
106 // multiple bits.
107 // 1 LSB bit so that the computed signature is always greater than 0
108 // 3 bits for the |type|.
109 // 1 bit for |touch_handled|
110 // 12 bits for |touch_id|
111 // 15 bits for the |gesture_state|.
112 unsigned int GestureRecognizer::Signature(GestureState gesture_state,
113 unsigned int touch_id, ui::EventType type,
114 bool touch_handled) {
115 CHECK((touch_id & 0xfff) == touch_id);
116 TouchState touch_state = TouchEventTypeToTouchState(type);
117 return 1 + ((touch_state & 0x7) << 1 | (touch_handled ? 1 << 4 : 0) |
118 ((touch_id & 0xfff) << 5) | (gesture_state << 17));
Ian Vollick 2011/11/18 15:25:34 If you're now using a switch statement, it might b
Gajen 2011/11/21 15:56:50 Added new enum GestureSignatureType and Changed Ge
119 }
cpu_(ooo_6.6-7.5) 2011/11/21 00:58:09 I agree with vollick.
Gajen 2011/11/21 15:56:50 Ditto
120
121 bool GestureRecognizer::IsInClickTimeWindow() {
122 double duration(last_touch_time_ - first_touch_time_);
123 return duration >= kMinimumTouchDownDurationInSecondsForClick &&
124 duration < kMaximumTouchDownDurationInSecondsForClick;
125 }
126
127 bool GestureRecognizer::IsInSecondClickTimeWindow() {
128 double duration(last_touch_time_ - last_click_time_);
129 return duration < kMaximumSecondsBetweenDoubleClick;
130 }
131
132 bool GestureRecognizer::IsInsideManhattanSquare(const TouchEvent& event) {
133 int manhattanDistance = abs(event.x() - first_touch_position_.x()) +
134 abs(event.y() - first_touch_position_.y());
135 return manhattanDistance < kMaximumTouchMoveInPixelsForClick;
136 }
137
138 bool GestureRecognizer::IsSecondClickInsideManhattanSquare(
139 const TouchEvent& event) {
140 int manhattanDistance = abs(event.x() - last_click_position_.x()) +
141 abs(event.y() - last_click_position_.y());
142 return manhattanDistance < kMaximumTouchMoveInPixelsForClick;
143 }
144
145 bool GestureRecognizer::IsOverMinFlickSpeed() {
146 return (x_velocity_ * x_velocity_ + y_velocity_ * y_velocity_) >
147 kMinFlickSpeedSquared;
148 }
149
150 void GestureRecognizer::AppendTapDownGestureEvent(const TouchEvent& event,
151 Gestures* gestures) {
152 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
153 ui::ET_GESTURE_TAP_DOWN,
154 first_touch_position_.x(),
155 first_touch_position_.y(),
156 event.flags(),
157 base::Time::FromDoubleT(last_touch_time_),
158 0.f, 0.f)));
159 }
160
161 void GestureRecognizer::AppendClickGestureEvent(const TouchEvent& event,
162 Gestures* gestures) {
163 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
164 ui::ET_GESTURE_TAP,
165 first_touch_position_.x(),
166 first_touch_position_.y(),
167 event.flags(),
168 base::Time::FromDoubleT(last_touch_time_),
169 0.f, 0.f)));
170 }
171
172 void GestureRecognizer::AppendDoubleClickGestureEvent(const TouchEvent& event,
173 Gestures* gestures) {
174 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
175 ui::ET_GESTURE_DOUBLE_TAP,
176 first_touch_position_.x(),
177 first_touch_position_.y(),
178 event.flags(),
179 base::Time::FromDoubleT(last_touch_time_),
180 0.f, 0.f)));
181 }
182
183 void GestureRecognizer::AppendScrollGestureBegin(const TouchEvent& event,
184 Gestures* gestures) {
185 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
186 ui::ET_GESTURE_SCROLL_BEGIN,
187 event.x(),
188 event.y(),
189 event.flags(),
190 base::Time::FromDoubleT(last_touch_time_),
191 0.f, 0.f)));
192 }
193
194 void GestureRecognizer::AppendScrollGestureEnd(const TouchEvent& event,
195 Gestures* gestures,
196 float x_velocity,
197 float y_velocity) {
198 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
199 ui::ET_GESTURE_SCROLL_END,
200 event.x(),
201 event.y(),
202 event.flags(),
203 base::Time::FromDoubleT(last_touch_time_),
204 x_velocity, y_velocity)));
205 }
206
207 void GestureRecognizer:: AppendScrollGestureUpdate(const TouchEvent& event,
208 Gestures* gestures) {
209 float delta_x(event.x() - first_touch_position_.x());
210 float delta_y(event.y() - first_touch_position_.y());
211
212 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
213 ui::ET_GESTURE_SCROLL_UPDATE,
214 event.x(),
215 event.y(),
216 event.flags(),
217 base::Time::FromDoubleT(last_touch_time_),
218 delta_x, delta_y)));
219
220 first_touch_position_ = event.location();
221 }
222
223 void GestureRecognizer::UpdateValues(const TouchEvent& event) {
224 if (state_ != GS_NO_GESTURE && event.type() == ui::ET_TOUCH_MOVED) {
225 double interval(event.time_stamp().ToDoubleT() - last_touch_time_);
226 x_velocity_ = (event.x() - last_touch_position_.x()) / interval;
227 y_velocity_ = (event.y() - last_touch_position_.y()) / interval;
228 }
229 last_touch_time_ = event.time_stamp().ToDoubleT();
230 last_touch_position_ = event.location();
231 if (state_ == GS_NO_GESTURE) {
232 first_touch_time_ = last_touch_time_;
233 first_touch_position_ = event.location();
234 x_velocity_ = 0.0;
235 y_velocity_ = 0.0;
236 }
237 }
238
239 bool GestureRecognizer::Click(const TouchEvent& event, Gestures* gestures) {
240 bool gesture_added = false;
241 if (IsInClickTimeWindow() && IsInsideManhattanSquare(event)) {
242 gesture_added = true;
243 AppendClickGestureEvent(event, gestures);
244 if (IsInSecondClickTimeWindow() &&
245 IsSecondClickInsideManhattanSquare(event))
246 AppendDoubleClickGestureEvent(event, gestures);
247 last_click_time_ = last_touch_time_;
248 last_click_position_ = last_touch_position_;
249 }
250 Reset();
251 return gesture_added;
252 }
253
254 bool GestureRecognizer::InClickOrScroll(const TouchEvent& event,
255 Gestures* gestures) {
256 if (IsInClickTimeWindow() && IsInsideManhattanSquare(event)) {
257 SetState(GS_PENDING_SYNTHETIC_CLICK);
258 return false;
259 }
260 if (event.type() == ui::ET_TOUCH_MOVED && !IsInsideManhattanSquare(event)) {
261 AppendScrollGestureBegin(event, gestures);
262 AppendScrollGestureUpdate(event, gestures);
263 SetState(GS_SCROLL);
264 return true;
265 }
266 return false;
267 }
268
269 bool GestureRecognizer::InScroll(const TouchEvent& event, Gestures* gestures) {
270 AppendScrollGestureUpdate(event, gestures);
271 return true;
272 }
273
274 bool GestureRecognizer::NoGesture(const TouchEvent&, Gestures*) {
275 Reset();
276 return false;
277 }
278
279 bool GestureRecognizer::TouchDown(const TouchEvent& event, Gestures* gestures) {
280 AppendTapDownGestureEvent(event, gestures);
281 SetState(GS_PENDING_SYNTHETIC_CLICK);
282 return false;
283 }
284
285 bool GestureRecognizer::ScrollEnd(const TouchEvent& event, Gestures* gestures) {
286 if (IsOverMinFlickSpeed() && event.type() != ui::ET_TOUCH_CANCELLED)
287 AppendScrollGestureEnd(event, gestures, x_velocity_, y_velocity_);
288 else
289 AppendScrollGestureEnd(event, gestures, 0.f, 0.f);
290 SetState(GS_NO_GESTURE);
291 Reset();
292 return false;
293 }
294
295 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698