Chromium Code Reviews| 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()); | |
| 264 ScrollEnd(event, point, gestures.get()); | |
| 265 three_finger_swipe_has_fired_ = false; | |
| 266 set_state(GS_THREE_FINGER_SWIPE); | |
| 267 break; | |
| 268 case GST_THREE_FINGER_SWIPE_FIRST_RELEASED: | |
| 269 case GST_THREE_FINGER_SWIPE_SECOND_RELEASED: | |
| 270 case GST_THREE_FINGER_SWIPE_THIRD_RELEASED: | |
| 271 case GST_THREE_FINGER_SWIPE_FIRST_CANCELLED: | |
| 272 case GST_THREE_FINGER_SWIPE_SECOND_CANCELLED: | |
| 273 case GST_THREE_FINGER_SWIPE_THIRD_CANCELLED: | |
| 274 PinchStart(event, point, gestures.get()); | |
| 275 ScrollStart(event, point, gestures.get()); | |
| 
 
sadrul
2012/04/11 19:07:26
Do we want ScrollStart here? It might be better to
 
tdresser
2012/04/12 13:36:16
It's clearer what's happening if the scroll begin
 
sadrul
2012/04/13 11:34:20
Since PinchStart already appends scroll-start for
 
tdresser
2012/04/16 14:09:24
You're right, there's no reason to call pinch/scro
 
 | |
