Merge "Touch pad improvements. Bug: 4124987" into honeycomb-mr2
This commit is contained in:
@@ -112,6 +112,20 @@ public class ViewConfiguration {
|
|||||||
*/
|
*/
|
||||||
private static final int DOUBLE_TAP_TIMEOUT = 300;
|
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
|
* Defines the duration in milliseconds we want to display zoom controls in response
|
||||||
* to a user panning within an application.
|
* to a user panning within an application.
|
||||||
@@ -379,6 +393,26 @@ public class ViewConfiguration {
|
|||||||
return DOUBLE_TAP_TIMEOUT;
|
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
|
* @return Inset in pixels to look for touchable content when the user touches the edge of the
|
||||||
* screen
|
* screen
|
||||||
|
|||||||
@@ -36,6 +36,12 @@
|
|||||||
// Log debug messages about gesture detection.
|
// Log debug messages about gesture detection.
|
||||||
#define DEBUG_GESTURES 0
|
#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 "InputReader.h"
|
||||||
|
|
||||||
#include <cutils/atomic.h>
|
#include <cutils/atomic.h>
|
||||||
@@ -186,23 +192,6 @@ static int32_t calculateEdgeFlagsUsingPointerBounds(
|
|||||||
return edgeFlags;
|
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) {
|
static float calculateCommonVector(float a, float b) {
|
||||||
if (a > 0 && b > 0) {
|
if (a > 0 && b > 0) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
@@ -746,8 +735,8 @@ void InputReader::dump(String8& dump) {
|
|||||||
mConfig.pointerGestureTapSlop);
|
mConfig.pointerGestureTapSlop);
|
||||||
dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
|
dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
|
||||||
mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
|
mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
|
||||||
dump.appendFormat(INDENT3 "MultitouchMinSpeed: %0.1fpx/s\n",
|
dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
|
||||||
mConfig.pointerGestureMultitouchMinSpeed);
|
mConfig.pointerGestureMultitouchMinDistance);
|
||||||
dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
|
dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
|
||||||
mConfig.pointerGestureSwipeTransitionAngleCosine);
|
mConfig.pointerGestureSwipeTransitionAngleCosine);
|
||||||
dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
|
dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
|
||||||
@@ -3291,11 +3280,18 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
|
|||||||
cancelPreviousGesture = false;
|
cancelPreviousGesture = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch pointer presentation.
|
// Update the pointer presentation and spots.
|
||||||
mPointerController->setPresentation(
|
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
||||||
mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
|
mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
|
||||||
? PointerControllerInterface::PRESENTATION_SPOT
|
if (finishPreviousGesture || cancelPreviousGesture) {
|
||||||
: PointerControllerInterface::PRESENTATION_POINTER);
|
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.
|
// Show or hide the pointer if needed.
|
||||||
switch (mPointerGesture.currentGestureMode) {
|
switch (mPointerGesture.currentGestureMode) {
|
||||||
@@ -3484,7 +3480,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
||||||
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
||||||
mPointerGesture.spotIdBits.clear();
|
mPointerGesture.spotIdBits.clear();
|
||||||
moveSpotsLocked();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3566,10 +3561,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
if (isQuietTime) {
|
if (isQuietTime) {
|
||||||
// Case 1: Quiet time. (QUIET)
|
// Case 1: Quiet time. (QUIET)
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: QUIET for next %0.3fms",
|
LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
|
||||||
(mPointerGesture.quietTime + QUIET_INTERVAL - when) * 0.000001f);
|
+ mConfig->pointerGestureQuietInterval - when) * 0.000001f);
|
||||||
#endif
|
#endif
|
||||||
*outFinishPreviousGesture = true;
|
if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
|
||||||
|
*outFinishPreviousGesture = true;
|
||||||
|
}
|
||||||
|
|
||||||
mPointerGesture.activeGestureId = -1;
|
mPointerGesture.activeGestureId = -1;
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
|
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
|
||||||
@@ -3580,7 +3577,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
||||||
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
||||||
mPointerGesture.spotIdBits.clear();
|
mPointerGesture.spotIdBits.clear();
|
||||||
moveSpotsLocked();
|
|
||||||
}
|
}
|
||||||
} else if (isPointerDown(mCurrentTouch.buttonState)) {
|
} else if (isPointerDown(mCurrentTouch.buttonState)) {
|
||||||
// Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
|
// Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
|
||||||
@@ -3684,11 +3680,12 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
mPointerGesture.spotIdToIndex[0] = 0;
|
mPointerGesture.spotIdToIndex[0] = 0;
|
||||||
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
|
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
|
||||||
}
|
}
|
||||||
moveSpotsLocked();
|
|
||||||
}
|
}
|
||||||
} else if (mCurrentTouch.pointerCount == 0) {
|
} else if (mCurrentTouch.pointerCount == 0) {
|
||||||
// Case 3. No fingers down and button is not pressed. (NEUTRAL)
|
// 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.
|
// Watch for taps coming out of HOVER or TAP_DRAG mode.
|
||||||
// Checking for taps after TAP_DRAG allows us to detect double-taps.
|
// 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.spotIdBits.markBit(lastActiveTouchId);
|
||||||
mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0;
|
mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0;
|
||||||
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
|
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
|
||||||
moveSpotsLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tapped = true;
|
tapped = true;
|
||||||
@@ -3762,7 +3758,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
||||||
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
||||||
mPointerGesture.spotIdBits.clear();
|
mPointerGesture.spotIdBits.clear();
|
||||||
moveSpotsLocked();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mCurrentTouch.pointerCount == 1) {
|
} else if (mCurrentTouch.pointerCount == 1) {
|
||||||
@@ -3826,7 +3821,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: HOVER");
|
LOGD("Gestures: HOVER");
|
||||||
#endif
|
#endif
|
||||||
*outFinishPreviousGesture = true;
|
if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
|
||||||
|
*outFinishPreviousGesture = true;
|
||||||
|
}
|
||||||
mPointerGesture.activeGestureId = 0;
|
mPointerGesture.activeGestureId = 0;
|
||||||
down = false;
|
down = false;
|
||||||
}
|
}
|
||||||
@@ -3857,7 +3854,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
mPointerGesture.spotIdBits.markBit(activeTouchId);
|
mPointerGesture.spotIdBits.markBit(activeTouchId);
|
||||||
mPointerGesture.spotIdToIndex[activeTouchId] = 0;
|
mPointerGesture.spotIdToIndex[activeTouchId] = 0;
|
||||||
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
|
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
|
||||||
moveSpotsLocked();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
|
// 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.
|
// Reset the gesture.
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
|
LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
|
||||||
"settle time remaining %0.3fms",
|
"settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
|
||||||
(mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
|
+ mConfig->pointerGestureMultitouchSettleInterval - when)
|
||||||
* 0.000001f);
|
* 0.000001f);
|
||||||
#endif
|
#endif
|
||||||
*outCancelPreviousGesture = true;
|
*outCancelPreviousGesture = true;
|
||||||
@@ -3908,8 +3904,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
// for the gesture. Other spots will be positioned relative to this one.
|
// for the gesture. Other spots will be positioned relative to this one.
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: Using active spot as reference for MULTITOUCH, "
|
LOGD("Gestures: Using active spot as reference for MULTITOUCH, "
|
||||||
"settle time expired %0.3fms ago",
|
"settle time expired %0.3fms ago", (when - mPointerGesture.firstTouchTime
|
||||||
(when - mPointerGesture.firstTouchTime - MULTITOUCH_SETTLE_INTERVAL)
|
- mConfig->pointerGestureMultitouchSettleInterval)
|
||||||
* 0.000001f);
|
* 0.000001f);
|
||||||
#endif
|
#endif
|
||||||
const PointerData& d = mLastTouch.pointers[mLastTouch.idToIndex[
|
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.
|
// Use the centroid and pointer location as the reference points for the gesture.
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
|
LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
|
||||||
"settle time remaining %0.3fms",
|
"settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
|
||||||
(mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
|
+ mConfig->pointerGestureMultitouchSettleInterval - when)
|
||||||
* 0.000001f);
|
* 0.000001f);
|
||||||
#endif
|
#endif
|
||||||
mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
|
mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
|
||||||
@@ -3935,68 +3931,121 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
|
// Clear the reference deltas for fingers not yet included in the reference calculation.
|
||||||
float d;
|
for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
|
||||||
if (mCurrentTouch.pointerCount > 2) {
|
!idBits.isEmpty(); ) {
|
||||||
// There are more than two pointers, switch to FREEFORM.
|
uint32_t id = idBits.firstMarkedBit();
|
||||||
#if DEBUG_GESTURES
|
idBits.clearBit(id);
|
||||||
LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
|
|
||||||
mCurrentTouch.pointerCount);
|
mPointerGesture.referenceDeltas[id].dx = 0;
|
||||||
#endif
|
mPointerGesture.referenceDeltas[id].dy = 0;
|
||||||
*outCancelPreviousGesture = true;
|
}
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
|
mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
|
||||||
} else if (((d = distance(
|
|
||||||
mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
|
// Add delta for all fingers and calculate a common movement delta.
|
||||||
mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
|
float commonDeltaX = 0, commonDeltaY = 0;
|
||||||
> mLocked.pointerGestureMaxSwipeWidth)) {
|
BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
|
||||||
// There are two pointers but they are too far apart, switch to FREEFORM.
|
for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
|
||||||
#if DEBUG_GESTURES
|
bool first = (idBits == commonIdBits);
|
||||||
LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
|
uint32_t id = idBits.firstMarkedBit();
|
||||||
d, mLocked.pointerGestureMaxSwipeWidth);
|
idBits.clearBit(id);
|
||||||
#endif
|
|
||||||
*outCancelPreviousGesture = true;
|
const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
|
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 {
|
} else {
|
||||||
// There are two pointers. Wait for both pointers to start moving
|
commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
|
||||||
// before deciding whether this is a SWIPE or FREEFORM gesture.
|
commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
|
||||||
uint32_t id1 = mCurrentTouch.pointers[0].id;
|
}
|
||||||
uint32_t id2 = mCurrentTouch.pointers[1].id;
|
}
|
||||||
|
|
||||||
float vx1, vy1, vx2, vy2;
|
// Consider transitions from PRESS to SWIPE or MULTITOUCH.
|
||||||
mPointerGesture.velocityTracker.getVelocity(id1, &vx1, &vy1);
|
if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
|
||||||
mPointerGesture.velocityTracker.getVelocity(id2, &vx2, &vy2);
|
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);
|
||||||
|
|
||||||
float speed1 = hypotf(vx1, vy1);
|
PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
|
||||||
float speed2 = hypotf(vx2, vy2);
|
dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale,
|
||||||
if (speed1 >= mConfig->pointerGestureMultitouchMinSpeed
|
delta.dy * mLocked.pointerGestureYZoomScale);
|
||||||
&& speed2 >= mConfig->pointerGestureMultitouchMinSpeed) {
|
if (dist[id] > mConfig->pointerGestureMultitouchMinDistance) {
|
||||||
// Calculate the dot product of the velocity vectors.
|
distOverThreshold += 1;
|
||||||
// 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;
|
// Only transition when at least two pointers have moved further than
|
||||||
float cosine = dot / (speed1 * speed2); // denominator always > 0
|
// the minimum distance threshold.
|
||||||
if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) {
|
if (distOverThreshold >= 2) {
|
||||||
// Pointers are moving in the same direction. Switch to SWIPE.
|
float d;
|
||||||
|
if (mCurrentTouch.pointerCount > 2) {
|
||||||
|
// There are more than two pointers, switch to FREEFORM.
|
||||||
#if DEBUG_GESTURES
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: PRESS transitioned to SWIPE, "
|
LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
|
||||||
"speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
|
mCurrentTouch.pointerCount);
|
||||||
"cosine %0.3f >= %0.3f",
|
|
||||||
speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
|
|
||||||
cosine, SWIPE_TRANSITION_ANGLE_COSINE);
|
|
||||||
#endif
|
#endif
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
|
*outCancelPreviousGesture = true;
|
||||||
} else {
|
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
|
||||||
// Pointers are moving in different directions. Switch to 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
|
#if DEBUG_GESTURES
|
||||||
LOGD("Gestures: PRESS transitioned to FREEFORM, "
|
LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
|
||||||
"speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
|
d, mLocked.pointerGestureMaxSwipeWidth);
|
||||||
"cosine %0.3f < %0.3f",
|
|
||||||
speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
|
|
||||||
cosine, SWIPE_TRANSITION_ANGLE_COSINE);
|
|
||||||
#endif
|
#endif
|
||||||
*outCancelPreviousGesture = true;
|
*outCancelPreviousGesture = true;
|
||||||
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4013,67 +4062,28 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the reference deltas for fingers not yet included in the reference calculation.
|
// Move the reference points based on the overall group motion of the fingers
|
||||||
for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
|
// except in PRESS mode while waiting for a transition to occur.
|
||||||
!idBits.isEmpty(); ) {
|
if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
|
||||||
uint32_t id = idBits.firstMarkedBit();
|
&& (commonDeltaX || commonDeltaY)) {
|
||||||
idBits.clearBit(id);
|
for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
|
||||||
|
|
||||||
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);
|
|
||||||
uint32_t id = idBits.firstMarkedBit();
|
uint32_t id = idBits.firstMarkedBit();
|
||||||
idBits.clearBit(id);
|
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];
|
PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
|
||||||
delta.dx += cpd.x - lpd.x;
|
delta.dx = 0;
|
||||||
delta.dy += cpd.y - lpd.y;
|
delta.dy = 0;
|
||||||
|
|
||||||
if (first) {
|
|
||||||
commonDeltaX = delta.dx;
|
|
||||||
commonDeltaY = delta.dy;
|
|
||||||
} else {
|
|
||||||
commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
|
|
||||||
commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commonDeltaX || commonDeltaY) {
|
mPointerGesture.referenceTouchX += commonDeltaX;
|
||||||
for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
|
mPointerGesture.referenceTouchY += commonDeltaY;
|
||||||
uint32_t id = idBits.firstMarkedBit();
|
|
||||||
idBits.clearBit(id);
|
|
||||||
|
|
||||||
PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
|
commonDeltaX *= mLocked.pointerGestureXMovementScale;
|
||||||
delta.dx = 0;
|
commonDeltaY *= mLocked.pointerGestureYMovementScale;
|
||||||
delta.dy = 0;
|
mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
|
||||||
}
|
|
||||||
|
|
||||||
mPointerGesture.referenceTouchX += commonDeltaX;
|
mPointerGesture.referenceGestureX += commonDeltaX;
|
||||||
mPointerGesture.referenceTouchY += commonDeltaY;
|
mPointerGesture.referenceGestureY += 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report gestures.
|
// Report gestures.
|
||||||
@@ -4225,9 +4235,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update spot locations for PRESS, SWIPE and FREEFORM.
|
// 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 (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();
|
mPointerGesture.spotIdBits.clear();
|
||||||
for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
|
for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
|
||||||
uint32_t id = mCurrentTouch.pointers[i].id;
|
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_Y, y);
|
||||||
mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
|
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;
|
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,
|
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
|
||||||
int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
|
int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
|
||||||
const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
|
const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ struct InputReaderConfiguration {
|
|||||||
nsecs_t pointerGestureMultitouchSettleInterval;
|
nsecs_t pointerGestureMultitouchSettleInterval;
|
||||||
|
|
||||||
// The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
|
// The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
|
||||||
// both of the pointers are moving at least this fast.
|
// at least two pointers have moved at least this far from their starting place.
|
||||||
float pointerGestureMultitouchMinSpeed; // in pixels per second
|
float pointerGestureMultitouchMinDistance; // in pixels
|
||||||
|
|
||||||
// The transition from PRESS to SWIPE gesture mode can only occur when the
|
// 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
|
// 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),
|
filterTouchEvents(false),
|
||||||
filterJumpyTouchEvents(false),
|
filterJumpyTouchEvents(false),
|
||||||
virtualKeyQuietTime(0),
|
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),
|
wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
|
||||||
pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
|
pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
|
||||||
pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
|
pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
|
||||||
@@ -142,10 +142,10 @@ struct InputReaderConfiguration {
|
|||||||
pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
|
pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
|
||||||
pointerGestureTapSlop(10.0f), // 10 pixels
|
pointerGestureTapSlop(10.0f), // 10 pixels
|
||||||
pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
|
pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
|
||||||
pointerGestureMultitouchMinSpeed(150.0f), // 150 pixels per second
|
pointerGestureMultitouchMinDistance(15), // 15 pixels
|
||||||
pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees
|
pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees
|
||||||
pointerGestureSwipeMaxWidthRatio(0.333f),
|
pointerGestureSwipeMaxWidthRatio(0.25f),
|
||||||
pointerGestureMovementSpeedRatio(0.3f),
|
pointerGestureMovementSpeedRatio(0.8f),
|
||||||
pointerGestureZoomSpeedRatio(0.3f) { }
|
pointerGestureZoomSpeedRatio(0.3f) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1192,7 +1192,6 @@ private:
|
|||||||
void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
|
void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
|
||||||
bool preparePointerGestures(nsecs_t when,
|
bool preparePointerGestures(nsecs_t when,
|
||||||
bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout);
|
bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout);
|
||||||
void moveSpotsLocked();
|
|
||||||
|
|
||||||
// Dispatches a motion event.
|
// Dispatches a motion event.
|
||||||
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
|
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
|
||||||
|
|||||||
@@ -540,8 +540,13 @@ public class InputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public int getTapTimeout() {
|
public int getHoverTapTimeout() {
|
||||||
return ViewConfiguration.getTapTimeout();
|
return ViewConfiguration.getHoverTapTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public int getHoverTapSlop() {
|
||||||
|
return ViewConfiguration.getHoverTapSlop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@@ -554,11 +559,6 @@ public class InputManager {
|
|||||||
return ViewConfiguration.getLongPressTimeout();
|
return ViewConfiguration.getLongPressTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public int getTouchSlop() {
|
|
||||||
return ViewConfiguration.get(mContext).getScaledTouchSlop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public int getMaxEventsPerSecond() {
|
public int getMaxEventsPerSecond() {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace android {
|
|||||||
// The exponent used to calculate the pointer speed scaling factor.
|
// The exponent used to calculate the pointer speed scaling factor.
|
||||||
// The scaling factor is calculated as 2 ^ (speed * exponent),
|
// The scaling factor is calculated as 2 ^ (speed * exponent),
|
||||||
// where the speed ranges from -7 to + 7 and is supplied by the user.
|
// 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 {
|
static struct {
|
||||||
jclass clazz;
|
jclass clazz;
|
||||||
@@ -77,10 +77,10 @@ static struct {
|
|||||||
jmethodID getKeyRepeatTimeout;
|
jmethodID getKeyRepeatTimeout;
|
||||||
jmethodID getKeyRepeatDelay;
|
jmethodID getKeyRepeatDelay;
|
||||||
jmethodID getMaxEventsPerSecond;
|
jmethodID getMaxEventsPerSecond;
|
||||||
jmethodID getTapTimeout;
|
jmethodID getHoverTapTimeout;
|
||||||
|
jmethodID getHoverTapSlop;
|
||||||
jmethodID getDoubleTapTimeout;
|
jmethodID getDoubleTapTimeout;
|
||||||
jmethodID getLongPressTimeout;
|
jmethodID getLongPressTimeout;
|
||||||
jmethodID getTouchSlop;
|
|
||||||
jmethodID getPointerLayer;
|
jmethodID getPointerLayer;
|
||||||
jmethodID getPointerIcon;
|
jmethodID getPointerIcon;
|
||||||
} gCallbacksClassInfo;
|
} gCallbacksClassInfo;
|
||||||
@@ -412,32 +412,32 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
|
|||||||
env->DeleteLocalRef(excludedDeviceNames);
|
env->DeleteLocalRef(excludedDeviceNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint tapTimeout = env->CallIntMethod(mCallbacksObj,
|
jint hoverTapTimeout = env->CallIntMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.getTapTimeout);
|
gCallbacksClassInfo.getHoverTapTimeout);
|
||||||
if (!checkAndClearExceptionFromCallback(env, "getTapTimeout")) {
|
if (!checkAndClearExceptionFromCallback(env, "getHoverTapTimeout")) {
|
||||||
jint doubleTapTimeout = env->CallIntMethod(mCallbacksObj,
|
jint doubleTapTimeout = env->CallIntMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.getDoubleTapTimeout);
|
gCallbacksClassInfo.getDoubleTapTimeout);
|
||||||
if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) {
|
if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) {
|
||||||
jint longPressTimeout = env->CallIntMethod(mCallbacksObj,
|
jint longPressTimeout = env->CallIntMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.getLongPressTimeout);
|
gCallbacksClassInfo.getLongPressTimeout);
|
||||||
if (!checkAndClearExceptionFromCallback(env, "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
|
// 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
|
// the long-press timeout because the tap is held down for the entire duration
|
||||||
// of the double-tap timeout.
|
// of the double-tap timeout.
|
||||||
jint tapDragInterval = max(min(longPressTimeout - 100,
|
jint tapDragInterval = max(min(longPressTimeout - 100,
|
||||||
doubleTapTimeout), tapTimeout);
|
doubleTapTimeout), hoverTapTimeout);
|
||||||
outConfig->pointerGestureTapDragInterval =
|
outConfig->pointerGestureTapDragInterval =
|
||||||
milliseconds_to_nanoseconds(tapDragInterval);
|
milliseconds_to_nanoseconds(tapDragInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jint touchSlop = env->CallIntMethod(mCallbacksObj,
|
jint hoverTapSlop = env->CallIntMethod(mCallbacksObj,
|
||||||
gCallbacksClassInfo.getTouchSlop);
|
gCallbacksClassInfo.getHoverTapSlop);
|
||||||
if (!checkAndClearExceptionFromCallback(env, "getTouchSlop")) {
|
if (!checkAndClearExceptionFromCallback(env, "getHoverTapSlop")) {
|
||||||
outConfig->pointerGestureTapSlop = touchSlop;
|
outConfig->pointerGestureTapSlop = hoverTapSlop;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // acquire lock
|
{ // acquire lock
|
||||||
@@ -1348,8 +1348,11 @@ int register_android_server_InputManager(JNIEnv* env) {
|
|||||||
GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, gCallbacksClassInfo.clazz,
|
||||||
"getKeyRepeatDelay", "()I");
|
"getKeyRepeatDelay", "()I");
|
||||||
|
|
||||||
GET_METHOD_ID(gCallbacksClassInfo.getTapTimeout, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.getHoverTapTimeout, gCallbacksClassInfo.clazz,
|
||||||
"getTapTimeout", "()I");
|
"getHoverTapTimeout", "()I");
|
||||||
|
|
||||||
|
GET_METHOD_ID(gCallbacksClassInfo.getHoverTapSlop, gCallbacksClassInfo.clazz,
|
||||||
|
"getHoverTapSlop", "()I");
|
||||||
|
|
||||||
GET_METHOD_ID(gCallbacksClassInfo.getDoubleTapTimeout, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.getDoubleTapTimeout, gCallbacksClassInfo.clazz,
|
||||||
"getDoubleTapTimeout", "()I");
|
"getDoubleTapTimeout", "()I");
|
||||||
@@ -1357,9 +1360,6 @@ int register_android_server_InputManager(JNIEnv* env) {
|
|||||||
GET_METHOD_ID(gCallbacksClassInfo.getLongPressTimeout, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.getLongPressTimeout, gCallbacksClassInfo.clazz,
|
||||||
"getLongPressTimeout", "()I");
|
"getLongPressTimeout", "()I");
|
||||||
|
|
||||||
GET_METHOD_ID(gCallbacksClassInfo.getTouchSlop, gCallbacksClassInfo.clazz,
|
|
||||||
"getTouchSlop", "()I");
|
|
||||||
|
|
||||||
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
|
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
|
||||||
"getMaxEventsPerSecond", "()I");
|
"getMaxEventsPerSecond", "()I");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user