Home | History | Annotate | Download | only in accessibility
      1 package com.android.server.accessibility;
      2 
      3 import android.util.MathUtils;
      4 import android.view.MotionEvent;
      5 
      6 /**
      7  * Some helper functions for gesture detection.
      8  */
      9 final class GestureUtils {
     10 
     11     private GestureUtils() {
     12         /* cannot be instantiated */
     13     }
     14 
     15     public static boolean isTap(MotionEvent down, MotionEvent up, int tapTimeSlop,
     16             int tapDistanceSlop, int actionIndex) {
     17         return eventsWithinTimeAndDistanceSlop(down, up, tapTimeSlop, tapDistanceSlop, actionIndex);
     18     }
     19 
     20     public static boolean isMultiTap(MotionEvent firstUp, MotionEvent secondUp,
     21             int multiTapTimeSlop, int multiTapDistanceSlop, int actionIndex) {
     22         return eventsWithinTimeAndDistanceSlop(firstUp, secondUp, multiTapTimeSlop,
     23                 multiTapDistanceSlop, actionIndex);
     24     }
     25 
     26     private static boolean eventsWithinTimeAndDistanceSlop(MotionEvent first, MotionEvent second,
     27             int timeout, int distance, int actionIndex) {
     28         if (isTimedOut(first, second, timeout)) {
     29             return false;
     30         }
     31         final double deltaMove = computeDistance(first, second, actionIndex);
     32         if (deltaMove >= distance) {
     33             return false;
     34         }
     35         return true;
     36     }
     37 
     38     public static double computeDistance(MotionEvent first, MotionEvent second, int pointerIndex) {
     39          return MathUtils.dist(first.getX(pointerIndex), first.getY(pointerIndex),
     40                  second.getX(pointerIndex), second.getY(pointerIndex));
     41     }
     42 
     43     public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) {
     44         final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime();
     45         return (deltaTime >= timeout);
     46     }
     47 
     48     public static boolean isSamePointerContext(MotionEvent first, MotionEvent second) {
     49         return (first.getPointerIdBits() == second.getPointerIdBits()
     50                 && first.getPointerId(first.getActionIndex())
     51                         == second.getPointerId(second.getActionIndex()));
     52     }
     53 
     54     /**
     55      * Determines whether a two pointer gesture is a dragging one.
     56      *
     57      * @param event The event with the pointer data.
     58      * @return True if the gesture is a dragging one.
     59      */
     60     public static boolean isDraggingGesture(float firstPtrDownX, float firstPtrDownY,
     61             float secondPtrDownX, float secondPtrDownY, float firstPtrX, float firstPtrY,
     62             float secondPtrX, float secondPtrY, float maxDraggingAngleCos) {
     63 
     64         // Check if the pointers are moving in the same direction.
     65         final float firstDeltaX = firstPtrX - firstPtrDownX;
     66         final float firstDeltaY = firstPtrY - firstPtrDownY;
     67 
     68         if (firstDeltaX == 0 && firstDeltaY == 0) {
     69             return true;
     70         }
     71 
     72         final float firstMagnitude = (float) Math.hypot(firstDeltaX, firstDeltaY);
     73         final float firstXNormalized =
     74             (firstMagnitude > 0) ? firstDeltaX / firstMagnitude : firstDeltaX;
     75         final float firstYNormalized =
     76             (firstMagnitude > 0) ? firstDeltaY / firstMagnitude : firstDeltaY;
     77 
     78         final float secondDeltaX = secondPtrX - secondPtrDownX;
     79         final float secondDeltaY = secondPtrY - secondPtrDownY;
     80 
     81         if (secondDeltaX == 0 && secondDeltaY == 0) {
     82             return true;
     83         }
     84 
     85         final float secondMagnitude = (float) Math.hypot(secondDeltaX, secondDeltaY);
     86         final float secondXNormalized =
     87             (secondMagnitude > 0) ? secondDeltaX / secondMagnitude : secondDeltaX;
     88         final float secondYNormalized =
     89             (secondMagnitude > 0) ? secondDeltaY / secondMagnitude : secondDeltaY;
     90 
     91         final float angleCos =
     92             firstXNormalized * secondXNormalized + firstYNormalized * secondYNormalized;
     93 
     94         if (angleCos < maxDraggingAngleCos) {
     95             return false;
     96         }
     97 
     98         return true;
     99     }
    100 }
    101