From ace13b17866dc9136aeecf6dfaf7077f37434469 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Wed, 9 Mar 2011 17:39:48 -0800 Subject: Use touch pad gestures to manipulate the pointer. 1. Single finger tap performs a click. 2. Single finger movement moves the pointer (hovers). 3. Button press plus movement performs click or drag. While dragging, the pointer follows the finger that is moving fastest. This is important if there are additional fingers down on the touch pad for the purpose of applying force to an integrated button underneath. 4. Two fingers near each other moving in the same direction are coalesced as a swipe gesture under the pointer. 5. Two or more fingers moving in arbitrary directions are transformed into touches in the vicinity of the pointer. This makes scale/zoom and rotate gestures possible. Added a native VelocityTracker implementation to enable intelligent switching of the active pointer during drags. Change-Id: I5ada57e7f2bdb9b0a791843eb354a8c706b365dc --- include/ui/Input.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/utils/BitSet.h | 6 ++++++ 2 files changed, 61 insertions(+) (limited to 'include') diff --git a/include/ui/Input.h b/include/ui/Input.h index d9d77c4..e9cacf4 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef HAVE_ANDROID_OS class SkMatrix; @@ -208,6 +209,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); }; @@ -543,6 +551,53 @@ private: }; /* + * 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. */ class InputDeviceInfo { diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h index f5dbcd9..f03825a 100644 --- a/include/utils/BitSet.h +++ b/include/utils/BitSet.h @@ -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; } }; -- cgit v1.1