Merge "Implement pointer acceleration." into honeycomb-mr2
This commit is contained in:
@ -627,6 +627,87 @@ private:
|
||||
int32_t mActivePointerId;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Specifies parameters that govern pointer or wheel acceleration.
|
||||
*/
|
||||
struct VelocityControlParameters {
|
||||
// A scale factor that is multiplied with the raw velocity deltas
|
||||
// prior to applying any other velocity control factors. The scale
|
||||
// factor should be used to adapt the input device resolution
|
||||
// (eg. counts per inch) to the output device resolution (eg. pixels per inch).
|
||||
//
|
||||
// Must be a positive value.
|
||||
// Default is 1.0 (no scaling).
|
||||
float scale;
|
||||
|
||||
// The scaled speed at which acceleration begins to be applied.
|
||||
// This value establishes the upper bound of a low speed regime for
|
||||
// small precise motions that are performed without any acceleration.
|
||||
//
|
||||
// Must be a non-negative value.
|
||||
// Default is 0.0 (no low threshold).
|
||||
float lowThreshold;
|
||||
|
||||
// The scaled speed at which maximum acceleration is applied.
|
||||
// The difference between highThreshold and lowThreshold controls
|
||||
// the range of speeds over which the acceleration factor is interpolated.
|
||||
// The wider the range, the smoother the acceleration.
|
||||
//
|
||||
// Must be a non-negative value greater than or equal to lowThreshold.
|
||||
// Default is 0.0 (no high threshold).
|
||||
float highThreshold;
|
||||
|
||||
// The acceleration factor.
|
||||
// When the speed is above the low speed threshold, the velocity will scaled
|
||||
// by an interpolated value between 1.0 and this amount.
|
||||
//
|
||||
// Must be a positive greater than or equal to 1.0.
|
||||
// Default is 1.0 (no acceleration).
|
||||
float acceleration;
|
||||
|
||||
VelocityControlParameters() :
|
||||
scale(1.0f), lowThreshold(0.0f), highThreshold(0.0f), acceleration(1.0f) {
|
||||
}
|
||||
|
||||
VelocityControlParameters(float scale, float lowThreshold,
|
||||
float highThreshold, float acceleration) :
|
||||
scale(scale), lowThreshold(lowThreshold),
|
||||
highThreshold(highThreshold), acceleration(acceleration) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Implements mouse pointer and wheel speed control and acceleration.
|
||||
*/
|
||||
class VelocityControl {
|
||||
public:
|
||||
VelocityControl();
|
||||
|
||||
/* Sets the various parameters. */
|
||||
void setParameters(const VelocityControlParameters& parameters);
|
||||
|
||||
/* Resets the current movement counters to zero.
|
||||
* This has the effect of nullifying any acceleration. */
|
||||
void reset();
|
||||
|
||||
/* Translates a raw movement delta into an appropriately
|
||||
* scaled / accelerated delta based on the current velocity. */
|
||||
void move(nsecs_t eventTime, float* deltaX, float* deltaY);
|
||||
|
||||
private:
|
||||
// If no movements are received within this amount of time,
|
||||
// we assume the movement has stopped and reset the movement counters.
|
||||
static const nsecs_t STOP_TIME = 500 * 1000000; // 500 ms
|
||||
|
||||
VelocityControlParameters mParameters;
|
||||
|
||||
nsecs_t mLastMovementTime;
|
||||
VelocityTracker::Position mRawPosition;
|
||||
VelocityTracker mVelocityTracker;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Describes the characteristics and capabilities of an input device.
|
||||
*/
|
||||
|
@ -13,6 +13,10 @@
|
||||
// Log debug messages about velocity tracking.
|
||||
#define DEBUG_VELOCITY 0
|
||||
|
||||
// Log debug messages about acceleration.
|
||||
#define DEBUG_ACCELERATION 0
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
@ -20,6 +24,7 @@
|
||||
#include <ui/Input.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
#include <binder/Parcel.h>
|
||||
@ -670,6 +675,11 @@ bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
|
||||
|
||||
// --- VelocityTracker ---
|
||||
|
||||
const uint32_t VelocityTracker::HISTORY_SIZE;
|
||||
const nsecs_t VelocityTracker::MAX_AGE;
|
||||
const nsecs_t VelocityTracker::MIN_WINDOW;
|
||||
const nsecs_t VelocityTracker::MIN_DURATION;
|
||||
|
||||
VelocityTracker::VelocityTracker() {
|
||||
clear();
|
||||
}
|
||||
@ -879,6 +889,85 @@ bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const
|
||||
}
|
||||
|
||||
|
||||
// --- VelocityControl ---
|
||||
|
||||
const nsecs_t VelocityControl::STOP_TIME;
|
||||
|
||||
VelocityControl::VelocityControl() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void VelocityControl::setParameters(const VelocityControlParameters& parameters) {
|
||||
mParameters = parameters;
|
||||
reset();
|
||||
}
|
||||
|
||||
void VelocityControl::reset() {
|
||||
mLastMovementTime = LLONG_MIN;
|
||||
mRawPosition.x = 0;
|
||||
mRawPosition.y = 0;
|
||||
mVelocityTracker.clear();
|
||||
}
|
||||
|
||||
void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
|
||||
if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
|
||||
if (eventTime >= mLastMovementTime + STOP_TIME) {
|
||||
#if DEBUG_ACCELERATION
|
||||
LOGD("VelocityControl: stopped, last movement was %0.3fms ago",
|
||||
(eventTime - mLastMovementTime) * 0.000001f);
|
||||
#endif
|
||||
reset();
|
||||
}
|
||||
|
||||
mLastMovementTime = eventTime;
|
||||
if (deltaX) {
|
||||
mRawPosition.x += *deltaX;
|
||||
}
|
||||
if (deltaY) {
|
||||
mRawPosition.y += *deltaY;
|
||||
}
|
||||
mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
|
||||
|
||||
float vx, vy;
|
||||
float scale = mParameters.scale;
|
||||
if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
|
||||
float speed = hypotf(vx, vy) * scale;
|
||||
if (speed >= mParameters.highThreshold) {
|
||||
// Apply full acceleration above the high speed threshold.
|
||||
scale *= mParameters.acceleration;
|
||||
} else if (speed > mParameters.lowThreshold) {
|
||||
// Linearly interpolate the acceleration to apply between the low and high
|
||||
// speed thresholds.
|
||||
scale *= 1 + (speed - mParameters.lowThreshold)
|
||||
/ (mParameters.highThreshold - mParameters.lowThreshold)
|
||||
* (mParameters.acceleration - 1);
|
||||
}
|
||||
|
||||
#if DEBUG_ACCELERATION
|
||||
LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
|
||||
"vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
|
||||
mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
|
||||
mParameters.acceleration,
|
||||
vx, vy, speed, scale / mParameters.scale);
|
||||
#endif
|
||||
} else {
|
||||
#if DEBUG_ACCELERATION
|
||||
LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
|
||||
mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
|
||||
mParameters.acceleration);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (deltaX) {
|
||||
*deltaX *= scale;
|
||||
}
|
||||
if (deltaY) {
|
||||
*deltaY *= scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- InputDeviceInfo ---
|
||||
|
||||
InputDeviceInfo::InputDeviceInfo() {
|
||||
|
@ -707,6 +707,20 @@ void InputReader::dump(String8& dump) {
|
||||
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);
|
||||
@ -1371,6 +1385,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() {
|
||||
@ -1432,6 +1450,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();
|
||||
@ -1585,11 +1608,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
|
||||
@ -1806,6 +1834,7 @@ void TouchInputMapper::initializeLocked() {
|
||||
mLocked.orientedRanges.haveOrientation = false;
|
||||
|
||||
mPointerGesture.reset();
|
||||
mPointerGesture.pointerVelocityControl.setParameters(mConfig->pointerVelocityControlParameters);
|
||||
}
|
||||
|
||||
void TouchInputMapper::configure() {
|
||||
@ -2239,11 +2268,10 @@ 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 = mConfig->pointerGestureMovementSpeedRatio
|
||||
* displayDiagonal / rawDiagonal;
|
||||
mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
|
||||
@ -3247,6 +3275,9 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
|
||||
if (!sendEvents) {
|
||||
return;
|
||||
}
|
||||
if (finishPreviousGesture) {
|
||||
cancelPreviousGesture = false;
|
||||
}
|
||||
|
||||
// Switch pointer presentation.
|
||||
mPointerController->setPresentation(
|
||||
@ -3436,6 +3467,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
||||
mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
|
||||
mPointerGesture.currentGestureIdBits.clear();
|
||||
|
||||
mPointerGesture.pointerVelocityControl.reset();
|
||||
|
||||
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
||||
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
||||
mPointerGesture.spotIdBits.clear();
|
||||
@ -3530,6 +3563,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
||||
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
|
||||
mPointerGesture.currentGestureIdBits.clear();
|
||||
|
||||
mPointerGesture.pointerVelocityControl.reset();
|
||||
|
||||
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
|
||||
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
|
||||
mPointerGesture.spotIdBits.clear();
|
||||
@ -3561,46 +3596,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 = 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 (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;
|
||||
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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
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;
|
||||
@ -3700,6 +3737,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
||||
}
|
||||
}
|
||||
|
||||
mPointerGesture.pointerVelocityControl.reset();
|
||||
|
||||
if (!tapped) {
|
||||
#if DEBUG_GESTURES
|
||||
LOGD("Gestures: NEUTRAL");
|
||||
@ -3756,9 +3795,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;
|
||||
@ -3820,16 +3863,32 @@ 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
|
||||
+ mConfig->pointerGestureMultitouchSettleInterval;
|
||||
if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
|
||||
&& mPointerGesture.lastGestureMode != PointerGesture::SWIPE
|
||||
&& mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
|
||||
*outFinishPreviousGesture = 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)
|
||||
* 0.000001f);
|
||||
#endif
|
||||
*outCancelPreviousGesture = true;
|
||||
} else {
|
||||
// Continue previous gesture.
|
||||
mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
|
||||
}
|
||||
|
||||
if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
|
||||
mPointerGesture.currentGestureMode = PointerGesture::PRESS;
|
||||
mPointerGesture.activeGestureId = 0;
|
||||
mPointerGesture.referenceIdBits.clear();
|
||||
mPointerGesture.pointerVelocityControl.reset();
|
||||
|
||||
if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
|
||||
&& mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) {
|
||||
@ -3850,37 +3909,18 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
||||
mPointerGesture.referenceGestureX = c.getAxisValue(AMOTION_EVENT_AXIS_X);
|
||||
mPointerGesture.referenceGestureY = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
|
||||
} else {
|
||||
// Use the centroid and pointer location as the reference points for the gesture.
|
||||
#if DEBUG_GESTURES
|
||||
LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
|
||||
"settle time remaining %0.3fms",
|
||||
(mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
|
||||
* 0.000001f);
|
||||
#endif
|
||||
needReference = true;
|
||||
mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
|
||||
&mPointerGesture.referenceTouchY);
|
||||
mPointerController->getPosition(&mPointerGesture.referenceGestureX,
|
||||
&mPointerGesture.referenceGestureY);
|
||||
}
|
||||
} 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)
|
||||
* 0.000001f);
|
||||
#endif
|
||||
*outCancelPreviousGesture = true;
|
||||
mPointerGesture.currentGestureMode = PointerGesture::PRESS;
|
||||
mPointerGesture.activeGestureId = 0;
|
||||
} else {
|
||||
// Continue previous gesture.
|
||||
mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
|
||||
}
|
||||
|
||||
if (needReference) {
|
||||
// Use the centroid and pointer location as the reference points for the gesture.
|
||||
mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
|
||||
&mPointerGesture.referenceTouchY);
|
||||
mPointerController->getPosition(&mPointerGesture.referenceGestureX,
|
||||
&mPointerGesture.referenceGestureY);
|
||||
}
|
||||
|
||||
if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
|
||||
@ -4010,10 +4050,14 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
|
||||
|
||||
mPointerGesture.referenceTouchX += commonDeltaX;
|
||||
mPointerGesture.referenceTouchY += commonDeltaY;
|
||||
mPointerGesture.referenceGestureX +=
|
||||
commonDeltaX * mLocked.pointerGestureXMovementScale;
|
||||
mPointerGesture.referenceGestureY +=
|
||||
commonDeltaY * mLocked.pointerGestureYMovementScale;
|
||||
|
||||
commonDeltaX *= mLocked.pointerGestureXMovementScale;
|
||||
commonDeltaY *= mLocked.pointerGestureYMovementScale;
|
||||
mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
|
||||
|
||||
mPointerGesture.referenceGestureX += commonDeltaX;
|
||||
mPointerGesture.referenceGestureY += commonDeltaY;
|
||||
|
||||
clampPositionUsingPointerBounds(mPointerController,
|
||||
&mPointerGesture.referenceGestureX,
|
||||
&mPointerGesture.referenceGestureY);
|
||||
|
@ -62,6 +62,12 @@ struct InputReaderConfiguration {
|
||||
// Devices with these names will be ignored.
|
||||
Vector<String8> excludedDeviceNames;
|
||||
|
||||
// Velocity control parameters for mouse pointer movements.
|
||||
VelocityControlParameters pointerVelocityControlParameters;
|
||||
|
||||
// Velocity control parameters for mouse wheel movements.
|
||||
VelocityControlParameters wheelVelocityControlParameters;
|
||||
|
||||
// Quiet time between certain pointer gesture transitions.
|
||||
// Time to allow for all fingers or buttons to settle into a stable state before
|
||||
// starting a new gesture.
|
||||
@ -128,6 +134,8 @@ struct InputReaderConfiguration {
|
||||
filterTouchEvents(false),
|
||||
filterJumpyTouchEvents(false),
|
||||
virtualKeyQuietTime(0),
|
||||
pointerVelocityControlParameters(1.0f, 80.0f, 400.0f, 4.0f),
|
||||
wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
|
||||
pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
|
||||
pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
|
||||
pointerGestureTapInterval(150 * 1000000LL), // 150 ms
|
||||
@ -137,7 +145,7 @@ struct InputReaderConfiguration {
|
||||
pointerGestureMultitouchMinSpeed(150.0f), // 150 pixels per second
|
||||
pointerGestureSwipeTransitionAngleCosine(0.5f), // cosine of 45degrees
|
||||
pointerGestureSwipeMaxWidthRatio(0.333f),
|
||||
pointerGestureMovementSpeedRatio(0.8f),
|
||||
pointerGestureMovementSpeedRatio(0.5f),
|
||||
pointerGestureZoomSpeedRatio(0.3f) { }
|
||||
};
|
||||
|
||||
@ -629,6 +637,12 @@ private:
|
||||
float mVWheelScale;
|
||||
float mHWheelScale;
|
||||
|
||||
// Velocity controls for mouse pointer and wheel movements.
|
||||
// The controls for X and Y wheel movements are separate to keep them decoupled.
|
||||
VelocityControl mPointerVelocityControl;
|
||||
VelocityControl mWheelXVelocityControl;
|
||||
VelocityControl mWheelYVelocityControl;
|
||||
|
||||
sp<PointerControllerInterface> mPointerController;
|
||||
|
||||
struct LockedState {
|
||||
@ -1133,6 +1147,9 @@ private:
|
||||
// A velocity tracker for determining whether to switch active pointers during drags.
|
||||
VelocityTracker velocityTracker;
|
||||
|
||||
// Velocity control for pointer movements.
|
||||
VelocityControl pointerVelocityControl;
|
||||
|
||||
void reset() {
|
||||
firstTouchTime = LLONG_MIN;
|
||||
activeTouchId = -1;
|
||||
@ -1147,6 +1164,7 @@ private:
|
||||
velocityTracker.clear();
|
||||
resetTap();
|
||||
resetQuietTime();
|
||||
pointerVelocityControl.reset();
|
||||
}
|
||||
|
||||
void resetTap() {
|
||||
|
Reference in New Issue
Block a user