| 276 set_state(GS_PINCH); | |
| 277 break; | |
| 278 case GST_THREE_FINGER_SWIPE_FIRST_MOVED: | |
| 279 case GST_THREE_FINGER_SWIPE_SECOND_MOVED: | |
| 280 case GST_THREE_FINGER_SWIPE_THIRD_MOVED: | |
| 281 if (!three_finger_swipe_has_fired_) { | |
| 282 ThreeFingerSwipeUpdate(event, point, gestures.get()); | |
| 283 GetPointByPointId(0)->UpdateForScroll(); | |
| 284 GetPointByPointId(1)->UpdateForScroll(); | |
| 285 GetPointByPointId(2)->UpdateForScroll(); | |
| 286 } | |
| 287 break; | |
| 230 } | 288 } | 
| 231 | 289 | 
| 232 if (state_ != last_state) | 290 if (state_ != last_state) | 
| 233 VLOG(4) << "Gesture Sequence" | 291 VLOG(4) << "Gesture Sequence" | 
| 234 << " State: " << state_ | 292 << " State: " << state_ | 
| 235 << " touch id: " << event.GetTouchId(); | 293 << " touch id: " << event.GetTouchId(); | 
| 236 | 294 | 
| 237 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) | 295 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) | 
| 238 long_press_timer_->Stop(); | 296 long_press_timer_->Stop(); | 
| 239 | 297 | 
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 // http://crbug.com/113145 | 460 // http://crbug.com/113145 | 
| 403 gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); | 461 gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); | 
| 404 gestures->push_back((helper_->CreateGestureEvent( | 462 gestures->push_back((helper_->CreateGestureEvent( | 
| 405 ui::ET_GESTURE_PINCH_UPDATE, | 463 ui::ET_GESTURE_PINCH_UPDATE, | 
| 406 center, | 464 center, | 
| 407 flags_, | 465 flags_, | 
| 408 base::Time::FromDoubleT(p1.last_touch_time()), | 466 base::Time::FromDoubleT(p1.last_touch_time()), | 
| 409 scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id()))); | 467 scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id()))); | 
| 410 } | 468 } | 
| 411 | 469 | 
| 470 void GestureSequence::AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, | |
| 471 const GesturePoint& p2, | |
| 472 const GesturePoint& p3, | |
| 473 float x_velocity, | |
| 474 float y_velocity, | |
| 475 Gestures* gestures) { | |
| 476 int x = ( | |
| 477 p1.last_touch_position().x() + | |
| 478 p2.last_touch_position().x() + | |
| 479 p3.last_touch_position().x()) / 3; | |
| 480 int y = ( | |
| 481 p1.last_touch_position().y() + | |
| 482 p2.last_touch_position().y() + | |
| 483 p3.last_touch_position().y()) / 3; | |
| 484 gfx::Point center(x, y); | |
| 485 gestures->push_back(helper_->CreateGestureEvent( | |
| 486 ui::ET_GESTURE_THREE_FINGER_SWIPE, | |
| 487 center, | |
| 488 flags_, | |
| 489 base::Time::FromDoubleT(p1.last_touch_time()), | |
| 490 x_velocity, y_velocity, | |
| 491 1 << p1.touch_id() | 1 << p2.touch_id() | 1 << p3.touch_id())); | |
| 492 } | |
| 493 | |
| 412 bool GestureSequence::Click(const TouchEvent& event, | 494 bool GestureSequence::Click(const TouchEvent& event, | 
| 413 const GesturePoint& point, Gestures* gestures) { | 495 const GesturePoint& point, Gestures* gestures) { | 
| 414 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 496 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 
| 415 if (point.IsInClickWindow(event)) { | 497 if (point.IsInClickWindow(event)) { | 
| 416 AppendClickGestureEvent(point, gestures); | 498 AppendClickGestureEvent(point, gestures); | 
| 417 if (point.IsInDoubleClickWindow(event)) | 499 if (point.IsInDoubleClickWindow(event)) | 
| 418 AppendDoubleClickGestureEvent(point, gestures); | 500 AppendDoubleClickGestureEvent(point, gestures); | 
| 419 return true; | 501 return true; | 
| 420 } | 502 } | 
| 421 return false; | 503 return false; | 
| 422 } | 504 } | 
| 423 | 505 | 
| 424 bool GestureSequence::ScrollStart(const TouchEvent& event, | 506 bool GestureSequence::ScrollStart(const TouchEvent& event, | 
| 425 GesturePoint& point, Gestures* gestures) { | 507 GesturePoint& point, Gestures* gestures) { | 
| 426 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 508 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || | 
| 427 if (point.IsInClickWindow(event) || | 509 state_ == GS_THREE_FINGER_SWIPE); | 
| 428 !point.IsInScrollWindow(event) || | 510 if (state_ == GS_PENDING_SYNTHETIC_CLICK && | 
| 429 !point.HasEnoughDataToEstablishRail()) | 511 (point.IsInClickWindow(event) || | 
| 512 !point.IsInScrollWindow(event) || | |
| 513 !point.HasEnoughDataToEstablishRail())) | |
| 430 return false; | 514 return false; | 
| 431 AppendScrollGestureBegin(point, point.first_touch_position(), gestures); | 515 AppendScrollGestureBegin(point, point.first_touch_position(), gestures); | 
| 432 if (point.IsInHorizontalRailWindow()) | 516 if (point.IsInHorizontalRailWindow()) | 
| 433 scroll_type_ = ST_HORIZONTAL; | 517 scroll_type_ = ST_HORIZONTAL; | 
| 434 else if (point.IsInVerticalRailWindow()) | 518 else if (point.IsInVerticalRailWindow()) | 
| 435 scroll_type_ = ST_VERTICAL; | 519 scroll_type_ = ST_VERTICAL; | 
| 436 else | 520 else | 
| 437 scroll_type_ = ST_FREE; | 521 scroll_type_ = ST_FREE; | 
| 438 return true; | 522 return true; | 
| 439 } | 523 } | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 ui::ET_GESTURE_LONG_PRESS, | 567 ui::ET_GESTURE_LONG_PRESS, | 
| 484 point->first_touch_position(), | 568 point->first_touch_position(), | 
| 485 flags_, | 569 flags_, | 
| 486 base::Time::FromDoubleT(point->last_touch_time()), | 570 base::Time::FromDoubleT(point->last_touch_time()), | 
| 487 point->point_id(), 0.f, 1 << point->touch_id())); | 571 point->point_id(), 0.f, 1 << point->touch_id())); | 
| 488 helper_->DispatchLongPressGestureEvent(gesture.get()); | 572 helper_->DispatchLongPressGestureEvent(gesture.get()); | 
| 489 } | 573 } | 
| 490 | 574 | 
| 491 bool GestureSequence::ScrollEnd(const TouchEvent& event, | 575 bool GestureSequence::ScrollEnd(const TouchEvent& event, | 
| 492 GesturePoint& point, Gestures* gestures) { | 576 GesturePoint& point, Gestures* gestures) { | 
| 493 DCHECK(state_ == GS_SCROLL); | 577 DCHECK(state_ == GS_SCROLL || state_ == GS_PINCH); | 
| 494 if (point.IsInFlickWindow(event)) { | 578 if (point.IsInFlickWindow(event)) { | 
| 495 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 579 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 
| 496 point.XVelocity(), point.YVelocity()); | 580 point.XVelocity(), point.YVelocity()); | 
| 497 } else { | 581 } else { | 
| 498 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 582 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 
| 499 0.f, 0.f); | 583 0.f, 0.f); | 
| 500 } | 584 } | 
| 501 return true; | 585 return true; | 
| 502 } | 586 } | 
| 503 | 587 | 
| 504 bool GestureSequence::PinchStart(const TouchEvent& event, | 588 bool GestureSequence::PinchStart(const TouchEvent& event, | 
| 505 const GesturePoint& point, Gestures* gestures) { | 589 const GesturePoint& point, Gestures* gestures) { | 
| 506 DCHECK(state_ == GS_SCROLL || | 590 DCHECK(state_ == GS_SCROLL || | 
| 507 state_ == GS_PENDING_SYNTHETIC_CLICK); | 591 state_ == GS_PENDING_SYNTHETIC_CLICK || | 
| 592 state_ == GS_THREE_FINGER_SWIPE); | |
| 508 AppendTapDownGestureEvent(point, gestures); | 593 AppendTapDownGestureEvent(point, gestures); | 
| 509 | 594 | 
| 510 const GesturePoint* point1 = GetPointByPointId(0); | 595 const GesturePoint* point1 = GetPointByPointId(0); | 
| 511 const GesturePoint* point2 = GetPointByPointId(1); | 596 const GesturePoint* point2 = GetPointByPointId(1); | 
| 512 | 597 | 
| 513 pinch_distance_current_ = point1->Distance(*point2); | 598 pinch_distance_current_ = point1->Distance(*point2); | 
| 514 pinch_distance_start_ = pinch_distance_current_; | 599 pinch_distance_start_ = pinch_distance_current_; | 
| 515 AppendPinchGestureBegin(*point1, *point2, gestures); | 600 AppendPinchGestureBegin(*point1, *point2, gestures); | 
| 516 | 601 | 
| 517 if (state_ == GS_PENDING_SYNTHETIC_CLICK) { | 602 if (state_ == GS_PENDING_SYNTHETIC_CLICK) { | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 | 647 | 
| 563 float distance = point1->Distance(*point2); | 648 float distance = point1->Distance(*point2); | 
| 564 AppendPinchGestureEnd(*point1, *point2, | 649 AppendPinchGestureEnd(*point1, *point2, | 
| 565 distance / pinch_distance_start_, gestures); | 650 distance / pinch_distance_start_, gestures); | 
| 566 | 651 | 
| 567 pinch_distance_start_ = 0; | 652 pinch_distance_start_ = 0; | 
| 568 pinch_distance_current_ = 0; | 653 pinch_distance_current_ = 0; | 
| 569 return true; | 654 return true; | 
| 570 } | 655 } | 
| 571 | 656 | 
| 657 bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, | |
| 658 const GesturePoint& point, Gestures* gestures) { | |
| 659 DCHECK(state_ == GS_THREE_FINGER_SWIPE); | |
| 660 | |
| 661 GesturePoint* point1 = GetPointByPointId(0); | |
| 662 GesturePoint* point2 = GetPointByPointId(1); | |
| 663 GesturePoint* point3 = GetPointByPointId(2); | |
| 664 | |
| 665 int min_velocity = GestureConfiguration::min_swipe_speed(); | |
| 666 | |
| 667 float vx1 = point1->XVelocity(); | |
| 668 float vx2 = point2->XVelocity(); | |
| 669 float vx3 = point3->XVelocity(); | |
| 670 float vy1 = point1->YVelocity(); | |
| 671 float vy2 = point2->YVelocity(); | |
| 672 float vy3 = point3->YVelocity(); | |
| 673 | |
| 674 float vx = (vx1 + vx2 + vx3) / 3; | |
| 675 float vy = (vy1 + vy2 + vy3) / 3; | |
| 676 | |
| 677 // Not moving fast enough | |
| 678 if (fabs(vx) < min_velocity && fabs(vy) < min_velocity) | |
| 679 return false; | |
| 680 | |
| 681 // Diagonal swipe, no event fired | |
| 682 // TODO(tdresser|sadrul): consider adding diagonal swipes | |
| 683 float ratio = fabs(vx) > fabs(vy) ? fabs(vx / vy) : fabs(vy / vx); | |
| 684 if (ratio < GestureConfiguration::max_swipe_deviation_ratio()) | |
| 685 return false; | |
| 686 | |
| 687 if (fabs(vx) > fabs(vy)) { | |
| 688 int sign = vx > 0 ? 1 : -1; | |
| 689 // ensure all touches are moving in the same direction, and are | |
| 690 // all moving faster than min_velocity. | |
| 691 if (vx1 * sign < min_velocity || | |
| 692 vx2 * sign < min_velocity || | |
| 693 vx3 * sign < min_velocity) | |
| 694 return false; | |
| 695 AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, | |
| 696 sign, 0, gestures); | |
| 697 } else { | |
| 698 int sign = vy > 0 ? 1 : -1; | |
| 699 // ensure all touches are moving in the same direction, and are | |
| 700 // all moving faster than min_velocity. | |
| 701 if (vy1 * sign < min_velocity || | |
| 702 vy2 * sign < min_velocity || | |
| 703 vy3 * sign < min_velocity) | |
| 704 return false; | |
| 705 AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, | |
| 706 0, sign, gestures); | |
| 707 } | |
| 708 three_finger_swipe_has_fired_ = true; | |
| 709 return true; | |
| 710 } | |
| 711 | |
| 572 } // namespace ui | 712 } // namespace ui | 
| OLD | NEW |