SystemGesturesPointerEventListener.java revision 994652991b5e3b5f85540af6aeb04609401509ed
157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock/* 257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * Copyright (C) 2013 The Android Open Source Project 357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * 457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * you may not use this file except in compliance with the License. 657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * You may obtain a copy of the License at 757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * 857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * http://www.apache.org/licenses/LICENSE-2.0 957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * 1057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * Unless required by applicable law or agreed to in writing, software 1157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 1257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * See the License for the specific language governing permissions and 1457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * limitations under the License. 1557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock */ 1657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 17b10e33ff804a831c71be9303146cea892b9aeb5dJorim Jaggipackage com.android.server.policy; 1857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 1957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlockimport android.content.Context; 20a4d22d718affbc7145d1012157feb819557b5c06Michael Wrightimport android.os.Handler; 21a4d22d718affbc7145d1012157feb819557b5c06Michael Wrightimport android.os.Looper; 22a4d22d718affbc7145d1012157feb819557b5c06Michael Wrightimport android.os.SystemClock; 2357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlockimport android.util.Slog; 24a4d22d718affbc7145d1012157feb819557b5c06Michael Wrightimport android.view.GestureDetector; 25994652991b5e3b5f85540af6aeb04609401509edJun Mukaiimport android.view.InputDevice; 2657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlockimport android.view.MotionEvent; 27037aa8d434984840691378f3cc7d99d63dcc4076Craig Mautnerimport android.view.WindowManagerPolicy.PointerEventListener; 28a4d22d718affbc7145d1012157feb819557b5c06Michael Wrightimport android.widget.OverScroller; 2957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 3057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock/* 3157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * Listens for system-wide input gestures, firing callbacks when detected. 3257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock * @hide 3357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock */ 34037aa8d434984840691378f3cc7d99d63dcc4076Craig Mautnerpublic class SystemGesturesPointerEventListener implements PointerEventListener { 3557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private static final String TAG = "SystemGestures"; 3657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private static final boolean DEBUG = false; 3757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private static final long SWIPE_TIMEOUT_MS = 500; 3857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private static final int MAX_TRACKED_POINTERS = 32; // max per input system 3957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private static final int UNTRACKED_POINTER = -1; 40a4d22d718affbc7145d1012157feb819557b5c06Michael Wright private static final int MAX_FLING_TIME_MILLIS = 5000; 4157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 42ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private static final int SWIPE_NONE = 0; 43ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private static final int SWIPE_FROM_TOP = 1; 44ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private static final int SWIPE_FROM_BOTTOM = 2; 45ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private static final int SWIPE_FROM_RIGHT = 3; 46ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock 47a4d22d718affbc7145d1012157feb819557b5c06Michael Wright private final Context mContext; 4857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private final int mSwipeStartThreshold; 499ba21fdc9ddf1d132215d29054b55af416561367John Spurlock private final int mSwipeDistanceThreshold; 5057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private final Callbacks mCallbacks; 5157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private final int[] mDownPointerId = new int[MAX_TRACKED_POINTERS]; 52ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private final float[] mDownX = new float[MAX_TRACKED_POINTERS]; 5357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private final float[] mDownY = new float[MAX_TRACKED_POINTERS]; 5457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private final long[] mDownTime = new long[MAX_TRACKED_POINTERS]; 5557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 56a4d22d718affbc7145d1012157feb819557b5c06Michael Wright private GestureDetector mGestureDetector; 57a4d22d718affbc7145d1012157feb819557b5c06Michael Wright private OverScroller mOverscroller; 58a4d22d718affbc7145d1012157feb819557b5c06Michael Wright 59ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock int screenHeight; 60ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock int screenWidth; 6157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private int mDownPointers; 62ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private boolean mSwipeFireable; 63ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private boolean mDebugFireable; 64d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai private boolean mMouseHoveringAtEdge; 65a4d22d718affbc7145d1012157feb819557b5c06Michael Wright private long mLastFlingTime; 6657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 67037aa8d434984840691378f3cc7d99d63dcc4076Craig Mautner public SystemGesturesPointerEventListener(Context context, Callbacks callbacks) { 68a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mContext = context; 6957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock mCallbacks = checkNull("callbacks", callbacks); 7057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock mSwipeStartThreshold = checkNull("context", context).getResources() 7157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 729ba21fdc9ddf1d132215d29054b55af416561367John Spurlock mSwipeDistanceThreshold = mSwipeStartThreshold; 739ba21fdc9ddf1d132215d29054b55af416561367John Spurlock if (DEBUG) Slog.d(TAG, "mSwipeStartThreshold=" + mSwipeStartThreshold 749ba21fdc9ddf1d132215d29054b55af416561367John Spurlock + " mSwipeDistanceThreshold=" + mSwipeDistanceThreshold); 7557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 7657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 7757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private static <T> T checkNull(String name, T arg) { 7857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (arg == null) { 7957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock throw new IllegalArgumentException(name + " must not be null"); 8057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 8157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock return arg; 8257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 8357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 84a4d22d718affbc7145d1012157feb819557b5c06Michael Wright public void systemReady() { 85a4d22d718affbc7145d1012157feb819557b5c06Michael Wright Handler h = new Handler(Looper.myLooper()); 86a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), h); 87a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mOverscroller = new OverScroller(mContext); 88a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 89a4d22d718affbc7145d1012157feb819557b5c06Michael Wright 9057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock @Override 91037aa8d434984840691378f3cc7d99d63dcc4076Craig Mautner public void onPointerEvent(MotionEvent event) { 92a4d22d718affbc7145d1012157feb819557b5c06Michael Wright if (mGestureDetector != null) { 93a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mGestureDetector.onTouchEvent(event); 94a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 9557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock switch (event.getActionMasked()) { 9657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock case MotionEvent.ACTION_DOWN: 97ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mSwipeFireable = true; 98ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mDebugFireable = true; 9957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock mDownPointers = 0; 10057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock captureDown(event, 0); 101d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai if (mMouseHoveringAtEdge) { 102d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mMouseHoveringAtEdge = false; 103d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mCallbacks.onMouseLeaveFromEdge(); 104d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai } 1053595be4d19caaa7ddfbff0b979d135aaf5ac20b1Adrian Roos mCallbacks.onDown(); 10657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock break; 10757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock case MotionEvent.ACTION_POINTER_DOWN: 10857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock captureDown(event, event.getActionIndex()); 109ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (mDebugFireable) { 110ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mDebugFireable = event.getPointerCount() < 5; 111ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (!mDebugFireable) { 112ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (DEBUG) Slog.d(TAG, "Firing debug"); 113ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mCallbacks.onDebug(); 114ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } 115ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } 11657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock break; 11757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock case MotionEvent.ACTION_MOVE: 118ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (mSwipeFireable) { 119ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock final int swipe = detectSwipe(event); 120ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mSwipeFireable = swipe == SWIPE_NONE; 121ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (swipe == SWIPE_FROM_TOP) { 122ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop"); 123ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mCallbacks.onSwipeFromTop(); 124ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } else if (swipe == SWIPE_FROM_BOTTOM) { 125ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (DEBUG) Slog.d(TAG, "Firing onSwipeFromBottom"); 126ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mCallbacks.onSwipeFromBottom(); 127ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } else if (swipe == SWIPE_FROM_RIGHT) { 128ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight"); 129ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mCallbacks.onSwipeFromRight(); 130ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } 13157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 13257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock break; 133d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai case MotionEvent.ACTION_HOVER_MOVE: 134994652991b5e3b5f85540af6aeb04609401509edJun Mukai if (event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) { 135d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai if (!mMouseHoveringAtEdge && event.getY() == 0) { 136d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mCallbacks.onMouseHoverAtTop(); 137d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mMouseHoveringAtEdge = true; 138d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai } else if (!mMouseHoveringAtEdge && event.getY() >= screenHeight - 1) { 139d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mCallbacks.onMouseHoverAtBottom(); 140d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mMouseHoveringAtEdge = true; 141d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai } else if (mMouseHoveringAtEdge 142d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai && (event.getY() > 0 && event.getY() < screenHeight - 1)) { 143d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mCallbacks.onMouseLeaveFromEdge(); 144d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai mMouseHoveringAtEdge = false; 145d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai } 146d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai } 147d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai break; 14857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock case MotionEvent.ACTION_UP: 14957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock case MotionEvent.ACTION_CANCEL: 150ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mSwipeFireable = false; 151ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mDebugFireable = false; 1523595be4d19caaa7ddfbff0b979d135aaf5ac20b1Adrian Roos mCallbacks.onUpOrCancel(); 15357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock break; 15457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock default: 15557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (DEBUG) Slog.d(TAG, "Ignoring " + event); 15657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 15757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 15857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 15957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private void captureDown(MotionEvent event, int pointerIndex) { 16057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final int pointerId = event.getPointerId(pointerIndex); 16157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final int i = findIndex(pointerId); 16257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (DEBUG) Slog.d(TAG, "pointer " + pointerId + 16357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock " down pointerIndex=" + pointerIndex + " trackingIndex=" + i); 16457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (i != UNTRACKED_POINTER) { 165ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock mDownX[i] = event.getX(pointerIndex); 16657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock mDownY[i] = event.getY(pointerIndex); 16757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock mDownTime[i] = event.getEventTime(); 168ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (DEBUG) Slog.d(TAG, "pointer " + pointerId + 169ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock " down x=" + mDownX[i] + " y=" + mDownY[i]); 17057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 17157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 17257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 17357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock private int findIndex(int pointerId) { 17457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock for (int i = 0; i < mDownPointers; i++) { 17557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (mDownPointerId[i] == pointerId) { 17657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock return i; 17757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 17857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 17957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (mDownPointers == MAX_TRACKED_POINTERS || pointerId == MotionEvent.INVALID_POINTER_ID) { 18057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock return UNTRACKED_POINTER; 18157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 18257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock mDownPointerId[mDownPointers++] = pointerId; 18357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock return mDownPointers - 1; 18457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 18557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 186ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private int detectSwipe(MotionEvent move) { 18757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final int historySize = move.getHistorySize(); 18857306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final int pointerCount = move.getPointerCount(); 18957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock for (int p = 0; p < pointerCount; p++) { 19057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final int pointerId = move.getPointerId(p); 19157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final int i = findIndex(pointerId); 19257306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (i != UNTRACKED_POINTER) { 19357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock for (int h = 0; h < historySize; h++) { 19457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final long time = move.getHistoricalEventTime(h); 195ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock final float x = move.getHistoricalX(p, h); 19657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final float y = move.getHistoricalY(p, h); 197ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock final int swipe = detectSwipe(i, time, x, y); 198ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (swipe != SWIPE_NONE) { 199ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return swipe; 20057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 20157306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 202ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock final int swipe = detectSwipe(i, move.getEventTime(), move.getX(p), move.getY(p)); 203ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (swipe != SWIPE_NONE) { 204ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return swipe; 20557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 20657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 20757306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 208ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return SWIPE_NONE; 20957306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 21057306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 211ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock private int detectSwipe(int i, long time, float x, float y) { 212ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock final float fromX = mDownX[i]; 21357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final float fromY = mDownY[i]; 21457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock final long elapsed = time - mDownTime[i]; 21557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock if (DEBUG) Slog.d(TAG, "pointer " + mDownPointerId[i] 216ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock + " moved (" + fromX + "->" + x + "," + fromY + "->" + y + ") in " + elapsed); 217ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (fromY <= mSwipeStartThreshold 2189ba21fdc9ddf1d132215d29054b55af416561367John Spurlock && y > fromY + mSwipeDistanceThreshold 219ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock && elapsed < SWIPE_TIMEOUT_MS) { 220ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return SWIPE_FROM_TOP; 221ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } 222ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (fromY >= screenHeight - mSwipeStartThreshold 2239ba21fdc9ddf1d132215d29054b55af416561367John Spurlock && y < fromY - mSwipeDistanceThreshold 224ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock && elapsed < SWIPE_TIMEOUT_MS) { 225ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return SWIPE_FROM_BOTTOM; 226ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } 227ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock if (fromX >= screenWidth - mSwipeStartThreshold 2289ba21fdc9ddf1d132215d29054b55af416561367John Spurlock && x < fromX - mSwipeDistanceThreshold 229ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock && elapsed < SWIPE_TIMEOUT_MS) { 230ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return SWIPE_FROM_RIGHT; 231ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock } 232ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock return SWIPE_NONE; 23357306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 23457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock 235a4d22d718affbc7145d1012157feb819557b5c06Michael Wright private final class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener { 236a4d22d718affbc7145d1012157feb819557b5c06Michael Wright @Override 237a4d22d718affbc7145d1012157feb819557b5c06Michael Wright public boolean onSingleTapUp(MotionEvent e) { 238a4d22d718affbc7145d1012157feb819557b5c06Michael Wright if (!mOverscroller.isFinished()) { 239a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mOverscroller.forceFinished(true); 240a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 241a4d22d718affbc7145d1012157feb819557b5c06Michael Wright return true; 242a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 243a4d22d718affbc7145d1012157feb819557b5c06Michael Wright @Override 244a4d22d718affbc7145d1012157feb819557b5c06Michael Wright public boolean onFling(MotionEvent down, MotionEvent up, 245a4d22d718affbc7145d1012157feb819557b5c06Michael Wright float velocityX, float velocityY) { 246a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mOverscroller.computeScrollOffset(); 247a4d22d718affbc7145d1012157feb819557b5c06Michael Wright long now = SystemClock.uptimeMillis(); 248a4d22d718affbc7145d1012157feb819557b5c06Michael Wright 249a4d22d718affbc7145d1012157feb819557b5c06Michael Wright if (mLastFlingTime != 0 && now > mLastFlingTime + MAX_FLING_TIME_MILLIS) { 250a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mOverscroller.forceFinished(true); 251a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 252a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mOverscroller.fling(0, 0, (int)velocityX, (int)velocityY, 253a4d22d718affbc7145d1012157feb819557b5c06Michael Wright Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE); 254a4d22d718affbc7145d1012157feb819557b5c06Michael Wright int duration = mOverscroller.getDuration(); 255a4d22d718affbc7145d1012157feb819557b5c06Michael Wright if (duration > MAX_FLING_TIME_MILLIS) { 256a4d22d718affbc7145d1012157feb819557b5c06Michael Wright duration = MAX_FLING_TIME_MILLIS; 257a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 258a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mLastFlingTime = now; 259a4d22d718affbc7145d1012157feb819557b5c06Michael Wright mCallbacks.onFling(duration); 260a4d22d718affbc7145d1012157feb819557b5c06Michael Wright return true; 261a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 262a4d22d718affbc7145d1012157feb819557b5c06Michael Wright } 263a4d22d718affbc7145d1012157feb819557b5c06Michael Wright 26457306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock interface Callbacks { 26557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock void onSwipeFromTop(); 266ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock void onSwipeFromBottom(); 267ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock void onSwipeFromRight(); 268a4d22d718affbc7145d1012157feb819557b5c06Michael Wright void onFling(int durationMs); 2693595be4d19caaa7ddfbff0b979d135aaf5ac20b1Adrian Roos void onDown(); 2703595be4d19caaa7ddfbff0b979d135aaf5ac20b1Adrian Roos void onUpOrCancel(); 271d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai void onMouseHoverAtTop(); 272d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai void onMouseHoverAtBottom(); 273d2e7e355d836f18adcdb44db9c1931d1c3663ef1Jun Mukai void onMouseLeaveFromEdge(); 274ad3e6cb4db99ad33fcfc61f236d37cd83446866dJohn Spurlock void onDebug(); 27557306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock } 27657306e6b79a87518b5739fc5717cd1cd47c75eaeJohn Spurlock} 277