| 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 = point.point_id(); |
| 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 |