| 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 |