Loading services/input/InputReader.cpp +140 −59 Original line number Diff line number Diff line Loading @@ -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. 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 // 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. // This is intended to be enough time to handle cases where the user puts down two Loading Loading @@ -2752,15 +2757,22 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { } } TouchResult touchResult; if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0 && mLastTouch.buttonState == mCurrentTouch.buttonState) { // Drop spurious syncs. touchResult = DROP_STROKE; } else { // Process touches and virtual keys. TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { suppressSwipeOntoVirtualKeys(when); if (mPointerController != NULL) { dispatchPointerGestures(when, policyFlags); dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); } dispatchTouches(when, policyFlags); } } // Copy current touch to last touch in preparation for the next cycle. // Keep the button state so we can track edge-triggered button state changes. Loading @@ -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( nsecs_t when, uint32_t policyFlags) { int32_t keyEventAction, keyEventFlags; Loading Loading @@ -3215,7 +3233,8 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags, *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. mPointerController->setPresentation( mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS Loading @@ -3224,7 +3243,11 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag // Update current gesture coordinates. bool cancelPreviousGesture, finishPreviousGesture; preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture); bool sendEvents = preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture, isTimeout); if (!sendEvents) { return; } // Show the pointer if needed. if (mPointerGesture.currentGestureMode != PointerGesture::NEUTRAL Loading @@ -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 // 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::SWIPE || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM; Loading Loading @@ -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. if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) { dispatchMotion(when, policyFlags, mPointerSource, Loading @@ -3372,13 +3376,49 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag } } void TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture) { bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) { *outCancelPreviousGesture = false; *outFinishPreviousGesture = false; 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. { VelocityTracker::Position positions[MAX_POINTERS]; Loading Loading @@ -3433,7 +3473,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, // 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. isQuietTime = true; } else if (mPointerGesture.lastGestureMode == PointerGesture::CLICK_OR_DRAG } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG && mCurrentTouch.pointerCount >= 2 && !isPointerDown(mCurrentTouch.buttonState)) { // Enter quiet time when releasing the button and there are still two or more Loading Loading @@ -3468,7 +3508,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, moveSpotsLocked(); } } 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. // Emit DOWN, MOVE, UP events at the pointer location. // Loading @@ -3482,11 +3522,11 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, // finger to drag then the active pointer should switch to the finger that is // being dragged. #if DEBUG_GESTURES LOGD("Gestures: CLICK_OR_DRAG activeTouchId=%d, " LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, " "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount); #endif // Reset state when just starting. if (mPointerGesture.lastGestureMode != PointerGesture::CLICK_OR_DRAG) { if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) { *outFinishPreviousGesture = true; mPointerGesture.activeGestureId = 0; } Loading @@ -3512,7 +3552,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.activeTouchId = activeTouchId = bestId; activeTouchChanged = true; #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); #endif } Loading @@ -3538,7 +3578,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, float x, y; mPointerController->getPosition(&x, &y); mPointerGesture.currentGestureMode = PointerGesture::CLICK_OR_DRAG; mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG; mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; Loading Loading @@ -3575,11 +3615,12 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, // Case 3. No fingers down and button is not pressed. (NEUTRAL) *outFinishPreviousGesture = true; // Watch for taps coming out of HOVER mode. // Watch for taps coming out of HOVER or TAP_DRAG mode. bool tapped = false; if (mPointerGesture.lastGestureMode == PointerGesture::HOVER if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) && mLastTouch.pointerCount == 1) { if (when <= mPointerGesture.tapTime + TAP_INTERVAL) { if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) { float x, y; mPointerController->getPosition(&x, &y); if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP Loading @@ -3587,6 +3628,10 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: TAP"); #endif mPointerGesture.tapUpTime = when; getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL); mPointerGesture.activeGestureId = 0; mPointerGesture.currentGestureMode = PointerGesture::TAP; mPointerGesture.currentGestureIdBits.clear(); Loading @@ -3603,7 +3648,6 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, AMOTION_EVENT_AXIS_PRESSURE, 1.0f); mPointerController->setButtonState(BUTTON_STATE_PRIMARY); mPointerController->setButtonState(0); if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP; Loading @@ -3624,8 +3668,8 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, } } else { #if DEBUG_GESTURES LOGD("Gestures: Not a TAP, delay=%lld", when - mPointerGesture.tapTime); LOGD("Gestures: Not a TAP, %0.3fms since down", (when - mPointerGesture.tapDownTime) * 0.000001f); #endif } } Loading @@ -3647,14 +3691,36 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, } } } 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. // Emit HOVER_MOVE events at the pointer location. assert(activeTouchId >= 0); // When in HOVER, emit HOVER_MOVE events at the pointer location. // 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 LOGD("Gestures: HOVER"); LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX, y - mPointerGesture.tapY); #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)) { const PointerData& currentPointer = Loading @@ -3667,35 +3733,49 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, * mLocked.pointerGestureYMovementScale; // 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); } bool down; 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; mPointerController->getPosition(&x, &y); mPointerGesture.currentGestureMode = PointerGesture::HOVER; mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; mPointerGesture.currentGestureCoords[0].clear(); 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_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) { mPointerGesture.tapTime = when; mPointerGesture.resetTap(); mPointerGesture.tapDownTime = when; mPointerGesture.tapX = x; mPointerGesture.tapY = y; } mPointerController->setButtonState(0); 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.markBit(activeTouchId); mPointerGesture.spotIdToIndex[activeTouchId] = 0; Loading Loading @@ -4098,6 +4178,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); } #endif return true; } void TouchInputMapper::moveSpotsLocked() { Loading services/input/InputReader.h +19 −9 Original line number Diff line number Diff line Loading @@ -570,6 +570,7 @@ public: const int32_t* keyCodes, uint8_t* outFlags); virtual void fadePointer(); virtual void timeoutExpired(nsecs_t when); protected: Mutex mLock; Loading Loading @@ -935,10 +936,15 @@ private: // Emits DOWN and UP events at the pointer location. 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. // Pointer follows the active finger if there is one. Other fingers are ignored. // Emits DOWN, MOVE and UP events at the pointer location. CLICK_OR_DRAG, BUTTON_CLICK_OR_DRAG, // Exactly one finger, button is not pressed. // Pointer follows the active finger. Loading Loading @@ -997,8 +1003,11 @@ private: // Time the pointer gesture last went down. nsecs_t downTime; // Time we started waiting for a tap gesture. nsecs_t tapTime; // Time when the pointer went down for a TAP. nsecs_t tapDownTime; // Time when the pointer went up for a TAP. nsecs_t tapUpTime; // Location of initial tap. float tapX, tapY; Loading Loading @@ -1030,12 +1039,13 @@ private: spotIdBits.clear(); downTime = 0; velocityTracker.clear(); resetTapTime(); resetTap(); resetQuietTime(); } void resetTapTime() { tapTime = LLONG_MIN; void resetTap() { tapDownTime = LLONG_MIN; tapUpTime = LLONG_MIN; } void resetQuietTime() { Loading @@ -1048,9 +1058,9 @@ private: TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags); void dispatchTouches(nsecs_t when, uint32_t policyFlags); void prepareTouches(int32_t* outEdgeFlags, float* outXPrecision, float* outYPrecision); void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags); void preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture); 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. Loading services/input/PointerController.h +3 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,9 @@ public: // Tap at current location. // Briefly display one spot at the tapped location. SPOT_GESTURE_TAP, // Drag at current location. // Display spot at pressed location. SPOT_GESTURE_DRAG, // Button pressed but no finger is down. // Display spot at pressed location. SPOT_GESTURE_BUTTON_CLICK, Loading Loading
services/input/InputReader.cpp +140 −59 Original line number Diff line number Diff line Loading @@ -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. 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 // 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. // This is intended to be enough time to handle cases where the user puts down two Loading Loading @@ -2752,15 +2757,22 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { } } TouchResult touchResult; if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0 && mLastTouch.buttonState == mCurrentTouch.buttonState) { // Drop spurious syncs. touchResult = DROP_STROKE; } else { // Process touches and virtual keys. TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { suppressSwipeOntoVirtualKeys(when); if (mPointerController != NULL) { dispatchPointerGestures(when, policyFlags); dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); } dispatchTouches(when, policyFlags); } } // Copy current touch to last touch in preparation for the next cycle. // Keep the button state so we can track edge-triggered button state changes. Loading @@ -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( nsecs_t when, uint32_t policyFlags) { int32_t keyEventAction, keyEventFlags; Loading Loading @@ -3215,7 +3233,8 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags, *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. mPointerController->setPresentation( mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS Loading @@ -3224,7 +3243,11 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag // Update current gesture coordinates. bool cancelPreviousGesture, finishPreviousGesture; preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture); bool sendEvents = preparePointerGestures(when, &cancelPreviousGesture, &finishPreviousGesture, isTimeout); if (!sendEvents) { return; } // Show the pointer if needed. if (mPointerGesture.currentGestureMode != PointerGesture::NEUTRAL Loading @@ -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 // 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::SWIPE || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM; Loading Loading @@ -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. if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) { dispatchMotion(when, policyFlags, mPointerSource, Loading @@ -3372,13 +3376,49 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag } } void TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture) { bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) { *outCancelPreviousGesture = false; *outFinishPreviousGesture = false; 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. { VelocityTracker::Position positions[MAX_POINTERS]; Loading Loading @@ -3433,7 +3473,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, // 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. isQuietTime = true; } else if (mPointerGesture.lastGestureMode == PointerGesture::CLICK_OR_DRAG } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG && mCurrentTouch.pointerCount >= 2 && !isPointerDown(mCurrentTouch.buttonState)) { // Enter quiet time when releasing the button and there are still two or more Loading Loading @@ -3468,7 +3508,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, moveSpotsLocked(); } } 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. // Emit DOWN, MOVE, UP events at the pointer location. // Loading @@ -3482,11 +3522,11 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, // finger to drag then the active pointer should switch to the finger that is // being dragged. #if DEBUG_GESTURES LOGD("Gestures: CLICK_OR_DRAG activeTouchId=%d, " LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, " "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount); #endif // Reset state when just starting. if (mPointerGesture.lastGestureMode != PointerGesture::CLICK_OR_DRAG) { if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) { *outFinishPreviousGesture = true; mPointerGesture.activeGestureId = 0; } Loading @@ -3512,7 +3552,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.activeTouchId = activeTouchId = bestId; activeTouchChanged = true; #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); #endif } Loading @@ -3538,7 +3578,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, float x, y; mPointerController->getPosition(&x, &y); mPointerGesture.currentGestureMode = PointerGesture::CLICK_OR_DRAG; mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG; mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; Loading Loading @@ -3575,11 +3615,12 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, // Case 3. No fingers down and button is not pressed. (NEUTRAL) *outFinishPreviousGesture = true; // Watch for taps coming out of HOVER mode. // Watch for taps coming out of HOVER or TAP_DRAG mode. bool tapped = false; if (mPointerGesture.lastGestureMode == PointerGesture::HOVER if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) && mLastTouch.pointerCount == 1) { if (when <= mPointerGesture.tapTime + TAP_INTERVAL) { if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) { float x, y; mPointerController->getPosition(&x, &y); if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP Loading @@ -3587,6 +3628,10 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: TAP"); #endif mPointerGesture.tapUpTime = when; getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL); mPointerGesture.activeGestureId = 0; mPointerGesture.currentGestureMode = PointerGesture::TAP; mPointerGesture.currentGestureIdBits.clear(); Loading @@ -3603,7 +3648,6 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, AMOTION_EVENT_AXIS_PRESSURE, 1.0f); mPointerController->setButtonState(BUTTON_STATE_PRIMARY); mPointerController->setButtonState(0); if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP; Loading @@ -3624,8 +3668,8 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, } } else { #if DEBUG_GESTURES LOGD("Gestures: Not a TAP, delay=%lld", when - mPointerGesture.tapTime); LOGD("Gestures: Not a TAP, %0.3fms since down", (when - mPointerGesture.tapDownTime) * 0.000001f); #endif } } Loading @@ -3647,14 +3691,36 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, } } } 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. // Emit HOVER_MOVE events at the pointer location. assert(activeTouchId >= 0); // When in HOVER, emit HOVER_MOVE events at the pointer location. // 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 LOGD("Gestures: HOVER"); LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f", x - mPointerGesture.tapX, y - mPointerGesture.tapY); #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)) { const PointerData& currentPointer = Loading @@ -3667,35 +3733,49 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, * mLocked.pointerGestureYMovementScale; // 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); } bool down; 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; mPointerController->getPosition(&x, &y); mPointerGesture.currentGestureMode = PointerGesture::HOVER; mPointerGesture.currentGestureIdBits.clear(); mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; mPointerGesture.currentGestureCoords[0].clear(); 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_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) { mPointerGesture.tapTime = when; mPointerGesture.resetTap(); mPointerGesture.tapDownTime = when; mPointerGesture.tapX = x; mPointerGesture.tapY = y; } mPointerController->setButtonState(0); 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.markBit(activeTouchId); mPointerGesture.spotIdToIndex[activeTouchId] = 0; Loading Loading @@ -4098,6 +4178,7 @@ void TouchInputMapper::preparePointerGestures(nsecs_t when, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)); } #endif return true; } void TouchInputMapper::moveSpotsLocked() { Loading
services/input/InputReader.h +19 −9 Original line number Diff line number Diff line Loading @@ -570,6 +570,7 @@ public: const int32_t* keyCodes, uint8_t* outFlags); virtual void fadePointer(); virtual void timeoutExpired(nsecs_t when); protected: Mutex mLock; Loading Loading @@ -935,10 +936,15 @@ private: // Emits DOWN and UP events at the pointer location. 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. // Pointer follows the active finger if there is one. Other fingers are ignored. // Emits DOWN, MOVE and UP events at the pointer location. CLICK_OR_DRAG, BUTTON_CLICK_OR_DRAG, // Exactly one finger, button is not pressed. // Pointer follows the active finger. Loading Loading @@ -997,8 +1003,11 @@ private: // Time the pointer gesture last went down. nsecs_t downTime; // Time we started waiting for a tap gesture. nsecs_t tapTime; // Time when the pointer went down for a TAP. nsecs_t tapDownTime; // Time when the pointer went up for a TAP. nsecs_t tapUpTime; // Location of initial tap. float tapX, tapY; Loading Loading @@ -1030,12 +1039,13 @@ private: spotIdBits.clear(); downTime = 0; velocityTracker.clear(); resetTapTime(); resetTap(); resetQuietTime(); } void resetTapTime() { tapTime = LLONG_MIN; void resetTap() { tapDownTime = LLONG_MIN; tapUpTime = LLONG_MIN; } void resetQuietTime() { Loading @@ -1048,9 +1058,9 @@ private: TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags); void dispatchTouches(nsecs_t when, uint32_t policyFlags); void prepareTouches(int32_t* outEdgeFlags, float* outXPrecision, float* outYPrecision); void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags); void preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture); 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. Loading
services/input/PointerController.h +3 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,9 @@ public: // Tap at current location. // Briefly display one spot at the tapped location. SPOT_GESTURE_TAP, // Drag at current location. // Display spot at pressed location. SPOT_GESTURE_DRAG, // Button pressed but no finger is down. // Display spot at pressed location. SPOT_GESTURE_BUTTON_CLICK, Loading