OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/gestures/gesture_recognizer_impl.h" | 5 #include "ui/base/gestures/gesture_recognizer_impl.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "ui/base/events/event.h" | 10 #include "ui/base/events/event.h" |
11 #include "ui/base/events/event_constants.h" | 11 #include "ui/base/events/event_constants.h" |
12 #include "ui/base/gestures/gesture_configuration.h" | 12 #include "ui/base/gestures/gesture_configuration.h" |
13 #include "ui/base/gestures/gesture_sequence.h" | 13 #include "ui/base/gestures/gesture_sequence.h" |
14 #include "ui/base/gestures/gesture_types.h" | 14 #include "ui/base/gestures/gesture_types.h" |
15 | 15 |
16 namespace ui { | 16 namespace ui { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 // This is used to pop a std::queue when returning from a function. | |
21 class ScopedPop { | |
22 public: | |
23 explicit ScopedPop(std::queue<TouchEvent*>* queue) : queue_(queue) { | |
24 } | |
25 | |
26 ~ScopedPop() { | |
27 delete queue_->front(); | |
28 queue_->pop(); | |
29 } | |
30 | |
31 private: | |
32 std::queue<TouchEvent*>* queue_; | |
33 DISALLOW_COPY_AND_ASSIGN(ScopedPop); | |
34 }; | |
35 | |
36 // CancelledTouchEvent mirrors a TouchEvent object. | 20 // CancelledTouchEvent mirrors a TouchEvent object. |
37 class MirroredTouchEvent : public TouchEvent { | 21 class MirroredTouchEvent : public TouchEvent { |
38 public: | 22 public: |
39 explicit MirroredTouchEvent(const TouchEvent* real) | 23 explicit MirroredTouchEvent(const TouchEvent* real) |
40 : TouchEvent(real->type(), | 24 : TouchEvent(real->type(), |
41 real->location(), | 25 real->location(), |
42 real->touch_id(), | 26 real->touch_id(), |
43 real->time_stamp()) { | 27 real->time_stamp()) { |
44 set_flags(real->flags()); | 28 set_flags(real->flags()); |
45 set_radius(real->radius_x(), real->radius_y()); | 29 set_radius(real->radius_x(), real->radius_y()); |
46 set_rotation_angle(real->rotation_angle()); | 30 set_rotation_angle(real->rotation_angle()); |
47 set_force(real->force()); | 31 set_force(real->force()); |
48 } | 32 } |
49 | 33 |
50 virtual ~MirroredTouchEvent() { | 34 virtual ~MirroredTouchEvent() { |
51 } | 35 } |
52 | 36 |
53 private: | 37 private: |
54 DISALLOW_COPY_AND_ASSIGN(MirroredTouchEvent); | 38 DISALLOW_COPY_AND_ASSIGN(MirroredTouchEvent); |
55 }; | 39 }; |
56 | 40 |
57 class QueuedTouchEvent : public MirroredTouchEvent { | |
58 public: | |
59 QueuedTouchEvent(const TouchEvent* real, EventResult result) | |
60 : MirroredTouchEvent(real), | |
61 result_(result) { | |
62 } | |
63 | |
64 virtual ~QueuedTouchEvent() { | |
65 } | |
66 | |
67 EventResult result() const { return result_; } | |
68 | |
69 private: | |
70 EventResult result_; | |
71 | |
72 DISALLOW_COPY_AND_ASSIGN(QueuedTouchEvent); | |
73 }; | |
74 | |
75 // A mirrored event, except for the type, which is always ET_TOUCH_CANCELLED. | 41 // A mirrored event, except for the type, which is always ET_TOUCH_CANCELLED. |
76 class CancelledTouchEvent : public MirroredTouchEvent { | 42 class CancelledTouchEvent : public MirroredTouchEvent { |
77 public: | 43 public: |
78 explicit CancelledTouchEvent(const TouchEvent* src) | 44 explicit CancelledTouchEvent(const TouchEvent* src) |
79 : MirroredTouchEvent(src) { | 45 : MirroredTouchEvent(src) { |
80 set_type(ET_TOUCH_CANCELLED); | 46 set_type(ET_TOUCH_CANCELLED); |
81 } | 47 } |
82 | 48 |
83 virtual ~CancelledTouchEvent() {} | 49 virtual ~CancelledTouchEvent() {} |
84 | 50 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 //////////////////////////////////////////////////////////////////////////////// | 98 //////////////////////////////////////////////////////////////////////////////// |
133 // GestureRecognizerImpl, public: | 99 // GestureRecognizerImpl, public: |
134 | 100 |
135 GestureRecognizerImpl::GestureRecognizerImpl(GestureEventHelper* helper) | 101 GestureRecognizerImpl::GestureRecognizerImpl(GestureEventHelper* helper) |
136 : helper_(helper) { | 102 : helper_(helper) { |
137 gesture_consumer_ignorer_.reset(new GestureConsumerIgnorer()); | 103 gesture_consumer_ignorer_.reset(new GestureConsumerIgnorer()); |
138 } | 104 } |
139 | 105 |
140 GestureRecognizerImpl::~GestureRecognizerImpl() { | 106 GestureRecognizerImpl::~GestureRecognizerImpl() { |
141 STLDeleteValues(&consumer_sequence_); | 107 STLDeleteValues(&consumer_sequence_); |
142 STLDeleteValues(&event_queue_); | |
143 } | 108 } |
144 | 109 |
145 // Checks if this finger is already down, if so, returns the current target. | 110 // Checks if this finger is already down, if so, returns the current target. |
146 // Otherwise, returns NULL. | 111 // Otherwise, returns NULL. |
147 GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget( | 112 GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget( |
148 TouchEvent* event) { | 113 TouchEvent* event) { |
149 return touch_id_target_[event->touch_id()]; | 114 return touch_id_target_[event->touch_id()]; |
150 } | 115 } |
151 | 116 |
152 GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent( | 117 GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent( |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 i->second = gesture_consumer_ignorer_.get(); | 166 i->second = gesture_consumer_ignorer_.get(); |
202 } | 167 } |
203 } | 168 } |
204 | 169 |
205 // Transer events from |current_consumer| to |new_consumer|. | 170 // Transer events from |current_consumer| to |new_consumer|. |
206 if (current_consumer && new_consumer) { | 171 if (current_consumer && new_consumer) { |
207 TransferTouchIdToConsumerMap(current_consumer, new_consumer, | 172 TransferTouchIdToConsumerMap(current_consumer, new_consumer, |
208 &touch_id_target_); | 173 &touch_id_target_); |
209 TransferTouchIdToConsumerMap(current_consumer, new_consumer, | 174 TransferTouchIdToConsumerMap(current_consumer, new_consumer, |
210 &touch_id_target_for_gestures_); | 175 &touch_id_target_for_gestures_); |
211 TransferConsumer(current_consumer, new_consumer, &event_queue_); | |
212 TransferConsumer(current_consumer, new_consumer, &consumer_sequence_); | 176 TransferConsumer(current_consumer, new_consumer, &consumer_sequence_); |
213 } | 177 } |
214 } | 178 } |
215 | 179 |
216 bool GestureRecognizerImpl::GetLastTouchPointForTarget( | 180 bool GestureRecognizerImpl::GetLastTouchPointForTarget( |
217 GestureConsumer* consumer, | 181 GestureConsumer* consumer, |
218 gfx::Point* point) { | 182 gfx::Point* point) { |
219 if (consumer_sequence_.count(consumer) == 0) | 183 if (consumer_sequence_.count(consumer) == 0) |
220 return false; | 184 return false; |
221 | 185 |
(...skipping 27 matching lines...) Expand all Loading... |
249 if (event.type() == ui::ET_TOUCH_RELEASED || | 213 if (event.type() == ui::ET_TOUCH_RELEASED || |
250 event.type() == ui::ET_TOUCH_CANCELLED) { | 214 event.type() == ui::ET_TOUCH_CANCELLED) { |
251 touch_id_target_[event.touch_id()] = NULL; | 215 touch_id_target_[event.touch_id()] = NULL; |
252 } else { | 216 } else { |
253 touch_id_target_[event.touch_id()] = target; | 217 touch_id_target_[event.touch_id()] = target; |
254 if (target) | 218 if (target) |
255 touch_id_target_for_gestures_[event.touch_id()] = target; | 219 touch_id_target_for_gestures_[event.touch_id()] = target; |
256 } | 220 } |
257 } | 221 } |
258 | 222 |
259 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueueByOne( | |
260 GestureConsumer* consumer, | |
261 ui::EventResult result) { | |
262 CHECK(event_queue_[consumer]); | |
263 CHECK(!event_queue_[consumer]->empty()); | |
264 | |
265 ScopedPop pop(event_queue_[consumer]); | |
266 TouchEvent* event = event_queue_[consumer]->front(); | |
267 GestureSequence* sequence = GetGestureSequenceForConsumer(consumer); | |
268 if (result != ER_UNHANDLED && | |
269 event->type() == ET_TOUCH_RELEASED) { | |
270 // A touch release was was processed (e.g. preventDefault()ed by a | |
271 // web-page), but we still need to process a touch cancel. | |
272 CancelledTouchEvent cancelled(event); | |
273 return sequence->ProcessTouchEventForGesture(cancelled, | |
274 ER_UNHANDLED); | |
275 } | |
276 return sequence->ProcessTouchEventForGesture(*event, result); | |
277 } | |
278 | |
279 GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture( | 223 GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture( |
280 const TouchEvent& event, | 224 const TouchEvent& event, |
281 ui::EventResult result, | 225 ui::EventResult result, |
282 GestureConsumer* target) { | 226 GestureConsumer* target) { |
283 if (event_queue_[target] && event_queue_[target]->size() > 0) { | |
284 // There are some queued touch-events for this target. Processing |event| | |
285 // before those queued events will result in unexpected gestures. So | |
286 // postpone the processing of the events until the queued events have been | |
287 // processed. | |
288 event_queue_[target]->push(new QueuedTouchEvent(&event, result)); | |
289 return NULL; | |
290 } | |
291 | |
292 SetupTargets(event, target); | 227 SetupTargets(event, target); |
293 | |
294 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); | 228 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); |
295 return gesture_sequence->ProcessTouchEventForGesture(event, result); | 229 return gesture_sequence->ProcessTouchEventForGesture(event, result); |
296 } | 230 } |
297 | 231 |
298 void GestureRecognizerImpl::QueueTouchEventForGesture(GestureConsumer* consumer, | 232 void GestureRecognizerImpl::CleanupStateForConsumer(GestureConsumer* consumer) { |
299 const TouchEvent& event) { | |
300 if (!event_queue_[consumer]) | |
301 event_queue_[consumer] = new std::queue<TouchEvent*>(); | |
302 event_queue_[consumer]->push( | |
303 new QueuedTouchEvent(&event, ER_ASYNC)); | |
304 | |
305 SetupTargets(event, consumer); | |
306 } | |
307 | |
308 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue( | |
309 GestureConsumer* consumer, | |
310 bool processed) { | |
311 if (!event_queue_[consumer] || event_queue_[consumer]->empty()) { | |
312 LOG(ERROR) << "Trying to advance an empty gesture queue for " << consumer; | |
313 return NULL; | |
314 } | |
315 | |
316 scoped_ptr<GestureSequence::Gestures> gestures( | |
317 AdvanceTouchQueueByOne(consumer, processed ? ER_HANDLED : | |
318 ER_UNHANDLED)); | |
319 | |
320 // Are there any queued touch-events that should be auto-dequeued? | |
321 while (!event_queue_[consumer]->empty()) { | |
322 QueuedTouchEvent* event = | |
323 static_cast<QueuedTouchEvent*>(event_queue_[consumer]->front()); | |
324 if (event->result() == ER_ASYNC) | |
325 break; | |
326 | |
327 scoped_ptr<GestureSequence::Gestures> current_gestures( | |
328 AdvanceTouchQueueByOne(consumer, event->result())); | |
329 if (current_gestures.get()) { | |
330 if (!gestures.get()) { | |
331 gestures.reset(current_gestures.release()); | |
332 } else { | |
333 gestures->insert(gestures->end(), current_gestures->begin(), | |
334 current_gestures->end()); | |
335 // The gestures in |current_gestures| are now owned by |gestures|. Make | |
336 // sure they don't get freed with |current_gestures|. | |
337 current_gestures->weak_clear(); | |
338 } | |
339 } | |
340 } | |
341 | |
342 return gestures.release(); | |
343 } | |
344 | |
345 void GestureRecognizerImpl::FlushTouchQueue(GestureConsumer* consumer) { | |
346 if (consumer_sequence_.count(consumer)) { | 233 if (consumer_sequence_.count(consumer)) { |
347 delete consumer_sequence_[consumer]; | 234 delete consumer_sequence_[consumer]; |
348 consumer_sequence_.erase(consumer); | 235 consumer_sequence_.erase(consumer); |
349 } | 236 } |
350 | 237 |
351 if (event_queue_.count(consumer)) { | |
352 delete event_queue_[consumer]; | |
353 event_queue_.erase(consumer); | |
354 } | |
355 | |
356 RemoveConsumerFromMap(consumer, &touch_id_target_); | 238 RemoveConsumerFromMap(consumer, &touch_id_target_); |
357 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); | 239 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); |
358 } | 240 } |
359 | 241 |
360 // GestureRecognizer, static | 242 // GestureRecognizer, static |
361 GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { | 243 GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { |
362 return new GestureRecognizerImpl(helper); | 244 return new GestureRecognizerImpl(helper); |
363 } | 245 } |
364 | 246 |
365 } // namespace ui | 247 } // namespace ui |
OLD | NEW |