am ed48fa89: Merge "Touch pad improvements. Bug: 4124987" into honeycomb-mr2

* commit 'ed48fa89a8e31b04681347a9235c2a566e7dbb8e':
  Touch pad improvements. Bug: 4124987
This commit is contained in:
Jeff Brown
2011-06-06 20:32:25 -07:00
committed by Android Git Automerger
5 changed files with 242 additions and 191 deletions

View File

@ -112,6 +112,20 @@ public class ViewConfiguration {
*/
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.
@ -379,6 +393,26 @@ public class ViewConfiguration {
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

View File

@ -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
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)
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
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,84 +3931,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
}
if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
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);
#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.
#if DEBUG_GESTURES
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.
#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);
#endif
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);
#endif
*outCancelPreviousGesture = true;
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
}
}
}
} else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
// Switch from SWIPE to FREEFORM if additional pointers go down.
// Cancel previous gesture.
if (mCurrentTouch.pointerCount > 2) {
#if DEBUG_GESTURES
LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
mCurrentTouch.pointerCount);
#endif
*outCancelPreviousGesture = true;
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
}
}
// Clear the reference deltas for fingers not yet included in the reference calculation.
for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
!idBits.isEmpty(); ) {
@ -4024,12 +3942,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
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()) {
// 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();
@ -4050,8 +3965,108 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
}
}
if (commonDeltaX || commonDeltaY) {
for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
// Consider transitions from PRESS to SWIPE or MULTITOUCH.
if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
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);
#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 for a SWIPE,
// switch to FREEFORM.
#if DEBUG_GESTURES
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 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, "
"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.
#if DEBUG_GESTURES
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;
}
}
}
}
} else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
// Switch from SWIPE to FREEFORM if additional pointers go down.
// Cancel previous gesture.
if (mCurrentTouch.pointerCount > 2) {
#if DEBUG_GESTURES
LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
mCurrentTouch.pointerCount);
#endif
*outCancelPreviousGesture = true;
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
}
}
// 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);
@ -4069,11 +4084,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.referenceGestureX += commonDeltaX;
mPointerGesture.referenceGestureY += commonDeltaY;
clampPositionUsingPointerBounds(mPointerController,
&mPointerGesture.referenceGestureX,
&mPointerGesture.referenceGestureY);
}
}
// 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,

View File

@ -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

View File

@ -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")
@ -554,11 +559,6 @@ public class InputManager {
return ViewConfiguration.getLongPressTimeout();
}
@SuppressWarnings("unused")
public int getTouchSlop() {
return ViewConfiguration.get(mContext).getScaledTouchSlop();
}
@SuppressWarnings("unused")
public int getMaxEventsPerSecond() {
int result = 0;

View File

@ -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");