diff options
Diffstat (limited to 'services/input/InputReader.cpp')
-rw-r--r-- | services/input/InputReader.cpp | 731 |
1 files changed, 337 insertions, 394 deletions
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 35e08d4..fcc6198 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -38,6 +38,7 @@ #include "InputReader.h" +#include <cutils/atomic.h> #include <cutils/log.h> #include <ui/Keyboard.h> #include <ui/VirtualKeyMap.h> @@ -61,65 +62,6 @@ namespace android { // Maximum number of slots supported when using the slot-based Multitouch Protocol B. static const size_t MAX_SLOTS = 32; -// Quiet time between certain gesture transitions. -// Time to allow for all fingers or buttons to settle into a stable state before -// starting a new gesture. -static const nsecs_t QUIET_INTERVAL = 100 * 1000000; // 100 ms - -// The minimum speed that a pointer must travel for us to consider switching the active -// touch pointer to it during a drag. This threshold is set to avoid switching due -// to noise from a finger resting on the touch pad (perhaps just pressing it down). -static const float DRAG_MIN_SWITCH_SPEED = 50.0f; // pixels per second - -// Tap gesture delay time. -// 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 = 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 -// fingers at almost but not quite exactly the same time. -static const nsecs_t MULTITOUCH_SETTLE_INTERVAL = 100 * 1000000; // 100ms - -// The transition from PRESS to SWIPE or FREEFORM gesture mode is made when -// both of the pointers are moving at least this fast. -static const float MULTITOUCH_MIN_SPEED = 150.0f; // pixels per second - -// 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 -// which indicates that the vectors are oriented in the same direction. -// When the vectors are oriented in the exactly same direction, the cosine is 1.0. -// (In exactly opposite directions, the cosine is -1.0.) -static const float SWIPE_TRANSITION_ANGLE_COSINE = 0.5f; // cosine of 45 degrees - -// The transition from PRESS to SWIPE gesture mode can only occur when the -// fingers are no more than this far apart relative to the diagonal size of -// the touch pad. For example, a ratio of 0.5 means that the fingers must be -// no more than half the diagonal size of the touch pad apart. -static const float SWIPE_MAX_WIDTH_RATIO = 0.333f; // 1/3 - -// The gesture movement speed factor relative to the size of the display. -// Movement speed applies when the fingers are moving in the same direction. -// Without acceleration, a full swipe of the touch pad diagonal in movement mode -// will cover this portion of the display diagonal. -static const float GESTURE_MOVEMENT_SPEED_RATIO = 0.8f; - -// The gesture zoom speed factor relative to the size of the display. -// Zoom speed applies when the fingers are mostly moving relative to each other -// to execute a scale gesture or similar. -// Without acceleration, a full swipe of the touch pad diagonal in zoom mode -// will cover this portion of the display diagonal. -static const float GESTURE_ZOOM_SPEED_RATIO = 0.3f; - - // --- Static Functions --- template<typename T> @@ -258,23 +200,6 @@ static int32_t calculateEdgeFlagsUsingPointerBounds( return edgeFlags; } -static void clampPositionUsingPointerBounds( - const sp<PointerControllerInterface>& pointerController, float* x, float* y) { - float minX, minY, maxX, maxY; - if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) { - if (*x < minX) { - *x = minX; - } else if (*x > maxX) { - *x = maxX; - } - if (*y < minY) { - *y = minY; - } else if (*y > maxY) { - *y = maxY; - } - } -} - static float calculateCommonVector(float a, float b) { if (a > 0 && b > 0) { return a < b ? a : b; @@ -319,8 +244,9 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputDispatcherInterface>& dispatcher) : mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), - mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) { - configureExcludedDevices(); + mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), + mRefreshConfiguration(0) { + configure(true /*firstTime*/); updateGlobalMetaState(); updateInputConfiguration(); } @@ -332,6 +258,11 @@ InputReader::~InputReader() { } void InputReader::loopOnce() { + if (android_atomic_acquire_load(&mRefreshConfiguration)) { + android_atomic_release_store(0, &mRefreshConfiguration); + configure(false /*firstTime*/); + } + int32_t timeoutMillis = -1; if (mNextTimeout != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); @@ -552,12 +483,12 @@ void InputReader::handleConfigurationChanged(nsecs_t when) { mDispatcher->notifyConfigurationChanged(when); } -void InputReader::configureExcludedDevices() { - Vector<String8> excludedDeviceNames; - mPolicy->getExcludedDeviceNames(excludedDeviceNames); +void InputReader::configure(bool firstTime) { + mPolicy->getReaderConfiguration(&mConfig); + mEventHub->setExcludedDevices(mConfig.excludedDeviceNames); - for (size_t i = 0; i < excludedDeviceNames.size(); i++) { - mEventHub->addExcludedDevice(excludedDeviceNames[i]); + if (!firstTime) { + mEventHub->reopenDevices(); } } @@ -778,6 +709,10 @@ bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, s } // release device registy reader lock } +void InputReader::refreshConfiguration() { + android_atomic_release_store(1, &mRefreshConfiguration); +} + void InputReader::dump(String8& dump) { mEventHub->dump(dump); dump.append("\n"); @@ -791,6 +726,60 @@ void InputReader::dump(String8& dump) { mDevices.valueAt(i)->dump(dump); } } // release device registy reader lock + + dump.append(INDENT "Configuration:\n"); + dump.append(INDENT2 "ExcludedDeviceNames: ["); + for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) { + if (i != 0) { + dump.append(", "); + } + dump.append(mConfig.excludedDeviceNames.itemAt(i).string()); + } + dump.append("]\n"); + dump.appendFormat(INDENT2 "FilterTouchEvents: %s\n", + toString(mConfig.filterTouchEvents)); + dump.appendFormat(INDENT2 "FilterJumpyTouchEvents: %s\n", + toString(mConfig.filterJumpyTouchEvents)); + dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n", + mConfig.virtualKeyQuietTime * 0.000001f); + + dump.appendFormat(INDENT2 "PointerVelocityControlParameters: " + "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n", + mConfig.pointerVelocityControlParameters.scale, + mConfig.pointerVelocityControlParameters.lowThreshold, + mConfig.pointerVelocityControlParameters.highThreshold, + mConfig.pointerVelocityControlParameters.acceleration); + + dump.appendFormat(INDENT2 "WheelVelocityControlParameters: " + "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n", + mConfig.wheelVelocityControlParameters.scale, + mConfig.wheelVelocityControlParameters.lowThreshold, + mConfig.wheelVelocityControlParameters.highThreshold, + mConfig.wheelVelocityControlParameters.acceleration); + + dump.appendFormat(INDENT2 "PointerGesture:\n"); + dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n", + mConfig.pointerGestureQuietInterval * 0.000001f); + dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n", + mConfig.pointerGestureDragMinSwitchSpeed); + dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n", + mConfig.pointerGestureTapInterval * 0.000001f); + dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n", + mConfig.pointerGestureTapDragInterval * 0.000001f); + dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n", + mConfig.pointerGestureTapSlop); + dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n", + mConfig.pointerGestureMultitouchSettleInterval * 0.000001f); + dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n", + mConfig.pointerGestureMultitouchMinDistance); + dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n", + mConfig.pointerGestureSwipeTransitionAngleCosine); + dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n", + mConfig.pointerGestureSwipeMaxWidthRatio); + dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n", + mConfig.pointerGestureMovementSpeedRatio); + dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n", + mConfig.pointerGestureZoomSpeedRatio); } @@ -1450,6 +1439,10 @@ void CursorInputMapper::configure() { mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL); mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL); + + mPointerVelocityControl.setParameters(getConfig()->pointerVelocityControlParameters); + mWheelXVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters); + mWheelYVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters); } void CursorInputMapper::configureParameters() { @@ -1511,6 +1504,11 @@ void CursorInputMapper::reset() { } } // release lock + // Reset velocity. + mPointerVelocityControl.reset(); + mWheelXVelocityControl.reset(); + mWheelYVelocityControl.reset(); + // Synthesize button up event on reset. nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC); mAccumulator.clear(); @@ -1674,11 +1672,16 @@ void CursorInputMapper::sync(nsecs_t when) { } else { vscroll = 0; } + mWheelYVelocityControl.move(when, NULL, &vscroll); + if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) { hscroll = mAccumulator.relHWheel; } else { hscroll = 0; } + mWheelXVelocityControl.move(when, &hscroll, NULL); + + mPointerVelocityControl.move(when, &deltaX, &deltaY); if (mPointerController != NULL) { if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0 @@ -1782,6 +1785,8 @@ void CursorInputMapper::fadePointer() { TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device) { + mConfig = getConfig(); + mLocked.surfaceOrientation = -1; mLocked.surfaceWidth = -1; mLocked.surfaceHeight = -1; @@ -1918,6 +1923,7 @@ void TouchInputMapper::initializeLocked() { mLocked.orientedRanges.haveDistance = false; mPointerGesture.reset(); + mPointerGesture.pointerVelocityControl.setParameters(mConfig->pointerVelocityControlParameters); } void TouchInputMapper::configure() { @@ -1960,14 +1966,15 @@ void TouchInputMapper::configure() { } void TouchInputMapper::configureParameters() { - mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents(); - mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents(); - mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); - mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime(); + mParameters.useBadTouchFilter = mConfig->filterTouchEvents; + mParameters.useAveragingTouchFilter = mConfig->filterTouchEvents; + mParameters.useJumpyTouchFilter = mConfig->filterJumpyTouchEvents; - // TODO: select the default gesture mode based on whether the device supports - // distinct multitouch - mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS; + // Use the pointer presentation mode for devices that do not support distinct + // multitouch. The spot-based presentation relies on being able to accurately + // locate two or more fingers on the touch pad. + mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT) + ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS; String8 gestureModeString; if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"), @@ -2388,26 +2395,26 @@ bool TouchInputMapper::configureSurfaceLocked() { mLocked.associatedDisplayHeight); // Scale movements such that one whole swipe of the touch pad covers a - // given area relative to the diagonal size of the display. + // given area relative to the diagonal size of the display when no acceleration + // is applied. // Assume that the touch pad has a square aspect ratio such that movements in // X and Y of the same number of raw units cover the same physical distance. - const float scaleFactor = 0.8f; - - mLocked.pointerGestureXMovementScale = GESTURE_MOVEMENT_SPEED_RATIO + mLocked.pointerGestureXMovementScale = mConfig->pointerGestureMovementSpeedRatio * displayDiagonal / rawDiagonal; mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale; // Scale zooms to cover a smaller range of the display than movements do. // This value determines the area around the pointer that is affected by freeform // pointer gestures. - mLocked.pointerGestureXZoomScale = GESTURE_ZOOM_SPEED_RATIO + mLocked.pointerGestureXZoomScale = mConfig->pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal; mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale; // Max width between pointers to detect a swipe gesture is more than some fraction // of the diagonal axis of the touch pad. Touches that are wider than this are // translated into freeform gestures. - mLocked.pointerGestureMaxSwipeWidth = SWIPE_MAX_WIDTH_RATIO * rawDiagonal; + mLocked.pointerGestureMaxSwipeWidth = + mConfig->pointerGestureSwipeMaxWidthRatio * rawDiagonal; // Reset the current pointer gesture. mPointerGesture.reset(); @@ -3130,8 +3137,8 @@ void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) { // area and accidentally triggers a virtual key. This often happens when virtual keys // are layed out below the screen near to where the on screen keyboard's space bar // is displayed. - if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { - mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime); + if (mConfig->virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { + mContext->disableVirtualKeysUntil(when + mConfig->virtualKeyQuietTime); } } @@ -3474,12 +3481,6 @@ void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags, void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout) { - // Switch pointer presentation. - mPointerController->setPresentation( - mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS - ? PointerControllerInterface::PRESENTATION_SPOT - : PointerControllerInterface::PRESENTATION_POINTER); - // Update current gesture coordinates. bool cancelPreviousGesture, finishPreviousGesture; bool sendEvents = preparePointerGestures(when, @@ -3487,6 +3488,22 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag if (!sendEvents) { return; } + if (finishPreviousGesture) { + cancelPreviousGesture = false; + } + + // Update the pointer presentation and spots. + if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT); + if (finishPreviousGesture || cancelPreviousGesture) { + mPointerController->clearSpots(); + } + mPointerController->setSpots(mPointerGesture.currentGestureCoords, + mPointerGesture.currentGestureIdToIndex, + mPointerGesture.currentGestureIdBits); + } else { + mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER); + } // Show or hide the pointer if needed. switch (mPointerGesture.currentGestureMode) { @@ -3669,9 +3686,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #endif if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { - if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) { + if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) { // The tap/drag timeout has not yet expired. - getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL); + getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + + mConfig->pointerGestureTapDragInterval); } else { // The tap is finished. #if DEBUG_GESTURES @@ -3683,11 +3701,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; mPointerGesture.currentGestureIdBits.clear(); - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL; - mPointerGesture.spotIdBits.clear(); - moveSpotsLocked(); - } + mPointerGesture.pointerVelocityControl.reset(); return true; } } @@ -3740,7 +3754,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (activeTouchId < 0) { mPointerGesture.resetQuietTime(); } else { - isQuietTime = when < mPointerGesture.quietTime + QUIET_INTERVAL; + isQuietTime = when < mPointerGesture.quietTime + mConfig->pointerGestureQuietInterval; if (!isQuietTime) { if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS || mPointerGesture.lastGestureMode == PointerGesture::SWIPE @@ -3768,20 +3782,18 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (isQuietTime) { // Case 1: Quiet time. (QUIET) #if DEBUG_GESTURES - LOGD("Gestures: QUIET for next %0.3fms", - (mPointerGesture.quietTime + QUIET_INTERVAL - when) * 0.000001f); + LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime + + mConfig->pointerGestureQuietInterval - when) * 0.000001f); #endif - *outFinishPreviousGesture = true; + if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) { + *outFinishPreviousGesture = true; + } mPointerGesture.activeGestureId = -1; mPointerGesture.currentGestureMode = PointerGesture::QUIET; mPointerGesture.currentGestureIdBits.clear(); - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL; - mPointerGesture.spotIdBits.clear(); - moveSpotsLocked(); - } + mPointerGesture.pointerVelocityControl.reset(); } else if (isPointerDown(mCurrentTouch.buttonState)) { // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG) // The pointer follows the active touch point. @@ -3808,46 +3820,48 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Switch pointers if needed. // Find the fastest pointer and follow it. - if (activeTouchId >= 0) { - if (mCurrentTouch.pointerCount > 1) { - int32_t bestId = -1; - float bestSpeed = DRAG_MIN_SWITCH_SPEED; - for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { - uint32_t id = mCurrentTouch.pointers[i].id; - float vx, vy; - if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) { - float speed = hypotf(vx, vy); - if (speed > bestSpeed) { - bestId = id; - bestSpeed = speed; - } + if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) { + int32_t bestId = -1; + float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed; + for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { + uint32_t id = mCurrentTouch.pointers[i].id; + float vx, vy; + if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) { + float speed = hypotf(vx, vy); + if (speed > bestSpeed) { + bestId = id; + bestSpeed = speed; } } - if (bestId >= 0 && bestId != activeTouchId) { - mPointerGesture.activeTouchId = activeTouchId = bestId; - activeTouchChanged = true; + } + if (bestId >= 0 && bestId != activeTouchId) { + mPointerGesture.activeTouchId = activeTouchId = bestId; + activeTouchChanged = true; #if DEBUG_GESTURES - LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, " - "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed); + LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, " + "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed); #endif - } } + } - if (mLastTouch.idBits.hasBit(activeTouchId)) { - const PointerData& currentPointer = - mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]]; - const PointerData& lastPointer = - mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]]; - float deltaX = (currentPointer.x - lastPointer.x) - * mLocked.pointerGestureXMovementScale; - float deltaY = (currentPointer.y - lastPointer.y) - * mLocked.pointerGestureYMovementScale; - - // Move the pointer using a relative motion. - // When using spots, the click will occur at the position of the anchor - // spot and all other spots will move there. - mPointerController->move(deltaX, deltaY); - } + if (activeTouchId >= 0 && mLastTouch.idBits.hasBit(activeTouchId)) { + const PointerData& currentPointer = + mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]]; + const PointerData& lastPointer = + mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]]; + float deltaX = (currentPointer.x - lastPointer.x) + * mLocked.pointerGestureXMovementScale; + float deltaY = (currentPointer.y - lastPointer.y) + * mLocked.pointerGestureYMovementScale; + + mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY); + + // Move the pointer using a relative motion. + // When using spots, the click will occur at the position of the anchor + // spot and all other spots will move there. + mPointerController->move(deltaX, deltaY); + } else { + mPointerGesture.pointerVelocityControl.reset(); } float x, y; @@ -3865,49 +3879,30 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, 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, 1.0f); - - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - if (activeTouchId >= 0) { - // Collapse all spots into one point at the pointer location. - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_BUTTON_DRAG; - mPointerGesture.spotIdBits.clear(); - for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { - uint32_t id = mCurrentTouch.pointers[i].id; - mPointerGesture.spotIdBits.markBit(id); - mPointerGesture.spotIdToIndex[id] = i; - mPointerGesture.spotCoords[i] = mPointerGesture.currentGestureCoords[0]; - } - } else { - // No fingers. Generate a spot at the pointer location so the - // anchor appears to be pressed. - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_BUTTON_CLICK; - mPointerGesture.spotIdBits.clear(); - mPointerGesture.spotIdBits.markBit(0); - mPointerGesture.spotIdToIndex[0] = 0; - mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0]; - } - moveSpotsLocked(); - } } else if (mCurrentTouch.pointerCount == 0) { // Case 3. No fingers down and button is not pressed. (NEUTRAL) - *outFinishPreviousGesture = true; + if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) { + *outFinishPreviousGesture = true; + } // Watch for taps coming out of HOVER or TAP_DRAG mode. + // Checking for taps after TAP_DRAG allows us to detect double-taps. bool tapped = false; if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) && mLastTouch.pointerCount == 1) { - if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) { + if (when <= mPointerGesture.tapDownTime + mConfig->pointerGestureTapInterval) { float x, y; mPointerController->getPosition(&x, &y); - if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP - && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) { + if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop + && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) { #if DEBUG_GESTURES LOGD("Gestures: TAP"); #endif mPointerGesture.tapUpTime = when; - getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL); + getContext()->requestTimeoutAtTime(when + + mConfig->pointerGestureTapDragInterval); mPointerGesture.activeGestureId = 0; mPointerGesture.currentGestureMode = PointerGesture::TAP; @@ -3929,15 +3924,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureCoords[0].setAxisValue( AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP; - mPointerGesture.spotIdBits.clear(); - mPointerGesture.spotIdBits.markBit(lastActiveTouchId); - mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0; - mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0]; - moveSpotsLocked(); - } - tapped = true; } else { #if DEBUG_GESTURES @@ -3954,6 +3940,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } } + mPointerGesture.pointerVelocityControl.reset(); + if (!tapped) { #if DEBUG_GESTURES LOGD("Gestures: NEUTRAL"); @@ -3961,12 +3949,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.activeGestureId = -1; mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL; mPointerGesture.currentGestureIdBits.clear(); - - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL; - mPointerGesture.spotIdBits.clear(); - moveSpotsLocked(); - } } } else if (mCurrentTouch.pointerCount == 1) { // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG) @@ -3977,11 +3959,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureMode = PointerGesture::HOVER; if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { - if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) { + if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) { float x, y; mPointerController->getPosition(&x, &y); - if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP - && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) { + if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop + && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) { mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; } else { #if DEBUG_GESTURES @@ -4010,9 +3992,13 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, float deltaY = (currentPointer.y - lastPointer.y) * mLocked.pointerGestureYMovementScale; + mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY); + // Move the pointer using a relative motion. // When using spots, the hover or drag will occur at the position of the anchor spot. mPointerController->move(deltaX, deltaY); + } else { + mPointerGesture.pointerVelocityControl.reset(); } bool down; @@ -4025,7 +4011,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: HOVER"); #endif - *outFinishPreviousGesture = true; + if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) { + *outFinishPreviousGesture = true; + } mPointerGesture.activeGestureId = 0; down = false; } @@ -4052,16 +4040,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.tapX = x; mPointerGesture.tapY = y; } - - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = down ? PointerControllerInterface::SPOT_GESTURE_DRAG - : PointerControllerInterface::SPOT_GESTURE_HOVER; - mPointerGesture.spotIdBits.clear(); - mPointerGesture.spotIdBits.markBit(activeTouchId); - mPointerGesture.spotIdToIndex[activeTouchId] = 0; - mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0]; - moveSpotsLocked(); - } } else { // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM) // We need to provide feedback for each finger that goes down so we cannot wait @@ -4078,129 +4056,165 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // a decision to transition into SWIPE or FREEFORM mode accordingly. LOG_ASSERT(activeTouchId >= 0); - bool needReference = false; - bool settled = when >= mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL; + bool settled = when >= mPointerGesture.firstTouchTime + + mConfig->pointerGestureMultitouchSettleInterval; if (mPointerGesture.lastGestureMode != PointerGesture::PRESS && mPointerGesture.lastGestureMode != PointerGesture::SWIPE && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { *outFinishPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::PRESS; - mPointerGesture.activeGestureId = 0; - mPointerGesture.referenceIdBits.clear(); - - if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS - && mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) { - // The spot is already visible and has settled, use it as the reference point - // for the gesture. Other spots will be positioned relative to this one. -#if DEBUG_GESTURES - LOGD("Gestures: Using active spot as reference for MULTITOUCH, " - "settle time expired %0.3fms ago", - (when - mPointerGesture.firstTouchTime - MULTITOUCH_SETTLE_INTERVAL) - * 0.000001f); -#endif - const PointerData& d = mLastTouch.pointers[mLastTouch.idToIndex[ - mPointerGesture.activeTouchId]]; - mPointerGesture.referenceTouchX = d.x; - mPointerGesture.referenceTouchY = d.y; - const PointerCoords& c = mPointerGesture.spotCoords[mPointerGesture.spotIdToIndex[ - mPointerGesture.activeTouchId]]; - mPointerGesture.referenceGestureX = c.getAxisValue(AMOTION_EVENT_AXIS_X); - mPointerGesture.referenceGestureY = c.getAxisValue(AMOTION_EVENT_AXIS_Y); - } else { -#if DEBUG_GESTURES - LOGD("Gestures: Using centroid as reference for MULTITOUCH, " - "settle time remaining %0.3fms", - (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when) - * 0.000001f); -#endif - needReference = true; - } } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) { // Additional pointers have gone down but not yet settled. // Reset the gesture. #if DEBUG_GESTURES LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, " - "settle time remaining %0.3fms", - (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when) + "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime + + mConfig->pointerGestureMultitouchSettleInterval - when) * 0.000001f); #endif *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::PRESS; - mPointerGesture.activeGestureId = 0; } else { // Continue previous gesture. mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode; } - if (needReference) { + if (*outFinishPreviousGesture || *outCancelPreviousGesture) { + mPointerGesture.currentGestureMode = PointerGesture::PRESS; + mPointerGesture.activeGestureId = 0; + mPointerGesture.referenceIdBits.clear(); + mPointerGesture.pointerVelocityControl.reset(); + // Use the centroid and pointer location as the reference points for the gesture. +#if DEBUG_GESTURES + LOGD("Gestures: Using centroid as reference for MULTITOUCH, " + "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime + + mConfig->pointerGestureMultitouchSettleInterval - when) + * 0.000001f); +#endif mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX, &mPointerGesture.referenceTouchY); mPointerController->getPosition(&mPointerGesture.referenceGestureX, &mPointerGesture.referenceGestureY); } + // Clear the reference deltas for fingers not yet included in the reference calculation. + for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value); + !idBits.isEmpty(); ) { + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + + mPointerGesture.referenceDeltas[id].dx = 0; + mPointerGesture.referenceDeltas[id].dy = 0; + } + mPointerGesture.referenceIdBits = mCurrentTouch.idBits; + + // Add delta for all fingers and calculate a common movement delta. + float commonDeltaX = 0, commonDeltaY = 0; + BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value); + for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { + bool first = (idBits == commonIdBits); + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + + const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]]; + const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]]; + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; + delta.dx += cpd.x - lpd.x; + delta.dy += cpd.y - lpd.y; + + if (first) { + commonDeltaX = delta.dx; + commonDeltaY = delta.dy; + } else { + commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); + commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); + } + } + + // Consider transitions from PRESS to SWIPE or MULTITOUCH. if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) { - float d; - if (mCurrentTouch.pointerCount > 2) { - // There are more than two pointers, switch to FREEFORM. + float dist[MAX_POINTER_ID + 1]; + int32_t distOverThreshold = 0; + for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { + uint32_t id = idBits.firstMarkedBit(); + idBits.clearBit(id); + + PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; + dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale, + delta.dy * mLocked.pointerGestureYZoomScale); + if (dist[id] > mConfig->pointerGestureMultitouchMinDistance) { + distOverThreshold += 1; + } + } + + // Only transition when at least two pointers have moved further than + // the minimum distance threshold. + if (distOverThreshold >= 2) { + float d; + if (mCurrentTouch.pointerCount > 2) { + // There are more than two pointers, switch to FREEFORM. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", - mCurrentTouch.pointerCount); + LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2", + mCurrentTouch.pointerCount); #endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else if (((d = distance( - mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y, - mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y)) - > mLocked.pointerGestureMaxSwipeWidth)) { - // There are two pointers but they are too far apart, switch to FREEFORM. + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } else if (((d = distance( + mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y, + mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y)) + > mLocked.pointerGestureMaxSwipeWidth)) { + // There are two pointers but they are too far apart for a SWIPE, + // switch to FREEFORM. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", - d, mLocked.pointerGestureMaxSwipeWidth); + LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f", + d, mLocked.pointerGestureMaxSwipeWidth); #endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; - } else { - // There are two pointers. Wait for both pointers to start moving - // before deciding whether this is a SWIPE or FREEFORM gesture. - uint32_t id1 = mCurrentTouch.pointers[0].id; - uint32_t id2 = mCurrentTouch.pointers[1].id; - - float vx1, vy1, vx2, vy2; - mPointerGesture.velocityTracker.getVelocity(id1, &vx1, &vy1); - mPointerGesture.velocityTracker.getVelocity(id2, &vx2, &vy2); - - float speed1 = hypotf(vx1, vy1); - float speed2 = hypotf(vx2, vy2); - if (speed1 >= MULTITOUCH_MIN_SPEED && speed2 >= MULTITOUCH_MIN_SPEED) { - // Calculate the dot product of the velocity vectors. - // When the vectors are oriented in approximately the same direction, - // the angle betweeen them is near zero and the cosine of the angle - // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2). - float dot = vx1 * vx2 + vy1 * vy2; - float cosine = dot / (speed1 * speed2); // denominator always > 0 - if (cosine >= SWIPE_TRANSITION_ANGLE_COSINE) { - // Pointers are moving in the same direction. Switch to SWIPE. + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } else { + // There are two pointers. Wait for both pointers to start moving + // before deciding whether this is a SWIPE or FREEFORM gesture. + uint32_t id1 = mCurrentTouch.pointers[0].id; + uint32_t id2 = mCurrentTouch.pointers[1].id; + float dist1 = dist[id1]; + float dist2 = dist[id2]; + if (dist1 >= mConfig->pointerGestureMultitouchMinDistance + && dist2 >= mConfig->pointerGestureMultitouchMinDistance) { + // Calculate the dot product of the displacement vectors. + // When the vectors are oriented in approximately the same direction, + // the angle betweeen them is near zero and the cosine of the angle + // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2). + PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1]; + PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2]; + float dx1 = delta1.dx * mLocked.pointerGestureXZoomScale; + float dy1 = delta1.dy * mLocked.pointerGestureYZoomScale; + float dx2 = delta2.dx * mLocked.pointerGestureXZoomScale; + float dy2 = delta2.dy * mLocked.pointerGestureYZoomScale; + float dot = dx1 * dx2 + dy1 * dy2; + float cosine = dot / (dist1 * dist2); // denominator always > 0 + if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) { + // Pointers are moving in the same direction. Switch to SWIPE. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to SWIPE, " - "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, " - "cosine %0.3f >= %0.3f", - speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED, - cosine, SWIPE_TRANSITION_ANGLE_COSINE); + LOGD("Gestures: PRESS transitioned to SWIPE, " + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " + "cosine %0.3f >= %0.3f", + dist1, mConfig->pointerGestureMultitouchMinDistance, + dist2, mConfig->pointerGestureMultitouchMinDistance, + cosine, mConfig->pointerGestureSwipeTransitionAngleCosine); #endif - mPointerGesture.currentGestureMode = PointerGesture::SWIPE; - } else { - // Pointers are moving in different directions. Switch to FREEFORM. + mPointerGesture.currentGestureMode = PointerGesture::SWIPE; + } else { + // Pointers are moving in different directions. Switch to FREEFORM. #if DEBUG_GESTURES - LOGD("Gestures: PRESS transitioned to FREEFORM, " - "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, " - "cosine %0.3f < %0.3f", - speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED, - cosine, SWIPE_TRANSITION_ANGLE_COSINE); + LOGD("Gestures: PRESS transitioned to FREEFORM, " + "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " + "cosine %0.3f < %0.3f", + dist1, mConfig->pointerGestureMultitouchMinDistance, + dist2, mConfig->pointerGestureMultitouchMinDistance, + cosine, mConfig->pointerGestureSwipeTransitionAngleCosine); #endif - *outCancelPreviousGesture = true; - mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + *outCancelPreviousGesture = true; + mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; + } } } } @@ -4217,63 +4231,28 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } } - // Clear the reference deltas for fingers not yet included in the reference calculation. - for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value); - !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); - - mPointerGesture.referenceDeltas[id].dx = 0; - mPointerGesture.referenceDeltas[id].dy = 0; - } - mPointerGesture.referenceIdBits = mCurrentTouch.idBits; - - // Move the reference points based on the overall group motion of the fingers. - // The objective is to calculate a vector delta that is common to the movement - // of all fingers. - BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value); - if (!commonIdBits.isEmpty()) { - float commonDeltaX = 0, commonDeltaY = 0; - for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { - bool first = (idBits == commonIdBits); + // Move the reference points based on the overall group motion of the fingers + // except in PRESS mode while waiting for a transition to occur. + if (mPointerGesture.currentGestureMode != PointerGesture::PRESS + && (commonDeltaX || commonDeltaY)) { + for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); - const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]]; - const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]]; PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - delta.dx += cpd.x - lpd.x; - delta.dy += cpd.y - lpd.y; - - if (first) { - commonDeltaX = delta.dx; - commonDeltaY = delta.dy; - } else { - commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); - commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); - } + delta.dx = 0; + delta.dy = 0; } - if (commonDeltaX || commonDeltaY) { - for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) { - uint32_t id = idBits.firstMarkedBit(); - idBits.clearBit(id); + mPointerGesture.referenceTouchX += commonDeltaX; + mPointerGesture.referenceTouchY += commonDeltaY; - PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; - delta.dx = 0; - delta.dy = 0; - } + commonDeltaX *= mLocked.pointerGestureXMovementScale; + commonDeltaY *= mLocked.pointerGestureYMovementScale; + mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); - mPointerGesture.referenceTouchX += commonDeltaX; - mPointerGesture.referenceTouchY += commonDeltaY; - mPointerGesture.referenceGestureX += - commonDeltaX * mLocked.pointerGestureXMovementScale; - mPointerGesture.referenceGestureY += - commonDeltaY * mLocked.pointerGestureYMovementScale; - clampPositionUsingPointerBounds(mPointerController, - &mPointerGesture.referenceGestureX, - &mPointerGesture.referenceGestureY); - } + mPointerGesture.referenceGestureX += commonDeltaX; + mPointerGesture.referenceGestureY += commonDeltaY; } // Report gestures. @@ -4299,10 +4278,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_PRESS; - } } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { // SWIPE mode. #if DEBUG_GESTURES @@ -4325,10 +4300,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_SWIPE; - } } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) { // FREEFORM mode. #if DEBUG_GESTURES @@ -4430,33 +4401,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, "activeGestureId=%d", mPointerGesture.activeGestureId); #endif } - - if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { - mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_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) { - mPointerGesture.spotIdBits.clear(); - for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { - uint32_t id = mCurrentTouch.pointers[i].id; - mPointerGesture.spotIdBits.markBit(id); - mPointerGesture.spotIdToIndex[id] = i; - - float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX) - * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX; - float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY) - * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY; - - mPointerGesture.spotCoords[i].clear(); - mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, x); - mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, y); - mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - } - moveSpotsLocked(); } } @@ -4499,11 +4443,6 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, return true; } -void TouchInputMapper::moveSpotsLocked() { - mPointerController->setSpots(mPointerGesture.spotGesture, - mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex, mPointerGesture.spotIdBits); -} - void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, const PointerProperties* properties, const PointerCoords* coords, @@ -5376,7 +5315,8 @@ MultiTouchInputMapper::~MultiTouchInputMapper() { } void MultiTouchInputMapper::clearState() { - mAccumulator.clear(mSlotCount); + mAccumulator.clearSlots(mSlotCount); + mAccumulator.clearButtons(); mButtonState = 0; } @@ -5410,13 +5350,13 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) { } if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) { - if (newSlot) { #if DEBUG_POINTERS + if (newSlot) { LOGW("MultiTouch device %s emitted invalid slot index %d but it " "should be between 0 and %d; ignoring this slot.", getDeviceName().string(), mAccumulator.currentSlot, mSlotCount); -#endif } +#endif break; } @@ -5619,7 +5559,10 @@ void MultiTouchInputMapper::sync(nsecs_t when) { syncTouch(when, havePointerIds); - mAccumulator.clear(mUsingSlotsProtocol ? 0 : mSlotCount); + if (!mUsingSlotsProtocol) { + mAccumulator.clearSlots(mSlotCount); + } + mAccumulator.clearButtons(); } void MultiTouchInputMapper::configureRawAxes() { |