Merge "Renable split tapping while in Touch Explore mode."
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
index 28121b4..e310801 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
@@ -64,6 +64,14 @@
// Indicates that motion events are being collected to match a gesture.
private boolean mRecognizingGesture;
+ // Indicates that motion events from the second pointer are being checked
+ // for a double tap.
+ private boolean mSecondFingerDoubleTap;
+
+ // Tracks the most recent time where ACTION_POINTER_DOWN was sent for the
+ // second pointer.
+ private long mSecondPointerDownTime;
+
// Policy flags of the previous event.
private int mPolicyFlags;
@@ -102,6 +110,7 @@
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mDoubleTapDetected = false;
+ mSecondFingerDoubleTap = false;
mRecognizingGesture = true;
mPreviousX = x;
mPreviousY = y;
@@ -133,6 +142,43 @@
}
}
break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // Once a second finger is used, we're definitely not
+ // recognizing a gesture.
+ cancelGesture();
+
+ if (event.getPointerCount() == 2) {
+ // If this was the second finger, attempt to recognize double
+ // taps on it.
+ mSecondFingerDoubleTap = true;
+ mSecondPointerDownTime = event.getEventTime();
+ } else {
+ // If there are more than two fingers down, stop watching
+ // for a double tap.
+ mSecondFingerDoubleTap = false;
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ // If we're detecting taps on the second finger, see if we
+ // should finish the double tap.
+ if (mSecondFingerDoubleTap && maybeFinishDoubleTap(event, policyFlags)) {
+ return true;
+ }
+ break;
+ }
+
+ // If we're detecting taps on the second finger, map events from the
+ // finger to the first finger.
+ if (mSecondFingerDoubleTap) {
+ MotionEvent newEvent = mapSecondPointerToFirstPointer(event);
+ if (newEvent == null) {
+ return false;
+ }
+ boolean handled = mGestureDetector.onTouchEvent(newEvent);
+ newEvent.recycle();
+ return handled;
}
if (!mRecognizingGesture) {
@@ -146,6 +192,7 @@
public void clear() {
mFirstTapDetected = false;
mDoubleTapDetected = false;
+ mSecondFingerDoubleTap = false;
cancelGesture();
mStrokeBuffer.clear();
}
@@ -229,4 +276,28 @@
return false;
}
+
+ private MotionEvent mapSecondPointerToFirstPointer(MotionEvent event) {
+ // Only map basic events when two fingers are down.
+ if (event.getPointerCount() != 2 ||
+ (event.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN &&
+ event.getActionMasked() != MotionEvent.ACTION_POINTER_UP &&
+ event.getActionMasked() != MotionEvent.ACTION_MOVE)) {
+ return null;
+ }
+
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ action = MotionEvent.ACTION_DOWN;
+ } else if (action == MotionEvent.ACTION_POINTER_UP) {
+ action = MotionEvent.ACTION_UP;
+ }
+
+ // Map the information from the second pointer to the first.
+ return MotionEvent.obtain(mSecondPointerDownTime, event.getEventTime(), action,
+ event.getX(1), event.getY(1), event.getPressure(1), event.getSize(1),
+ event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
+ event.getDeviceId(), event.getEdgeFlags());
+ }
}