Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: ui/base/gestures/gesture_sequence.cc

Issue 10037012: Three Finger Swipe (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address sadrul's comments. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698