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> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
9 #include "base/time.h" | 11 #include "base/time.h" |
10 #include "ui/base/events.h" | 12 #include "ui/base/events.h" |
11 #include "ui/base/gestures/gesture_configuration.h" | 13 #include "ui/base/gestures/gesture_configuration.h" |
12 | 14 |
13 namespace ui { | 15 namespace ui { |
14 | 16 |
15 namespace { | 17 namespace { |
16 | 18 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 G(GS_PINCH, 0, TS_RELEASED, false), | 97 G(GS_PINCH, 0, TS_RELEASED, false), |
96 | 98 |
97 GST_PINCH_SECOND_RELEASED = | 99 GST_PINCH_SECOND_RELEASED = |
98 G(GS_PINCH, 1, TS_RELEASED, false), | 100 G(GS_PINCH, 1, TS_RELEASED, false), |
99 | 101 |
100 GST_PINCH_FIRST_CANCELLED = | 102 GST_PINCH_FIRST_CANCELLED = |
101 G(GS_PINCH, 0, TS_CANCELLED, false), | 103 G(GS_PINCH, 0, TS_CANCELLED, false), |
102 | 104 |
103 GST_PINCH_SECOND_CANCELLED = | 105 GST_PINCH_SECOND_CANCELLED = |
104 G(GS_PINCH, 1, TS_CANCELLED, false), | 106 G(GS_PINCH, 1, TS_CANCELLED, false), |
| 107 |
| 108 GST_PINCH_THIRD_PRESSED = |
| 109 G(GS_PINCH, 2, TS_PRESSED, false), |
| 110 |
| 111 GST_THREE_FINGER_SWIPE_FIRST_RELEASED = |
| 112 G(GS_THREE_FINGER_SWIPE, 0, TS_RELEASED, false), |
| 113 |
| 114 GST_THREE_FINGER_SWIPE_SECOND_RELEASED = |
| 115 G(GS_THREE_FINGER_SWIPE, 1, TS_RELEASED, false), |
| 116 |
| 117 GST_THREE_FINGER_SWIPE_THIRD_RELEASED = |
| 118 G(GS_THREE_FINGER_SWIPE, 2, TS_RELEASED, false), |
| 119 |
| 120 GST_THREE_FINGER_SWIPE_FIRST_MOVED = |
| 121 G(GS_THREE_FINGER_SWIPE, 0, TS_MOVED, false), |
| 122 |
| 123 GST_THREE_FINGER_SWIPE_SECOND_MOVED = |
| 124 G(GS_THREE_FINGER_SWIPE, 1, TS_MOVED, false), |
| 125 |
| 126 GST_THREE_FINGER_SWIPE_THIRD_MOVED = |
| 127 G(GS_THREE_FINGER_SWIPE, 2, TS_MOVED, false), |
| 128 |
| 129 GST_THREE_FINGER_SWIPE_FIRST_CANCELLED = |
| 130 G(GS_THREE_FINGER_SWIPE, 0, TS_CANCELLED, false), |
| 131 |
| 132 GST_THREE_FINGER_SWIPE_SECOND_CANCELLED = |
| 133 G(GS_THREE_FINGER_SWIPE, 1, TS_CANCELLED, false), |
| 134 |
| 135 GST_THREE_FINGER_SWIPE_THIRD_CANCELLED = |
| 136 G(GS_THREE_FINGER_SWIPE, 2, TS_CANCELLED, false), |
105 }; | 137 }; |
106 | 138 |
107 // Builds a signature. Signatures are assembled by joining together | 139 // Builds a signature. Signatures are assembled by joining together |
108 // multiple bits. | 140 // multiple bits. |
109 // 1 LSB bit so that the computed signature is always greater than 0 | 141 // 1 LSB bit so that the computed signature is always greater than 0 |
110 // 3 bits for the |type|. | 142 // 3 bits for the |type|. |
111 // 1 bit for |touch_handled| | 143 // 1 bit for |touch_handled| |
112 // 12 bits for |touch_id| | 144 // 12 bits for |touch_id| |
113 // 15 bits for the |gesture_state|. | 145 // 15 bits for the |gesture_state|. |
114 EdgeStateSignatureType Signature(GestureState gesture_state, | 146 EdgeStateSignatureType Signature(GestureState gesture_state, |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 case GST_PINCH_SECOND_RELEASED: | 252 case GST_PINCH_SECOND_RELEASED: |
221 case GST_PINCH_FIRST_CANCELLED: | 253 case GST_PINCH_FIRST_CANCELLED: |
222 case GST_PINCH_SECOND_CANCELLED: | 254 case GST_PINCH_SECOND_CANCELLED: |
223 PinchEnd(event, point, gestures.get()); | 255 PinchEnd(event, point, gestures.get()); |
224 | 256 |
225 // Once pinch ends, it should still be possible to scroll with the | 257 // Once pinch ends, it should still be possible to scroll with the |
226 // remaining finger on the screen. | 258 // remaining finger on the screen. |
227 scroll_type_ = ST_FREE; | 259 scroll_type_ = ST_FREE; |
228 set_state(GS_SCROLL); | 260 set_state(GS_SCROLL); |
229 break; | 261 break; |
| 262 case GST_PINCH_THIRD_PRESSED: |
| 263 three_finger_swipe_has_fired_ = false; |
| 264 set_state(GS_THREE_FINGER_SWIPE); |
| 265 break; |
| 266 case GST_THREE_FINGER_SWIPE_FIRST_RELEASED: |
| 267 case GST_THREE_FINGER_SWIPE_SECOND_RELEASED: |
| 268 case GST_THREE_FINGER_SWIPE_THIRD_RELEASED: |
| 269 case GST_THREE_FINGER_SWIPE_FIRST_CANCELLED: |
| 270 case GST_THREE_FINGER_SWIPE_SECOND_CANCELLED: |
| 271 case GST_THREE_FINGER_SWIPE_THIRD_CANCELLED: |
| 272 set_state(GS_PINCH); |
| 273 break; |
| 274 case GST_THREE_FINGER_SWIPE_FIRST_MOVED: |
| 275 case GST_THREE_FINGER_SWIPE_SECOND_MOVED: |
| 276 case GST_THREE_FINGER_SWIPE_THIRD_MOVED: |
| 277 if (!three_finger_swipe_has_fired_) { |
| 278 ThreeFingerSwipeUpdate(event, point, gestures.get()); |
| 279 GetPointByPointId(0)->UpdateForScroll(); |
| 280 GetPointByPointId(1)->UpdateForScroll(); |
| 281 GetPointByPointId(2)->UpdateForScroll(); |
| 282 } |
| 283 break; |
230 } | 284 } |
231 | 285 |
232 if (state_ != last_state) | 286 if (state_ != last_state) |
233 VLOG(4) << "Gesture Sequence" | 287 VLOG(4) << "Gesture Sequence" |
234 << " State: " << state_ | 288 << " State: " << state_ |
235 << " touch id: " << event.GetTouchId(); | 289 << " touch id: " << event.GetTouchId(); |
236 | 290 |
237 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) | 291 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) |
238 long_press_timer_->Stop(); | 292 long_press_timer_->Stop(); |
239 | 293 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 // http://crbug.com/113145 | 456 // http://crbug.com/113145 |
403 gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); | 457 gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); |
404 gestures->push_back((helper_->CreateGestureEvent( | 458 gestures->push_back((helper_->CreateGestureEvent( |
405 ui::ET_GESTURE_PINCH_UPDATE, | 459 ui::ET_GESTURE_PINCH_UPDATE, |
406 center, | 460 center, |
407 flags_, | 461 flags_, |
408 base::Time::FromDoubleT(p1.last_touch_time()), | 462 base::Time::FromDoubleT(p1.last_touch_time()), |
409 scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id()))); | 463 scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id()))); |
410 } | 464 } |
411 | 465 |
| 466 void GestureSequence::AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, |
| 467 const GesturePoint& p2, |
| 468 const GesturePoint& p3, |
| 469 float x_velocity, |
| 470 float y_velocity, |
| 471 Gestures* gestures) { |
| 472 int x = ( |
| 473 p1.last_touch_position().x() + |
| 474 p2.last_touch_position().x() + |
| 475 p3.last_touch_position().x()) / 3; |
| 476 int y = ( |
| 477 p1.last_touch_position().y() + |
| 478 p2.last_touch_position().y() + |
| 479 p3.last_touch_position().y()) / 3; |
| 480 gfx::Point center(x, y); |
| 481 gestures->push_back(helper_->CreateGestureEvent( |
| 482 ui::ET_GESTURE_THREE_FINGER_SWIPE, |
| 483 center, |
| 484 flags_, |
| 485 base::Time::FromDoubleT(p1.last_touch_time()), |
| 486 x_velocity, y_velocity, |
| 487 1 << p1.touch_id() | 1 << p2.touch_id() | 1 << p3.touch_id())); |
| 488 } |
| 489 |
412 bool GestureSequence::Click(const TouchEvent& event, | 490 bool GestureSequence::Click(const TouchEvent& event, |
413 const GesturePoint& point, Gestures* gestures) { | 491 const GesturePoint& point, Gestures* gestures) { |
414 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 492 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); |
415 if (point.IsInClickWindow(event)) { | 493 if (point.IsInClickWindow(event)) { |
416 AppendClickGestureEvent(point, gestures); | 494 AppendClickGestureEvent(point, gestures); |
417 if (point.IsInDoubleClickWindow(event)) | 495 if (point.IsInDoubleClickWindow(event)) |
418 AppendDoubleClickGestureEvent(point, gestures); | 496 AppendDoubleClickGestureEvent(point, gestures); |
419 return true; | 497 return true; |
420 } | 498 } |
421 return false; | 499 return false; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 | 640 |
563 float distance = point1->Distance(*point2); | 641 float distance = point1->Distance(*point2); |
564 AppendPinchGestureEnd(*point1, *point2, | 642 AppendPinchGestureEnd(*point1, *point2, |
565 distance / pinch_distance_start_, gestures); | 643 distance / pinch_distance_start_, gestures); |
566 | 644 |
567 pinch_distance_start_ = 0; | 645 pinch_distance_start_ = 0; |
568 pinch_distance_current_ = 0; | 646 pinch_distance_current_ = 0; |
569 return true; | 647 return true; |
570 } | 648 } |
571 | 649 |
| 650 bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, |
| 651 const GesturePoint& point, Gestures* gestures) { |
| 652 DCHECK(state_ == GS_THREE_FINGER_SWIPE); |
| 653 |
| 654 GesturePoint* point1 = GetPointByPointId(0); |
| 655 GesturePoint* point2 = GetPointByPointId(1); |
| 656 GesturePoint* point3 = GetPointByPointId(2); |
| 657 |
| 658 int min_velocity = GestureConfiguration::min_swipe_speed(); |
| 659 |
| 660 float vx1 = point1->XVelocity(); |
| 661 float vx2 = point2->XVelocity(); |
| 662 float vx3 = point3->XVelocity(); |
| 663 float vy1 = point1->YVelocity(); |
| 664 float vy2 = point2->YVelocity(); |
| 665 float vy3 = point3->YVelocity(); |
| 666 |
| 667 float vx = (vx1 + vx2 + vx3) / 3; |
| 668 float vy = (vy1 + vy2 + vy3) / 3; |
| 669 |
| 670 // Not moving fast enough |
| 671 if (fabs(vx) < min_velocity && fabs(vy) < min_velocity) |
| 672 return false; |
| 673 |
| 674 // Diagonal swipe, no event fired |
| 675 // TODO(tdresser|sadrul): consider adding diagonal swipes |
| 676 float ratio = fabs(vx) > fabs(vy) ? fabs(vx / vy) : fabs(vy / vx); |
| 677 if (ratio < GestureConfiguration::max_swipe_deviation_ratio()) |
| 678 return false; |
| 679 |
| 680 if (fabs(vx) > fabs(vy)) { |
| 681 int sign = vx > 0 ? 1 : -1; |
| 682 // ensure all touches are moving in the same direction, and are |
| 683 // all moving faster than min_velocity. |
| 684 if (vx1 * sign < min_velocity || |
| 685 vx2 * sign < min_velocity || |
| 686 vx3 * sign < min_velocity) |
| 687 return false; |
| 688 AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, |
| 689 sign, 0, gestures); |
| 690 } else { |
| 691 int sign = vy > 0 ? 1 : -1; |
| 692 // ensure all touches are moving in the same direction, and are |
| 693 // all moving faster than min_velocity. |
| 694 if (vy1 * sign < min_velocity || |
| 695 vy2 * sign < min_velocity || |
| 696 vy3 * sign < min_velocity) |
| 697 return false; |
| 698 AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, |
| 699 0, sign, gestures); |
| 700 } |
| 701 three_finger_swipe_has_fired_ = true; |
| 702 return true; |
| 703 } |
| 704 |
572 } // namespace ui | 705 } // namespace ui |
OLD | NEW |