am fa574c0e: Merge "Touch pad UX improvements." into honeycomb-mr2

* commit 'fa574c0e0ce7f84eea34e96dededea35329dbd18':
  Touch pad UX improvements.
This commit is contained in:
Jeff Brown
2011-05-25 19:16:39 -07:00
committed by Android Git Automerger
5 changed files with 158 additions and 52 deletions

View File

@ -1627,7 +1627,7 @@ void CursorInputMapper::sync(nsecs_t when) {
mPointerController->setButtonState(mLocked.buttonState); mPointerController->setButtonState(mLocked.buttonState);
} }
mPointerController->unfade(); mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
} }
float x, y; float x, y;
@ -1686,7 +1686,7 @@ void CursorInputMapper::fadePointer() {
{ // acquire lock { // acquire lock
AutoMutex _l(mLock); AutoMutex _l(mLock);
if (mPointerController != NULL) { if (mPointerController != NULL) {
mPointerController->fade(); mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
} }
} // release lock } // release lock
} }
@ -1873,10 +1873,22 @@ void TouchInputMapper::configureParameters() {
mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime(); mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
// TODO: Make this configurable. // TODO: select the default gesture mode based on whether the device supports
//mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER; // distinct multitouch
mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS; mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
String8 gestureModeString;
if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
gestureModeString)) {
if (gestureModeString == "pointer") {
mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
} else if (gestureModeString == "spots") {
mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
} else if (gestureModeString != "default") {
LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
}
}
if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X) if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
|| getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) { || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
// The device is a cursor device with a touch pad attached. // The device is a cursor device with a touch pad attached.
@ -1897,7 +1909,7 @@ void TouchInputMapper::configureParameters() {
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD; mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
} else if (deviceTypeString == "pointer") { } else if (deviceTypeString == "pointer") {
mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
} else { } else if (deviceTypeString != "default") {
LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
} }
} }
@ -1915,6 +1927,17 @@ void TouchInputMapper::configureParameters() {
void TouchInputMapper::dumpParameters(String8& dump) { void TouchInputMapper::dumpParameters(String8& dump) {
dump.append(INDENT3 "Parameters:\n"); dump.append(INDENT3 "Parameters:\n");
switch (mParameters.gestureMode) {
case Parameters::GESTURE_MODE_POINTER:
dump.append(INDENT4 "GestureMode: pointer\n");
break;
case Parameters::GESTURE_MODE_SPOTS:
dump.append(INDENT4 "GestureMode: spots\n");
break;
default:
assert(false);
}
switch (mParameters.deviceType) { switch (mParameters.deviceType) {
case Parameters::DEVICE_TYPE_TOUCH_SCREEN: case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
dump.append(INDENT4 "DeviceType: touchScreen\n"); dump.append(INDENT4 "DeviceType: touchScreen\n");
@ -3251,10 +3274,36 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag
return; return;
} }
// Show the pointer if needed. // Show or hide the pointer if needed.
if (mPointerGesture.currentGestureMode != PointerGesture::NEUTRAL switch (mPointerGesture.currentGestureMode) {
&& mPointerGesture.currentGestureMode != PointerGesture::QUIET) { case PointerGesture::NEUTRAL:
mPointerController->unfade(); case PointerGesture::QUIET:
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
&& (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
|| mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
// Remind the user of where the pointer is after finishing a gesture with spots.
mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
}
break;
case PointerGesture::TAP:
case PointerGesture::TAP_DRAG:
case PointerGesture::BUTTON_CLICK_OR_DRAG:
case PointerGesture::HOVER:
case PointerGesture::PRESS:
// Unfade the pointer when the current gesture manipulates the
// area directly under the pointer.
mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
break;
case PointerGesture::SWIPE:
case PointerGesture::FREEFORM:
// Fade the pointer when the current gesture manipulates a different
// area and there are spots to guide the user experience.
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
} else {
mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
}
break;
} }
// Send events! // Send events!
@ -3808,6 +3857,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
*outFinishPreviousGesture = true; *outFinishPreviousGesture = true;
mPointerGesture.currentGestureMode = PointerGesture::PRESS; mPointerGesture.currentGestureMode = PointerGesture::PRESS;
mPointerGesture.activeGestureId = 0; mPointerGesture.activeGestureId = 0;
mPointerGesture.referenceIdBits.clear();
if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
&& mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) { && mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) {
@ -3938,6 +3988,17 @@ 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. // 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 // The objective is to calculate a vector delta that is common to the movement
// of all fingers. // of all fingers.
@ -3951,27 +4012,39 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when,
const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]]; const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]]; const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
float deltaX = cpd.x - lpd.x; PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
float deltaY = cpd.y - lpd.y; delta.dx += cpd.x - lpd.x;
delta.dy += cpd.y - lpd.y;
if (first) { if (first) {
commonDeltaX = deltaX; commonDeltaX = delta.dx;
commonDeltaY = deltaY; commonDeltaY = delta.dy;
} else { } else {
commonDeltaX = calculateCommonVector(commonDeltaX, deltaX); commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
commonDeltaY = calculateCommonVector(commonDeltaY, deltaY); commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
} }
} }
mPointerGesture.referenceTouchX += commonDeltaX; if (commonDeltaX || commonDeltaY) {
mPointerGesture.referenceTouchY += commonDeltaY; for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
mPointerGesture.referenceGestureX += uint32_t id = idBits.firstMarkedBit();
commonDeltaX * mLocked.pointerGestureXMovementScale; idBits.clearBit(id);
mPointerGesture.referenceGestureY +=
commonDeltaY * mLocked.pointerGestureYMovementScale; PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
clampPositionUsingPointerBounds(mPointerController, delta.dx = 0;
&mPointerGesture.referenceGestureX, delta.dy = 0;
&mPointerGesture.referenceGestureY); }
mPointerGesture.referenceTouchX += commonDeltaX;
mPointerGesture.referenceTouchY += commonDeltaY;
mPointerGesture.referenceGestureX +=
commonDeltaX * mLocked.pointerGestureXMovementScale;
mPointerGesture.referenceGestureY +=
commonDeltaY * mLocked.pointerGestureYMovementScale;
clampPositionUsingPointerBounds(mPointerController,
&mPointerGesture.referenceGestureX,
&mPointerGesture.referenceGestureY);
}
} }
// Report gestures. // Report gestures.
@ -4255,7 +4328,7 @@ void TouchInputMapper::fadePointer() {
{ // acquire lock { // acquire lock
AutoMutex _l(mLock); AutoMutex _l(mLock);
if (mPointerController != NULL) { if (mPointerController != NULL) {
mPointerController->fade(); mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
} }
} // release lock } // release lock
} }

