diff options
author | Jeff Brown <jeffbrown@android.com> | 2011-06-06 20:32:25 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-06-06 20:32:25 -0700 |
commit | b3536145725250401d25ffa00cda85d222dfc21e (patch) | |
tree | 93b59c5c04aab3a428f7ebf7f3d24456ed63ec9a | |
parent | b400184ad6277676048a30b042ed0667de662ad8 (diff) | |
parent | ed48fa89a8e31b04681347a9235c2a566e7dbb8e (diff) | |
download | frameworks_base-b3536145725250401d25ffa00cda85d222dfc21e.zip frameworks_base-b3536145725250401d25ffa00cda85d222dfc21e.tar.gz frameworks_base-b3536145725250401d25ffa00cda85d222dfc21e.tar.bz2 |
am ed48fa89: Merge "Touch pad improvements. Bug: 4124987" into honeycomb-mr2
* commit 'ed48fa89a8e31b04681347a9235c2a566e7dbb8e':
Touch pad improvements. Bug: 4124987
-rw-r--r-- | core/java/android/view/ViewConfiguration.java | 40 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 328 | ||||
-rw-r--r-- | services/input/InputReader.h | 13 | ||||
-rw-r--r-- | services/java/com/android/server/wm/InputManager.java | 14 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 34 |
5 files changed, 240 insertions, 189 deletions
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index 739758c..392797c 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -111,7 +111,21 @@ public class ViewConfiguration { * double-tap. */ private static final int DOUBLE_TAP_TIMEOUT = 300; - + + /** + * Defines the maximum duration in milliseconds between a touch pad + * touch and release for a given touch to be considered a tap (click) as + * opposed to a hover movement gesture. + */ + private static final int HOVER_TAP_TIMEOUT = 150; + + /** + * Defines the maximum distance in pixels that a touch pad touch can move + * before being released for it to be considered a tap (click) as opposed + * to a hover movement gesture. + */ + private static final int HOVER_TAP_SLOP = 20; + /** * Defines the duration in milliseconds we want to display zoom controls in response * to a user panning within an application. @@ -360,7 +374,7 @@ public class ViewConfiguration { public static int getTapTimeout() { return TAP_TIMEOUT; } - + /** * @return the duration in milliseconds we will wait to see if a touch event * is a jump tap. If the user does not move within this interval, it is @@ -378,7 +392,27 @@ public class ViewConfiguration { public static int getDoubleTapTimeout() { return DOUBLE_TAP_TIMEOUT; } - + + /** + * @return the maximum duration in milliseconds between a touch pad + * touch and release for a given touch to be considered a tap (click) as + * opposed to a hover movement gesture. + * @hide + */ + public static int getHoverTapTimeout() { + return HOVER_TAP_TIMEOUT; + } + + /** + * @return the maximum distance in pixels that a touch pad touch can move + * before being released for it to be considered a tap (click) as opposed + * to a hover movement gesture. + * @hide + */ + public static int getHoverTapSlop() { + return HOVER_TAP_SLOP; + } + /** * @return Inset in pixels to look for touchable content when the user touches the edge of the * screen diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index a22ec1c..36a5f89 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -36,6 +36,12 @@ // Log debug messages about gesture detection. #define DEBUG_GESTURES 0 +// Specifies whether spots follow fingers or touch points. +// If 1, show exactly one spot per finger in multitouch gestures. +// If 0, show exactly one spot per generated touch point in multitouch gestures, so the +// spots indicate exactly which points on screen are being touched. +#define SPOT_FOLLOWS_FINGER 0 + #include "InputReader.h" #include <cutils/atomic.h> @@ -186,23 +192,6 @@ static int32_t calculateEdgeFlagsUsingPointerBounds( return edgeFlags; } -static void clampPositionUsingPointerBounds( - const sp<PointerControllerInterface>& pointerController, float* x, float* y) { - float minX, minY, maxX, maxY; - if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) { - if (*x < minX) { - *x = minX; - } else if (*x > maxX) { - *x = maxX; - } - if (*y < minY) { - *y = minY; - } else if (*y > maxY) { - *y = maxY; - } - } -} - static float calculateCommonVector(float a, float b) { if (a > 0 && b > 0) { return a < b ? a : b; @@ -746,8 +735,8 @@ void InputReader::dump(String8& dump) { mConfig.pointerGestureTapSlop); dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n", mConfig.pointerGestureMultitouchSettleInterval * 0.000001f); - dump.appendFormat(INDENT3 "MultitouchMinSpeed: %0.1fpx/s\n", - mConfig.pointerGestureMultitouchMinSpeed); + dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n", + mConfig.pointerGestureMultitouchMinDistance); dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n", mConfig.pointerGestureSwipeTransitionAngleCosine); dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n", @@ -3291,11 +3280,18 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag cancelPreviousGesture = false; } - // Switch pointer presentation. - mPointerController->setPresentation( - mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS - ? PointerControllerInterface::PRESENTATION_SPOT - : PointerControllerInterface::PRESENTATION_POINTER); + // Update the pointer presentation and spots. + if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); + if (finishPreviousGesture || cancelPreviousGesture) { + mPointerController->clearSpots(); + } + mPointerController->setSpots(mPointerGesture.spotGesture, + mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex, + mPointerGesture.spotIdBits); + } else { + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); + } // Show or hide the pointer if needed. switch (mPointerGesture.currentGestureMode) { @@ -3484,7 +3480,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL; mPointerGesture.spotIdBits.clear(); - moveSpotsLocked(); } return true; } @@ -3566,10 +3561,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (isQuietTime) { // Case 1: Quiet time. (QUIET) #if DEBUG_GESTURES - LOGD("Gestures: QUIET for next %0.3fms", - (mPointerGesture.quietTime + QUIET_INTERVAL - when) * 0.000001f); + LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime + + mConfig->pointerGestureQuietInterval - when) * 0.000001f); #endif - *outFinishPreviousGesture = true; + if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) { + *outFinishPreviousGesture = true; + } mPointerGesture.activeGestureId = -1; mPointerGesture.currentGestureMode = PointerGesture::QUIET; @@ -3580,7 +3577,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL; mPointerGesture.spotIdBits.clear(); - moveSpotsLocked(); } } else if (isPointerDown(mCurrentTouch.buttonState)) { // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG) @@ -3684,11 +3680,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.spotIdToIndex[0] = 0; mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0]; } - moveSpotsLocked(); } } else if (mCurrentTouch.pointerCount == 0) { // Case 3. No fingers down and button is not pressed. (NEUTRAL) - *outFinishPreviousGesture = true; + if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) { + *outFinishPreviousGesture = true; + } // Watch for taps coming out of HOVER or TAP_DRAG mode. // Checking for taps after TAP_DRAG allows us to detect double-taps. @@ -3730,7 +3727,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.spotIdBits.markBit(lastActiveTouchId); mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0; mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0]; - moveSpotsLocked(); } tapped = true; @@ -3762,7 +3758,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL; mPointerGesture.spotIdBits.clear(); - moveSpotsLocked(); } } } else if (mCurrentTouch.pointerCount == 1) { @@ -3826,7 +3821,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: HOVER"); #endif - *outFinishPreviousGesture = true; + if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) { + *outFinishPreviousGesture = true; + } mPointerGesture.activeGestureId = 0; down = false; } @@ -3857,7 +3854,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.spotIdBits.markBit(activeTouchId); mPointerGesture.spotIdToIndex[activeTouchId] = 0; mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0]; - moveSpotsLocked(); } } else { // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM) @@ -3886,8 +3882,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Reset the gesture. #if DEBUG_GESTURES LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, " - "settle time remaining %0.3fms", - (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when) + "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime + + mConfig->pointerGestureMultitouchSettleInterval - when) * 0.000001f); #endif *outCancelPreviousGesture = true; @@ -3908,8 +3904,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // for the gesture. Other spots will be positioned relative to this one. #if DEBUG_GESTURES LOGD("Gestures: Using active spot as reference for MULTITOUCH, " - "settle time expired %0.3fms ago", - (when - mPointerGesture.firstTouchTime - MULTITOUCH_SETTLE_INTERVAL) + "settle time expired %0.3fms ago", (when - mPointerGesture.firstTouchTime + - mConfig->pointerGestureMultitouchSettleInterval) * 0.000001f); #endif const PointerData& d = mLastTouch.pointers[mLastTouch.idToIndex[ @@ -3924,8 +3920,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Use the centroid and pointer location as the reference points for the gesture. #if DEBUG_GESTURES LOGD("Gestures: Using centroid as reference for MULTITOUCH, " - "settle time remaining %0.3fms", - (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when) + "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime + + mConfig->pointerGestureMultitouchSettleInterval - when) * 0.000001f); #endif mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX, @@ -3935,68 +3931,121 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } } + // Clear the reference deltas for fingers not yet included in the reference calculation. + for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value); + !idBits.isEmpty(); ) { + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + + mPointerGesture.referenceDeltas[id].dx = 0; + mPointerGesture.referenceDeltas[id].dy = 0; + } + mPointerGesture.referenceIdBits = mCurrentTouch.idBits; + + // Add delta for all fingers and calculate a common movement delta. + float commonDeltaX = 0, commonDeltaY = 0; + BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value); + for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { + bool first = (idBits == commonIdBits); + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + + const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]]; + const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]]; + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; + delta.dx += cpd.x - lpd.x; + delta.dy += cpd.y - lpd.y; + + if (first) { + commonDeltaX = delta.dx; + commonDeltaY = delta.dy; + } else { + commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); + commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); + } + } + + // Consider transitions from PRESS to SWIPE or MULTITOUCH. if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) { - float d; - if (mCurrentTouch.pointerCount > 2) { - // There are more than two pointers, switch to FREEFORM. + float dist[MAX_POINTER_ID + 1]; + int32_t distOverThreshold = 0; + for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; + dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale, + delta.dy * mLocked.pointerGestureYZoomScale); + if (dist[id] > mConfig->pointerGestureMultitouchMinDistance) { + distOverThreshold += 1; + } + } + + // Only transition when at least two pointers have moved further than + // the minimum distance threshold. + if (distOverThreshold >= 2) { + float d; + if (mCurrentTouch.pointerCount > 2) { + // There are more than two pointers, switch to FREEFORM. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", - mCurrentTouch.pointerCount); + LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", + mCurrentTouch.pointerCount); #endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else if (((d = distance( - mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y, - mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y)) - > mLocked.pointerGestureMaxSwipeWidth)) { - // There are two pointers but they are too far apart, switch to FREEFORM. + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } else if (((d = distance( + mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y, + mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y)) + > mLocked.pointerGestureMaxSwipeWidth)) { + // There are two pointers but they are too far apart for a SWIPE, + // switch to FREEFORM. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", - d, mLocked.pointerGestureMaxSwipeWidth); + LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", + d, mLocked.pointerGestureMaxSwipeWidth); #endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else { - // There are two pointers. Wait for both pointers to start moving - // before deciding whether this is a SWIPE or FREEFORM gesture. - uint32_t id1 = mCurrentTouch.pointers[0].id; - uint32_t id2 = mCurrentTouch.pointers[1].id; - - float vx1, vy1, vx2, vy2; - mPointerGesture.velocityTracker.getVelocity(id1, &vx1, &vy1); - mPointerGesture.velocityTracker.getVelocity(id2, &vx2, &vy2); - - float speed1 = hypotf(vx1, vy1); - float speed2 = hypotf(vx2, vy2); - if (speed1 >= mConfig->pointerGestureMultitouchMinSpeed - && speed2 >= mConfig->pointerGestureMultitouchMinSpeed) { - // Calculate the dot product of the velocity vectors. - // When the vectors are oriented in approximately the same direction, - // the angle betweeen them is near zero and the cosine of the angle - // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2). - float dot = vx1 * vx2 + vy1 * vy2; - float cosine = dot / (speed1 * speed2); // denominator always > 0 - if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) { - // Pointers are moving in the same direction. Switch to SWIPE. + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } else { + // There are two pointers. Wait for both pointers to start moving + // before deciding whether this is a SWIPE or FREEFORM gesture. + uint32_t id1 = mCurrentTouch.pointers[0].id; + uint32_t id2 = mCurrentTouch.pointers[1].id; + float dist1 = dist[id1]; + float dist2 = dist[id2]; + if (dist1 >= mConfig->pointerGestureMultitouchMinDistance + && dist2 >= mConfig->pointerGestureMultitouchMinDistance) { + // Calculate the dot product of the displacement vectors. + // When the vectors are oriented in approximately the same direction, + // the angle betweeen them is near zero and the cosine of the angle + // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2). + PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1]; + PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2]; + float dot = delta1.dx * delta2.dx + delta1.dy * delta2.dy; + float cosine = dot / (dist1 * dist2); // denominator always > 0 + if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) { + // Pointers are moving in the same direction. Switch to SWIPE. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to SWIPE, " - "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, " - "cosine %0.3f >= %0.3f", - speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED, - cosine, SWIPE_TRANSITION_ANGLE_COSINE); + LOGD("Gestures: PRESS transitioned to SWIPE, " + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " + "cosine %0.3f >= %0.3f", + dist1, mConfig->pointerGestureMultitouchMinDistance, + dist2, mConfig->pointerGestureMultitouchMinDistance, + cosine, mConfig->pointerGestureSwipeTransitionAngleCosine); #endif - mPointerGesture.currentGestureMode = PointerGesture::SWIPE; - } else { - // Pointers are moving in different directions. Switch to FREEFORM. + mPointerGesture.currentGestureMode = PointerGesture::SWIPE; + } else { + // Pointers are moving in different directions. Switch to FREEFORM. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to FREEFORM, " - "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, " - "cosine %0.3f < %0.3f", - speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED, - cosine, SWIPE_TRANSITION_ANGLE_COSINE); + LOGD("Gestures: PRESS transitioned to FREEFORM, " + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " + "cosine %0.3f < %0.3f", + dist1, mConfig->pointerGestureMultitouchMinDistance, + dist2, mConfig->pointerGestureMultitouchMinDistance, + cosine, mConfig->pointerGestureSwipeTransitionAngleCosine); #endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } } } } @@ -4013,67 +4062,28 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } } - // Clear the reference deltas for fingers not yet included in the reference calculation. - for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value); - !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - - mPointerGesture.referenceDeltas[id].dx = 0; - mPointerGesture.referenceDeltas[id].dy = 0; - } - mPointerGesture.referenceIdBits = mCurrentTouch.idBits; - - // Move the reference points based on the overall group motion of the fingers. - // The objective is to calculate a vector delta that is common to the movement - // of all fingers. - BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value); - if (!commonIdBits.isEmpty()) { - float commonDeltaX = 0, commonDeltaY = 0; - for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { - bool first = (idBits == commonIdBits); + // Move the reference points based on the overall group motion of the fingers + // except in PRESS mode while waiting for a transition to occur. + if (mPointerGesture.currentGestureMode != PointerGesture::PRESS + && (commonDeltaX || commonDeltaY)) { + for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); - const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]]; - const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]]; PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - delta.dx += cpd.x - lpd.x; - delta.dy += cpd.y - lpd.y; - - if (first) { - commonDeltaX = delta.dx; - commonDeltaY = delta.dy; - } else { - commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); - commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); - } + delta.dx = 0; + delta.dy = 0; } - if (commonDeltaX || commonDeltaY) { - for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - - PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - delta.dx = 0; - delta.dy = 0; - } - - mPointerGesture.referenceTouchX += commonDeltaX; - mPointerGesture.referenceTouchY += commonDeltaY; + mPointerGesture.referenceTouchX += commonDeltaX; + mPointerGesture.referenceTouchY += commonDeltaY; - commonDeltaX *= mLocked.pointerGestureXMovementScale; - commonDeltaY *= mLocked.pointerGestureYMovementScale; - mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); + commonDeltaX *= mLocked.pointerGestureXMovementScale; + commonDeltaY *= mLocked.pointerGestureYMovementScale; + mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); - mPointerGesture.referenceGestureX += commonDeltaX; - mPointerGesture.referenceGestureY += commonDeltaY; - - clampPositionUsingPointerBounds(mPointerController, - &mPointerGesture.referenceGestureX, - &mPointerGesture.referenceGestureY); - } + mPointerGesture.referenceGestureX += commonDeltaX; + mPointerGesture.referenceGestureY += commonDeltaY; } // Report gestures. @@ -4225,9 +4235,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } // Update spot locations for PRESS, SWIPE and FREEFORM. - // We use the same calculation as we do to calculate the gesture pointers - // for FREEFORM so that the spots smoothly track gestures. if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { +#if SPOT_FOLLOWS_FINGER + // Use the same calculation as we do to calculate the gesture pointers + // for FREEFORM so that the spots smoothly track fingers across gestures. mPointerGesture.spotIdBits.clear(); for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { uint32_t id = mCurrentTouch.pointers[i].id; @@ -4244,7 +4255,19 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, y); mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); } - moveSpotsLocked(); +#else + // Show one spot per generated touch point. + // This may cause apparent discontinuities in spot motion when transitioning + // from PRESS to FREEFORM. + mPointerGesture.spotIdBits = mPointerGesture.currentGestureIdBits; + for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) { + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + uint32_t index = mPointerGesture.currentGestureIdToIndex[id]; + mPointerGesture.spotIdToIndex[id] = index; + mPointerGesture.spotCoords[index] = mPointerGesture.currentGestureCoords[index]; + } +#endif } } @@ -4281,11 +4304,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, return true; } -void TouchInputMapper::moveSpotsLocked() { - mPointerController->setSpots(mPointerGesture.spotGesture, - mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex, mPointerGesture.spotIdBits); -} - void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 5028b60..9bb37874 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -101,8 +101,8 @@ struct InputReaderConfiguration { nsecs_t pointerGestureMultitouchSettleInterval; // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when - // both of the pointers are moving at least this fast. - float pointerGestureMultitouchMinSpeed; // in pixels per second + // at least two pointers have moved at least this far from their starting place. + float pointerGestureMultitouchMinDistance; // in pixels // The transition from PRESS to SWIPE gesture mode can only occur when the // cosine of the angle between the two vectors is greater than or equal to than this value @@ -134,7 +134,7 @@ struct InputReaderConfiguration { filterTouchEvents(false), filterJumpyTouchEvents(false), virtualKeyQuietTime(0), - pointerVelocityControlParameters(1.0f, 80.0f, 400.0f, 4.0f), + pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f), pointerGestureQuietInterval(100 * 1000000LL), // 100 ms pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second @@ -142,10 +142,10 @@ struct InputReaderConfiguration { pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms pointerGestureTapSlop(10.0f), // 10 pixels pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms - pointerGestureMultitouchMinSpeed(150.0f), // 150 pixels per second + pointerGestureMultitouchMinDistance(15), // 15 pixels pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees - pointerGestureSwipeMaxWidthRatio(0.333f), - pointerGestureMovementSpeedRatio(0.3f), + pointerGestureSwipeMaxWidthRatio(0.25f), + pointerGestureMovementSpeedRatio(0.8f), pointerGestureZoomSpeedRatio(0.3f) { } }; @@ -1192,7 +1192,6 @@ private: void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout); bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout); - void moveSpotsLocked(); // Dispatches a motion event. // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java index 4eda684..3b01217 100644 --- a/services/java/com/android/server/wm/InputManager.java +++ b/services/java/com/android/server/wm/InputManager.java @@ -540,8 +540,13 @@ public class InputManager { } @SuppressWarnings("unused") - public int getTapTimeout() { - return ViewConfiguration.getTapTimeout(); + public int getHoverTapTimeout() { + return ViewConfiguration.getHoverTapTimeout(); + } + + @SuppressWarnings("unused") + public int getHoverTapSlop() { + return ViewConfiguration.getHoverTapSlop(); } @SuppressWarnings("unused") @@ -555,11 +560,6 @@ public class InputManager { } @SuppressWarnings("unused") - public int getTouchSlop() { - return ViewConfiguration.get(mContext).getScaledTouchSlop(); - } - - @SuppressWarnings("unused") public int getMaxEventsPerSecond() { int result = 0; try { diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 2704647..608ea1a 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -56,7 +56,7 @@ namespace android { // The exponent used to calculate the pointer speed scaling factor. // The scaling factor is calculated as 2 ^ (speed * exponent), // where the speed ranges from -7 to + 7 and is supplied by the user. -static const float POINTER_SPEED_EXPONENT = 1.0f / 3; +static const float POINTER_SPEED_EXPONENT = 1.0f / 4; static struct { jclass clazz; @@ -77,10 +77,10 @@ static struct { jmethodID getKeyRepeatTimeout; jmethodID getKeyRepeatDelay; jmethodID getMaxEventsPerSecond; - jmethodID getTapTimeout; + jmethodID getHoverTapTimeout; + jmethodID getHoverTapSlop; jmethodID getDoubleTapTimeout; jmethodID getLongPressTimeout; - jmethodID getTouchSlop; jmethodID getPointerLayer; jmethodID getPointerIcon; } gCallbacksClassInfo; @@ -412,32 +412,32 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon env->DeleteLocalRef(excludedDeviceNames); } - jint tapTimeout = env->CallIntMethod(mCallbacksObj, - gCallbacksClassInfo.getTapTimeout); - if (!checkAndClearExceptionFromCallback(env, "getTapTimeout")) { + jint hoverTapTimeout = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.getHoverTapTimeout); + if (!checkAndClearExceptionFromCallback(env, "getHoverTapTimeout")) { jint doubleTapTimeout = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getDoubleTapTimeout); if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) { jint longPressTimeout = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getLongPressTimeout); if (!checkAndClearExceptionFromCallback(env, "getLongPressTimeout")) { - outConfig->pointerGestureTapInterval = milliseconds_to_nanoseconds(tapTimeout); + outConfig->pointerGestureTapInterval = milliseconds_to_nanoseconds(hoverTapTimeout); // We must ensure that the tap-drag interval is significantly shorter than // the long-press timeout because the tap is held down for the entire duration // of the double-tap timeout. jint tapDragInterval = max(min(longPressTimeout - 100, - doubleTapTimeout), tapTimeout); + doubleTapTimeout), hoverTapTimeout); outConfig->pointerGestureTapDragInterval = milliseconds_to_nanoseconds(tapDragInterval); } } } - jint touchSlop = env->CallIntMethod(mCallbacksObj, - gCallbacksClassInfo.getTouchSlop); - if (!checkAndClearExceptionFromCallback(env, "getTouchSlop")) { - outConfig->pointerGestureTapSlop = touchSlop; + jint hoverTapSlop = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.getHoverTapSlop); + if (!checkAndClearExceptionFromCallback(env, "getHoverTapSlop")) { + outConfig->pointerGestureTapSlop = hoverTapSlop; } { // acquire lock @@ -1348,8 +1348,11 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, gCallbacksClassInfo.clazz, "getKeyRepeatDelay", "()I"); - GET_METHOD_ID(gCallbacksClassInfo.getTapTimeout, gCallbacksClassInfo.clazz, - "getTapTimeout", "()I"); + GET_METHOD_ID(gCallbacksClassInfo.getHoverTapTimeout, gCallbacksClassInfo.clazz, + "getHoverTapTimeout", "()I"); + + GET_METHOD_ID(gCallbacksClassInfo.getHoverTapSlop, gCallbacksClassInfo.clazz, + "getHoverTapSlop", "()I"); GET_METHOD_ID(gCallbacksClassInfo.getDoubleTapTimeout, gCallbacksClassInfo.clazz, "getDoubleTapTimeout", "()I"); @@ -1357,9 +1360,6 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gCallbacksClassInfo.getLongPressTimeout, gCallbacksClassInfo.clazz, "getLongPressTimeout", "()I"); - GET_METHOD_ID(gCallbacksClassInfo.getTouchSlop, gCallbacksClassInfo.clazz, - "getTouchSlop", "()I"); - GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz, "getMaxEventsPerSecond", "()I"); |