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

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

Issue 9452024: Gestures are now possible using touch events with any ids (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Commented GetPointByPointId Created 8 years, 10 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/aura/gestures/gesture_sequence.h" 5 #include "ui/aura/gestures/gesture_sequence.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "ui/aura/event.h" 10 #include "ui/aura/event.h"
11 #include "ui/aura/root_window.h" 11 #include "ui/aura/root_window.h"
12 #include "ui/aura/gestures/gesture_configuration.h" 12 #include "ui/aura/gestures/gesture_configuration.h"
13 #include "ui/base/events.h" 13 #include "ui/base/events.h"
14 14
15 // TODO(sad): Pinch gestures currently always assume that the first two 15 // TODO(sad): Pinch gestures currently always assume that the first two
16 // touch-points (i.e. at indices 0 and 1) are involved. This may not 16 // touch-points (i.e. at indices 0 and 1) are involved. This may not
17 // always be the case. This needs to be fixed eventually. 17 // always be the case. This needs to be fixed eventually.
18 // http://crbug.com/113144 18 // http://crbug.com/113144
sadrul 2012/02/23 21:44:14 Remove this TODO too
tdresser 2012/02/23 22:16:55 Done.
19 19
20 namespace { 20 namespace {
21 21
22 // TODO(girard): Make these configurable in sync with this CL 22 // TODO(girard): Make these configurable in sync with this CL
23 // http://crbug.com/100773 23 // http://crbug.com/100773
24 const float kMinimumPinchUpdateDistance = 5; // in pixels 24 const float kMinimumPinchUpdateDistance = 5; // in pixels
25 const float kMinimumDistanceForPinchScroll = 20; 25 const float kMinimumDistanceForPinchScroll = 20;
26 const float kLongPressTimeInMilliseconds = 500; 26 const float kLongPressTimeInMilliseconds = 500;
27 27
28 } // namespace 28 } // namespace
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 GST_SCROLL_FIRST_RELEASED = 93 GST_SCROLL_FIRST_RELEASED =
94 G(GS_SCROLL, 0, TS_RELEASED, false), 94 G(GS_SCROLL, 0, TS_RELEASED, false),
95 95
96 GST_SCROLL_FIRST_MOVED = 96 GST_SCROLL_FIRST_MOVED =
97 G(GS_SCROLL, 0, TS_MOVED, false), 97 G(GS_SCROLL, 0, TS_MOVED, false),
98 98
99 GST_SCROLL_FIRST_CANCELLED = 99 GST_SCROLL_FIRST_CANCELLED =
100 G(GS_SCROLL, 0, TS_CANCELLED, false), 100 G(GS_SCROLL, 0, TS_CANCELLED, false),
101 101
102 GST_SCROLL_FIRST_PRESSED = 102 GST_SCROLL_FIRST_PRESSED =
103 G(GS_SCROLL, 0, TS_PRESSED, false), 103 G(GS_SCROLL, 0, TS_PRESSED, false),
sadrul 2012/02/23 21:44:14 I believe this should not be necessary anymore.
tdresser 2012/02/23 22:16:55 Done.
104 104
105 GST_SCROLL_SECOND_RELEASED = 105 GST_SCROLL_SECOND_RELEASED =
106 G(GS_SCROLL, 1, TS_RELEASED, false), 106 G(GS_SCROLL, 1, TS_RELEASED, false),
sadrul 2012/02/23 21:44:14 ditto
107 107
108 GST_SCROLL_SECOND_MOVED = 108 GST_SCROLL_SECOND_MOVED =
109 G(GS_SCROLL, 1, TS_MOVED, false), 109 G(GS_SCROLL, 1, TS_MOVED, false),
sadrul 2012/02/23 21:44:14 ditto
110 110
111 GST_SCROLL_SECOND_CANCELLED = 111 GST_SCROLL_SECOND_CANCELLED =
112 G(GS_SCROLL, 1, TS_CANCELLED, false), 112 G(GS_SCROLL, 1, TS_CANCELLED, false),
sadrul 2012/02/23 21:44:14 ditto
113 113
114 GST_SCROLL_SECOND_PRESSED = 114 GST_SCROLL_SECOND_PRESSED =
115 G(GS_SCROLL, 1, TS_PRESSED, false), 115 G(GS_SCROLL, 1, TS_PRESSED, false),
116 116
117 GST_PINCH_FIRST_MOVED = 117 GST_PINCH_FIRST_MOVED =
118 G(GS_PINCH, 0, TS_MOVED, false), 118 G(GS_PINCH, 0, TS_MOVED, false),
119 119
120 GST_PINCH_SECOND_MOVED = 120 GST_PINCH_SECOND_MOVED =
121 G(GS_PINCH, 1, TS_MOVED, false), 121 G(GS_PINCH, 1, TS_MOVED, false),
122 122
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 //////////////////////////////////////////////////////////////////////////////// 156 ////////////////////////////////////////////////////////////////////////////////
157 // GestureSequence Public: 157 // GestureSequence Public:
158 158
159 GestureSequence::GestureSequence() 159 GestureSequence::GestureSequence()
160 : state_(GS_NO_GESTURE), 160 : state_(GS_NO_GESTURE),
161 flags_(0), 161 flags_(0),
162 pinch_distance_start_(0.f), 162 pinch_distance_start_(0.f),
163 pinch_distance_current_(0.f), 163 pinch_distance_current_(0.f),
164 long_press_timer_(CreateTimer()), 164 long_press_timer_(CreateTimer()),
165 point_count_(0) { 165 point_count_(0) {
166 for (int i = 0; i < kMaxGesturePoints; ++i) {
167 points_[i].set_touch_id(i);
168 }
169 } 166 }
170 167
171 GestureSequence::~GestureSequence() { 168 GestureSequence::~GestureSequence() {
172 } 169 }
173 170
174 GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( 171 GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture(
175 const TouchEvent& event, 172 const TouchEvent& event,
176 ui::TouchStatus status) { 173 ui::TouchStatus status) {
177 if (status != ui::TOUCH_STATUS_UNKNOWN) 174 if (status != ui::TOUCH_STATUS_UNKNOWN)
178 return NULL; // The event was consumed by a touch sequence. 175 return NULL; // The event was consumed by a touch sequence.
179 176
180 // Set a limit on the number of simultaneous touches in a gesture. 177 // Set a limit on the number of simultaneous touches in a gesture.
181 if (event.touch_id() >= kMaxGesturePoints) 178 if (event.touch_id() >= kMaxGesturePoints)
182 return NULL; 179 return NULL;
183 180
184 if (event.type() == ui::ET_TOUCH_PRESSED) { 181 if (event.type() == ui::ET_TOUCH_PRESSED) {
185 if (point_count_ == kMaxGesturePoints) 182 if (point_count_ == kMaxGesturePoints)
186 return NULL; 183 return NULL;
187 ++point_count_; 184 GesturePoint* new_point = &points_[event.touch_id()];
185 // We shouldn't be able to get two PRESSED events, without a RELEASE
186 DCHECK(!points_[event.touch_id()].in_use());
187 new_point->set_point_id(point_count_++);
188 } else {
189 // Make sure the point we're modifying was PRESSED at some point in the past
190 DCHECK(points_[event.touch_id()].in_use());
188 } 191 }
189 192
190 GestureState last_state = state_; 193 GestureState last_state = state_;
191 194
192 // NOTE: when modifying these state transitions, also update gestures.dot 195 // NOTE: when modifying these state transitions, also update gestures.dot
193 scoped_ptr<Gestures> gestures(new Gestures()); 196 scoped_ptr<Gestures> gestures(new Gestures());
194 GesturePoint& point = GesturePointForEvent(event); 197 GesturePoint& point = GesturePointForEvent(event);
195 point.UpdateValues(event); 198 point.UpdateValues(event);
196 flags_ = event.flags(); 199 flags_ = event.flags();
197 switch (Signature(state_, event.touch_id(), event.type(), false)) { 200 const int point_id = points_[event.touch_id()].point_id();
201 switch (Signature(state_, point_id, event.type(), false)) {
198 case GST_NO_GESTURE_FIRST_PRESSED: 202 case GST_NO_GESTURE_FIRST_PRESSED:
199 TouchDown(event, point, gestures.get()); 203 TouchDown(event, point, gestures.get());
200 set_state(GS_PENDING_SYNTHETIC_CLICK); 204 set_state(GS_PENDING_SYNTHETIC_CLICK);
201 break; 205 break;
202 case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED: 206 case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED:
203 if (Click(event, point, gestures.get())) 207 if (Click(event, point, gestures.get()))
204 point.UpdateForTap(); 208 point.UpdateForTap();
205 set_state(GS_NO_GESTURE); 209 set_state(GS_NO_GESTURE);
206 break; 210 break;
207 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED: 211 case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED:
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } 261 }
258 262
259 if (state_ != last_state) 263 if (state_ != last_state)
260 VLOG(4) << "Gesture Sequence" 264 VLOG(4) << "Gesture Sequence"
261 << " State: " << state_ 265 << " State: " << state_
262 << " touch id: " << event.touch_id(); 266 << " touch id: " << event.touch_id();
263 267
264 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) 268 if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state)
265 long_press_timer_->Stop(); 269 long_press_timer_->Stop();
266 270
267 if (event.type() == ui::ET_TOUCH_RELEASED) 271 // The set of point_ids must be contiguous and include 0.
272 // When a touch point is released, all points with ids greater than the
273 // released point must have their ids decremented, or the set of point_ids
274 // could end up with gaps.
275 if (event.type() == ui::ET_TOUCH_RELEASED) {
276 GesturePoint& old_point = points_[event.touch_id()];
277 for (int i = 0; i < kMaxGesturePoints; ++i) {
278 GesturePoint& point = points_[i];
279 if (point.point_id() > old_point.point_id())
280 point.set_point_id(point.point_id() - 1);
281 }
282 old_point.Reset();
268 --point_count_; 283 --point_count_;
284 }
269 285
270 return gestures.release(); 286 return gestures.release();
271 } 287 }
272 288
273 void GestureSequence::Reset() { 289 void GestureSequence::Reset() {
274 set_state(GS_NO_GESTURE); 290 set_state(GS_NO_GESTURE);
275 for (int i = 0; i < point_count_; ++i) 291 for (int i = 0; i < kMaxGesturePoints; ++i)
276 points_[i].Reset(); 292 points_[i].Reset();
277 } 293 }
278 294
279 //////////////////////////////////////////////////////////////////////////////// 295 ////////////////////////////////////////////////////////////////////////////////
280 // GestureSequence Protected: 296 // GestureSequence Protected:
281 297
282 base::OneShotTimer<GestureSequence>* GestureSequence::CreateTimer() { 298 base::OneShotTimer<GestureSequence>* GestureSequence::CreateTimer() {
283 return new base::OneShotTimer<GestureSequence>(); 299 return new base::OneShotTimer<GestureSequence>();
284 } 300 }
285 301
286 //////////////////////////////////////////////////////////////////////////////// 302 ////////////////////////////////////////////////////////////////////////////////
287 // GestureSequence Private: 303 // GestureSequence Private:
288 304
289 GesturePoint& GestureSequence::GesturePointForEvent( 305 GesturePoint& GestureSequence::GesturePointForEvent(
290 const TouchEvent& event) { 306 const TouchEvent& event) {
291 return points_[event.touch_id()]; 307 return points_[event.touch_id()];
292 } 308 }
293 309
310 GesturePoint* GestureSequence::GetPointByPointId(int point_id) {
311 DCHECK(0 <= point_id && point_id < kMaxGesturePoints);
312 for (int i = 0; i < kMaxGesturePoints; ++i) {
313 GesturePoint& point = points_[i];
314 if (point.in_use() && point.point_id() == point_id)
315 return &point;
316 }
317 DCHECK(false);
sadrul 2012/02/23 21:44:14 NOTREACHED
tdresser 2012/02/23 22:16:55 Done.
318 return NULL;
319 }
320
294 void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, 321 void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point,
295 Gestures* gestures) { 322 Gestures* gestures) {
296 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent( 323 gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent(
297 ui::ET_GESTURE_TAP_DOWN, 324 ui::ET_GESTURE_TAP_DOWN,
298 point.first_touch_position().x(), 325 point.first_touch_position().x(),
299 point.first_touch_position().y(), 326 point.first_touch_position().y(),
300 flags_, 327 flags_,
301 base::Time::FromDoubleT(point.last_touch_time()), 328 base::Time::FromDoubleT(point.last_touch_time()),
302 0.f, 0.f))); 329 0.f, 0.f)));
303 } 330 }
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 AppendTapDownGestureEvent(point, gestures); 501 AppendTapDownGestureEvent(point, gestures);
475 long_press_timer_->Start( 502 long_press_timer_->Start(
476 FROM_HERE, 503 FROM_HERE,
477 base::TimeDelta::FromMilliseconds(kLongPressTimeInMilliseconds), 504 base::TimeDelta::FromMilliseconds(kLongPressTimeInMilliseconds),
478 this, 505 this,
479 &GestureSequence::AppendLongPressGestureEvent); 506 &GestureSequence::AppendLongPressGestureEvent);
480 return true; 507 return true;
481 } 508 }
482 509
483 void GestureSequence::AppendLongPressGestureEvent() { 510 void GestureSequence::AppendLongPressGestureEvent() {
484 // TODO(tdresser) - this may not always be the first point 511 const GesturePoint* point = GetPointByPointId(0);
485 const GesturePoint& point = points_[0]; 512 DCHECK(point);
486 GestureEvent* gesture = new GestureEvent( 513 GestureEvent* gesture = new GestureEvent(
487 ui::ET_GESTURE_LONG_PRESS, 514 ui::ET_GESTURE_LONG_PRESS,
488 point.first_touch_position().x(), 515 point->first_touch_position().x(),
489 point.first_touch_position().y(), 516 point->first_touch_position().y(),
490 flags_, 517 flags_,
491 base::Time::FromDoubleT(point.last_touch_time()), 518 base::Time::FromDoubleT(point->last_touch_time()),
492 point.touch_id(), 0.f); 519 point->point_id(), 0.f);
493
494 RootWindow::GetInstance()->DispatchGestureEvent(gesture); 520 RootWindow::GetInstance()->DispatchGestureEvent(gesture);
495 } 521 }
496 522
497 bool GestureSequence::ScrollEnd(const TouchEvent& event, 523 bool GestureSequence::ScrollEnd(const TouchEvent& event,
498 GesturePoint& point, Gestures* gestures) { 524 GesturePoint& point, Gestures* gestures) {
499 DCHECK(state_ == GS_SCROLL); 525 DCHECK(state_ == GS_SCROLL);
500 if (point.IsInFlickWindow(event)) { 526 if (point.IsInFlickWindow(event)) {
501 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, 527 AppendScrollGestureEnd(point, point.last_touch_position(), gestures,
502 point.XVelocity(), point.YVelocity()); 528 point.XVelocity(), point.YVelocity());
503 } else { 529 } else {
504 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, 530 AppendScrollGestureEnd(point, point.last_touch_position(), gestures,
505 0.f, 0.f); 531 0.f, 0.f);
506 } 532 }
507 return true; 533 return true;
508 } 534 }
509 535
510 bool GestureSequence::PinchStart(const TouchEvent& event, 536 bool GestureSequence::PinchStart(const TouchEvent& event,
511 const GesturePoint& point, Gestures* gestures) { 537 const GesturePoint& point, Gestures* gestures) {
512 DCHECK(state_ == GS_SCROLL || 538 DCHECK(state_ == GS_SCROLL ||
513 state_ == GS_PENDING_SYNTHETIC_CLICK); 539 state_ == GS_PENDING_SYNTHETIC_CLICK);
514 AppendTapDownGestureEvent(point, gestures); 540 AppendTapDownGestureEvent(point, gestures);
515 541
516 pinch_distance_current_ = points_[0].Distance(points_[1]); 542 const GesturePoint* point1 = GetPointByPointId(0);
543 const GesturePoint* point2 = GetPointByPointId(1);
544
545 pinch_distance_current_ = point1->Distance(*point2);
517 pinch_distance_start_ = pinch_distance_current_; 546 pinch_distance_start_ = pinch_distance_current_;
518 AppendPinchGestureBegin(points_[0], points_[1], gestures); 547 AppendPinchGestureBegin(*point1, *point2, gestures);
519 548
520 if (state_ == GS_PENDING_SYNTHETIC_CLICK) { 549 if (state_ == GS_PENDING_SYNTHETIC_CLICK) {
521 gfx::Point center = points_[0].last_touch_position().Middle( 550 gfx::Point center = point1->last_touch_position().Middle(
522 points_[1].last_touch_position()); 551 point2->last_touch_position());
523 AppendScrollGestureBegin(point, center, gestures); 552 AppendScrollGestureBegin(point, center, gestures);
524 } 553 }
525 554
526 return true; 555 return true;
527 } 556 }
528 557
529 bool GestureSequence::PinchUpdate(const TouchEvent& event, 558 bool GestureSequence::PinchUpdate(const TouchEvent& event,
530 const GesturePoint& point, Gestures* gestures) { 559 const GesturePoint& point, Gestures* gestures) {
531 DCHECK(state_ == GS_PINCH); 560 DCHECK(state_ == GS_PINCH);
532 float distance = points_[0].Distance(points_[1]); 561
562 const GesturePoint* point1 = GetPointByPointId(0);
563 const GesturePoint* point2 = GetPointByPointId(1);
564
565 float distance = point1->Distance(*point2);
533 if (abs(distance - pinch_distance_current_) < 566 if (abs(distance - pinch_distance_current_) <
534 GestureConfiguration::minimum_pinch_update_distance_in_pixels()) { 567 GestureConfiguration::minimum_pinch_update_distance_in_pixels()) {
535 // The fingers didn't move towards each other, or away from each other, 568 // The fingers didn't move towards each other, or away from each other,
536 // enough to constitute a pinch. But perhaps they moved enough in the same 569 // enough to constitute a pinch. But perhaps they moved enough in the same
537 // direction to do a two-finger scroll. 570 // direction to do a two-finger scroll.
538 if (!points_[0].DidScroll(event, 571 if (!point1->DidScroll(event,
539 GestureConfiguration::minimum_distance_for_pinch_scroll_in_pixels()) || 572 GestureConfiguration::minimum_distance_for_pinch_scroll_in_pixels()) ||
540 !points_[1].DidScroll(event, 573 !point2->DidScroll(event,
541 GestureConfiguration::minimum_distance_for_pinch_scroll_in_pixels())) 574 GestureConfiguration::minimum_distance_for_pinch_scroll_in_pixels()))
542 return false; 575 return false;
543 576
544 gfx::Point center = points_[0].last_touch_position().Middle( 577 gfx::Point center = point1->last_touch_position().Middle(
545 points_[1].last_touch_position()); 578 point2->last_touch_position());
546 AppendScrollGestureUpdate(point, center, gestures); 579 AppendScrollGestureUpdate(point, center, gestures);
547 } else { 580 } else {
548 AppendPinchGestureUpdate(points_[0], points_[1], 581 AppendPinchGestureUpdate(*point1, *point2,
549 distance / pinch_distance_current_, gestures); 582 distance / pinch_distance_current_, gestures);
550 pinch_distance_current_ = distance; 583 pinch_distance_current_ = distance;
551 } 584 }
552 return true; 585 return true;
553 } 586 }
554 587
555 bool GestureSequence::PinchEnd(const TouchEvent& event, 588 bool GestureSequence::PinchEnd(const TouchEvent& event,
556 const GesturePoint& point, Gestures* gestures) { 589 const GesturePoint& point, Gestures* gestures) {
557 DCHECK(state_ == GS_PINCH); 590 DCHECK(state_ == GS_PINCH);
558 float distance = points_[0].Distance(points_[1]); 591
559 AppendPinchGestureEnd(points_[0], points_[1], 592 const GesturePoint* point1 = GetPointByPointId(0);
593 const GesturePoint* point2 = GetPointByPointId(1);
594
595 float distance = point1->Distance(*point2);
596 AppendPinchGestureEnd(*point1, *point2,
560 distance / pinch_distance_start_, gestures); 597 distance / pinch_distance_start_, gestures);
561 598
562 pinch_distance_start_ = 0; 599 pinch_distance_start_ = 0;
563 pinch_distance_current_ = 0; 600 pinch_distance_current_ = 0;
564 return true; 601 return true;
565 } 602 }
566 603
567 } // namespace aura 604 } // namespace aura
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698