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 "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/time/time.h" 10 #include "ui/events/event.h" 11 #include "ui/events/event_constants.h" 12 #include "ui/events/event_utils.h" 13 #include "ui/events/gestures/gesture_configuration.h" 14 #include "ui/events/gestures/gesture_sequence.h" 15 #include "ui/events/gestures/gesture_types.h" 16 17 namespace ui { 18 19 namespace { 20 21 template <typename T> 22 void TransferConsumer(GestureConsumer* current_consumer, 23 GestureConsumer* new_consumer, 24 std::map<GestureConsumer*, T>* map) { 25 if (map->count(current_consumer)) { 26 (*map)[new_consumer] = (*map)[current_consumer]; 27 map->erase(current_consumer); 28 } 29 } 30 31 void RemoveConsumerFromMap(GestureConsumer* consumer, 32 GestureRecognizerImpl::TouchIdToConsumerMap* map) { 33 for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin(); 34 i != map->end();) { 35 if (i->second == consumer) 36 map->erase(i++); 37 else 38 ++i; 39 } 40 } 41 42 void TransferTouchIdToConsumerMap( 43 GestureConsumer* old_consumer, 44 GestureConsumer* new_consumer, 45 GestureRecognizerImpl::TouchIdToConsumerMap* map) { 46 for (GestureRecognizerImpl::TouchIdToConsumerMap::iterator i = map->begin(); 47 i != map->end(); ++i) { 48 if (i->second == old_consumer) 49 i->second = new_consumer; 50 } 51 } 52 53 } // namespace 54 55 //////////////////////////////////////////////////////////////////////////////// 56 // GestureRecognizerImpl, public: 57 58 GestureRecognizerImpl::GestureRecognizerImpl() { 59 } 60 61 GestureRecognizerImpl::~GestureRecognizerImpl() { 62 STLDeleteValues(&consumer_sequence_); 63 } 64 65 // Checks if this finger is already down, if so, returns the current target. 66 // Otherwise, returns NULL. 67 GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget( 68 const TouchEvent& event) { 69 return touch_id_target_[event.touch_id()]; 70 } 71 72 GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent( 73 const GestureEvent& event) { 74 GestureConsumer* target = NULL; 75 int touch_id = event.GetLowestTouchId(); 76 target = touch_id_target_for_gestures_[touch_id]; 77 return target; 78 } 79 80 GestureConsumer* GestureRecognizerImpl::GetTargetForLocation( 81 const gfx::Point& location) { 82 const GesturePoint* closest_point = NULL; 83 int64 closest_distance_squared = 0; 84 std::map<GestureConsumer*, GestureSequence*>::iterator i; 85 for (i = consumer_sequence_.begin(); i != consumer_sequence_.end(); ++i) { 86 const GesturePoint* points = i->second->points(); 87 for (int j = 0; j < GestureSequence::kMaxGesturePoints; ++j) { 88 if (!points[j].in_use()) 89 continue; 90 gfx::Vector2d delta = points[j].last_touch_position() - location; 91 // Relative distance is all we need here, so LengthSquared() is 92 // appropriate, and cheaper than Length(). 93 int64 distance_squared = delta.LengthSquared(); 94 if (!closest_point || distance_squared < closest_distance_squared) { 95 closest_point = &points[j]; 96 closest_distance_squared = distance_squared; 97 } 98 } 99 } 100 101 const int max_distance = 102 GestureConfiguration::max_separation_for_gesture_touches_in_pixels(); 103 104 if (closest_distance_squared < max_distance * max_distance && closest_point) 105 return touch_id_target_[closest_point->touch_id()]; 106 else 107 return NULL; 108 } 109 110 void GestureRecognizerImpl::TransferEventsTo(GestureConsumer* current_consumer, 111 GestureConsumer* new_consumer) { 112 // Send cancel to all those save |new_consumer| and |current_consumer|. 113 // Don't send a cancel to |current_consumer|, unless |new_consumer| is NULL. 114 // Dispatching a touch-cancel event can end up altering |touch_id_target_| 115 // (e.g. when the target of the event is destroyed, causing it to be removed 116 // from |touch_id_target_| in |CleanupStateForConsumer()|). So create a list 117 // of the touch-ids that need to be cancelled, and dispatch the cancel events 118 // for them at the end. 119 std::vector<std::pair<int, GestureConsumer*> > ids; 120 for (TouchIdToConsumerMap::iterator i = touch_id_target_.begin(); 121 i != touch_id_target_.end(); ++i) { 122 if (i->second && i->second != new_consumer && 123 (i->second != current_consumer || new_consumer == NULL) && 124 i->second) { 125 ids.push_back(std::make_pair(i->first, i->second)); 126 } 127 } 128 129 CancelTouches(&ids); 130 131 // Transfer events from |current_consumer| to |new_consumer|. 132 if (current_consumer && new_consumer) { 133 TransferTouchIdToConsumerMap(current_consumer, new_consumer, 134 &touch_id_target_); 135 TransferTouchIdToConsumerMap(current_consumer, new_consumer, 136 &touch_id_target_for_gestures_); 137 TransferConsumer(current_consumer, new_consumer, &consumer_sequence_); 138 } 139 } 140 141 bool GestureRecognizerImpl::GetLastTouchPointForTarget( 142 GestureConsumer* consumer, 143 gfx::Point* point) { 144 if (consumer_sequence_.count(consumer) == 0) 145 return false; 146 147 *point = consumer_sequence_[consumer]->last_touch_location(); 148 return true; 149 } 150 151 void GestureRecognizerImpl::CancelActiveTouches( 152 GestureConsumer* consumer) { 153 std::vector<std::pair<int, GestureConsumer*> > ids; 154 for (TouchIdToConsumerMap::const_iterator i = touch_id_target_.begin(); 155 i != touch_id_target_.end(); ++i) { 156 if (i->second == consumer) 157 ids.push_back(std::make_pair(i->first, i->second)); 158 } 159 CancelTouches(&ids); 160 } 161 162 //////////////////////////////////////////////////////////////////////////////// 163 // GestureRecognizerImpl, protected: 164 165 GestureSequence* GestureRecognizerImpl::CreateSequence( 166 GestureSequenceDelegate* delegate) { 167 return new GestureSequence(delegate); 168 } 169 170 //////////////////////////////////////////////////////////////////////////////// 171 // GestureRecognizerImpl, private: 172 173 GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer( 174 GestureConsumer* consumer) { 175 GestureSequence* gesture_sequence = consumer_sequence_[consumer]; 176 if (!gesture_sequence) { 177 gesture_sequence = CreateSequence(this); 178 consumer_sequence_[consumer] = gesture_sequence; 179 } 180 return gesture_sequence; 181 } 182 183 void GestureRecognizerImpl::SetupTargets(const TouchEvent& event, 184 GestureConsumer* target) { 185 if (event.type() == ui::ET_TOUCH_RELEASED || 186 event.type() == ui::ET_TOUCH_CANCELLED) { 187 touch_id_target_.erase(event.touch_id()); 188 } else if (event.type() == ui::ET_TOUCH_PRESSED) { 189 touch_id_target_[event.touch_id()] = target; 190 if (target) 191 touch_id_target_for_gestures_[event.touch_id()] = target; 192 } 193 } 194 195 void GestureRecognizerImpl::CancelTouches( 196 std::vector<std::pair<int, GestureConsumer*> >* touches) { 197 while (!touches->empty()) { 198 int touch_id = touches->begin()->first; 199 GestureConsumer* target = touches->begin()->second; 200 TouchEvent touch_event(ui::ET_TOUCH_CANCELLED, gfx::Point(0, 0), 201 ui::EF_IS_SYNTHESIZED, touch_id, 202 ui::EventTimeForNow(), 0.0f, 0.0f, 0.0f, 0.0f); 203 GestureEventHelper* helper = FindDispatchHelperForConsumer(target); 204 if (helper) 205 helper->DispatchCancelTouchEvent(&touch_event); 206 touches->erase(touches->begin()); 207 } 208 } 209 210 GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture( 211 const TouchEvent& event, 212 ui::EventResult result, 213 GestureConsumer* target) { 214 SetupTargets(event, target); 215 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); 216 return gesture_sequence->ProcessTouchEventForGesture(event, result); 217 } 218 219 void GestureRecognizerImpl::CleanupStateForConsumer(GestureConsumer* consumer) { 220 if (consumer_sequence_.count(consumer)) { 221 delete consumer_sequence_[consumer]; 222 consumer_sequence_.erase(consumer); 223 } 224 225 RemoveConsumerFromMap(consumer, &touch_id_target_); 226 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); 227 } 228 229 void GestureRecognizerImpl::AddGestureEventHelper(GestureEventHelper* helper) { 230 helpers_.push_back(helper); 231 } 232 233 void GestureRecognizerImpl::RemoveGestureEventHelper( 234 GestureEventHelper* helper) { 235 std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(), 236 helpers_.end(), helper); 237 if (it != helpers_.end()) 238 helpers_.erase(it); 239 } 240 241 void GestureRecognizerImpl::DispatchPostponedGestureEvent(GestureEvent* event) { 242 GestureConsumer* consumer = GetTargetForGestureEvent(*event); 243 if (consumer) { 244 GestureEventHelper* helper = FindDispatchHelperForConsumer(consumer); 245 if (helper) 246 helper->DispatchPostponedGestureEvent(event); 247 } 248 } 249 250 GestureEventHelper* GestureRecognizerImpl::FindDispatchHelperForConsumer( 251 GestureConsumer* consumer) { 252 std::vector<GestureEventHelper*>::iterator it; 253 for (it = helpers_.begin(); it != helpers_.end(); ++it) { 254 if ((*it)->CanDispatchToConsumer(consumer)) 255 return (*it); 256 } 257 return NULL; 258 } 259 260 // GestureRecognizer, static 261 GestureRecognizer* GestureRecognizer::Create() { 262 return new GestureRecognizerImpl(); 263 } 264 265 static GestureRecognizerImpl* g_gesture_recognizer_instance = NULL; 266 267 // GestureRecognizer, static 268 GestureRecognizer* GestureRecognizer::Get() { 269 if (!g_gesture_recognizer_instance) 270 g_gesture_recognizer_instance = new GestureRecognizerImpl(); 271 return g_gesture_recognizer_instance; 272 } 273 274 void SetGestureRecognizerForTesting(GestureRecognizer* gesture_recognizer) { 275 // Transfer helpers to the new GR. 276 std::vector<GestureEventHelper*>& helpers = 277 g_gesture_recognizer_instance->helpers(); 278 std::vector<GestureEventHelper*>::iterator it; 279 for (it = helpers.begin(); it != helpers.end(); ++it) 280 gesture_recognizer->AddGestureEventHelper(*it); 281 282 helpers.clear(); 283 g_gesture_recognizer_instance = 284 static_cast<GestureRecognizerImpl*>(gesture_recognizer); 285 } 286 287 } // namespace ui 288