View File

@ -1021,6 +1021,14 @@ private:
float referenceGestureX; // reference gesture X/Y coordinates in pixels float referenceGestureX; // reference gesture X/Y coordinates in pixels
float referenceGestureY; float referenceGestureY;
// Distance that each pointer has traveled which has not yet been
// subsumed into the reference gesture position.
BitSet32 referenceIdBits;
struct Delta {
float dx, dy;
};
Delta referenceDeltas[MAX_POINTER_ID + 1];
// Describes how touch ids are mapped to gesture ids for freeform gestures. // Describes how touch ids are mapped to gesture ids for freeform gestures.
uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1]; uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];

View File

@ -69,10 +69,10 @@ PointerController::PointerController(const sp<PointerControllerPolicyInterface>&
mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL; mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
mLocked.pointerIsFading = true; // keep the pointer initially faded mLocked.pointerFadeDirection = 0;
mLocked.pointerX = 0; mLocked.pointerX = 0;
mLocked.pointerY = 0; mLocked.pointerY = 0;
mLocked.pointerAlpha = 0.0f; mLocked.pointerAlpha = 0.0f; // pointer is initially faded
mLocked.pointerSprite = mSpriteController->createSprite(); mLocked.pointerSprite = mSpriteController->createSprite();
mLocked.pointerIconChanged = false; mLocked.pointerIconChanged = false;
@ -191,23 +191,37 @@ void PointerController::getPosition(float* outX, float* outY) const {
*outY = mLocked.pointerY; *outY = mLocked.pointerY;
} }
void PointerController::fade() { void PointerController::fade(Transition transition) {
AutoMutex _l(mLock); AutoMutex _l(mLock);
sendImmediateInactivityTimeoutLocked(); // Remove the inactivity timeout, since we are fading now.
removeInactivityTimeoutLocked();
// Start fading.
if (transition == TRANSITION_IMMEDIATE) {
mLocked.pointerFadeDirection = 0;
mLocked.pointerAlpha = 0.0f;
updatePointerLocked();
} else {
mLocked.pointerFadeDirection = -1;
startAnimationLocked();
}
} }
void PointerController::unfade() { void PointerController::unfade(Transition transition) {
AutoMutex _l(mLock); AutoMutex _l(mLock);
// Always reset the inactivity timer. // Always reset the inactivity timer.
resetInactivityTimeoutLocked(); resetInactivityTimeoutLocked();
// Unfade immediately if needed. // Start unfading.
if (mLocked.pointerIsFading) { if (transition == TRANSITION_IMMEDIATE) {
mLocked.pointerIsFading = false; mLocked.pointerFadeDirection = 0;
mLocked.pointerAlpha = 1.0f; mLocked.pointerAlpha = 1.0f;
updatePointerLocked(); updatePointerLocked();
} else {
mLocked.pointerFadeDirection = 1;
startAnimationLocked();
} }
} }
@ -401,10 +415,20 @@ void PointerController::doAnimate() {
nsecs_t frameDelay = systemTime(SYSTEM_TIME_MONOTONIC) - mLocked.animationTime; nsecs_t frameDelay = systemTime(SYSTEM_TIME_MONOTONIC) - mLocked.animationTime;
// Animate pointer fade. // Animate pointer fade.
if (mLocked.pointerIsFading) { if (mLocked.pointerFadeDirection < 0) {
mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION; mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
if (mLocked.pointerAlpha <= 0) { if (mLocked.pointerAlpha <= 0.0f) {
mLocked.pointerAlpha = 0; mLocked.pointerAlpha = 0.0f;
mLocked.pointerFadeDirection = 0;
} else {
keepAnimating = true;
}
updatePointerLocked();
} else if (mLocked.pointerFadeDirection > 0) {
mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
if (mLocked.pointerAlpha >= 1.0f) {
mLocked.pointerAlpha = 1.0f;
mLocked.pointerFadeDirection = 0;
} else { } else {
keepAnimating = true; keepAnimating = true;
} }
@ -432,12 +456,7 @@ void PointerController::doAnimate() {
} }
void PointerController::doInactivityTimeout() { void PointerController::doInactivityTimeout() {
AutoMutex _l(mLock); fade(TRANSITION_GRADUAL);
if (!mLocked.pointerIsFading) {
mLocked.pointerIsFading = true;
startAnimationLocked();
}
} }
void PointerController::startAnimationLocked() { void PointerController::startAnimationLocked() {
@ -456,9 +475,8 @@ void PointerController::resetInactivityTimeoutLocked() {
mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT); mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
} }
void PointerController::sendImmediateInactivityTimeoutLocked() { void PointerController::removeInactivityTimeoutLocked() {
mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT); mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
mLooper->sendMessage(mHandler, MSG_INACTIVITY_TIMEOUT);
} }
void PointerController::updatePointerLocked() { void PointerController::updatePointerLocked() {

View File

@ -64,14 +64,21 @@ public:
/* Gets the absolute location of the pointer. */ /* Gets the absolute location of the pointer. */
virtual void getPosition(float* outX, float* outY) const = 0; virtual void getPosition(float* outX, float* outY) const = 0;
enum Transition {
// Fade/unfade immediately.
TRANSITION_IMMEDIATE,
// Fade/unfade gradually.
TRANSITION_GRADUAL,
};
/* Fades the pointer out now. */ /* Fades the pointer out now. */
virtual void fade() = 0; virtual void fade(Transition transition) = 0;
/* Makes the pointer visible if it has faded out. /* Makes the pointer visible if it has faded out.
* The pointer never unfades itself automatically. This method must be called * The pointer never unfades itself automatically. This method must be called
* by the client whenever the pointer is moved or a button is pressed and it * by the client whenever the pointer is moved or a button is pressed and it
* wants to ensure that the pointer becomes visible again. */ * wants to ensure that the pointer becomes visible again. */
virtual void unfade() = 0; virtual void unfade(Transition transition) = 0;
enum Presentation { enum Presentation {
// Show the mouse pointer. // Show the mouse pointer.
@ -187,8 +194,8 @@ public:
virtual uint32_t getButtonState() const; virtual uint32_t getButtonState() const;
virtual void setPosition(float x, float y); virtual void setPosition(float x, float y);
virtual void getPosition(float* outX, float* outY) const; virtual void getPosition(float* outX, float* outY) const;
virtual void fade(); virtual void fade(Transition transition);
virtual void unfade(); virtual void unfade(Transition transition);
virtual void setPresentation(Presentation presentation); virtual void setPresentation(Presentation presentation);
virtual void setSpots(SpotGesture spotGesture, virtual void setSpots(SpotGesture spotGesture,
@ -250,7 +257,7 @@ private:
Presentation presentation; Presentation presentation;
bool presentationChanged; bool presentationChanged;
bool pointerIsFading; int32_t pointerFadeDirection;
float pointerX; float pointerX;
float pointerY; float pointerY;
float pointerAlpha; float pointerAlpha;
@ -274,7 +281,7 @@ private:
void startAnimationLocked(); void startAnimationLocked();
void resetInactivityTimeoutLocked(); void resetInactivityTimeoutLocked();
void sendImmediateInactivityTimeoutLocked(); void removeInactivityTimeoutLocked();
void updatePointerLocked(); void updatePointerLocked();
Spot* getSpotLocked(uint32_t id); Spot* getSpotLocked(uint32_t id);

View File

@ -92,10 +92,10 @@ private:
*outY = 0; *outY = 0;
} }
virtual void fade() { virtual void fade(Transition transition) {
} }
virtual void unfade() { virtual void unfade(Transition transition) {
} }
virtual void setPresentation(Presentation presentation) { virtual void setPresentation(Presentation presentation) {