am 82e4373e
: Merge "Use touch pad gestures to manipulate the pointer. (DO NOT MERGE)" into honeycomb-mr2
* commit '82e4373ed3775395a23d161e58c003e82511921a': Use touch pad gestures to manipulate the pointer. (DO NOT MERGE)
This commit is contained in:
@ -27,6 +27,7 @@
|
||||
#include <utils/Timers.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/BitSet.h>
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
class SkMatrix;
|
||||
@ -210,6 +211,13 @@ struct PointerCoords {
|
||||
status_t writeToParcel(Parcel* parcel) const;
|
||||
#endif
|
||||
|
||||
bool operator==(const PointerCoords& other) const;
|
||||
inline bool operator!=(const PointerCoords& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void copyFrom(const PointerCoords& other);
|
||||
|
||||
private:
|
||||
void tooManyAxes(int axis);
|
||||
};
|
||||
@ -544,6 +552,53 @@ private:
|
||||
MotionEvent mMotionEvent;
|
||||
};
|
||||
|
||||
/*
|
||||
* Calculates the velocity of pointer motions over time.
|
||||
* Uses essentially the same algorithm as android.view.VelocityTracker.
|
||||
*/
|
||||
class VelocityTracker {
|
||||
public:
|
||||
struct Position {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
VelocityTracker();
|
||||
|
||||
// Resets the velocity tracker state.
|
||||
void clear();
|
||||
|
||||
// Adds movement information for a set of pointers.
|
||||
// The idBits bitfield specifies the pointer ids of the pointers whose positions
|
||||
// are included in the movement.
|
||||
// The positions array contains position information for each pointer in order by
|
||||
// increasing id. Its size should be equal to the number of one bits in idBits.
|
||||
void addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions);
|
||||
|
||||
// Gets the velocity of the specified pointer id in position units per second.
|
||||
// Returns false and sets the velocity components to zero if there is no movement
|
||||
// information for the pointer.
|
||||
bool getVelocity(uint32_t id, float* outVx, float* outVy) const;
|
||||
|
||||
private:
|
||||
// Number of samples to keep.
|
||||
static const uint32_t HISTORY_SIZE = 10;
|
||||
|
||||
// Oldest sample to consider when calculating the velocity.
|
||||
static const nsecs_t MAX_AGE = 200 * 1000000; // 200 ms
|
||||
|
||||
// The minimum duration between samples when estimating velocity.
|
||||
static const nsecs_t MIN_DURATION = 5 * 1000000; // 5 ms
|
||||
|
||||
struct Movement {
|
||||
nsecs_t eventTime;
|
||||
BitSet32 idBits;
|
||||
Position positions[MAX_POINTERS];
|
||||
};
|
||||
|
||||
uint32_t mIndex;
|
||||
Movement mMovements[HISTORY_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* Describes the characteristics and capabilities of an input device.
|
||||
*/
|
||||
|
@ -61,6 +61,12 @@ struct BitSet32 {
|
||||
// Result is undefined if all bits are marked.
|
||||
inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
|
||||
|
||||
// Gets the index of the specified bit in the set, which is the number of
|
||||
// marked bits that appear before the specified bit.
|
||||
inline uint32_t getIndexOfBit(uint32_t n) const {
|
||||
return __builtin_popcount(value & ~(0xffffffffUL >> n));
|
||||
}
|
||||
|
||||
inline bool operator== (const BitSet32& other) const { return value == other.value; }
|
||||
inline bool operator!= (const BitSet32& other) const { return value != other.value; }
|
||||
};
|
||||
|
@ -7,8 +7,12 @@
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
// Log debug messages about keymap probing.
|
||||
#define DEBUG_PROBE 0
|
||||
|
||||
// Log debug messages about velocity tracking.
|
||||
#define DEBUG_VELOCITY 0
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
@ -347,6 +351,27 @@ void PointerCoords::tooManyAxes(int axis) {
|
||||
"cannot contain more than %d axis values.", axis, int(MAX_AXES));
|
||||
}
|
||||
|
||||
bool PointerCoords::operator==(const PointerCoords& other) const {
|
||||
if (bits != other.bits) {
|
||||
return false;
|
||||
}
|
||||
uint32_t count = __builtin_popcountll(bits);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (values[i] != other.values[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PointerCoords::copyFrom(const PointerCoords& other) {
|
||||
bits = other.bits;
|
||||
uint32_t count = __builtin_popcountll(bits);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
values[i] = other.values[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- MotionEvent ---
|
||||
|
||||
@ -633,6 +658,135 @@ bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
|
||||
}
|
||||
|
||||
|
||||
// --- VelocityTracker ---
|
||||
|
||||
VelocityTracker::VelocityTracker() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void VelocityTracker::clear() {
|
||||
mIndex = 0;
|
||||
mMovements[0].idBits.clear();
|
||||
}
|
||||
|
||||
void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) {
|
||||
if (++mIndex == HISTORY_SIZE) {
|
||||
mIndex = 0;
|
||||
}
|
||||
Movement& movement = mMovements[mIndex];
|
||||
movement.eventTime = eventTime;
|
||||
movement.idBits = idBits;
|
||||
uint32_t count = idBits.count();
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
movement.positions[i] = positions[i];
|
||||
}
|
||||
|
||||
#if DEBUG_VELOCITY
|
||||
LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x", eventTime, idBits.value);
|
||||
for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
|
||||
uint32_t id = iterBits.firstMarkedBit();
|
||||
uint32_t index = idBits.getIndexOfBit(id);
|
||||
iterBits.clearBit(id);
|
||||
float vx, vy;
|
||||
bool available = getVelocity(id, &vx, &vy);
|
||||
if (available) {
|
||||
LOGD(" %d: position (%0.3f, %0.3f), velocity (%0.3f, %0.3f), speed %0.3f",
|
||||
id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy));
|
||||
} else {
|
||||
assert(vx == 0 && vy == 0);
|
||||
LOGD(" %d: position (%0.3f, %0.3f), velocity not available",
|
||||
id, positions[index].x, positions[index].y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
|
||||
const Movement& newestMovement = mMovements[mIndex];
|
||||
if (newestMovement.idBits.hasBit(id)) {
|
||||
// Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
|
||||
nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
|
||||
uint32_t oldestIndex = mIndex;
|
||||
uint32_t numTouches = 1;
|
||||
do {
|
||||
uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
|
||||
const Movement& nextOldestMovement = mMovements[nextOldestIndex];
|
||||
if (!nextOldestMovement.idBits.hasBit(id)
|
||||
|| nextOldestMovement.eventTime < minTime) {
|
||||
break;
|
||||
}
|
||||
oldestIndex = nextOldestIndex;
|
||||
} while (++numTouches < HISTORY_SIZE);
|
||||
|
||||
// If we have a lot of samples, skip the last received sample since it is
|
||||
// probably pretty noisy compared to the sum of all of the traces already acquired.
|
||||
//
|
||||
// NOTE: This condition exists in the android.view.VelocityTracker and imposes a
|
||||
// bias against the most recent data.
|
||||
if (numTouches > 3) {
|
||||
numTouches -= 1;
|
||||
}
|
||||
|
||||
// Calculate an exponentially weighted moving average of the velocity at different
|
||||
// points in time measured relative to the oldest samples. This is essentially
|
||||
// an IIR filter.
|
||||
//
|
||||
// One problem with this algorithm is that the sample data may be poorly conditioned.
|
||||
// Sometimes samples arrive very close together in time which can cause us to
|
||||
// overestimate the velocity at that time point. Most samples might be measured
|
||||
// 16ms apart but some consecutive samples could be only 0.5sm apart due to
|
||||
// the way they are reported by the hardware or driver (sometimes in bursts or with
|
||||
// significant jitter). The instantaneous velocity for those samples 0.5ms apart will
|
||||
// be calculated to be 32 times what it should have been.
|
||||
// To work around this effect, we impose a minimum duration on the samples.
|
||||
//
|
||||
// FIXME: Samples close together in time can have an disproportionately large
|
||||
// impact on the result because all samples are equally weighted. The average should
|
||||
// instead take the time factor into account.
|
||||
//
|
||||
// FIXME: The minimum duration condition does not exist in
|
||||
// android.view.VelocityTracker yet. It is less important there because sample times
|
||||
// are truncated to the millisecond so back to back samples will often appear to be
|
||||
// zero milliseconds apart and will be ignored if they are the oldest ones.
|
||||
float accumVx = 0;
|
||||
float accumVy = 0;
|
||||
uint32_t index = oldestIndex;
|
||||
uint32_t samplesUsed = 0;
|
||||
const Movement& oldestMovement = mMovements[oldestIndex];
|
||||
const Position& oldestPosition =
|
||||
oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
|
||||
while (numTouches-- > 1) {
|
||||
if (++index == HISTORY_SIZE) {
|
||||
index = 0;
|
||||
}
|
||||
const Movement& movement = mMovements[index];
|
||||
nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
|
||||
if (duration > MIN_DURATION) {
|
||||
const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)];
|
||||
float scale = 1000000000.0f / duration; // one over time delta in seconds
|
||||
float vx = (position.x - oldestPosition.x) * scale;
|
||||
float vy = (position.y - oldestPosition.y) * scale;
|
||||
accumVx = accumVx == 0 ? vx : (accumVx + vx) * 0.5f;
|
||||
accumVy = accumVy == 0 ? vy : (accumVy + vy) * 0.5f;
|
||||
samplesUsed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we used at least one sample.
|
||||
if (samplesUsed != 0) {
|
||||
*outVx = accumVx;
|
||||
*outVy = accumVy;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No data available for this pointer.
|
||||
*outVx = 0;
|
||||
*outVy = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// --- InputDeviceInfo ---
|
||||
|
||||
InputDeviceInfo::InputDeviceInfo() {
|
||||
|
@ -406,7 +406,7 @@ status_t InputPublisher::publishMotionEvent(
|
||||
|
||||
for (size_t i = 0; i < pointerCount; i++) {
|
||||
mSharedMessage->motion.pointerIds[i] = pointerIds[i];
|
||||
mSharedMessage->motion.sampleData[0].coords[i] = pointerCoords[i];
|
||||
mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
|
||||
}
|
||||
|
||||
// Cache essential information about the motion event to ensure that a malicious consumer
|
||||
@ -475,7 +475,7 @@ status_t InputPublisher::appendMotionSample(
|
||||
|
||||
mMotionEventSampleDataTail->eventTime = eventTime;
|
||||
for (size_t i = 0; i < mMotionEventPointerCount; i++) {
|
||||
mMotionEventSampleDataTail->coords[i] = pointerCoords[i];
|
||||
mMotionEventSampleDataTail->coords[i].copyFrom(pointerCoords[i]);
|
||||
}
|
||||
mMotionEventSampleDataTail = newTail;
|
||||
|
||||
|
@ -2178,8 +2178,8 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
|
||||
if (pointerIds.hasBit(pointerId)) {
|
||||
splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
|
||||
splitPointerIds[splitPointerCount] = pointerId;
|
||||
splitPointerCoords[splitPointerCount] =
|
||||
originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
|
||||
splitPointerCoords[splitPointerCount].copyFrom(
|
||||
originalMotionEntry->firstSample.pointerCoords[originalPointerIndex]);
|
||||
splitPointerCount += 1;
|
||||
}
|
||||
}
|
||||
@ -2242,8 +2242,8 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
|
||||
for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
|
||||
splitPointerIndex++) {
|
||||
uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
|
||||
splitPointerCoords[splitPointerIndex] =
|
||||
originalMotionSample->pointerCoords[originalPointerIndex];
|
||||
splitPointerCoords[splitPointerIndex].copyFrom(
|
||||
originalMotionSample->pointerCoords[originalPointerIndex]);
|
||||
}
|
||||
|
||||
mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
|
||||
@ -3497,7 +3497,7 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec
|
||||
entry->lastSample = & entry->firstSample;
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
entry->pointerIds[i] = pointerIds[i];
|
||||
entry->firstSample.pointerCoords[i] = pointerCoords[i];
|
||||
entry->firstSample.pointerCoords[i].copyFrom(pointerCoords[i]);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
@ -3601,7 +3601,7 @@ void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
|
||||
sample->eventTime = eventTime;
|
||||
uint32_t pointerCount = motionEntry->pointerCount;
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
sample->pointerCoords[i] = pointerCoords[i];
|
||||
sample->pointerCoords[i].copyFrom(pointerCoords[i]);
|
||||
}
|
||||
|
||||
sample->next = NULL;
|
||||
@ -3738,7 +3738,7 @@ void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry*
|
||||
pointerCount = entry->pointerCount;
|
||||
for (uint32_t i = 0; i < entry->pointerCount; i++) {
|
||||
pointerIds[i] = entry->pointerIds[i];
|
||||
pointerCoords[i] = entry->lastSample->pointerCoords[i];
|
||||
pointerCoords[i].copyFrom(entry->lastSample->pointerCoords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -558,6 +558,8 @@ public:
|
||||
virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
|
||||
const int32_t* keyCodes, uint8_t* outFlags);
|
||||
|
||||
virtual void fadePointer();
|
||||
|
||||
protected:
|
||||
Mutex mLock;
|
||||
|
||||
@ -611,10 +613,12 @@ protected:
|
||||
PointerData pointers[MAX_POINTERS];
|
||||
BitSet32 idBits;
|
||||
uint32_t idToIndex[MAX_POINTER_ID + 1];
|
||||
uint32_t buttonState;
|
||||
|
||||
void copyFrom(const TouchData& other) {
|
||||
pointerCount = other.pointerCount;
|
||||
idBits = other.idBits;
|
||||
buttonState = other.buttonState;
|
||||
|
||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||
pointers[i] = other.pointers[i];
|
||||
@ -627,17 +631,20 @@ protected:
|
||||
inline void clear() {
|
||||
pointerCount = 0;
|
||||
idBits.clear();
|
||||
buttonState = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Input sources supported by the device.
|
||||
uint32_t mTouchSource; // sources when reporting touch data
|
||||
uint32_t mPointerSource; // sources when reporting pointer gestures
|
||||
|
||||
// Immutable configuration parameters.
|
||||
struct Parameters {
|
||||
enum DeviceType {
|
||||
DEVICE_TYPE_TOUCH_SCREEN,
|
||||
DEVICE_TYPE_TOUCH_PAD,
|
||||
DEVICE_TYPE_POINTER,
|
||||
};
|
||||
|
||||
DeviceType deviceType;
|
||||
@ -735,11 +742,17 @@ protected:
|
||||
|
||||
// Current and previous touch sample data.
|
||||
TouchData mCurrentTouch;
|
||||
PointerCoords mCurrentTouchCoords[MAX_POINTERS];
|
||||
|
||||
TouchData mLastTouch;
|
||||
PointerCoords mLastTouchCoords[MAX_POINTERS];
|
||||
|
||||
// The time the primary pointer last went down.
|
||||
nsecs_t mDownTime;
|
||||
|
||||
// The pointer controller, or null if the device is not a pointer.
|
||||
sp<PointerControllerInterface> mPointerController;
|
||||
|
||||
struct LockedState {
|
||||
Vector<VirtualKey> virtualKeys;
|
||||
|
||||
@ -804,6 +817,17 @@ protected:
|
||||
int32_t keyCode;
|
||||
int32_t scanCode;
|
||||
} currentVirtualKey;
|
||||
|
||||
// Scale factor for gesture based pointer movements.
|
||||
float pointerGestureXMovementScale;
|
||||
float pointerGestureYMovementScale;
|
||||
|
||||
// Scale factor for gesture based zooming and other freeform motions.
|
||||
float pointerGestureXZoomScale;
|
||||
float pointerGestureYZoomScale;
|
||||
|
||||
// The maximum swipe width squared.
|
||||
int32_t pointerGestureMaxSwipeWidthSquared;
|
||||
} mLocked;
|
||||
|
||||
virtual void configureParameters();
|
||||
@ -869,13 +893,148 @@ private:
|
||||
uint64_t distance : 48; // squared distance
|
||||
};
|
||||
|
||||
struct PointerGesture {
|
||||
enum Mode {
|
||||
// No fingers, button is not pressed.
|
||||
// Nothing happening.
|
||||
NEUTRAL,
|
||||
|
||||
// No fingers, button is not pressed.
|
||||
// Tap detected.
|
||||
// Emits DOWN and UP events at the pointer location.
|
||||
TAP,
|
||||
|
||||
// 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,
|
||||
|
||||
// Exactly one finger, button is not pressed.
|
||||
// Pointer follows the active finger.
|
||||
// Emits HOVER_MOVE events at the pointer location.
|
||||
HOVER,
|
||||
|
||||
// More than two fingers involved but they haven't moved enough for us
|
||||
// to figure out what is intended.
|
||||
INDETERMINATE_MULTITOUCH,
|
||||
|
||||
// Exactly two fingers moving in the same direction, button is not pressed.
|
||||
// Pointer does not move.
|
||||
// Emits DOWN, MOVE and UP events with a single pointer coordinate that
|
||||
// follows the midpoint between both fingers.
|
||||
// The centroid is fixed when entering this state.
|
||||
SWIPE,
|
||||
|
||||
// Two or more fingers moving in arbitrary directions, button is not pressed.
|
||||
// Pointer does not move.
|
||||
// Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
|
||||
// each finger individually relative to the initial centroid of the finger.
|
||||
// The centroid is fixed when entering this state.
|
||||
FREEFORM,
|
||||
|
||||
// Waiting for quiet time to end before starting the next gesture.
|
||||
QUIET,
|
||||
};
|
||||
|
||||
// The active pointer id from the raw touch data.
|
||||
int32_t activeTouchId; // -1 if none
|
||||
|
||||
// The active pointer id from the gesture last delivered to the application.
|
||||
int32_t activeGestureId; // -1 if none
|
||||
|
||||
// Pointer coords and ids for the current and previous pointer gesture.
|
||||
Mode currentGestureMode;
|
||||
uint32_t currentGesturePointerCount;
|
||||
BitSet32 currentGestureIdBits;
|
||||
uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
|
||||
PointerCoords currentGestureCoords[MAX_POINTERS];
|
||||
|
||||
Mode lastGestureMode;
|
||||
uint32_t lastGesturePointerCount;
|
||||
BitSet32 lastGestureIdBits;
|
||||
uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
|
||||
PointerCoords lastGestureCoords[MAX_POINTERS];
|
||||
|
||||
// Tracks for all pointers originally went down.
|
||||
TouchData touchOrigin;
|
||||
|
||||
// Describes how touch ids are mapped to gesture ids for freeform gestures.
|
||||
uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
|
||||
|
||||
// Initial centroid of the movement.
|
||||
// Used to calculate how far the touch pointers have moved since the gesture started.
|
||||
int32_t initialCentroidX;
|
||||
int32_t initialCentroidY;
|
||||
|
||||
// Initial pointer location.
|
||||
// Used to track where the pointer was when the gesture started.
|
||||
float initialPointerX;
|
||||
float initialPointerY;
|
||||
|
||||
// Time the pointer gesture last went down.
|
||||
nsecs_t downTime;
|
||||
|
||||
// Time we started waiting for a tap gesture.
|
||||
nsecs_t tapTime;
|
||||
|
||||
// Time we started waiting for quiescence.
|
||||
nsecs_t quietTime;
|
||||
|
||||
// A velocity tracker for determining whether to switch active pointers during drags.
|
||||
VelocityTracker velocityTracker;
|
||||
|
||||
void reset() {
|
||||
activeTouchId = -1;
|
||||
activeGestureId = -1;
|
||||
currentGestureMode = NEUTRAL;
|
||||
currentGesturePointerCount = 0;
|
||||
currentGestureIdBits.clear();
|
||||
lastGestureMode = NEUTRAL;
|
||||
lastGesturePointerCount = 0;
|
||||
lastGestureIdBits.clear();
|
||||
touchOrigin.clear();
|
||||
initialCentroidX = 0;
|
||||
initialCentroidY = 0;
|
||||
initialPointerX = 0;
|
||||
initialPointerY = 0;
|
||||
downTime = 0;
|
||||
velocityTracker.clear();
|
||||
resetTapTime();
|
||||
resetQuietTime();
|
||||
}
|
||||
|
||||
void resetTapTime() {
|
||||
tapTime = LLONG_MIN;
|
||||
}
|
||||
|
||||
void resetQuietTime() {
|
||||
quietTime = LLONG_MIN;
|
||||
}
|
||||
} mPointerGesture;
|
||||
|
||||
void initializeLocked();
|
||||
|
||||
TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
|
||||
void dispatchTouches(nsecs_t when, uint32_t policyFlags);
|
||||
void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
|
||||
BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
|
||||
int32_t motionEventAction);
|
||||
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);
|
||||
|
||||
// Dispatches a motion event.
|
||||
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
|
||||
// method will take care of setting the index and transmuting the action to DOWN or UP
|
||||
// it is the first / last pointer to go down / up.
|
||||
void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
|
||||
int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
|
||||
const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
|
||||
int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
|
||||
|
||||
// Updates pointer coords for pointers with specified ids that have moved.
|
||||
// Returns true if any of them changed.
|
||||
bool updateMovedPointerCoords(const PointerCoords* inCoords, const uint32_t* inIdToIndex,
|
||||
PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const;
|
||||
|
||||
void suppressSwipeOntoVirtualKeys(nsecs_t when);
|
||||
|
||||
bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
|
||||
@ -907,6 +1066,7 @@ private:
|
||||
FIELD_ABS_Y = 4,
|
||||
FIELD_ABS_PRESSURE = 8,
|
||||
FIELD_ABS_TOOL_WIDTH = 16,
|
||||
FIELD_BUTTONS = 32,
|
||||
};
|
||||
|
||||
uint32_t fields;
|
||||
@ -917,8 +1077,13 @@ private:
|
||||
int32_t absPressure;
|
||||
int32_t absToolWidth;
|
||||
|
||||
uint32_t buttonDown;
|
||||
uint32_t buttonUp;
|
||||
|
||||
inline void clear() {
|
||||
fields = 0;
|
||||
buttonDown = 0;
|
||||
buttonUp = 0;
|
||||
}
|
||||
} mAccumulator;
|
||||
|
||||
@ -927,6 +1092,7 @@ private:
|
||||
int32_t mY;
|
||||
int32_t mPressure;
|
||||
int32_t mToolWidth;
|
||||
uint32_t mButtonState;
|
||||
|
||||
void initialize();
|
||||
|
||||
@ -978,12 +1144,20 @@ private:
|
||||
}
|
||||
} pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
|
||||
|
||||
// Bitfield of buttons that went down or up.
|
||||
uint32_t buttonDown;
|
||||
uint32_t buttonUp;
|
||||
|
||||
inline void clear() {
|
||||
pointerCount = 0;
|
||||
pointers[0].clear();
|
||||
buttonDown = 0;
|
||||
buttonUp = 0;
|
||||
}
|
||||
} mAccumulator;
|
||||
|
||||
uint32_t mButtonState;
|
||||
|
||||
void initialize();
|
||||
|
||||
void sync(nsecs_t when);
|
||||
|
@ -2460,11 +2460,21 @@ void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
|
||||
}
|
||||
|
||||
|
||||
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecified_ReturnsTouchPad) {
|
||||
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
|
||||
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
|
||||
prepareAxes(POSITION);
|
||||
addMapperAndConfigure(mapper);
|
||||
|
||||
ASSERT_EQ(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
|
||||
}
|
||||
|
||||
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsACursor_ReturnsTouchPad) {
|
||||
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
|
||||
mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X);
|
||||
mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y);
|
||||
prepareAxes(POSITION);
|
||||
addMapperAndConfigure(mapper);
|
||||
|
||||
ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user