am 325bd07b: Add tap/drag touchpad gesture. (DO NOT MERGE)

* commit '325bd07b311f8ba68079000e9fe8afbcc076d7b6':
  Add tap/drag touchpad gesture. (DO NOT MERGE)
This commit is contained in:
Jeff Brown
2011-05-25 14:43:37 -07:00
committed by Android Git Automerger
3 changed files with 162 additions and 68 deletions

View File

@ -72,9 +72,14 @@ static const float DRAG_MIN_SWITCH_SPEED = 50.0f; // pixels per second
// The time between down and up must be less than this to be considered a tap. // The time between down and up must be less than this to be considered a tap.
static const nsecs_t TAP_INTERVAL = 150 * 1000000; // 150 ms static const nsecs_t TAP_INTERVAL = 150 * 1000000; // 150 ms
// Tap drag gesture delay time.
// The time between up and the next up must be greater than this to be considered a
// drag. Otherwise, the previous tap is finished and a new tap begins.
static const nsecs_t TAP_DRAG_INTERVAL = 150 * 1000000; // 150 ms
// The distance in pixels that the pointer is allowed to move from initial down // The distance in pixels that the pointer is allowed to move from initial down
// to up and still be called a tap. // to up and still be called a tap.
static const float TAP_SLOP = 5.0f; // 5 pixels static const float TAP_SLOP = 10.0f; // 10 pixels
// Time after the first touch points go down to settle on an initial centroid. // Time after the first touch points go down to settle on an initial centroid.
// This is intended to be enough time to handle cases where the user puts down two // This is intended to be enough time to handle cases where the user puts down two
@ -2752,14 +2757,21 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
} }
} }
// Process touches and virtual keys. TouchResult touchResult;
TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
if (touchResult == DISPATCH_TOUCH) { && mLastTouch.buttonState == mCurrentTouch.buttonState) {
suppressSwipeOntoVirtualKeys(when); // Drop spurious syncs.
if (mPointerController != NULL) { touchResult = DROP_STROKE;
dispatchPointerGestures(when, policyFlags); } else {
// Process touches and virtual keys.
touchResult = consumeOffScreenTouches(when, policyFlags);
if (touchResult == DISPATCH_TOUCH) {
suppressSwipeOntoVirtualKeys(when);
if (mPointerController != NULL) {
dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
}
dispatchTouches(when, policyFlags);
} }
dispatchTouches(when, policyFlags);
} }
// Copy current touch to last touch in preparation for the next cycle. // Copy current touch to last touch in preparation for the next cycle.
@ -2772,6 +2784,12 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
} }
} }
void TouchInputMapper::timeoutExpired(nsecs_t when) {
if (mPointerController != NULL) {
dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
}
}
TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
nsecs_t when, uint32_t policyFlags) { nsecs_t when, uint32_t policyFlags) {
int32_t keyEventAction, keyEventFlags; int32_t keyEventAction, keyEventFlags;
@ -3215,7 +3233,8 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
*outYPrecision = mLocked.orientedYPrecision; *outYPrecision = mLocked.orientedYPrecision;
} }
void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags) { void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
bool isTimeout) {
// Switch pointer presentation. // Switch pointer presentation.
mPointerController->setPresentation( mPointerController->setPresentation(
mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
@ -3224,7 +3243,11 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
// Update current gesture coordinates. // Update current gesture coordinates.
bool cancelPreviousGesture, finishPreviousGesture; bool cancelPreviousGesture, finishPreviousGesture;
preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture); bool sendEvents = preparePointerGestures(when,
&cancelPreviousGesture, &finishPreviousGesture, isTimeout);
if (!sendEvents) {
return;
}
// Show the pointer if needed. // Show the pointer if needed.
if (mPointerGesture.currentGestureMode != PointerGesture::NEUTRAL if (mPointerGesture.currentGestureMode != PointerGesture::NEUTRAL
@ -3237,7 +3260,9 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
// Update last coordinates of pointers that have moved so that we observe the new // Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up. // pointer positions at the same time as other pointers that have just gone up.
bool down = mPointerGesture.currentGestureMode == PointerGesture::CLICK_OR_DRAG bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
|| mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
|| mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
|| mPointerGesture.currentGestureMode == PointerGesture::PRESS || mPointerGesture.currentGestureMode == PointerGesture::PRESS
|| mPointerGesture.currentGestureMode == PointerGesture::SWIPE || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
|| mPointerGesture.currentGestureMode == PointerGesture::FREEFORM; || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
@ -3325,27 +3350,6 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
} }
} }
// Send down and up for a tap.
if (mPointerGesture.currentGestureMode == PointerGesture::TAP) {
const PointerCoords& coords = mPointerGesture.currentGestureCoords[0];
int32_t edgeFlags = calculateEdgeFlagsUsingPointerBounds(mPointerController,
coords.getAxisValue(AMOTION_EVENT_AXIS_X),
coords.getAxisValue(AMOTION_EVENT_AXIS_Y));
nsecs_t downTime = mPointerGesture.downTime = mPointerGesture.tapTime;
mPointerGesture.resetTapTime();
dispatchMotion(downTime, policyFlags, mPointerSource,
AMOTION_EVENT_ACTION_DOWN, 0, metaState, edgeFlags,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
mPointerGesture.currentGestureIdBits, -1,
0, 0, downTime);
dispatchMotion(when, policyFlags, mPointerSource,
AMOTION_EVENT_ACTION_UP, 0, metaState, edgeFlags,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
mPointerGesture.currentGestureIdBits, -1,
0, 0, downTime);
}
// Send motion events for hover. // Send motion events for hover.
if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) { if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
dispatchMotion(when, policyFlags, mPointerSource, dispatchMotion(when, policyFlags, mPointerSource,
@ -3372,13 +3376,49 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
} }
} }
void TouchInputMapper::preparePointerGestures(nsecs_t when, bool TouchInputMapper::preparePointerGestures(nsecs_t when,
bool* outCancelPreviousGesture, bool* outFinishPreviousGesture) { bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
*outCancelPreviousGesture = false; *outCancelPreviousGesture = false;
*outFinishPreviousGesture = false; *outFinishPreviousGesture = false;
AutoMutex _l(mLock); AutoMutex _l(mLock);
// Handle TAP timeout.
if (isTimeout) {
#if DEBUG_GESTURES
LOGD("Gestures: Processing timeout");
#endif
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
// The tap/drag timeout has not yet expired.
getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL);
} else {
// The tap is finished.
#if DEBUG_GESTURES
LOGD("Gestures: TAP finished");
#endif
*outFinishPreviousGesture = true;
mPointerGesture.activeGestureId = -1;
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
mPointerController->setButtonState(0);
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
moveSpotsLocked();
}
return true;
}
}
// We did not handle this timeout.
return false;
}
// Update the velocity tracker. // Update the velocity tracker.
{ {
VelocityTracker::Position positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS];
@ -3433,7 +3473,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
// This is to prevent accidentally entering the hover state and flinging the // This is to prevent accidentally entering the hover state and flinging the
// pointer when finishing a swipe and there is still one pointer left onscreen. // pointer when finishing a swipe and there is still one pointer left onscreen.
isQuietTime = true; isQuietTime = true;
} else if (mPointerGesture.lastGestureMode == PointerGesture::CLICK_OR_DRAG } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
&& mCurrentTouch.pointerCount >= 2 && mCurrentTouch.pointerCount >= 2
&& !isPointerDown(mCurrentTouch.buttonState)) { && !isPointerDown(mCurrentTouch.buttonState)) {
// Enter quiet time when releasing the button and there are still two or more // Enter quiet time when releasing the button and there are still two or more
@ -3468,7 +3508,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
moveSpotsLocked(); moveSpotsLocked();
} }
} else if (isPointerDown(mCurrentTouch.buttonState)) { } else if (isPointerDown(mCurrentTouch.buttonState)) {
// Case 2: Button is pressed. (CLICK_OR_DRAG) // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
// The pointer follows the active touch point. // The pointer follows the active touch point.
// Emit DOWN, MOVE, UP events at the pointer location. // Emit DOWN, MOVE, UP events at the pointer location.
// //
@ -3482,11 +3522,11 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
// finger to drag then the active pointer should switch to the finger that is // finger to drag then the active pointer should switch to the finger that is
// being dragged. // being dragged.
#if DEBUG_GESTURES #if DEBUG_GESTURES
LOGD("Gestures: CLICK_OR_DRAG activeTouchId=%d, " LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
"currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount); "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount);
#endif #endif
// Reset state when just starting. // Reset state when just starting.
if (mPointerGesture.lastGestureMode != PointerGesture::CLICK_OR_DRAG) { if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
*outFinishPreviousGesture = true; *outFinishPreviousGesture = true;
mPointerGesture.activeGestureId = 0; mPointerGesture.activeGestureId = 0;
} }
@ -3512,7 +3552,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
mPointerGesture.activeTouchId = activeTouchId = bestId; mPointerGesture.activeTouchId = activeTouchId = bestId;
activeTouchChanged = true; activeTouchChanged = true;
#if DEBUG_GESTURES #if DEBUG_GESTURES
LOGD("Gestures: CLICK_OR_DRAG switched pointers, " LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
"bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed); "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
#endif #endif
} }
@ -3538,7 +3578,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
float x, y; float x, y;
mPointerController->getPosition(&x, &y); mPointerController->getPosition(&x, &y);
mPointerGesture.currentGestureMode = PointerGesture::CLICK_OR_DRAG; mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
@ -3575,11 +3615,12 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
// Case 3. No fingers down and button is not pressed. (NEUTRAL) // Case 3. No fingers down and button is not pressed. (NEUTRAL)
*outFinishPreviousGesture = true; *outFinishPreviousGesture = true;
// Watch for taps coming out of HOVER mode. // Watch for taps coming out of HOVER or TAP_DRAG mode.
bool tapped = false; bool tapped = false;
if (mPointerGesture.lastGestureMode == PointerGesture::HOVER if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
|| mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
&& mLastTouch.pointerCount == 1) { && mLastTouch.pointerCount == 1) {
if (when <= mPointerGesture.tapTime + TAP_INTERVAL) { if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) {
float x, y; float x, y;
mPointerController->getPosition(&x, &y); mPointerController->getPosition(&x, &y);
if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
@ -3587,6 +3628,10 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
#if DEBUG_GESTURES #if DEBUG_GESTURES
LOGD("Gestures: TAP"); LOGD("Gestures: TAP");
#endif #endif
mPointerGesture.tapUpTime = when;
getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL);
mPointerGesture.activeGestureId = 0; mPointerGesture.activeGestureId = 0;
mPointerGesture.currentGestureMode = PointerGesture::TAP; mPointerGesture.currentGestureMode = PointerGesture::TAP;
mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.clear();
@ -3603,7 +3648,6 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
AMOTION_EVENT_AXIS_PRESSURE, 1.0f); AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
mPointerController->setButtonState(BUTTON_STATE_PRIMARY); mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
mPointerController->setButtonState(0);
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP; mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP;
@ -3624,8 +3668,8 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
} }
} else { } else {
#if DEBUG_GESTURES #if DEBUG_GESTURES
LOGD("Gestures: Not a TAP, delay=%lld", LOGD("Gestures: Not a TAP, %0.3fms since down",
when - mPointerGesture.tapTime); (when - mPointerGesture.tapDownTime) * 0.000001f);
#endif #endif
} }
} }
@ -3647,14 +3691,36 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
} }
} }
} else if (mCurrentTouch.pointerCount == 1) { } else if (mCurrentTouch.pointerCount == 1) {
// Case 4. Exactly one finger down, button is not pressed. (HOVER) // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
// The pointer follows the active touch point. // The pointer follows the active touch point.
// Emit HOVER_MOVE events at the pointer location. // When in HOVER, emit HOVER_MOVE events at the pointer location.
assert(activeTouchId >= 0); // When in TAP_DRAG, emit MOVE events at the pointer location.
LOG_ASSERT(activeTouchId >= 0);
mPointerGesture.currentGestureMode = PointerGesture::HOVER;
if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
float x, y;
mPointerController->getPosition(&x, &y);
if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
&& fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
} else {
#if DEBUG_GESTURES #if DEBUG_GESTURES
LOGD("Gestures: HOVER"); LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
x - mPointerGesture.tapX,
y - mPointerGesture.tapY);
#endif #endif
}
} else {
#if DEBUG_GESTURES
LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
(when - mPointerGesture.tapUpTime) * 0.000001f);
#endif
}
} else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
}
if (mLastTouch.idBits.hasBit(activeTouchId)) { if (mLastTouch.idBits.hasBit(activeTouchId)) {
const PointerData& currentPointer = const PointerData& currentPointer =
@ -3667,35 +3733,49 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
* mLocked.pointerGestureYMovementScale; * mLocked.pointerGestureYMovementScale;
// Move the pointer using a relative motion. // Move the pointer using a relative motion.
// When using spots, the hover will occur at the position of the anchor spot. // When using spots, the hover or drag will occur at the position of the anchor spot.
mPointerController->move(deltaX, deltaY); mPointerController->move(deltaX, deltaY);
} }
*outFinishPreviousGesture = true; bool down;
mPointerGesture.activeGestureId = 0; if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
#if DEBUG_GESTURES
LOGD("Gestures: TAP_DRAG");
#endif
down = true;
} else {
#if DEBUG_GESTURES
LOGD("Gestures: HOVER");
#endif
*outFinishPreviousGesture = true;
mPointerGesture.activeGestureId = 0;
down = false;
}
float x, y; float x, y;
mPointerController->getPosition(&x, &y); mPointerController->getPosition(&x, &y);
mPointerGesture.currentGestureMode = PointerGesture::HOVER;
mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
mPointerGesture.currentGestureCoords[0].clear(); mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
down ? 1.0f : 0.0f);
mPointerController->setButtonState(down ? BUTTON_STATE_PRIMARY : 0);
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) { if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
mPointerGesture.tapTime = when; mPointerGesture.resetTap();
mPointerGesture.tapDownTime = when;
mPointerGesture.tapX = x; mPointerGesture.tapX = x;
mPointerGesture.tapY = y; mPointerGesture.tapY = y;
} }
mPointerController->setButtonState(0);
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_HOVER; mPointerGesture.spotGesture = down ? PointerControllerInterface::SPOT_GESTURE_DRAG
: PointerControllerInterface::SPOT_GESTURE_HOVER;
mPointerGesture.spotIdBits.clear(); mPointerGesture.spotIdBits.clear();
mPointerGesture.spotIdBits.markBit(activeTouchId); mPointerGesture.spotIdBits.markBit(activeTouchId);
mPointerGesture.spotIdToIndex[activeTouchId] = 0; mPointerGesture.spotIdToIndex[activeTouchId] = 0;
@ -4098,6 +4178,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when,
coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
} }
#endif #endif
return true;
} }
void TouchInputMapper::moveSpotsLocked() { void TouchInputMapper::moveSpotsLocked() {

View File

@ -570,6 +570,7 @@ public:
const int32_t* keyCodes, uint8_t* outFlags); const int32_t* keyCodes, uint8_t* outFlags);
virtual void fadePointer(); virtual void fadePointer();
virtual void timeoutExpired(nsecs_t when);
protected: protected:
Mutex mLock; Mutex mLock;
@ -935,10 +936,15 @@ private:
// Emits DOWN and UP events at the pointer location. // Emits DOWN and UP events at the pointer location.
TAP, TAP,
// Exactly one finger dragging following a tap.
// Pointer follows the active finger.
// Emits DOWN, MOVE and UP events at the pointer location.
TAP_DRAG,
// Button is pressed. // Button is pressed.
// Pointer follows the active finger if there is one. Other fingers are ignored. // Pointer follows the active finger if there is one. Other fingers are ignored.
// Emits DOWN, MOVE and UP events at the pointer location. // Emits DOWN, MOVE and UP events at the pointer location.
CLICK_OR_DRAG, BUTTON_CLICK_OR_DRAG,
// Exactly one finger, button is not pressed. // Exactly one finger, button is not pressed.
// Pointer follows the active finger. // Pointer follows the active finger.
@ -997,8 +1003,11 @@ private:
// Time the pointer gesture last went down. // Time the pointer gesture last went down.
nsecs_t downTime; nsecs_t downTime;
// Time we started waiting for a tap gesture. // Time when the pointer went down for a TAP.
nsecs_t tapTime; nsecs_t tapDownTime;
// Time when the pointer went up for a TAP.
nsecs_t tapUpTime;
// Location of initial tap. // Location of initial tap.
float tapX, tapY; float tapX, tapY;
@ -1030,12 +1039,13 @@ private:
spotIdBits.clear(); spotIdBits.clear();
downTime = 0; downTime = 0;
velocityTracker.clear(); velocityTracker.clear();
resetTapTime(); resetTap();
resetQuietTime(); resetQuietTime();
} }
void resetTapTime() { void resetTap() {
tapTime = LLONG_MIN; tapDownTime = LLONG_MIN;
tapUpTime = LLONG_MIN;
} }
void resetQuietTime() { void resetQuietTime() {
@ -1048,9 +1058,9 @@ private:
TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags); TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
void dispatchTouches(nsecs_t when, uint32_t policyFlags); void dispatchTouches(nsecs_t when, uint32_t policyFlags);
void prepareTouches(int32_t* outEdgeFlags, float* outXPrecision, float* outYPrecision); void prepareTouches(int32_t* outEdgeFlags, float* outXPrecision, float* outYPrecision);
void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags); void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
void preparePointerGestures(nsecs_t when, bool preparePointerGestures(nsecs_t when,
bool* outCancelPreviousGesture, bool* outFinishPreviousGesture); bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout);
void moveSpotsLocked(); void moveSpotsLocked();
// Dispatches a motion event. // Dispatches a motion event.

View File

@ -91,6 +91,9 @@ public:
// Tap at current location. // Tap at current location.
// Briefly display one spot at the tapped location. // Briefly display one spot at the tapped location.
SPOT_GESTURE_TAP, SPOT_GESTURE_TAP,
// Drag at current location.
// Display spot at pressed location.
SPOT_GESTURE_DRAG,
// Button pressed but no finger is down. // Button pressed but no finger is down.
// Display spot at pressed location. // Display spot at pressed location.
SPOT_GESTURE_BUTTON_CLICK, SPOT_GESTURE_BUTTON_CLICK,