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 #include "ui/events/gestures/gesture_recognizer_impl.h" 6 7 #include <limits> 8 9 #include "base/command_line.h" 10 #include "base/logging.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/time/time.h" 14 #include "ui/events/event.h" 15 #include "ui/events/event_constants.h" 16 #include "ui/events/event_switches.h" 17 #include "ui/events/event_utils.h" 18 #include "ui/events/gestures/gesture_configuration.h" 19 #include "ui/events/gestures/gesture_sequence.h" 20 #include "ui/events/gestures/gesture_types.h" 21 #include "ui/events/gestures/unified_gesture_detector_enabled.h" 22 23 namespace ui { 24 25 namespace { 26 27 template <typename T> 28 void TransferConsumer(GestureConsumer* current_consumer, 29 GestureConsumer* new_consumer, 30 std::map<GestureConsumer*, T>* map) { 31 if (map->count(current_consumer)) { 32 (*map)[new_consumer] = (*map)[current_consumer]; 33 map->erase(current_consumer); 34 } 35 } 36 37 bool RemoveConsumerFromMap(GestureConsumer* consumer, 38 GestureRecognizerImpl::TouchIdToConsumerMap* map) { 39 bool consumer_removed = false; 40 for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin(); 41 i != map->end();) { 42 if (i->second == consumer) { 43 map->erase(i++); 44 consumer_removed = true; 45 } else { 46 ++i; 47 } 48 } 49 return consumer_removed; 50 } 51 52 void TransferTouchIdToConsumerMap( 53 GestureConsumer* old_consumer, 54 GestureConsumer* new_consumer, 55 GestureRecognizerImpl::TouchIdToConsumerMap* map) { 56 for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin(); 57 i != map->end(); ++i) { 58 if (i->second == old_consumer) 59 i->second = new_consumer; 60 } 61 } 62 63 GestureProviderAura* CreateGestureProvider(GestureProviderAuraClient* client) { 64 return new GestureProviderAura(client); 65 } 66 67 } // namespace 68 69 //////////////////////////////////////////////////////////////////////////////// 70 // GestureRecognizerImpl, public: 71 72 GestureRecognizerImpl::GestureRecognizerImpl() { 73 use_unified_gesture_detector_ = IsUnifiedGestureDetectorEnabled(); 74 } 75 76 GestureRecognizerImpl::~GestureRecognizerImpl() { 77 STLDeleteValues(&consumer_sequence_); 78 STLDeleteValues(&consumer_gesture_provider_); 79 } 80 81 // Checks if this finger is already down, if so, returns the current target. 82 // Otherwise, returns NULL. 83 GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget( 84 const TouchEvent& event) { 85 return touch_id_target_[event.touch_id()]; 86 } 87 88 GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent( 89 const GestureEvent& event) { 90 GestureConsumer* target = NULL; 91 int touch_id = event.GetLowestTouchId(); 92 target = touch_id_target_for_gestures_[touch_id]; 93 return target; 94 } 95 96 GestureConsumer* GestureRecognizerImpl::GetTargetForLocation( 97 const gfx::PointF& location, int source_device_id) { 98 const int max_distance = 99 GestureConfiguration::max_separation_for_gesture_touches_in_pixels(); 100 101 if (!use_unified_gesture_detector_) { 102 const GesturePoint* closest_point = NULL; 103 int64 closest_distance_squared = 0; 104 std::map<GestureConsumer*, GestureSequence*>::iterator i; 105 for (i = consumer_sequence_.begin(); i != consumer_sequence_.end(); ++i) { 106 const GesturePoint* points = i->second->points(); 107 for (int j = 0; j < GestureSequence::kMaxGesturePoints; ++j) { 108 if (!points[j].in_use() || 109 source_device_id != points[j].source_device_id()) { 110 continue; 111 } 112 gfx::Vector2dF delta = points[j].last_touch_position() - location; 113 // Relative distance is all we need here, so LengthSquared() is 114 // appropriate, and cheaper than Length(). 115 int64 distance_squared = delta.LengthSquared(); 116 if (!closest_point || distance_squared < closest_distance_squared) { 117 closest_point = &points[j]; 118 closest_distance_squared = distance_squared; 119 } 120 } 121 } 122 123 if (closest_distance_squared < max_distance * max_distance && closest_point) 124 return touch_id_target_[closest_point->touch_id()]; 125 else 126 return NULL; 127 } else { 128 gfx::PointF closest_point; 129 int closest_touch_id; 130 float closest_distance_squared = std::numeric_limits<float>::infinity(); 131 132 std::map<GestureConsumer*, GestureProviderAura*>::iterator i; 133 for (i = consumer_gesture_provider_.begin(); 134 i != consumer_gesture_provider_.end(); 135 ++i) { 136 const MotionEventAura& pointer_state = i->second->pointer_state(); 137 for (size_t j = 0; j < pointer_state.GetPointerCount(); ++j) { 138 if (source_device_id != pointer_state.GetSourceDeviceId(j)) 139 continue; 140 gfx::PointF point(pointer_state.GetX(j), pointer_state.GetY(j)); 141 // Relative distance is all we need here, so LengthSquared() is 142 // appropriate, and cheaper than Length(). 143 float distance_squared = (point - location).LengthSquared(); 144 if (distance_squared < closest_distance_squared) { 145 closest_point = point; 146 closest_touch_id = pointer_state.GetPointerId(j); 147 closest_distance_squared = distance_squared; 148 } 149 } 150 } 151 152 if (closest_distance_squared < max_distance * max_distance) 153 return touch_id_target_[closest_touch_id]; 154 else 155 return NULL; 156 } 157 } 158 159 void GestureRecognizerImpl::TransferEventsTo(GestureConsumer* current_consumer, 160 GestureConsumer* new_consumer) { 161 // Send cancel to all those save |new_consumer| and |current_consumer|. 162 // Don't send a cancel to |current_consumer|, unless |new_consumer| is NULL. 163 // Dispatching a touch-cancel event can end up altering |touch_id_target_| 164 // (e.g. when the target of the event is destroyed, causing it to be removed 165 // from |touch_id_target_| in |CleanupStateForConsumer()|). So create a list 166 // of the touch-ids that need to be cancelled, and dispatch the cancel events 167 // for them at the end. 168 std::vector<std::pair<int, GestureConsumer*> > ids; 169 for (TouchIdToConsumerMap::iterator i = touch_id_target_.begin(); 170 i != touch_id_target_.end(); ++i) { 171 if (i->second && i->second != new_consumer && 172 (i->second != current_consumer || new_consumer == NULL) && 173 i->second) { 174 ids.push_back(std::make_pair(i->first, i->second)); 175 } 176 } 177 178 CancelTouches(&ids); 179 180 // Transfer events from |current_consumer| to |new_consumer|. 181 if (current_consumer && new_consumer) { 182 TransferTouchIdToConsumerMap(current_consumer, new_consumer, 183 &touch_id_target_); 184 TransferTouchIdToConsumerMap(current_consumer, new_consumer, 185 &touch_id_target_for_gestures_); 186 if (!use_unified_gesture_detector_) 187 TransferConsumer(current_consumer, new_consumer, &consumer_sequence_); 188 else 189 TransferConsumer( 190 current_consumer, new_consumer, &consumer_gesture_provider_); 191 } 192 } 193 194 bool GestureRecognizerImpl::GetLastTouchPointForTarget( 195 GestureConsumer* consumer, 196 gfx::PointF* point) { 197 if (!use_unified_gesture_detector_) { 198 if (consumer_sequence_.count(consumer) == 0) 199 return false; 200 *point = consumer_sequence_[consumer]->last_touch_location(); 201 return true; 202 } else { 203 if (consumer_gesture_provider_.count(consumer) == 0) 204 return false; 205 const MotionEvent& pointer_state = 206 consumer_gesture_provider_[consumer]->pointer_state(); 207 *point = gfx::PointF(pointer_state.GetX(), pointer_state.GetY()); 208 return true; 209 } 210 } 211 212 bool GestureRecognizerImpl::CancelActiveTouches(GestureConsumer* consumer) { 213 std::vector<std::pair<int, GestureConsumer*> > ids; 214 for (TouchIdToConsumerMap::const_iterator i = touch_id_target_.begin(); 215 i != touch_id_target_.end(); ++i) { 216 if (i->second == consumer) 217 ids.push_back(std::make_pair(i->first, i->second)); 218 } 219 bool cancelled_touch = !ids.empty(); 220 CancelTouches(&ids); 221 return cancelled_touch; 222 } 223 224 //////////////////////////////////////////////////////////////////////////////// 225 // GestureRecognizerImpl, protected: 226 227 GestureSequence* GestureRecognizerImpl::CreateSequence( 228 GestureSequenceDelegate* delegate) { 229 return new GestureSequence(delegate); 230 } 231 232 //////////////////////////////////////////////////////////////////////////////// 233 // GestureRecognizerImpl, private: 234 235 GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer( 236 GestureConsumer* consumer) { 237 GestureSequence* gesture_sequence = consumer_sequence_[consumer]; 238 if (!gesture_sequence) { 239 gesture_sequence = CreateSequence(this); 240 consumer_sequence_[consumer] = gesture_sequence; 241 } 242 return gesture_sequence; 243 } 244 245 GestureProviderAura* GestureRecognizerImpl::GetGestureProviderForConsumer( 246 GestureConsumer* consumer) { 247 GestureProviderAura* gesture_provider = consumer_gesture_provider_[consumer]; 248 if (!gesture_provider) { 249 gesture_provider = CreateGestureProvider(this); 250 consumer_gesture_provider_[consumer] = gesture_provider; 251 } 252 return gesture_provider; 253 } 254 255 void GestureRecognizerImpl::SetupTargets(const TouchEvent& event, 256 GestureConsumer* target) { 257 if (event.type() == ui::ET_TOUCH_RELEASED || 258 event.type() == ui::ET_TOUCH_CANCELLED) { 259 touch_id_target_.erase(event.touch_id()); 260 } else if (event.type() == ui::ET_TOUCH_PRESSED) { 261 touch_id_target_[event.touch_id()] = target; 262 if (target) 263 touch_id_target_for_gestures_[event.touch_id()] = target; 264 } 265 } 266 267 void GestureRecognizerImpl::CancelTouches( 268 std::vector<std::pair<int, GestureConsumer*> >* touches) { 269 while (!touches->empty()) { 270 int touch_id = touches->begin()->first; 271 GestureConsumer* target = touches->begin()->second; 272 TouchEvent touch_event(ui::ET_TOUCH_CANCELLED, gfx::PointF(0, 0), 273 ui::EF_IS_SYNTHESIZED, touch_id, 274 ui::EventTimeForNow(), 0.0f, 0.0f, 0.0f, 0.0f); 275 GestureEventHelper* helper = FindDispatchHelperForConsumer(target); 276 if (helper) 277 helper->DispatchCancelTouchEvent(&touch_event); 278 touches->erase(touches->begin()); 279 } 280 } 281 282 void GestureRecognizerImpl::DispatchGestureEvent(GestureEvent* event) { 283 GestureConsumer* consumer = GetTargetForGestureEvent(*event); 284 if (consumer) { 285 GestureEventHelper* helper = FindDispatchHelperForConsumer(consumer); 286 if (helper) 287 helper->DispatchGestureEvent(event); 288 } 289 } 290 291 ScopedVector<GestureEvent>* GestureRecognizerImpl::ProcessTouchEventForGesture( 292 const TouchEvent& event, 293 ui::EventResult result, 294 GestureConsumer* target) { 295 SetupTargets(event, target); 296 297 if (!use_unified_gesture_detector_) { 298 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); 299 return gesture_sequence->ProcessTouchEventForGesture(event, result); 300 } else { 301 GestureProviderAura* gesture_provider = 302 GetGestureProviderForConsumer(target); 303 // TODO(tdresser) - detect gestures eagerly. 304 if (!(result & ER_CONSUMED)) { 305 if (gesture_provider->OnTouchEvent(event)) { 306 gesture_provider->OnTouchEventAck(result != ER_UNHANDLED); 307 return gesture_provider->GetAndResetPendingGestures(); 308 } 309 } 310 return NULL; 311 } 312 } 313 314 bool GestureRecognizerImpl::CleanupStateForConsumer( 315 GestureConsumer* consumer) { 316 bool state_cleaned_up = false; 317 318 if (!use_unified_gesture_detector_) { 319 if (consumer_sequence_.count(consumer)) { 320 state_cleaned_up = true; 321 delete consumer_sequence_[consumer]; 322 consumer_sequence_.erase(consumer); 323 } 324 } else { 325 if (consumer_gesture_provider_.count(consumer)) { 326 state_cleaned_up = true; 327 delete consumer_gesture_provider_[consumer]; 328 consumer_gesture_provider_.erase(consumer); 329 } 330 } 331 332 state_cleaned_up |= RemoveConsumerFromMap(consumer, &touch_id_target_); 333 state_cleaned_up |= 334 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); 335 return state_cleaned_up; 336 } 337 338 void GestureRecognizerImpl::AddGestureEventHelper(GestureEventHelper* helper) { 339 helpers_.push_back(helper); 340 } 341 342 void GestureRecognizerImpl::RemoveGestureEventHelper( 343 GestureEventHelper* helper) { 344 std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(), 345 helpers_.end(), helper); 346 if (it != helpers_.end()) 347 helpers_.erase(it); 348 } 349 350 void GestureRecognizerImpl::DispatchPostponedGestureEvent(GestureEvent* event) { 351 DispatchGestureEvent(event); 352 } 353 354 void GestureRecognizerImpl::OnGestureEvent(GestureEvent* event) { 355 DispatchGestureEvent(event); 356 } 357 358 GestureEventHelper* GestureRecognizerImpl::FindDispatchHelperForConsumer( 359 GestureConsumer* consumer) { 360 std::vector<GestureEventHelper*>::iterator it; 361 for (it = helpers_.begin(); it != helpers_.end(); ++it) { 362 if ((*it)->CanDispatchToConsumer(consumer)) 363 return (*it); 364 } 365 return NULL; 366 } 367 368 // GestureRecognizer, static 369 GestureRecognizer* GestureRecognizer::Create() { 370 return new GestureRecognizerImpl(); 371 } 372 373 static GestureRecognizerImpl* g_gesture_recognizer_instance = NULL; 374 375 // GestureRecognizer, static 376 GestureRecognizer* GestureRecognizer::Get() { 377 if (!g_gesture_recognizer_instance) 378 g_gesture_recognizer_instance = new GestureRecognizerImpl(); 379 return g_gesture_recognizer_instance; 380 } 381 382 // GestureRecognizer, static 383 void GestureRecognizer::Reset() { 384 delete g_gesture_recognizer_instance; 385 g_gesture_recognizer_instance = NULL; 386 } 387 388 void SetGestureRecognizerForTesting(GestureRecognizer* gesture_recognizer) { 389 // Transfer helpers to the new GR. 390 std::vector<GestureEventHelper*>& helpers = 391 g_gesture_recognizer_instance->helpers(); 392 std::vector<GestureEventHelper*>::iterator it; 393 for (it = helpers.begin(); it != helpers.end(); ++it) 394 gesture_recognizer->AddGestureEventHelper(*it); 395 396 helpers.clear(); 397 g_gesture_recognizer_instance = 398 static_cast<GestureRecognizerImpl*>(gesture_recognizer); 399 } 400 401 } // namespace ui 402