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

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/third_party/GestureDetector.java

Issue 141533006: [Android] Move the java content/ package to content_public/ to start the split. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Small fixes and findbugs line update Created 6 years, 11 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // This is a copy of Android GestureDetector.java from AOSP 4.2. We include it in Chromium in order
18 // to have JB-style behavior on ICS devices. Some edits for NDK v16 compliance were needed; they're
19 // noted explicitly below.
20
21 // New imports in Chromium for NDK compliance.
22 package org.chromium.content.browser.third_party;
23 import android.view.MotionEvent;
24 import android.view.VelocityTracker;
25 import android.view.ViewConfiguration;
26
27 /* Commented out in Chromium for NDK compliance
28 package android.view;
29 */
30
31 import android.content.Context;
32 import android.os.Build;
33 import android.os.Handler;
34 import android.os.Message;
35
36 /**
37 * Detects various gestures and events using the supplied {@link MotionEvent}s.
38 * The {@link OnGestureListener} callback will notify users when a particular
39 * motion event has occurred. This class should only be used with {@link MotionE vent}s
40 * reported via touch (don't use for trackball events).
41 *
42 * To use this class:
43 * <ul>
44 * <li>Create an instance of the {@code GestureDetector} for your {@link View}
45 * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
46 * {@link #onTouchEvent(MotionEvent)}. The methods defined in your call back
47 * will be executed when the events occur.
48 * </ul>
49 */
50 public class GestureDetector {
51 /**
52 * The listener that is used to notify when gestures occur.
53 * If you want to listen for all the different gestures then implement
54 * this interface. If you only want to listen for a subset it might
55 * be easier to extend {@link SimpleOnGestureListener}.
56 */
57 public interface OnGestureListener {
58
59 /**
60 * Notified when a tap occurs with the down {@link MotionEvent}
61 * that triggered it. This will be triggered immediately for
62 * every down event. All other events should be preceded by this.
63 *
64 * @param e The down motion event.
65 */
66 boolean onDown(MotionEvent e);
67
68 /**
69 * The user has performed a down {@link MotionEvent} and not performed
70 * a move or up yet. This event is commonly used to provide visual
71 * feedback to the user to let them know that their action has been
72 * recognized i.e. highlight an element.
73 *
74 * @param e The down motion event
75 */
76 void onShowPress(MotionEvent e);
77
78 /**
79 * Notified when a tap occurs with the up {@link MotionEvent}
80 * that triggered it.
81 *
82 * @param e The up motion event that completed the first tap
83 * @return true if the event is consumed, else false
84 */
85 boolean onSingleTapUp(MotionEvent e);
86
87 /**
88 * Notified when a scroll occurs with the initial on down {@link MotionE vent} and the
89 * current move {@link MotionEvent}. The distance in x and y is also sup plied for
90 * convenience.
91 *
92 * @param e1 The first down motion event that started the scrolling.
93 * @param e2 The move motion event that triggered the current onScroll.
94 * @param distanceX The distance along the X axis that has been scrolled since the last
95 * call to onScroll. This is NOT the distance between {@cod e e1}
96 * and {@code e2}.
97 * @param distanceY The distance along the Y axis that has been scrolled since the last
98 * call to onScroll. This is NOT the distance between {@cod e e1}
99 * and {@code e2}.
100 * @return true if the event is consumed, else false
101 */
102 boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
103
104 /**
105 * Notified when a long press occurs with the initial on down {@link Mot ionEvent}
106 * that trigged it.
107 *
108 * @param e The initial on down motion event that started the longpress.
109 */
110 void onLongPress(MotionEvent e);
111
112 /**
113 * Notified of a fling event when it occurs with the initial on down {@l ink MotionEvent}
114 * and the matching up {@link MotionEvent}. The calculated velocity is s upplied along
115 * the x and y axis in pixels per second.
116 *
117 * @param e1 The first down motion event that started the fling.
118 * @param e2 The move motion event that triggered the current onFling.
119 * @param velocityX The velocity of this fling measured in pixels per se cond
120 * along the x axis.
121 * @param velocityY The velocity of this fling measured in pixels per se cond
122 * along the y axis.
123 * @return true if the event is consumed, else false
124 */
125 boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float v elocityY);
126 }
127
128 /**
129 * The listener that is used to notify when a double-tap or a confirmed
130 * single-tap occur.
131 */
132 public interface OnDoubleTapListener {
133 /**
134 * Notified when a single-tap occurs.
135 * <p>
136 * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
137 * will only be called after the detector is confident that the user's
138 * first tap is not followed by a second tap leading to a double-tap
139 * gesture.
140 *
141 * @param e The down motion event of the single-tap.
142 * @return true if the event is consumed, else false
143 */
144 boolean onSingleTapConfirmed(MotionEvent e);
145
146 /**
147 * Notified when a double-tap occurs.
148 *
149 * @param e The down motion event of the first tap of the double-tap.
150 * @return true if the event is consumed, else false
151 */
152 boolean onDoubleTap(MotionEvent e);
153
154 /**
155 * Notified when an event within a double-tap gesture occurs, including
156 * the down, move, and up events.
157 *
158 * @param e The motion event that occurred during the double-tap gesture .
159 * @return true if the event is consumed, else false
160 */
161 boolean onDoubleTapEvent(MotionEvent e);
162 }
163
164 /**
165 * A convenience class to extend when you only want to listen for a subset
166 * of all the gestures. This implements all methods in the
167 * {@link OnGestureListener} and {@link OnDoubleTapListener} but does
168 * nothing and return {@code false} for all applicable methods.
169 */
170 public static class SimpleOnGestureListener implements OnGestureListener, On DoubleTapListener {
171 public boolean onSingleTapUp(MotionEvent e) {
172 return false;
173 }
174
175 public void onLongPress(MotionEvent e) {
176 }
177
178 public boolean onScroll(MotionEvent e1, MotionEvent e2,
179 float distanceX, float distanceY) {
180 return false;
181 }
182
183 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
184 float velocityY) {
185 return false;
186 }
187
188 public void onShowPress(MotionEvent e) {
189 }
190
191 public boolean onDown(MotionEvent e) {
192 return false;
193 }
194
195 public boolean onDoubleTap(MotionEvent e) {
196 return false;
197 }
198
199 public boolean onDoubleTapEvent(MotionEvent e) {
200 return false;
201 }
202
203 public boolean onSingleTapConfirmed(MotionEvent e) {
204 return false;
205 }
206 }
207
208 private int mTouchSlopSquare;
209 private int mDoubleTapTouchSlopSquare;
210 private int mDoubleTapSlopSquare;
211 private int mMinimumFlingVelocity;
212 private int mMaximumFlingVelocity;
213
214 private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressT imeout();
215 private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
216 private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTap Timeout();
217
218 // constants for Message.what used by GestureHandler below
219 private static final int SHOW_PRESS = 1;
220 private static final int LONG_PRESS = 2;
221 private static final int TAP = 3;
222
223 private final Handler mHandler;
224 private final OnGestureListener mListener;
225 private OnDoubleTapListener mDoubleTapListener;
226
227 private boolean mStillDown;
228 private boolean mDeferConfirmSingleTap;
229 private boolean mInLongPress;
230 private boolean mAlwaysInTapRegion;
231 private boolean mAlwaysInBiggerTapRegion;
232
233 private MotionEvent mCurrentDownEvent;
234 private MotionEvent mPreviousUpEvent;
235
236 /**
237 * True when the user is still touching for the second tap (down, move, and
238 * up events). Can only be true if there is a double tap listener attached.
239 */
240 private boolean mIsDoubleTapping;
241
242 private float mLastFocusX;
243 private float mLastFocusY;
244 private float mDownFocusX;
245 private float mDownFocusY;
246
247 private boolean mIsLongpressEnabled;
248
249 /**
250 * Determines speed during touch scrolling
251 */
252 private VelocityTracker mVelocityTracker;
253
254 /**
255 * Consistency verifier for debugging purposes.
256 */
257 /* Commented out in Chromium for NDK compliance
258 private final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
259 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
260 new InputEventConsistencyVerifier(this, 0) : null;
261 */
262
263 private class GestureHandler extends Handler {
264 GestureHandler() {
265 super();
266 }
267
268 GestureHandler(Handler handler) {
269 super(handler.getLooper());
270 }
271
272 @Override
273 public void handleMessage(Message msg) {
274 switch (msg.what) {
275 case SHOW_PRESS:
276 mListener.onShowPress(mCurrentDownEvent);
277 break;
278
279 case LONG_PRESS:
280 dispatchLongPress();
281 break;
282
283 case TAP:
284 // If the user's finger is still down, do not count it as a tap
285 if (mDoubleTapListener != null) {
286 if (!mStillDown) {
287 mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEven t);
288 } else {
289 mDeferConfirmSingleTap = true;
290 }
291 }
292 break;
293
294 default:
295 throw new RuntimeException("Unknown message " + msg); //never
296 }
297 }
298 }
299
300 /**
301 * Creates a GestureDetector with the supplied listener.
302 * This variant of the constructor should be used from a non-UI thread
303 * (as it allows specifying the Handler).
304 *
305 * @param listener the listener invoked for all the callbacks, this must
306 * not be null.
307 * @param handler the handler to use
308 *
309 * @throws NullPointerException if either {@code listener} or
310 * {@code handler} is null.
311 *
312 * @deprecated Use {@link #GestureDetector(android.content.Context,
313 * android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead.
314 */
315 @Deprecated
316 public GestureDetector(OnGestureListener listener, Handler handler) {
317 this(null, listener, handler);
318 }
319
320 /**
321 * Creates a GestureDetector with the supplied listener.
322 * You may only use this constructor from a UI thread (this is the usual sit uation).
323 * @see android.os.Handler#Handler()
324 *
325 * @param listener the listener invoked for all the callbacks, this must
326 * not be null.
327 *
328 * @throws NullPointerException if {@code listener} is null.
329 *
330 * @deprecated Use {@link #GestureDetector(android.content.Context,
331 * android.view.GestureDetector.OnGestureListener)} instead.
332 */
333 @Deprecated
334 public GestureDetector(OnGestureListener listener) {
335 this(null, listener, null);
336 }
337
338 /**
339 * Creates a GestureDetector with the supplied listener.
340 * You may only use this constructor from a UI thread (this is the usual sit uation).
341 * @see android.os.Handler#Handler()
342 *
343 * @param context the application's context
344 * @param listener the listener invoked for all the callbacks, this must
345 * not be null.
346 *
347 * @throws NullPointerException if {@code listener} is null.
348 */
349 public GestureDetector(Context context, OnGestureListener listener) {
350 this(context, listener, null);
351 }
352
353 /**
354 * Creates a GestureDetector with the supplied listener.
355 * You may only use this constructor from a UI thread (this is the usual sit uation).
356 * @see android.os.Handler#Handler()
357 *
358 * @param context the application's context
359 * @param listener the listener invoked for all the callbacks, this must
360 * not be null.
361 * @param handler the handler to use
362 *
363 * @throws NullPointerException if {@code listener} is null.
364 */
365 public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
366 if (handler != null) {
367 mHandler = new GestureHandler(handler);
368 } else {
369 mHandler = new GestureHandler();
370 }
371 mListener = listener;
372 if (listener instanceof OnDoubleTapListener) {
373 setOnDoubleTapListener((OnDoubleTapListener) listener);
374 }
375 init(context);
376 }
377
378 /**
379 * Creates a GestureDetector with the supplied listener.
380 * You may only use this constructor from a UI thread (this is the usual sit uation).
381 * @see android.os.Handler#Handler()
382 *
383 * @param context the application's context
384 * @param listener the listener invoked for all the callbacks, this must
385 * not be null.
386 * @param handler the handler to use
387 *
388 * @throws NullPointerException if {@code listener} is null.
389 */
390 public GestureDetector(Context context, OnGestureListener listener, Handler handler,
391 boolean unused) {
392 this(context, listener, handler);
393 }
394
395 private void init(Context context) {
396 if (mListener == null) {
397 throw new NullPointerException("OnGestureListener must not be null") ;
398 }
399 mIsLongpressEnabled = true;
400
401 // Fallback to support pre-donuts releases
402 int touchSlop, doubleTapSlop, doubleTapTouchSlop;
403 /* Commented out in Chromium for NDK compliance
404 if (context == null) {
405 //noinspection deprecation
406 touchSlop = ViewConfiguration.getTouchSlop();
407 doubleTapTouchSlop = touchSlop; // Hack rather than adding a hiden m ethod for this
408 doubleTapSlop = ViewConfiguration.getDoubleTapSlop();
409 //noinspection deprecation
410 mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity();
411 mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity();
412 } else */ {
413 final ViewConfiguration configuration = ViewConfiguration.get(contex t);
414 touchSlop = configuration.getScaledTouchSlop();
415 /* Commented out in Chromium for NDK compliance and replaced with the following line. Note that
416 * ViewConfiguration.TOUCH_SLOP has the same value as DOUBLE_TAP_TOUCH_SLOP in current Android, so
417 * this doesn't introduce a behavior difference in Android versions <= 4.2.
418 doubleTapTouchSlop = configuration.getScaledDoubleTapTouchSlop();
419 */
420 doubleTapTouchSlop = touchSlop;
421 doubleTapSlop = configuration.getScaledDoubleTapSlop();
422 mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity( );
423 mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity( );
424 }
425 mTouchSlopSquare = touchSlop * touchSlop;
426 mDoubleTapTouchSlopSquare = doubleTapTouchSlop * doubleTapTouchSlop;
427 mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
428 }
429
430 /**
431 * Sets the listener which will be called for double-tap and related
432 * gestures.
433 *
434 * @param onDoubleTapListener the listener invoked for all the callbacks, or
435 * null to stop listening for double-tap gestures.
436 */
437 public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) {
438 mDoubleTapListener = onDoubleTapListener;
439 }
440
441 /**
442 * Set whether longpress is enabled, if this is enabled when a user
443 * presses and holds down you get a longpress event and nothing further.
444 * If it's disabled the user can press and hold down and then later
445 * moved their finger and you will get scroll events. By default
446 * longpress is enabled.
447 *
448 * @param isLongpressEnabled whether longpress should be enabled.
449 */
450 public void setIsLongpressEnabled(boolean isLongpressEnabled) {
451 mIsLongpressEnabled = isLongpressEnabled;
452 }
453
454 /**
455 * @return true if longpress is enabled, else false.
456 */
457 public boolean isLongpressEnabled() {
458 return mIsLongpressEnabled;
459 }
460
461 /**
462 * Analyzes the given motion event and if applicable triggers the
463 * appropriate callbacks on the {@link OnGestureListener} supplied.
464 *
465 * @param ev The current motion event.
466 * @return true if the {@link OnGestureListener} consumed the event,
467 * else false.
468 */
469 public boolean onTouchEvent(MotionEvent ev) {
470 /* Commented out in Chromium for NDK compliance
471 if (mInputEventConsistencyVerifier != null) {
472 mInputEventConsistencyVerifier.onTouchEvent(ev, 0);
473 }
474 */
475
476 final int action = ev.getAction();
477
478 if (mVelocityTracker == null) {
479 mVelocityTracker = VelocityTracker.obtain();
480 }
481 mVelocityTracker.addMovement(ev);
482
483 final boolean pointerUp =
484 (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER _UP;
485 final int skipIndex = pointerUp ? ev.getActionIndex() : -1;
486
487 // Determine focal point
488 float sumX = 0, sumY = 0;
489 final int count = ev.getPointerCount();
490 for (int i = 0; i < count; i++) {
491 if (skipIndex == i) continue;
492 sumX += ev.getX(i);
493 sumY += ev.getY(i);
494 }
495 final int div = pointerUp ? count - 1 : count;
496 final float focusX = sumX / div;
497 final float focusY = sumY / div;
498
499 boolean handled = false;
500
501 switch (action & MotionEvent.ACTION_MASK) {
502 case MotionEvent.ACTION_POINTER_DOWN:
503 mDownFocusX = mLastFocusX = focusX;
504 mDownFocusY = mLastFocusY = focusY;
505 // Cancel long press and taps
506 cancelTaps();
507 break;
508
509 case MotionEvent.ACTION_POINTER_UP:
510 mDownFocusX = mLastFocusX = focusX;
511 mDownFocusY = mLastFocusY = focusY;
512
513 // Check the dot product of current velocities.
514 // If the pointer that left was opposing another velocity vector, cl ear.
515 mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity) ;
516 final int upIndex = ev.getActionIndex();
517 final int id1 = ev.getPointerId(upIndex);
518 final float x1 = mVelocityTracker.getXVelocity(id1);
519 final float y1 = mVelocityTracker.getYVelocity(id1);
520 for (int i = 0; i < count; i++) {
521 if (i == upIndex) continue;
522
523 final int id2 = ev.getPointerId(i);
524 final float x = x1 * mVelocityTracker.getXVelocity(id2);
525 final float y = y1 * mVelocityTracker.getYVelocity(id2);
526
527 final float dot = x + y;
528 if (dot < 0) {
529 mVelocityTracker.clear();
530 break;
531 }
532 }
533 break;
534
535 case MotionEvent.ACTION_DOWN:
536 if (mDoubleTapListener != null) {
537 boolean hadTapMessage = mHandler.hasMessages(TAP);
538 if (hadTapMessage) mHandler.removeMessages(TAP);
539 if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
540 isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEven t, ev)) {
541 // This is a second tap
542 mIsDoubleTapping = true;
543 // Give a callback with the first tap of the double-tap
544 handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent) ;
545 // Give a callback with down event of the double-tap
546 handled |= mDoubleTapListener.onDoubleTapEvent(ev);
547 } else {
548 // This is a first tap
549 mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
550 }
551 }
552
553 mDownFocusX = mLastFocusX = focusX;
554 mDownFocusY = mLastFocusY = focusY;
555 if (mCurrentDownEvent != null) {
556 mCurrentDownEvent.recycle();
557 }
558 mCurrentDownEvent = MotionEvent.obtain(ev);
559 mAlwaysInTapRegion = true;
560 mAlwaysInBiggerTapRegion = true;
561 mStillDown = true;
562 mInLongPress = false;
563 mDeferConfirmSingleTap = false;
564
565 if (mIsLongpressEnabled) {
566 mHandler.removeMessages(LONG_PRESS);
567 mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.ge tDownTime()
568 + TAP_TIMEOUT + LONGPRESS_TIMEOUT);
569 }
570 mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDow nTime() + TAP_TIMEOUT);
571 handled |= mListener.onDown(ev);
572 break;
573
574 case MotionEvent.ACTION_MOVE:
575 if (mInLongPress) {
576 break;
577 }
578 final float scrollX = mLastFocusX - focusX;
579 final float scrollY = mLastFocusY - focusY;
580 if (mIsDoubleTapping) {
581 // Give the move events of the double-tap
582 handled |= mDoubleTapListener.onDoubleTapEvent(ev);
583 } else if (mAlwaysInTapRegion) {
584 final int deltaX = (int) (focusX - mDownFocusX);
585 final int deltaY = (int) (focusY - mDownFocusY);
586 int distance = (deltaX * deltaX) + (deltaY * deltaY);
587 if (distance > mTouchSlopSquare) {
588 handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
589 mLastFocusX = focusX;
590 mLastFocusY = focusY;
591 mAlwaysInTapRegion = false;
592 mHandler.removeMessages(TAP);
593 mHandler.removeMessages(SHOW_PRESS);
594 mHandler.removeMessages(LONG_PRESS);
595 }
596 if (distance > mDoubleTapTouchSlopSquare) {
597 mAlwaysInBiggerTapRegion = false;
598 }
599 } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
600 handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scr ollY);
601 mLastFocusX = focusX;
602 mLastFocusY = focusY;
603 }
604 break;
605
606 case MotionEvent.ACTION_UP:
607 mStillDown = false;
608 MotionEvent currentUpEvent = MotionEvent.obtain(ev);
609 if (mIsDoubleTapping) {
610 // Finally, give the up event of the double-tap
611 handled |= mDoubleTapListener.onDoubleTapEvent(ev);
612 } else if (mInLongPress) {
613 mHandler.removeMessages(TAP);
614 mInLongPress = false;
615 } else if (mAlwaysInTapRegion) {
616 handled = mListener.onSingleTapUp(ev);
617 if (mDeferConfirmSingleTap && mDoubleTapListener != null) {
618 mDoubleTapListener.onSingleTapConfirmed(ev);
619 }
620 } else {
621
622 // A fling must travel the minimum tap distance
623 final VelocityTracker velocityTracker = mVelocityTracker;
624 final int pointerId = ev.getPointerId(0);
625 velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVeloci ty);
626 final float velocityY = velocityTracker.getYVelocity(pointerId);
627 final float velocityX = velocityTracker.getXVelocity(pointerId);
628
629 if ((Math.abs(velocityY) > mMinimumFlingVelocity)
630 || (Math.abs(velocityX) > mMinimumFlingVelocity)){
631 handled = mListener.onFling(mCurrentDownEvent, ev, velocityX , velocityY);
632 }
633 }
634 if (mPreviousUpEvent != null) {
635 mPreviousUpEvent.recycle();
636 }
637 // Hold the event we obtained above - listeners may have changed the original.
638 mPreviousUpEvent = currentUpEvent;
639 if (mVelocityTracker != null) {
640 // This may have been cleared when we called out to the
641 // application above.
642 mVelocityTracker.recycle();
643 mVelocityTracker = null;
644 }
645 mIsDoubleTapping = false;
646 mDeferConfirmSingleTap = false;
647 mHandler.removeMessages(SHOW_PRESS);
648 mHandler.removeMessages(LONG_PRESS);
649 break;
650
651 case MotionEvent.ACTION_CANCEL:
652 cancel();
653 break;
654 }
655
656 /* Commented out in Chromium for NDK compliance
657 if (!handled && mInputEventConsistencyVerifier != null) {
658 mInputEventConsistencyVerifier.onUnhandledEvent(ev, 0);
659 }
660 */
661 return handled;
662 }
663
664 private void cancel() {
665 mHandler.removeMessages(SHOW_PRESS);
666 mHandler.removeMessages(LONG_PRESS);
667 mHandler.removeMessages(TAP);
668 mVelocityTracker.recycle();
669 mVelocityTracker = null;
670 mIsDoubleTapping = false;
671 mStillDown = false;
672 mAlwaysInTapRegion = false;
673 mAlwaysInBiggerTapRegion = false;
674 mDeferConfirmSingleTap = false;
675 if (mInLongPress) {
676 mInLongPress = false;
677 }
678 }
679
680 private void cancelTaps() {
681 mHandler.removeMessages(SHOW_PRESS);
682 mHandler.removeMessages(LONG_PRESS);
683 mHandler.removeMessages(TAP);
684 mIsDoubleTapping = false;
685 mAlwaysInTapRegion = false;
686 mAlwaysInBiggerTapRegion = false;
687 mDeferConfirmSingleTap = false;
688 if (mInLongPress) {
689 mInLongPress = false;
690 }
691 }
692
693 private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent fir stUp,
694 MotionEvent secondDown) {
695 if (!mAlwaysInBiggerTapRegion) {
696 return false;
697 }
698
699 if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIME OUT) {
700 return false;
701 }
702
703 int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
704 int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
705 return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
706 }
707
708 private void dispatchLongPress() {
709 mHandler.removeMessages(TAP);
710 mDeferConfirmSingleTap = false;
711 mInLongPress = true;
712 mListener.onLongPress(mCurrentDownEvent);
713 }
714 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698