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 PinchEnd(event, point, gestures.get()); | |
sadrul
2012/04/10 20:32:51
Should there also be a ScrollEnd here?
tdresser
2012/04/11 18:17:04
And the related ScrollStart, when a finger from a
| |
264 three_finger_swipe_has_fired_ = false; | |
265 set_state(GS_THREE_FINGER_SWIPE); | |
266 break; | |
267 case GST_THREE_FINGER_SWIPE_FIRST_RELEASED: | |
268 case GST_THREE_FINGER_SWIPE_SECOND_RELEASED: | |
269 case GST_THREE_FINGER_SWIPE_THIRD_RELEASED: | |
270 case GST_THREE_FINGER_SWIPE_FIRST_CANCELLED: | |
271 case GST_THREE_FINGER_SWIPE_SECOND_CANCELLED: | |
272 case GST_THREE_FINGER_SWIPE_THIRD_CANCELLED: | |
273 PinchStart(event, point, gestures.get()); | |
274 set_state(GS_PINCH); | |
275 break; | |
276 case GST_THREE_FINGER_SWIPE_FIRST_MOVED: | |
277 case GST_THREE_FINGER_SWIPE_SECOND_MOVED: | |
278 case GST_THREE_FINGER_SWIPE_THIRD_MOVED: | |
279 if (!three_finger_swipe_has_fired_) { | |
280 ThreeFingerSwipeUpdate(event, point, gestures.get()); | |
281 GetPointByPointId(0)->UpdateForScroll(); | |
282 GetPointByPointId(1)->UpdateForScroll(); | |
283 GetPointByPointId(2)->UpdateForScroll(); | |
284 } | |
285 break; | |
230 } | 286 } |
231 | 287 |
232 if (state_ != last_state) | 288 if (state_ != last_state) |
233 VLOG(4) << "Gesture Sequence" | 289 VLOG(4) << "Gesture Sequence" |
234 << " State: " << state_ | 290 << " State: " << state_ |
235 << " touch id: " << event.GetTouchId(); | 291 << " touch id: " << event.GetTouchId(); |
236 | 292 |
237 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) | 293 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) |
238 long_press_timer_->Stop(); | 294 long_press_timer_->Stop(); |
239 | 295 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 // http://crbug.com/113145 | 458 // http://crbug.com/113145 |
403 gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); | 459 gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); |
404 gestures->push_back((helper_->CreateGestureEvent( | 460 gestures->push_back((helper_->CreateGestureEvent( |
405 ui::ET_GESTURE_PINCH_UPDATE, | 461 ui::ET_GESTURE_PINCH_UPDATE, |
406 center, | 462 center, |
407 flags_, | 463 flags_, |
408 base::Time::FromDoubleT(p1.last_touch_time()), | 464 base::Time::FromDoubleT(p1.last_touch_time()), |
409 scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id()))); | 465 scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id()))); |
410 } | 466 } |
411 | 467 |
468 void GestureSequence::AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, | |
469 const GesturePoint& p2, | |
470 const GesturePoint& p3, | |
471 float xVelocity, | |
472 float yVelocity, | |
473 Gestures* gestures) { | |
474 int x = ( | |
475 p1.last_touch_position().x() + | |
476 p2.last_touch_position().x() + | |
477 p3.last_touch_position().x()) / 3; | |
478 int y = ( | |
479 p1.last_touch_position().y() + | |
480 p2.last_touch_position().y() + | |
481 p3.last_touch_position().y()) / 3; | |
482 gfx::Point center(x, y); | |
483 gestures->push_back(helper_->CreateGestureEvent( | |
484 ui::ET_GESTURE_THREE_FINGER_SWIPE, | |
485 center, | |
486 flags_, | |
487 base::Time::FromDoubleT(p1.last_touch_time()), | |
488 xVelocity, yVelocity, | |
489 1 << p1.touch_id() | 1 << p2.touch_id() | 1 << p3.touch_id())); | |
490 } | |
491 | |
412 bool GestureSequence::Click(const TouchEvent& event, | 492 bool GestureSequence::Click(const TouchEvent& event, |
413 const GesturePoint& point, Gestures* gestures) { | 493 const GesturePoint& point, Gestures* gestures) { |
414 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 494 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); |
415 if (point.IsInClickWindow(event)) { | 495 if (point.IsInClickWindow(event)) { |
416 AppendClickGestureEvent(point, gestures); | 496 AppendClickGestureEvent(point, gestures); |
417 if (point.IsInDoubleClickWindow(event)) | 497 if (point.IsInDoubleClickWindow(event)) |
418 AppendDoubleClickGestureEvent(point, gestures); | 498 AppendDoubleClickGestureEvent(point, gestures); |
419 return true; | 499 return true; |
420 } | 500 } |
421 return false; | 501 return false; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
497 } else { | 577 } else { |
498 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 578 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, |
499 0.f, 0.f); | 579 0.f, 0.f); |
500 } | 580 } |
501 return true; | 581 return true; |
502 } | 582 } |
503 | 583 |
504 bool GestureSequence::PinchStart(const TouchEvent& event, | 584 bool GestureSequence::PinchStart(const TouchEvent& event, |
505 const GesturePoint& point, Gestures* gestures) { | 585 const GesturePoint& point, Gestures* gestures) { |
506 DCHECK(state_ == GS_SCROLL || | 586 DCHECK(state_ == GS_SCROLL || |
507 state_ == GS_PENDING_SYNTHETIC_CLICK); | 587 state_ == GS_PENDING_SYNTHETIC_CLICK || |
588 state_ == GS_THREE_FINGER_SWIPE); | |
508 AppendTapDownGestureEvent(point, gestures); | 589 AppendTapDownGestureEvent(point, gestures); |
509 | 590 |
510 const GesturePoint* point1 = GetPointByPointId(0); | 591 const GesturePoint* point1 = GetPointByPointId(0); |
511 const GesturePoint* point2 = GetPointByPointId(1); | 592 const GesturePoint* point2 = GetPointByPointId(1); |
512 | 593 |
513 pinch_distance_current_ = point1->Distance(*point2); | 594 pinch_distance_current_ = point1->Distance(*point2); |
514 pinch_distance_start_ = pinch_distance_current_; | 595 pinch_distance_start_ = pinch_distance_current_; |
515 AppendPinchGestureBegin(*point1, *point2, gestures); | 596 AppendPinchGestureBegin(*point1, *point2, gestures); |
516 | 597 |
517 if (state_ == GS_PENDING_SYNTHETIC_CLICK) { | 598 if (state_ == GS_PENDING_SYNTHETIC_CLICK) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 | 643 |
563 float distance = point1->Distance(*point2); | 644 float distance = point1->Distance(*point2); |
564 AppendPinchGestureEnd(*point1, *point2, | 645 AppendPinchGestureEnd(*point1, *point2, |
565 distance / pinch_distance_start_, gestures); | 646 distance / pinch_distance_start_, gestures); |
566 | 647 |
567 pinch_distance_start_ = 0; | 648 pinch_distance_start_ = 0; |
568 pinch_distance_current_ = 0; | 649 pinch_distance_current_ = 0; |
569 return true; | 650 return true; |
570 } | 651 } |
571 | 652 |
653 bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, | |
654 const GesturePoint& point, Gestures* gestures) { | |
655 DCHECK(state_ == GS_THREE_FINGER_SWIPE); | |
656 | |
657 GesturePoint* point1 = GetPointByPointId(0); | |
658 GesturePoint* point2 = GetPointByPointId(1); | |
659 GesturePoint* point3 = GetPointByPointId(2); | |
660 | |
661 int minVelocity = 20; | |
sadrul
2012/04/10 20:32:51
min_velocity
tdresser
2012/04/11 18:17:04
Done.
| |
662 | |
663 float vx1 = point1->XVelocity(); | |
664 float vx2 = point2->XVelocity(); | |
665 float vx3 = point3->XVelocity(); | |
666 float vy1 = point1->YVelocity(); | |
667 float vy2 = point2->YVelocity(); | |
668 float vy3 = point3->YVelocity(); | |
669 | |
sadrul
2012/04/10 20:32:51
I think we should check whether all points are mov
tdresser
2012/04/11 18:17:04
I feel like ensuring that the points are within a
| |
670 float vx = (vx1 + vx2 + vx3) / 3; | |
671 float vy = (vy1 + vy2 + vy3) / 3; | |
672 | |
673 // Not moving fast enough | |
674 if (fabs(vx) < minVelocity && fabs(vy) < minVelocity) | |
675 return true; | |
sadrul
2012/04/10 20:32:51
return false;
tdresser
2012/04/11 18:17:04
Done.
| |
676 | |
677 // Diagonal swipe, no event fired | |
678 if (fabs(vx) >= minVelocity && fabs(vy) >= minVelocity) { | |
679 float ratio = fabs(vx) > fabs(vy) ? fabs(vx / vy) : fabs(vy / vx); | |
680 if (ratio < 3) | |
681 return true; | |
sadrul
2012/04/10 20:32:51
return false;
Also, why this restriction?
tdresser
2012/04/11 18:17:04
Done.
Added TODO to consider diagonal swipes.
| |
682 } | |
683 | |
684 if (fabs(vx) > fabs(vy)) { | |
685 int sign = vx > 0 ? 1 : -1; | |
686 // ensure all touches are moving in the same direction, and are | |
687 // all moving faster than minVelocity. | |
688 if (vx1 * sign < minVelocity || | |
689 vx2 * sign < minVelocity || | |
690 vx3 * sign < minVelocity) | |
691 return true; | |
692 AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, | |
693 sign, 0, gestures); | |
694 three_finger_swipe_has_fired_ = true; | |
695 } else { | |
696 int sign = vy > 0 ? 1 : -1; | |
697 // ensure all touches are moving in the same direction, and are | |
698 // all moving faster than minVelocity. | |
699 if (vy1 * sign < minVelocity || | |
700 vy2 * sign < minVelocity || | |
701 vy3 * sign < minVelocity) | |
702 return true; | |
703 AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, | |
704 0, sign, gestures); | |
sadrul
2012/04/10 20:32:51
It looks like one of the velocities is always zero
tdresser
2012/04/11 18:17:04
This implementation currently assumes that we aren
| |
705 three_finger_swipe_has_fired_ = true; | |
706 } | |
707 return true; | |
708 } | |
709 | |
572 } // namespace ui | 710 } // namespace ui |
OLD | NEW |