| package com.android.server.accessibility; |
| |
| import android.util.MathUtils; |
| import android.view.MotionEvent; |
| |
| /** |
| * Some helper functions for gesture detection. |
| */ |
| final class GestureUtils { |
| |
| private GestureUtils() { |
| /* cannot be instantiated */ |
| } |
| |
| public static boolean isTap(MotionEvent down, MotionEvent up, int tapTimeSlop, |
| int tapDistanceSlop, int actionIndex) { |
| return eventsWithinTimeAndDistanceSlop(down, up, tapTimeSlop, tapDistanceSlop, actionIndex); |
| } |
| |
| public static boolean isMultiTap(MotionEvent firstUp, MotionEvent secondUp, |
| int multiTapTimeSlop, int multiTapDistanceSlop, int actionIndex) { |
| return eventsWithinTimeAndDistanceSlop(firstUp, secondUp, multiTapTimeSlop, |
| multiTapDistanceSlop, actionIndex); |
| } |
| |
| private static boolean eventsWithinTimeAndDistanceSlop(MotionEvent first, MotionEvent second, |
| int timeout, int distance, int actionIndex) { |
| if (isTimedOut(first, second, timeout)) { |
| return false; |
| } |
| final double deltaMove = computeDistance(first, second, actionIndex); |
| if (deltaMove >= distance) { |
| return false; |
| } |
| return true; |
| } |
| |
| public static double computeDistance(MotionEvent first, MotionEvent second, int pointerIndex) { |
| return MathUtils.dist(first.getX(pointerIndex), first.getY(pointerIndex), |
| second.getX(pointerIndex), second.getY(pointerIndex)); |
| } |
| |
| public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) { |
| final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime(); |
| return (deltaTime >= timeout); |
| } |
| |
| public static boolean isSamePointerContext(MotionEvent first, MotionEvent second) { |
| return (first.getPointerIdBits() == second.getPointerIdBits() |
| && first.getPointerId(first.getActionIndex()) |
| == second.getPointerId(second.getActionIndex())); |
| } |
| |
| /** |
| * Determines whether a two pointer gesture is a dragging one. |
| * |
| * @param event The event with the pointer data. |
| * @return True if the gesture is a dragging one. |
| */ |
| public static boolean isDraggingGesture(float firstPtrDownX, float firstPtrDownY, |
| float secondPtrDownX, float secondPtrDownY, float firstPtrX, float firstPtrY, |
| float secondPtrX, float secondPtrY, float maxDraggingAngleCos) { |
| |
| // Check if the pointers are moving in the same direction. |
| final float firstDeltaX = firstPtrX - firstPtrDownX; |
| final float firstDeltaY = firstPtrY - firstPtrDownY; |
| |
| if (firstDeltaX == 0 && firstDeltaY == 0) { |
| return true; |
| } |
| |
| final float firstMagnitude = |
| (float) Math.sqrt(firstDeltaX * firstDeltaX + firstDeltaY * firstDeltaY); |
| final float firstXNormalized = |
| (firstMagnitude > 0) ? firstDeltaX / firstMagnitude : firstDeltaX; |
| final float firstYNormalized = |
| (firstMagnitude > 0) ? firstDeltaY / firstMagnitude : firstDeltaY; |
| |
| final float secondDeltaX = secondPtrX - secondPtrDownX; |
| final float secondDeltaY = secondPtrY - secondPtrDownY; |
| |
| if (secondDeltaX == 0 && secondDeltaY == 0) { |
| return true; |
| } |
| |
| final float secondMagnitude = |
| (float) Math.sqrt(secondDeltaX * secondDeltaX + secondDeltaY * secondDeltaY); |
| final float secondXNormalized = |
| (secondMagnitude > 0) ? secondDeltaX / secondMagnitude : secondDeltaX; |
| final float secondYNormalized = |
| (secondMagnitude > 0) ? secondDeltaY / secondMagnitude : secondDeltaY; |
| |
| final float angleCos = |
| firstXNormalized * secondXNormalized + firstYNormalized * secondYNormalized; |
| |
| if (angleCos < maxDraggingAngleCos) { |
| return false; |
| } |
| |
| return true; |
| } |
| } |