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_sequence.h" | 5 #include "ui/base/gestures/gesture_sequence.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 | 291 |
292 // Set a limit on the number of simultaneous touches in a gesture. | 292 // Set a limit on the number of simultaneous touches in a gesture. |
293 if (event.touch_id() >= kMaxGesturePoints) | 293 if (event.touch_id() >= kMaxGesturePoints) |
294 return NULL; | 294 return NULL; |
295 | 295 |
296 if (event.type() == ui::ET_TOUCH_PRESSED) { | 296 if (event.type() == ui::ET_TOUCH_PRESSED) { |
297 if (point_count_ == kMaxGesturePoints) | 297 if (point_count_ == kMaxGesturePoints) |
298 return NULL; | 298 return NULL; |
299 GesturePoint* new_point = &points_[event.touch_id()]; | 299 GesturePoint* new_point = &points_[event.touch_id()]; |
300 // We shouldn't be able to get two PRESSED events from the same | 300 // We shouldn't be able to get two PRESSED events from the same |
301 // finger without either a RELEASE or CANCEL in between. | 301 // finger without either a RELEASE or CANCEL in between. But let's not crash |
302 DCHECK(!new_point->in_use()); | 302 // in a release build. |
303 if (new_point->in_use()) { | |
304 LOG(ERROR) << "Received a second press for a point: " << event.touch_id(); | |
305 new_point->ResetVelocity(); | |
306 new_point->UpdateValues(event); | |
307 return NULL; | |
308 } | |
303 new_point->set_point_id(point_count_++); | 309 new_point->set_point_id(point_count_++); |
304 new_point->set_touch_id(event.touch_id()); | 310 new_point->set_touch_id(event.touch_id()); |
305 } | 311 } |
306 | 312 |
307 GestureState last_state = state_; | 313 GestureState last_state = state_; |
308 | 314 |
309 // NOTE: when modifying these state transitions, also update gestures.dot | 315 // NOTE: when modifying these state transitions, also update gestures.dot |
310 scoped_ptr<Gestures> gestures(new Gestures()); | 316 scoped_ptr<Gestures> gestures(new Gestures()); |
311 GesturePoint& point = GesturePointForEvent(event); | 317 GesturePoint& point = GesturePointForEvent(event); |
312 point.UpdateValues(event); | 318 point.UpdateValues(event); |
313 RecreateBoundingBox(); | 319 RecreateBoundingBox(); |
314 flags_ = event.flags(); | 320 flags_ = event.flags(); |
315 const int point_id = points_[event.touch_id()].point_id(); | 321 const int point_id = points_[event.touch_id()].point_id(); |
varunjain
2012/08/13 20:40:44
also change this to point.point_id()?
sadrul
2012/08/13 20:43:55
Good point. Done.
| |
316 if (point_id < 0) | 322 if (point_id < 0) |
317 return NULL; | 323 return NULL; |
318 | 324 |
319 // Send GESTURE_BEGIN for any touch pressed. | 325 // Send GESTURE_BEGIN for any touch pressed. |
320 if (event.type() == ui::ET_TOUCH_PRESSED) | 326 if (event.type() == ui::ET_TOUCH_PRESSED) |
321 AppendBeginGestureEvent(point, gestures.get()); | 327 AppendBeginGestureEvent(point, gestures.get()); |
322 | 328 |
323 TouchStatusInternal status_internal = (status == ui::TOUCH_STATUS_UNKNOWN) ? | 329 TouchStatusInternal status_internal = (status == ui::TOUCH_STATUS_UNKNOWN) ? |
324 TSI_NOT_PROCESSED : TSI_PROCESSED; | 330 TSI_NOT_PROCESSED : TSI_PROCESSED; |
325 | 331 |
(...skipping 18 matching lines...) Expand all Loading... | |
344 break; | 350 break; |
345 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED: | 351 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED: |
346 case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: | 352 case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: |
347 if (ScrollStart(event, point, gestures.get())) { | 353 if (ScrollStart(event, point, gestures.get())) { |
348 set_state(GS_SCROLL); | 354 set_state(GS_SCROLL); |
349 if (ScrollUpdate(event, point, gestures.get())) | 355 if (ScrollUpdate(event, point, gestures.get())) |
350 point.UpdateForScroll(); | 356 point.UpdateForScroll(); |
351 } | 357 } |
352 break; | 358 break; |
353 case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: | 359 case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: |
354 NoGesture(event, point, gestures.get()); | 360 set_state(GS_NO_GESTURE); |
355 break; | 361 break; |
356 case GST_SCROLL_FIRST_MOVED: | 362 case GST_SCROLL_FIRST_MOVED: |
357 if (scroll_type_ == ST_VERTICAL || | 363 if (scroll_type_ == ST_VERTICAL || |
358 scroll_type_ == ST_HORIZONTAL) | 364 scroll_type_ == ST_HORIZONTAL) |
359 BreakRailScroll(event, point, gestures.get()); | 365 BreakRailScroll(event, point, gestures.get()); |
360 if (ScrollUpdate(event, point, gestures.get())) | 366 if (ScrollUpdate(event, point, gestures.get())) |
361 point.UpdateForScroll(); | 367 point.UpdateForScroll(); |
362 break; | 368 break; |
363 case GST_SCROLL_FIRST_RELEASED: | 369 case GST_SCROLL_FIRST_RELEASED: |
364 case GST_SCROLL_FIRST_CANCELLED: | 370 case GST_SCROLL_FIRST_CANCELLED: |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 | 457 |
452 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) | 458 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) |
453 long_press_timer_->Stop(); | 459 long_press_timer_->Stop(); |
454 | 460 |
455 // The set of point_ids must be contiguous and include 0. | 461 // The set of point_ids must be contiguous and include 0. |
456 // When a touch point is released, all points with ids greater than the | 462 // When a touch point is released, all points with ids greater than the |
457 // released point must have their ids decremented, or the set of point_ids | 463 // released point must have their ids decremented, or the set of point_ids |
458 // could end up with gaps. | 464 // could end up with gaps. |
459 if (event.type() == ui::ET_TOUCH_RELEASED || | 465 if (event.type() == ui::ET_TOUCH_RELEASED || |
460 event.type() == ui::ET_TOUCH_CANCELLED) { | 466 event.type() == ui::ET_TOUCH_CANCELLED) { |
461 GesturePoint& old_point = points_[event.touch_id()]; | |
462 for (int i = 0; i < kMaxGesturePoints; ++i) { | 467 for (int i = 0; i < kMaxGesturePoints; ++i) { |
463 GesturePoint& point = points_[i]; | 468 GesturePoint& iter_point = points_[i]; |
464 if (point.point_id() > old_point.point_id()) | 469 if (iter_point.point_id() > point.point_id()) |
465 point.set_point_id(point.point_id() - 1); | 470 iter_point.set_point_id(iter_point.point_id() - 1); |
466 } | 471 } |
467 | 472 |
468 if (old_point.in_use()) { | 473 point.Reset(); |
469 old_point.Reset(); | 474 --point_count_; |
470 --point_count_; | 475 CHECK_GE(point_count_, 0); |
471 DCHECK_GE(point_count_, 0); | 476 RecreateBoundingBox(); |
472 RecreateBoundingBox(); | 477 if (state_ == GS_PINCH) { |
473 if (state_ == GS_PINCH) { | 478 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); |
474 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); | 479 pinch_distance_start_ = pinch_distance_current_; |
475 pinch_distance_start_ = pinch_distance_current_; | |
476 } | |
477 } | 480 } |
478 } | 481 } |
479 | |
480 return gestures.release(); | 482 return gestures.release(); |
481 } | 483 } |
482 | 484 |
483 void GestureSequence::Reset() { | |
484 set_state(GS_NO_GESTURE); | |
485 for (int i = 0; i < kMaxGesturePoints; ++i) | |
486 points_[i].Reset(); | |
487 point_count_ = 0; | |
488 } | |
489 | |
490 void GestureSequence::RecreateBoundingBox() { | 485 void GestureSequence::RecreateBoundingBox() { |
491 // TODO(sad): Recreating the bounding box at every touch-event is not very | 486 // TODO(sad): Recreating the bounding box at every touch-event is not very |
492 // efficient. This should be made better. | 487 // efficient. This should be made better. |
493 int left = INT_MAX, top = INT_MAX, right = INT_MIN, bottom = INT_MIN; | 488 int left = INT_MAX, top = INT_MAX, right = INT_MIN, bottom = INT_MIN; |
494 for (int i = 0; i < kMaxGesturePoints; ++i) { | 489 for (int i = 0; i < kMaxGesturePoints; ++i) { |
495 if (!points_[i].in_use()) | 490 if (!points_[i].in_use()) |
496 continue; | 491 continue; |
497 gfx::Rect rect = points_[i].enclosing_rectangle(); | 492 gfx::Rect rect = points_[i].enclosing_rectangle(); |
498 if (left > rect.x()) | 493 if (left > rect.x()) |
499 left = rect.x(); | 494 left = rect.x(); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
793 | 788 |
794 bool GestureSequence::ScrollUpdate(const TouchEvent& event, | 789 bool GestureSequence::ScrollUpdate(const TouchEvent& event, |
795 const GesturePoint& point, Gestures* gestures) { | 790 const GesturePoint& point, Gestures* gestures) { |
796 DCHECK(state_ == GS_SCROLL); | 791 DCHECK(state_ == GS_SCROLL); |
797 if (!point.DidScroll(event, 0)) | 792 if (!point.DidScroll(event, 0)) |
798 return false; | 793 return false; |
799 AppendScrollGestureUpdate(point, point.last_touch_position(), gestures); | 794 AppendScrollGestureUpdate(point, point.last_touch_position(), gestures); |
800 return true; | 795 return true; |
801 } | 796 } |
802 | 797 |
803 bool GestureSequence::NoGesture(const TouchEvent&, | |
804 const GesturePoint& point, Gestures*) { | |
805 Reset(); | |
806 return false; | |
807 } | |
808 | |
809 bool GestureSequence::TouchDown(const TouchEvent& event, | 798 bool GestureSequence::TouchDown(const TouchEvent& event, |
810 const GesturePoint& point, Gestures* gestures) { | 799 const GesturePoint& point, Gestures* gestures) { |
811 DCHECK(state_ == GS_NO_GESTURE); | 800 DCHECK(state_ == GS_NO_GESTURE); |
812 AppendTapDownGestureEvent(point, gestures); | 801 AppendTapDownGestureEvent(point, gestures); |
813 long_press_timer_->Start( | 802 long_press_timer_->Start( |
814 FROM_HERE, | 803 FROM_HERE, |
815 base::TimeDelta::FromMilliseconds( | 804 base::TimeDelta::FromMilliseconds( |
816 GestureConfiguration::long_press_time_in_seconds() * 1000), | 805 GestureConfiguration::long_press_time_in_seconds() * 1000), |
817 this, | 806 this, |
818 &GestureSequence::AppendLongPressGestureEvent); | 807 &GestureSequence::AppendLongPressGestureEvent); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1028 return; | 1017 return; |
1029 | 1018 |
1030 // Since long press timer has been started, there should be a non-NULL point. | 1019 // Since long press timer has been started, there should be a non-NULL point. |
1031 const GesturePoint* point = GetPointByPointId(0); | 1020 const GesturePoint* point = GetPointByPointId(0); |
1032 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), | 1021 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), |
1033 event.location())) | 1022 event.location())) |
1034 long_press_timer_->Stop(); | 1023 long_press_timer_->Stop(); |
1035 } | 1024 } |
1036 | 1025 |
1037 } // namespace ui | 1026 } // namespace ui |
OLD | NEW |