| 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 return signature; | 257 return signature; |
| 258 } | 258 } |
| 259 #undef G | 259 #undef G |
| 260 | 260 |
| 261 float BoundingBoxDiagonal(const gfx::Rect& rect) { | 261 float BoundingBoxDiagonal(const gfx::Rect& rect) { |
| 262 float width = rect.width() * rect.width(); | 262 float width = rect.width() * rect.width(); |
| 263 float height = rect.height() * rect.height(); | 263 float height = rect.height() * rect.height(); |
| 264 return sqrt(width + height); | 264 return sqrt(width + height); |
| 265 } | 265 } |
| 266 | 266 |
| 267 float BoundingBoxDiagonalAngle(const gfx::Rect& rect) { |
| 268 float width = rect.width(); |
| 269 float height = rect.height(); |
| 270 return width == 0.f ? M_PI_2 : atan(height / width); |
| 271 } |
| 272 |
| 267 unsigned int ComputeTouchBitmask(const GesturePoint* points) { | 273 unsigned int ComputeTouchBitmask(const GesturePoint* points) { |
| 268 unsigned int touch_bitmask = 0; | 274 unsigned int touch_bitmask = 0; |
| 269 for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) { | 275 for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) { |
| 270 if (points[i].in_use()) | 276 if (points[i].in_use()) |
| 271 touch_bitmask |= 1 << points[i].touch_id(); | 277 touch_bitmask |= 1 << points[i].touch_id(); |
| 272 } | 278 } |
| 273 return touch_bitmask; | 279 return touch_bitmask; |
| 274 } | 280 } |
| 275 | 281 |
| 276 float CalibrateFlingVelocity(float velocity) { | 282 float CalibrateFlingVelocity(float velocity) { |
| 277 // TODO(sad|rjkroege): fling-curve is currently configured to work well with | 283 // TODO(sad|rjkroege): fling-curve is currently configured to work well with |
| 278 // touchpad scroll-events. This curve needs to be adjusted to work correctly | 284 // touchpad scroll-events. This curve needs to be adjusted to work correctly |
| 279 // with both touchpad and touchscreen. Until then, scale quadratically. | 285 // with both touchpad and touchscreen. Until then, scale quadratically. |
| 280 // http://crbug.com/120154 | 286 // http://crbug.com/120154 |
| 281 const float velocity_scaling = | 287 const float velocity_scaling = |
| 282 GestureConfiguration::touchscreen_fling_acceleration_adjustment(); | 288 GestureConfiguration::touchscreen_fling_acceleration_adjustment(); |
| 283 return velocity_scaling * velocity; | 289 return velocity_scaling * velocity; |
| 284 } | 290 } |
| 285 | 291 |
| 286 } // namespace | 292 } // namespace |
| 287 | 293 |
| 288 //////////////////////////////////////////////////////////////////////////////// | 294 //////////////////////////////////////////////////////////////////////////////// |
| 289 // GestureSequence Public: | 295 // GestureSequence Public: |
| 290 | 296 |
| 291 GestureSequence::GestureSequence(GestureEventHelper* helper) | 297 GestureSequence::GestureSequence(GestureEventHelper* helper) |
| 292 : state_(GS_NO_GESTURE), | 298 : state_(GS_NO_GESTURE), |
| 293 flags_(0), | 299 flags_(0), |
| 300 bounding_box_diagonal_angle_(0.f), |
| 294 pinch_distance_start_(0.f), | 301 pinch_distance_start_(0.f), |
| 295 pinch_distance_current_(0.f), | 302 pinch_distance_current_(0.f), |
| 296 scroll_type_(ST_FREE), | 303 scroll_type_(ST_FREE), |
| 297 long_press_timer_(CreateTimer()), | 304 long_press_timer_(CreateTimer()), |
| 298 point_count_(0), | 305 point_count_(0), |
| 299 helper_(helper) { | 306 helper_(helper) { |
| 300 } | 307 } |
| 301 | 308 |
| 302 GestureSequence::~GestureSequence() { | 309 GestureSequence::~GestureSequence() { |
| 303 } | 310 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 // pinch_distance_current_ and pinch_distance_start_ will be updated | 474 // pinch_distance_current_ and pinch_distance_start_ will be updated |
| 468 // when the bounding-box is updated. | 475 // when the bounding-box is updated. |
| 469 } | 476 } |
| 470 ResetVelocities(); | 477 ResetVelocities(); |
| 471 break; | 478 break; |
| 472 case GST_PINCH_THIRD_PRESSED: | 479 case GST_PINCH_THIRD_PRESSED: |
| 473 case GST_PINCH_FOURTH_PRESSED: | 480 case GST_PINCH_FOURTH_PRESSED: |
| 474 case GST_PINCH_FIFTH_PRESSED: | 481 case GST_PINCH_FIFTH_PRESSED: |
| 475 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); | 482 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); |
| 476 pinch_distance_start_ = pinch_distance_current_; | 483 pinch_distance_start_ = pinch_distance_current_; |
| 484 bounding_box_diagonal_angle_ = BoundingBoxDiagonalAngle(bounding_box_); |
| 477 break; | 485 break; |
| 478 } | 486 } |
| 479 | 487 |
| 480 if (event.type() == ui::ET_TOUCH_RELEASED || | 488 if (event.type() == ui::ET_TOUCH_RELEASED || |
| 481 event.type() == ui::ET_TOUCH_CANCELLED) | 489 event.type() == ui::ET_TOUCH_CANCELLED) |
| 482 AppendEndGestureEvent(point, gestures.get()); | 490 AppendEndGestureEvent(point, gestures.get()); |
| 483 | 491 |
| 484 if (state_ != last_state) | 492 if (state_ != last_state) |
| 485 DVLOG(4) << "Gesture Sequence" | 493 DVLOG(4) << "Gesture Sequence" |
| 486 << " State: " << state_ | 494 << " State: " << state_ |
| (...skipping 14 matching lines...) Expand all Loading... |
| 501 iter_point.set_point_id(iter_point.point_id() - 1); | 509 iter_point.set_point_id(iter_point.point_id() - 1); |
| 502 } | 510 } |
| 503 | 511 |
| 504 point.Reset(); | 512 point.Reset(); |
| 505 --point_count_; | 513 --point_count_; |
| 506 CHECK_GE(point_count_, 0); | 514 CHECK_GE(point_count_, 0); |
| 507 RecreateBoundingBox(); | 515 RecreateBoundingBox(); |
| 508 if (state_ == GS_PINCH) { | 516 if (state_ == GS_PINCH) { |
| 509 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); | 517 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); |
| 510 pinch_distance_start_ = pinch_distance_current_; | 518 pinch_distance_start_ = pinch_distance_current_; |
| 519 bounding_box_diagonal_angle_ = BoundingBoxDiagonalAngle(bounding_box_); |
| 511 } | 520 } |
| 512 } | 521 } |
| 513 return gestures.release(); | 522 return gestures.release(); |
| 514 } | 523 } |
| 515 | 524 |
| 516 void GestureSequence::RecreateBoundingBox() { | 525 void GestureSequence::RecreateBoundingBox() { |
| 517 // TODO(sad): Recreating the bounding box at every touch-event is not very | 526 // TODO(sad): Recreating the bounding box at every touch-event is not very |
| 518 // efficient. This should be made better. | 527 // efficient. This should be made better. |
| 519 int left = INT_MAX, top = INT_MAX, right = INT_MIN, bottom = INT_MIN; | 528 int left = INT_MAX, top = INT_MAX, right = INT_MIN, bottom = INT_MIN; |
| 520 for (int i = 0; i < kMaxGesturePoints; ++i) { | 529 for (int i = 0; i < kMaxGesturePoints; ++i) { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 gestures->push_back(CreateGestureEvent( | 754 gestures->push_back(CreateGestureEvent( |
| 746 GestureEventDetails(ui::ET_GESTURE_PINCH_END, 0, 0), | 755 GestureEventDetails(ui::ET_GESTURE_PINCH_END, 0, 0), |
| 747 center, | 756 center, |
| 748 flags_, | 757 flags_, |
| 749 base::Time::FromDoubleT(p1.last_touch_time()), | 758 base::Time::FromDoubleT(p1.last_touch_time()), |
| 750 1 << p1.touch_id() | 1 << p2.touch_id())); | 759 1 << p1.touch_id() | 1 << p2.touch_id())); |
| 751 } | 760 } |
| 752 | 761 |
| 753 void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, | 762 void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, |
| 754 float scale, | 763 float scale, |
| 764 float rotation, |
| 755 Gestures* gestures) { | 765 Gestures* gestures) { |
| 756 // TODO(sad): Compute rotation and include it in delta_y. | 766 // TODO(sad): Compute rotation and include it in delta_y. |
| 757 // http://crbug.com/113145 | 767 // http://crbug.com/113145 |
| 758 gestures->push_back(CreateGestureEvent( | 768 gestures->push_back(CreateGestureEvent( |
| 759 GestureEventDetails(ui::ET_GESTURE_PINCH_UPDATE, scale, 0), | 769 GestureEventDetails(ui::ET_GESTURE_PINCH_UPDATE, scale, rotation), |
| 760 bounding_box_.CenterPoint(), | 770 bounding_box_.CenterPoint(), |
| 761 flags_, | 771 flags_, |
| 762 base::Time::FromDoubleT(point.last_touch_time()), | 772 base::Time::FromDoubleT(point.last_touch_time()), |
| 763 ComputeTouchBitmask(points_))); | 773 ComputeTouchBitmask(points_))); |
| 764 } | 774 } |
| 765 | 775 |
| 766 void GestureSequence::AppendSwipeGesture(const GesturePoint& point, | 776 void GestureSequence::AppendSwipeGesture(const GesturePoint& point, |
| 767 int swipe_x, | 777 int swipe_x, |
| 768 int swipe_y, | 778 int swipe_y, |
| 769 Gestures* gestures) { | 779 Gestures* gestures) { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 state_ == GS_PENDING_TWO_FINGER_TAP); | 935 state_ == GS_PENDING_TWO_FINGER_TAP); |
| 926 | 936 |
| 927 // Once pinch starts, we immediately break rail scroll. | 937 // Once pinch starts, we immediately break rail scroll. |
| 928 scroll_type_ = ST_FREE; | 938 scroll_type_ = ST_FREE; |
| 929 | 939 |
| 930 const GesturePoint* point1 = GetPointByPointId(0); | 940 const GesturePoint* point1 = GetPointByPointId(0); |
| 931 const GesturePoint* point2 = GetPointByPointId(1); | 941 const GesturePoint* point2 = GetPointByPointId(1); |
| 932 | 942 |
| 933 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); | 943 pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); |
| 934 pinch_distance_start_ = pinch_distance_current_; | 944 pinch_distance_start_ = pinch_distance_current_; |
| 945 bounding_box_diagonal_angle_ = BoundingBoxDiagonalAngle(bounding_box_); |
| 946 |
| 935 AppendPinchGestureBegin(*point1, *point2, gestures); | 947 AppendPinchGestureBegin(*point1, *point2, gestures); |
| 936 | 948 |
| 937 if (state_ == GS_PENDING_SYNTHETIC_CLICK || | 949 if (state_ == GS_PENDING_SYNTHETIC_CLICK || |
| 938 state_ == GS_PENDING_TWO_FINGER_TAP) { | 950 state_ == GS_PENDING_TWO_FINGER_TAP) { |
| 939 gfx::Point center = bounding_box_.CenterPoint(); | 951 gfx::Point center = bounding_box_.CenterPoint(); |
| 940 AppendScrollGestureBegin(point, center, gestures); | 952 AppendScrollGestureBegin(point, center, gestures); |
| 941 } | 953 } |
| 942 | 954 |
| 943 return true; | 955 return true; |
| 944 } | 956 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 961 break; | 973 break; |
| 962 } | 974 } |
| 963 | 975 |
| 964 if (!did_scroll) | 976 if (!did_scroll) |
| 965 return false; | 977 return false; |
| 966 | 978 |
| 967 float distance = BoundingBoxDiagonal(bounding_box_); | 979 float distance = BoundingBoxDiagonal(bounding_box_); |
| 968 | 980 |
| 969 if (abs(distance - pinch_distance_current_) >= | 981 if (abs(distance - pinch_distance_current_) >= |
| 970 GestureConfiguration::min_pinch_update_distance_in_pixels()) { | 982 GestureConfiguration::min_pinch_update_distance_in_pixels()) { |
| 971 AppendPinchGestureUpdate(point, | 983 float scale = distance / pinch_distance_current_; |
| 972 distance / pinch_distance_current_, gestures); | 984 float angle = bounding_box_diagonal_angle_; |
| 985 // Compute rotation only if the the bounding box remained of roughly the |
| 986 // same size. |
| 987 if (fabs(1.f - scale) < 0.15f) |
| 988 angle = BoundingBoxDiagonalAngle(bounding_box_); |
| 989 else |
| 990 LOG(ERROR) << "Scale: " << scale; |
| 991 AppendPinchGestureUpdate(point, scale, angle - bounding_box_diagonal_angle_, |
| 992 gestures); |
| 973 pinch_distance_current_ = distance; | 993 pinch_distance_current_ = distance; |
| 994 bounding_box_diagonal_angle_ = angle; |
| 974 } else { | 995 } else { |
| 975 gfx::Point center = bounding_box_.CenterPoint(); | 996 gfx::Point center = bounding_box_.CenterPoint(); |
| 976 AppendScrollGestureUpdate(point, center, gestures); | 997 AppendScrollGestureUpdate(point, center, gestures); |
| 977 } | 998 } |
| 978 | 999 |
| 979 return true; | 1000 return true; |
| 980 } | 1001 } |
| 981 | 1002 |
| 982 bool GestureSequence::PinchEnd(const TouchEvent& event, | 1003 bool GestureSequence::PinchEnd(const TouchEvent& event, |
| 983 const GesturePoint& point, | 1004 const GesturePoint& point, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 return; | 1090 return; |
| 1070 | 1091 |
| 1071 // Since long press timer has been started, there should be a non-NULL point. | 1092 // Since long press timer has been started, there should be a non-NULL point. |
| 1072 const GesturePoint* point = GetPointByPointId(0); | 1093 const GesturePoint* point = GetPointByPointId(0); |
| 1073 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), | 1094 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), |
| 1074 event.location())) | 1095 event.location())) |
| 1075 long_press_timer_->Stop(); | 1096 long_press_timer_->Stop(); |
| 1076 } | 1097 } |
| 1077 | 1098 |
| 1078 } // namespace ui | 1099 } // namespace ui |
| OLD | NEW |