summaryrefslogtreecommitdiffstats
path: root/libs/ui
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-06-30 16:10:35 -0700
committerJeff Brown <jeffbrown@google.com>2010-07-13 17:04:57 -0700
commitfd03582995e0fce963dd0fa0669e3211b74c0dd7 (patch)
tree8f7fe0e2a437620a7cbe4e494f71fe8ccfdbe2eb /libs/ui
parentc0a7e690bfd32dd897ceccd04dd0fa6bf6e9cee6 (diff)
downloadframeworks_base-fd03582995e0fce963dd0fa0669e3211b74c0dd7.zip
frameworks_base-fd03582995e0fce963dd0fa0669e3211b74c0dd7.tar.gz
frameworks_base-fd03582995e0fce963dd0fa0669e3211b74c0dd7.tar.bz2
Add initial gamepad support.
Change-Id: I0439648f6eb5405f200e4223c915eb3a418b32b9
Diffstat (limited to 'libs/ui')
-rw-r--r--libs/ui/Android.mk11
-rw-r--r--libs/ui/EventHub.cpp124
-rw-r--r--libs/ui/Input.cpp80
-rw-r--r--libs/ui/InputDevice.cpp729
-rw-r--r--libs/ui/InputDispatcher.cpp8
-rw-r--r--libs/ui/InputReader.cpp716
-rw-r--r--libs/ui/tests/InputPublisherAndConsumer_test.cpp2
7 files changed, 884 insertions, 786 deletions
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 24cdc78..4243bbf 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -12,6 +12,7 @@ LOCAL_SRC_FILES:= \
KeyLayoutMap.cpp \
KeyCharacterMap.cpp \
Input.cpp \
+ InputDevice.cpp \
InputDispatcher.cpp \
InputManager.cpp \
InputReader.cpp \
@@ -38,3 +39,13 @@ ifeq ($(TARGET_SIMULATOR),true)
endif
include $(BUILD_SHARED_LIBRARY)
+
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 27895f2..768b04e 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -54,6 +54,9 @@
*/
#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
+/* this macro computes the number of bytes needed to represent a bit array of the specified size */
+#define sizeof_bit_array(bits) ((bits + 7) / 8)
+
#define ID_MASK 0x0000ffff
#define SEQ_MASK 0x7fff0000
#define SEQ_SHIFT 16
@@ -182,7 +185,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t deviceClasses,
}
int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
- uint8_t key_bitmask[(KEY_MAX + 7) / 8];
+ uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
if (ioctl(mFDs[id_to_index(device->id)].fd,
EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
@@ -218,7 +221,7 @@ int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const
Vector<int32_t> scanCodes;
device->layoutMap->findScancodes(keyCode, &scanCodes);
- uint8_t key_bitmask[(KEY_MAX + 7) / 8];
+ uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
if (ioctl(mFDs[id_to_index(device->id)].fd,
EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
@@ -264,7 +267,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_
}
int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
- uint8_t sw_bitmask[(SW_MAX + 7) / 8];
+ uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
memset(sw_bitmask, 0, sizeof(sw_bitmask));
if (ioctl(mFDs[id_to_index(device->id)].fd,
EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
@@ -409,7 +412,7 @@ bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",
iev.code, *outKeycode, *outFlags, err);
if (err != 0) {
- *outKeycode = 0;
+ *outKeycode = AKEYCODE_UNKNOWN;
*outFlags = 0;
}
} else {
@@ -509,6 +512,26 @@ bool EventHub::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFla
// ----------------------------------------------------------------------------
+static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
+ const uint8_t* end = array + endIndex;
+ array += startIndex;
+ while (array != end) {
+ if (*(array++) != 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static const int32_t GAMEPAD_KEYCODES[] = {
+ AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
+ AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
+ AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
+ AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
+ AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
+ AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
+};
+
int EventHub::open_device(const char *deviceName)
{
int version;
@@ -626,27 +649,27 @@ int EventHub::open_device(const char *deviceName)
mFDs[mFDCount].fd = fd;
mFDs[mFDCount].events = POLLIN;
- // figure out the kinds of events the device reports
+ // Figure out the kinds of events the device reports.
- // See if this is a keyboard, and classify it. Note that we only
- // consider up through the function keys; we don't want to include
- // ones after that (play cd etc) so we don't mistakenly consider a
- // controller to be a keyboard.
- uint8_t key_bitmask[(KEY_MAX+7)/8];
+ uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
+
LOGV("Getting keys...");
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
//LOGI("MAP\n");
- //for (int i=0; i<((KEY_MAX+7)/8); i++) {
+ //for (int i = 0; i < sizeof(key_bitmask); i++) {
// LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
//}
- for (int i=0; i<((BTN_MISC+7)/8); i++) {
- if (key_bitmask[i] != 0) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- break;
- }
- }
- if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
+
+ // See if this is a keyboard. Ignore everything in the button range except for
+ // gamepads which are also considered keyboards.
+ if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
+ || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
+ sizeof_bit_array(BTN_DIGI))
+ || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
+ sizeof_bit_array(KEY_MAX + 1))) {
+ device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+
device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
if (device->keyBitmask != NULL) {
memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
@@ -658,39 +681,39 @@ int EventHub::open_device(const char *deviceName)
}
}
- // See if this is a trackball.
+ // See if this is a trackball (or mouse).
if (test_bit(BTN_MOUSE, key_bitmask)) {
- uint8_t rel_bitmask[(REL_MAX+7)/8];
+ uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
memset(rel_bitmask, 0, sizeof(rel_bitmask));
LOGV("Getting relative controllers...");
- if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
- {
+ if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
}
}
}
-
- uint8_t abs_bitmask[(ABS_MAX+7)/8];
+
+ // See if this is a touch pad.
+ uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
memset(abs_bitmask, 0, sizeof(abs_bitmask));
LOGV("Getting absolute controllers...");
- ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
-
- // Is this a new modern multi-touch driver?
- if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
- && test_bit(ABS_MT_POSITION_X, abs_bitmask)
- && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
-
- // Is this an old style single-touch driver?
- } else if (test_bit(BTN_TOUCH, key_bitmask)
- && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
+ if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
+ // Is this a new modern multi-touch driver?
+ if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
+ && test_bit(ABS_MT_POSITION_X, abs_bitmask)
+ && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+ device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
+
+ // Is this an old style single-touch driver?
+ } else if (test_bit(BTN_TOUCH, key_bitmask)
+ && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
+ device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
+ }
}
#ifdef EV_SW
// figure out the switches this device reports
- uint8_t sw_bitmask[(SW_MAX+7)/8];
+ uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
memset(sw_bitmask, 0, sizeof(sw_bitmask));
if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
for (int i=0; i<EV_SW; i++) {
@@ -726,7 +749,10 @@ int EventHub::open_device(const char *deviceName)
"%s/usr/keylayout/%s", root, "qwerty.kl");
defaultKeymap = true;
}
- device->layoutMap->load(keylayoutFilename);
+ status_t status = device->layoutMap->load(keylayoutFilename);
+ if (status) {
+ LOGE("Error %d loading key layout.", status);
+ }
// tell the world about the devname (the descriptive name)
if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
@@ -746,19 +772,27 @@ int EventHub::open_device(const char *deviceName)
property_set(propName, name);
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (hasKeycode(device, kKeyCodeQ)) {
+ if (hasKeycode(device, AKEYCODE_Q)) {
device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
}
- // See if this has a DPAD.
- if (hasKeycode(device, kKeyCodeDpadUp) &&
- hasKeycode(device, kKeyCodeDpadDown) &&
- hasKeycode(device, kKeyCodeDpadLeft) &&
- hasKeycode(device, kKeyCodeDpadRight) &&
- hasKeycode(device, kKeyCodeDpadCenter)) {
+ // See if this device has a DPAD.
+ if (hasKeycode(device, AKEYCODE_DPAD_UP) &&
+ hasKeycode(device, AKEYCODE_DPAD_DOWN) &&
+ hasKeycode(device, AKEYCODE_DPAD_LEFT) &&
+ hasKeycode(device, AKEYCODE_DPAD_RIGHT) &&
+ hasKeycode(device, AKEYCODE_DPAD_CENTER)) {
device->classes |= INPUT_DEVICE_CLASS_DPAD;
}
+ // See if this device has a gamepad.
+ for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES); i++) {
+ if (hasKeycode(device, GAMEPAD_KEYCODES[i])) {
+ device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
+ break;
+ }
+ }
+
LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
device->id, name, propName, keylayoutFilename);
}
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index a64251f..1f19c2c 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -22,26 +22,26 @@ void InputEvent::initialize(int32_t deviceId, int32_t nature) {
bool KeyEvent::hasDefaultAction(int32_t keyCode) {
switch (keyCode) {
- case KEYCODE_HOME:
- case KEYCODE_BACK:
- case KEYCODE_CALL:
- case KEYCODE_ENDCALL:
- case KEYCODE_VOLUME_UP:
- case KEYCODE_VOLUME_DOWN:
- case KEYCODE_POWER:
- case KEYCODE_CAMERA:
- case KEYCODE_HEADSETHOOK:
- case KEYCODE_MENU:
- case KEYCODE_NOTIFICATION:
- case KEYCODE_FOCUS:
- case KEYCODE_SEARCH:
- case KEYCODE_MEDIA_PLAY_PAUSE:
- case KEYCODE_MEDIA_STOP:
- case KEYCODE_MEDIA_NEXT:
- case KEYCODE_MEDIA_PREVIOUS:
- case KEYCODE_MEDIA_REWIND:
- case KEYCODE_MEDIA_FAST_FORWARD:
- case KEYCODE_MUTE:
+ case AKEYCODE_HOME:
+ case AKEYCODE_BACK:
+ case AKEYCODE_CALL:
+ case AKEYCODE_ENDCALL:
+ case AKEYCODE_VOLUME_UP:
+ case AKEYCODE_VOLUME_DOWN:
+ case AKEYCODE_POWER:
+ case AKEYCODE_CAMERA:
+ case AKEYCODE_HEADSETHOOK:
+ case AKEYCODE_MENU:
+ case AKEYCODE_NOTIFICATION:
+ case AKEYCODE_FOCUS:
+ case AKEYCODE_SEARCH:
+ case AKEYCODE_MEDIA_PLAY_PAUSE:
+ case AKEYCODE_MEDIA_STOP:
+ case AKEYCODE_MEDIA_NEXT:
+ case AKEYCODE_MEDIA_PREVIOUS:
+ case AKEYCODE_MEDIA_REWIND:
+ case AKEYCODE_MEDIA_FAST_FORWARD:
+ case AKEYCODE_MUTE:
return true;
}
@@ -54,26 +54,26 @@ bool KeyEvent::hasDefaultAction() const {
bool KeyEvent::isSystemKey(int32_t keyCode) {
switch (keyCode) {
- case KEYCODE_MENU:
- case KEYCODE_SOFT_RIGHT:
- case KEYCODE_HOME:
- case KEYCODE_BACK:
- case KEYCODE_CALL:
- case KEYCODE_ENDCALL:
- case KEYCODE_VOLUME_UP:
- case KEYCODE_VOLUME_DOWN:
- case KEYCODE_MUTE:
- case KEYCODE_POWER:
- case KEYCODE_HEADSETHOOK:
- case KEYCODE_MEDIA_PLAY_PAUSE:
- case KEYCODE_MEDIA_STOP:
- case KEYCODE_MEDIA_NEXT:
- case KEYCODE_MEDIA_PREVIOUS:
- case KEYCODE_MEDIA_REWIND:
- case KEYCODE_MEDIA_FAST_FORWARD:
- case KEYCODE_CAMERA:
- case KEYCODE_FOCUS:
- case KEYCODE_SEARCH:
+ case AKEYCODE_MENU:
+ case AKEYCODE_SOFT_RIGHT:
+ case AKEYCODE_HOME:
+ case AKEYCODE_BACK:
+ case AKEYCODE_CALL:
+ case AKEYCODE_ENDCALL:
+ case AKEYCODE_VOLUME_UP:
+ case AKEYCODE_VOLUME_DOWN:
+ case AKEYCODE_MUTE:
+ case AKEYCODE_POWER:
+ case AKEYCODE_HEADSETHOOK:
+ case AKEYCODE_MEDIA_PLAY_PAUSE:
+ case AKEYCODE_MEDIA_STOP:
+ case AKEYCODE_MEDIA_NEXT:
+ case AKEYCODE_MEDIA_PREVIOUS:
+ case AKEYCODE_MEDIA_REWIND:
+ case AKEYCODE_MEDIA_FAST_FORWARD:
+ case AKEYCODE_CAMERA:
+ case AKEYCODE_FOCUS:
+ case AKEYCODE_SEARCH:
return true;
}
diff --git a/libs/ui/InputDevice.cpp b/libs/ui/InputDevice.cpp
new file mode 100644
index 0000000..6014017
--- /dev/null
+++ b/libs/ui/InputDevice.cpp
@@ -0,0 +1,729 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// The input reader.
+//
+#define LOG_TAG "InputDevice"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages for each raw event received from the EventHub.
+#define DEBUG_RAW_EVENTS 0
+
+// Log debug messages about touch screen filtering hacks.
+#define DEBUG_HACKS 0
+
+// Log debug messages about virtual key processing.
+#define DEBUG_VIRTUAL_KEYS 0
+
+// Log debug messages about pointers.
+#define DEBUG_POINTERS 0
+
+// Log debug messages about pointer assignment calculations.
+#define DEBUG_POINTER_ASSIGNMENT 0
+
+#include <cutils/log.h>
+#include <ui/InputDevice.h>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+/* Slop distance for jumpy pointer detection.
+ * The vertical range of the screen divided by this is our epsilon value. */
+#define JUMPY_EPSILON_DIVISOR 212
+
+/* Number of jumpy points to drop for touchscreens that need it. */
+#define JUMPY_TRANSITION_DROPS 3
+#define JUMPY_DROP_LIMIT 3
+
+/* Maximum squared distance for averaging.
+ * If moving farther than this, turn of averaging to avoid lag in response. */
+#define AVERAGING_DISTANCE_LIMIT (75 * 75)
+
+
+namespace android {
+
+// --- Static Functions ---
+
+template<typename T>
+inline static T abs(const T& value) {
+ return value < 0 ? - value : value;
+}
+
+template<typename T>
+inline static T min(const T& a, const T& b) {
+ return a < b ? a : b;
+}
+
+template<typename T>
+inline static void swap(T& a, T& b) {
+ T temp = a;
+ a = b;
+ b = temp;
+}
+
+
+// --- InputDevice ---
+
+InputDevice::InputDevice(int32_t id, uint32_t classes, String8 name) :
+ id(id), classes(classes), name(name), ignored(false) {
+}
+
+void InputDevice::reset() {
+ if (isKeyboard()) {
+ keyboard.reset();
+ }
+
+ if (isTrackball()) {
+ trackball.reset();
+ }
+
+ if (isMultiTouchScreen()) {
+ multiTouchScreen.reset();
+ } else if (isSingleTouchScreen()) {
+ singleTouchScreen.reset();
+ }
+
+ if (isTouchScreen()) {
+ touchScreen.reset();
+ }
+}
+
+
+// --- InputDevice::TouchData ---
+
+void InputDevice::TouchData::copyFrom(const TouchData& other) {
+ pointerCount = other.pointerCount;
+ idBits = other.idBits;
+
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ pointers[i] = other.pointers[i];
+ idToIndex[i] = other.idToIndex[i];
+ }
+}
+
+
+// --- InputDevice::KeyboardState ---
+
+void InputDevice::KeyboardState::reset() {
+ current.metaState = META_NONE;
+ current.downTime = 0;
+}
+
+
+// --- InputDevice::TrackballState ---
+
+void InputDevice::TrackballState::reset() {
+ accumulator.clear();
+ current.down = false;
+ current.downTime = 0;
+}
+
+
+// --- InputDevice::TouchScreenState ---
+
+void InputDevice::TouchScreenState::reset() {
+ lastTouch.clear();
+ downTime = 0;
+ currentVirtualKey.status = CurrentVirtualKeyState::STATUS_UP;
+
+ for (uint32_t i = 0; i < MAX_POINTERS; i++) {
+ averagingTouchFilter.historyStart[i] = 0;
+ averagingTouchFilter.historyEnd[i] = 0;
+ }
+
+ jumpyTouchFilter.jumpyPointsDropped = 0;
+}
+
+struct PointerDistanceHeapElement {
+ uint32_t currentPointerIndex : 8;
+ uint32_t lastPointerIndex : 8;
+ uint64_t distance : 48; // squared distance
+};
+
+void InputDevice::TouchScreenState::calculatePointerIds() {
+ uint32_t currentPointerCount = currentTouch.pointerCount;
+ uint32_t lastPointerCount = lastTouch.pointerCount;
+
+ if (currentPointerCount == 0) {
+ // No pointers to assign.
+ currentTouch.idBits.clear();
+ } else if (lastPointerCount == 0) {
+ // All pointers are new.
+ currentTouch.idBits.clear();
+ for (uint32_t i = 0; i < currentPointerCount; i++) {
+ currentTouch.pointers[i].id = i;
+ currentTouch.idToIndex[i] = i;
+ currentTouch.idBits.markBit(i);
+ }
+ } else if (currentPointerCount == 1 && lastPointerCount == 1) {
+ // Only one pointer and no change in count so it must have the same id as before.
+ uint32_t id = lastTouch.pointers[0].id;
+ currentTouch.pointers[0].id = id;
+ currentTouch.idToIndex[id] = 0;
+ currentTouch.idBits.value = BitSet32::valueForBit(id);
+ } else {
+ // General case.
+ // We build a heap of squared euclidean distances between current and last pointers
+ // associated with the current and last pointer indices. Then, we find the best
+ // match (by distance) for each current pointer.
+ PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
+
+ uint32_t heapSize = 0;
+ for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
+ currentPointerIndex++) {
+ for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
+ lastPointerIndex++) {
+ int64_t deltaX = currentTouch.pointers[currentPointerIndex].x
+ - lastTouch.pointers[lastPointerIndex].x;
+ int64_t deltaY = currentTouch.pointers[currentPointerIndex].y
+ - lastTouch.pointers[lastPointerIndex].y;
+
+ uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+ // Insert new element into the heap (sift up).
+ heap[heapSize].currentPointerIndex = currentPointerIndex;
+ heap[heapSize].lastPointerIndex = lastPointerIndex;
+ heap[heapSize].distance = distance;
+ heapSize += 1;
+ }
+ }
+
+ // Heapify
+ for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
+ startIndex -= 1;
+ for (uint32_t parentIndex = startIndex; ;) {
+ uint32_t childIndex = parentIndex * 2 + 1;
+ if (childIndex >= heapSize) {
+ break;
+ }
+
+ if (childIndex + 1 < heapSize
+ && heap[childIndex + 1].distance < heap[childIndex].distance) {
+ childIndex += 1;
+ }
+
+ if (heap[parentIndex].distance <= heap[childIndex].distance) {
+ break;
+ }
+
+ swap(heap[parentIndex], heap[childIndex]);
+ parentIndex = childIndex;
+ }
+ }
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
+ for (size_t i = 0; i < heapSize; i++) {
+ LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
+ i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+ heap[i].distance);
+ }
+#endif
+
+ // Pull matches out by increasing order of distance.
+ // To avoid reassigning pointers that have already been matched, the loop keeps track
+ // of which last and current pointers have been matched using the matchedXXXBits variables.
+ // It also tracks the used pointer id bits.
+ BitSet32 matchedLastBits(0);
+ BitSet32 matchedCurrentBits(0);
+ BitSet32 usedIdBits(0);
+ bool first = true;
+ for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
+ for (;;) {
+ if (first) {
+ // The first time through the loop, we just consume the root element of
+ // the heap (the one with smallest distance).
+ first = false;
+ } else {
+ // Previous iterations consumed the root element of the heap.
+ // Pop root element off of the heap (sift down).
+ heapSize -= 1;
+ assert(heapSize > 0);
+
+ // Sift down.
+ heap[0] = heap[heapSize];
+ for (uint32_t parentIndex = 0; ;) {
+ uint32_t childIndex = parentIndex * 2 + 1;
+ if (childIndex >= heapSize) {
+ break;
+ }
+
+ if (childIndex + 1 < heapSize
+ && heap[childIndex + 1].distance < heap[childIndex].distance) {
+ childIndex += 1;
+ }
+
+ if (heap[parentIndex].distance <= heap[childIndex].distance) {
+ break;
+ }
+
+ swap(heap[parentIndex], heap[childIndex]);
+ parentIndex = childIndex;
+ }
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
+ for (size_t i = 0; i < heapSize; i++) {
+ LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
+ i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+ heap[i].distance);
+ }
+#endif
+ }
+
+ uint32_t currentPointerIndex = heap[0].currentPointerIndex;
+ if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
+
+ uint32_t lastPointerIndex = heap[0].lastPointerIndex;
+ if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
+
+ matchedCurrentBits.markBit(currentPointerIndex);
+ matchedLastBits.markBit(lastPointerIndex);
+
+ uint32_t id = lastTouch.pointers[lastPointerIndex].id;
+ currentTouch.pointers[currentPointerIndex].id = id;
+ currentTouch.idToIndex[id] = currentPointerIndex;
+ usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
+ lastPointerIndex, currentPointerIndex, id, heap[0].distance);
+#endif
+ break;
+ }
+ }
+
+ // Assign fresh ids to new pointers.
+ if (currentPointerCount > lastPointerCount) {
+ for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
+ uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
+ uint32_t id = usedIdBits.firstUnmarkedBit();
+
+ currentTouch.pointers[currentPointerIndex].id = id;
+ currentTouch.idToIndex[id] = currentPointerIndex;
+ usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+ LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
+ currentPointerIndex, id);
+#endif
+
+ if (--i == 0) break; // done
+ matchedCurrentBits.markBit(currentPointerIndex);
+ }
+ }
+
+ // Fix id bits.
+ currentTouch.idBits = usedIdBits;
+ }
+}
+
+/* Special hack for devices that have bad screen data: if one of the
+ * points has moved more than a screen height from the last position,
+ * then drop it. */
+bool InputDevice::TouchScreenState::applyBadTouchFilter() {
+ // This hack requires valid axis parameters.
+ if (! parameters.yAxis.valid) {
+ return false;
+ }
+
+ uint32_t pointerCount = currentTouch.pointerCount;
+
+ // Nothing to do if there are no points.
+ if (pointerCount == 0) {
+ return false;
+ }
+
+ // Don't do anything if a finger is going down or up. We run
+ // here before assigning pointer IDs, so there isn't a good
+ // way to do per-finger matching.
+ if (pointerCount != lastTouch.pointerCount) {
+ return false;
+ }
+
+ // We consider a single movement across more than a 7/16 of
+ // the long size of the screen to be bad. This was a magic value
+ // determined by looking at the maximum distance it is feasible
+ // to actually move in one sample.
+ int32_t maxDeltaY = parameters.yAxis.range * 7 / 16;
+
+ // XXX The original code in InputDevice.java included commented out
+ // code for testing the X axis. Note that when we drop a point
+ // we don't actually restore the old X either. Strange.
+ // The old code also tries to track when bad points were previously
+ // detected but it turns out that due to the placement of a "break"
+ // at the end of the loop, we never set mDroppedBadPoint to true
+ // so it is effectively dead code.
+ // Need to figure out if the old code is busted or just overcomplicated
+ // but working as intended.
+
+ // Look through all new points and see if any are farther than
+ // acceptable from all previous points.
+ for (uint32_t i = pointerCount; i-- > 0; ) {
+ int32_t y = currentTouch.pointers[i].y;
+ int32_t closestY = INT_MAX;
+ int32_t closestDeltaY = 0;
+
+#if DEBUG_HACKS
+ LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
+#endif
+
+ for (uint32_t j = pointerCount; j-- > 0; ) {
+ int32_t lastY = lastTouch.pointers[j].y;
+ int32_t deltaY = abs(y - lastY);
+
+#if DEBUG_HACKS
+ LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
+ j, lastY, deltaY);
+#endif
+
+ if (deltaY < maxDeltaY) {
+ goto SkipSufficientlyClosePoint;
+ }
+ if (deltaY < closestDeltaY) {
+ closestDeltaY = deltaY;
+ closestY = lastY;
+ }
+ }
+
+ // Must not have found a close enough match.
+#if DEBUG_HACKS
+ LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
+ i, y, closestY, closestDeltaY, maxDeltaY);
+#endif
+
+ currentTouch.pointers[i].y = closestY;
+ return true; // XXX original code only corrects one point
+
+ SkipSufficientlyClosePoint: ;
+ }
+
+ // No change.
+ return false;
+}
+
+/* Special hack for devices that have bad screen data: drop points where
+ * the coordinate value for one axis has jumped to the other pointer's location.
+ */
+bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
+ // This hack requires valid axis parameters.
+ if (! parameters.yAxis.valid) {
+ return false;
+ }
+
+ uint32_t pointerCount = currentTouch.pointerCount;
+ if (lastTouch.pointerCount != pointerCount) {
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
+ lastTouch.pointerCount, pointerCount);
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ LOGD(" Pointer %d (%d, %d)", i,
+ currentTouch.pointers[i].x, currentTouch.pointers[i].y);
+ }
+#endif
+
+ if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
+ if (lastTouch.pointerCount == 1 && pointerCount == 2) {
+ // Just drop the first few events going from 1 to 2 pointers.
+ // They're bad often enough that they're not worth considering.
+ currentTouch.pointerCount = 1;
+ jumpyTouchFilter.jumpyPointsDropped += 1;
+
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Pointer 2 dropped");
+#endif
+ return true;
+ } else if (lastTouch.pointerCount == 2 && pointerCount == 1) {
+ // The event when we go from 2 -> 1 tends to be messed up too
+ currentTouch.pointerCount = 2;
+ currentTouch.pointers[0] = lastTouch.pointers[0];
+ currentTouch.pointers[1] = lastTouch.pointers[1];
+ jumpyTouchFilter.jumpyPointsDropped += 1;
+
+#if DEBUG_HACKS
+ for (int32_t i = 0; i < 2; i++) {
+ LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
+ currentTouch.pointers[i].x, currentTouch.pointers[i].y);
+ }
+#endif
+ return true;
+ }
+ }
+ // Reset jumpy points dropped on other transitions or if limit exceeded.
+ jumpyTouchFilter.jumpyPointsDropped = 0;
+
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Transition - drop limit reset");
+#endif
+ return false;
+ }
+
+ // We have the same number of pointers as last time.
+ // A 'jumpy' point is one where the coordinate value for one axis
+ // has jumped to the other pointer's location. No need to do anything
+ // else if we only have one pointer.
+ if (pointerCount < 2) {
+ return false;
+ }
+
+ if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
+ int jumpyEpsilon = parameters.yAxis.range / JUMPY_EPSILON_DIVISOR;
+
+ // We only replace the single worst jumpy point as characterized by pointer distance
+ // in a single axis.
+ int32_t badPointerIndex = -1;
+ int32_t badPointerReplacementIndex = -1;
+ int32_t badPointerDistance = INT_MIN; // distance to be corrected
+
+ for (uint32_t i = pointerCount; i-- > 0; ) {
+ int32_t x = currentTouch.pointers[i].x;
+ int32_t y = currentTouch.pointers[i].y;
+
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
+#endif
+
+ // Check if a touch point is too close to another's coordinates
+ bool dropX = false, dropY = false;
+ for (uint32_t j = 0; j < pointerCount; j++) {
+ if (i == j) {
+ continue;
+ }
+
+ if (abs(x - currentTouch.pointers[j].x) <= jumpyEpsilon) {
+ dropX = true;
+ break;
+ }
+
+ if (abs(y - currentTouch.pointers[j].y) <= jumpyEpsilon) {
+ dropY = true;
+ break;
+ }
+ }
+ if (! dropX && ! dropY) {
+ continue; // not jumpy
+ }
+
+ // Find a replacement candidate by comparing with older points on the
+ // complementary (non-jumpy) axis.
+ int32_t distance = INT_MIN; // distance to be corrected
+ int32_t replacementIndex = -1;
+
+ if (dropX) {
+ // X looks too close. Find an older replacement point with a close Y.
+ int32_t smallestDeltaY = INT_MAX;
+ for (uint32_t j = 0; j < pointerCount; j++) {
+ int32_t deltaY = abs(y - lastTouch.pointers[j].y);
+ if (deltaY < smallestDeltaY) {
+ smallestDeltaY = deltaY;
+ replacementIndex = j;
+ }
+ }
+ distance = abs(x - lastTouch.pointers[replacementIndex].x);
+ } else {
+ // Y looks too close. Find an older replacement point with a close X.
+ int32_t smallestDeltaX = INT_MAX;
+ for (uint32_t j = 0; j < pointerCount; j++) {
+ int32_t deltaX = abs(x - lastTouch.pointers[j].x);
+ if (deltaX < smallestDeltaX) {
+ smallestDeltaX = deltaX;
+ replacementIndex = j;
+ }
+ }
+ distance = abs(y - lastTouch.pointers[replacementIndex].y);
+ }
+
+ // If replacing this pointer would correct a worse error than the previous ones
+ // considered, then use this replacement instead.
+ if (distance > badPointerDistance) {
+ badPointerIndex = i;
+ badPointerReplacementIndex = replacementIndex;
+ badPointerDistance = distance;
+ }
+ }
+
+ // Correct the jumpy pointer if one was found.
+ if (badPointerIndex >= 0) {
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
+ badPointerIndex,
+ lastTouch.pointers[badPointerReplacementIndex].x,
+ lastTouch.pointers[badPointerReplacementIndex].y);
+#endif
+
+ currentTouch.pointers[badPointerIndex].x =
+ lastTouch.pointers[badPointerReplacementIndex].x;
+ currentTouch.pointers[badPointerIndex].y =
+ lastTouch.pointers[badPointerReplacementIndex].y;
+ jumpyTouchFilter.jumpyPointsDropped += 1;
+ return true;
+ }
+ }
+
+ jumpyTouchFilter.jumpyPointsDropped = 0;
+ return false;
+}
+
+/* Special hack for devices that have bad screen data: aggregate and
+ * compute averages of the coordinate data, to reduce the amount of
+ * jitter seen by applications. */
+void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
+ for (uint32_t currentIndex = 0; currentIndex < currentTouch.pointerCount; currentIndex++) {
+ uint32_t id = currentTouch.pointers[currentIndex].id;
+ int32_t x = currentTouch.pointers[currentIndex].x;
+ int32_t y = currentTouch.pointers[currentIndex].y;
+ int32_t pressure = currentTouch.pointers[currentIndex].pressure;
+
+ if (lastTouch.idBits.hasBit(id)) {
+ // Pointer was down before and is still down now.
+ // Compute average over history trace.
+ uint32_t start = averagingTouchFilter.historyStart[id];
+ uint32_t end = averagingTouchFilter.historyEnd[id];
+
+ int64_t deltaX = x - averagingTouchFilter.historyData[end].pointers[id].x;
+ int64_t deltaY = y - averagingTouchFilter.historyData[end].pointers[id].y;
+ uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+#if DEBUG_HACKS
+ LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
+ id, distance);
+#endif
+
+ if (distance < AVERAGING_DISTANCE_LIMIT) {
+ // Increment end index in preparation for recording new historical data.
+ end += 1;
+ if (end > AVERAGING_HISTORY_SIZE) {
+ end = 0;
+ }
+
+ // If the end index has looped back to the start index then we have filled
+ // the historical trace up to the desired size so we drop the historical
+ // data at the start of the trace.
+ if (end == start) {
+ start += 1;
+ if (start > AVERAGING_HISTORY_SIZE) {
+ start = 0;
+ }
+ }
+
+ // Add the raw data to the historical trace.
+ averagingTouchFilter.historyStart[id] = start;
+ averagingTouchFilter.historyEnd[id] = end;
+ averagingTouchFilter.historyData[end].pointers[id].x = x;
+ averagingTouchFilter.historyData[end].pointers[id].y = y;
+ averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
+
+ // Average over all historical positions in the trace by total pressure.
+ int32_t averagedX = 0;
+ int32_t averagedY = 0;
+ int32_t totalPressure = 0;
+ for (;;) {
+ int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
+ int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].y;
+ int32_t historicalPressure = averagingTouchFilter.historyData[start]
+ .pointers[id].pressure;
+
+ averagedX += historicalX * historicalPressure;
+ averagedY += historicalY * historicalPressure;
+ totalPressure += historicalPressure;
+
+ if (start == end) {
+ break;
+ }
+
+ start += 1;
+ if (start > AVERAGING_HISTORY_SIZE) {
+ start = 0;
+ }
+ }
+
+ averagedX /= totalPressure;
+ averagedY /= totalPressure;
+
+#if DEBUG_HACKS
+ LOGD("AveragingTouchFilter: Pointer id %d - "
+ "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
+ averagedX, averagedY);
+#endif
+
+ currentTouch.pointers[currentIndex].x = averagedX;
+ currentTouch.pointers[currentIndex].y = averagedY;
+ } else {
+#if DEBUG_HACKS
+ LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
+#endif
+ }
+ } else {
+#if DEBUG_HACKS
+ LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
+#endif
+ }
+
+ // Reset pointer history.
+ averagingTouchFilter.historyStart[id] = 0;
+ averagingTouchFilter.historyEnd[id] = 0;
+ averagingTouchFilter.historyData[0].pointers[id].x = x;
+ averagingTouchFilter.historyData[0].pointers[id].y = y;
+ averagingTouchFilter.historyData[0].pointers[id].pressure = pressure;
+ }
+}
+
+bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
+ if (! parameters.xAxis.valid || ! parameters.yAxis.valid) {
+ // Assume all points on a touch screen without valid axis parameters are
+ // inside the display.
+ return true;
+ }
+
+ return x >= parameters.xAxis.minValue
+ && x <= parameters.xAxis.maxValue
+ && y >= parameters.yAxis.minValue
+ && y <= parameters.yAxis.maxValue;
+}
+
+const InputDevice::VirtualKey* InputDevice::TouchScreenState::findVirtualKeyHit() const {
+ int32_t x = currentTouch.pointers[0].x;
+ int32_t y = currentTouch.pointers[0].y;
+ for (size_t i = 0; i < virtualKeys.size(); i++) {
+ const InputDevice::VirtualKey& virtualKey = virtualKeys[i];
+
+#if DEBUG_VIRTUAL_KEYS
+ LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
+ "left=%d, top=%d, right=%d, bottom=%d",
+ x, y,
+ virtualKey.keyCode, virtualKey.scanCode,
+ virtualKey.hitLeft, virtualKey.hitTop,
+ virtualKey.hitRight, virtualKey.hitBottom);
+#endif
+
+ if (virtualKey.isHit(x, y)) {
+ return & virtualKey;
+ }
+ }
+
+ return NULL;
+}
+
+
+// --- InputDevice::SingleTouchScreenState ---
+
+void InputDevice::SingleTouchScreenState::reset() {
+ accumulator.clear();
+ current.down = false;
+ current.x = 0;
+ current.y = 0;
+ current.pressure = 0;
+ current.size = 0;
+}
+
+
+// --- InputDevice::MultiTouchScreenState ---
+
+void InputDevice::MultiTouchScreenState::reset() {
+ accumulator.clear();
+}
+
+} // namespace android
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index f809cba..c4ffce1 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -40,10 +40,10 @@ namespace android {
// TODO, this needs to be somewhere else, perhaps in the policy
static inline bool isMovementKey(int32_t keyCode) {
- return keyCode == KEYCODE_DPAD_UP
- || keyCode == KEYCODE_DPAD_DOWN
- || keyCode == KEYCODE_DPAD_LEFT
- || keyCode == KEYCODE_DPAD_RIGHT;
+ return keyCode == AKEYCODE_DPAD_UP
+ || keyCode == AKEYCODE_DPAD_DOWN
+ || keyCode == AKEYCODE_DPAD_LEFT
+ || keyCode == AKEYCODE_DPAD_RIGHT;
}
static inline nsecs_t now() {
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index fced15c..0a21db7 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -33,18 +33,6 @@
/** Amount that trackball needs to move in order to generate a key event. */
#define TRACKBALL_MOVEMENT_THRESHOLD 6
-/* Slop distance for jumpy pointer detection.
- * The vertical range of the screen divided by this is our epsilon value. */
-#define JUMPY_EPSILON_DIVISOR 212
-
-/* Number of jumpy points to drop for touchscreens that need it. */
-#define JUMPY_TRANSITION_DROPS 3
-#define JUMPY_DROP_LIMIT 3
-
-/* Maximum squared distance for averaging.
- * If moving farther than this, turn of averaging to avoid lag in response. */
-#define AVERAGING_DISTANCE_LIMIT (75 * 75)
-
namespace android {
@@ -71,19 +59,19 @@ inline static void swap(T& a, T& b) {
int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
int32_t mask;
switch (keyCode) {
- case KEYCODE_ALT_LEFT:
+ case AKEYCODE_ALT_LEFT:
mask = META_ALT_LEFT_ON;
break;
- case KEYCODE_ALT_RIGHT:
+ case AKEYCODE_ALT_RIGHT:
mask = META_ALT_RIGHT_ON;
break;
- case KEYCODE_SHIFT_LEFT:
+ case AKEYCODE_SHIFT_LEFT:
mask = META_SHIFT_LEFT_ON;
break;
- case KEYCODE_SHIFT_RIGHT:
+ case AKEYCODE_SHIFT_RIGHT:
mask = META_SHIFT_RIGHT_ON;
break;
- case KEYCODE_SYM:
+ case AKEYCODE_SYM:
mask = META_SYM_ON;
break;
default:
@@ -107,10 +95,10 @@ int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
static const int32_t keyCodeRotationMap[][4] = {
// key codes enumerated counter-clockwise with the original (unrotated) key first
// no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
- { KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT },
- { KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN },
- { KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT },
- { KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP },
+ { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
+ { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
+ { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
+ { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
};
static const int keyCodeRotationMapSize =
sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
@@ -127,668 +115,6 @@ int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
}
-// --- InputDevice ---
-
-InputDevice::InputDevice(int32_t id, uint32_t classes, String8 name) :
- id(id), classes(classes), name(name), ignored(false) {
-}
-
-void InputDevice::reset() {
- if (isKeyboard()) {
- keyboard.reset();
- }
-
- if (isTrackball()) {
- trackball.reset();
- }
-
- if (isMultiTouchScreen()) {
- multiTouchScreen.reset();
- } else if (isSingleTouchScreen()) {
- singleTouchScreen.reset();
- }
-
- if (isTouchScreen()) {
- touchScreen.reset();
- }
-}
-
-
-// --- InputDevice::TouchData ---
-
-void InputDevice::TouchData::copyFrom(const TouchData& other) {
- pointerCount = other.pointerCount;
- idBits = other.idBits;
-
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointers[i] = other.pointers[i];
- idToIndex[i] = other.idToIndex[i];
- }
-}
-
-
-// --- InputDevice::KeyboardState ---
-
-void InputDevice::KeyboardState::reset() {
- current.metaState = META_NONE;
- current.downTime = 0;
-}
-
-
-// --- InputDevice::TrackballState ---
-
-void InputDevice::TrackballState::reset() {
- accumulator.clear();
- current.down = false;
- current.downTime = 0;
-}
-
-
-// --- InputDevice::TouchScreenState ---
-
-void InputDevice::TouchScreenState::reset() {
- lastTouch.clear();
- downTime = 0;
- currentVirtualKey.status = CurrentVirtualKeyState::STATUS_UP;
-
- for (uint32_t i = 0; i < MAX_POINTERS; i++) {
- averagingTouchFilter.historyStart[i] = 0;
- averagingTouchFilter.historyEnd[i] = 0;
- }
-
- jumpyTouchFilter.jumpyPointsDropped = 0;
-}
-
-struct PointerDistanceHeapElement {
- uint32_t currentPointerIndex : 8;
- uint32_t lastPointerIndex : 8;
- uint64_t distance : 48; // squared distance
-};
-
-void InputDevice::TouchScreenState::calculatePointerIds() {
- uint32_t currentPointerCount = currentTouch.pointerCount;
- uint32_t lastPointerCount = lastTouch.pointerCount;
-
- if (currentPointerCount == 0) {
- // No pointers to assign.
- currentTouch.idBits.clear();
- } else if (lastPointerCount == 0) {
- // All pointers are new.
- currentTouch.idBits.clear();
- for (uint32_t i = 0; i < currentPointerCount; i++) {
- currentTouch.pointers[i].id = i;
- currentTouch.idToIndex[i] = i;
- currentTouch.idBits.markBit(i);
- }
- } else if (currentPointerCount == 1 && lastPointerCount == 1) {
- // Only one pointer and no change in count so it must have the same id as before.
- uint32_t id = lastTouch.pointers[0].id;
- currentTouch.pointers[0].id = id;
- currentTouch.idToIndex[id] = 0;
- currentTouch.idBits.value = BitSet32::valueForBit(id);
- } else {
- // General case.
- // We build a heap of squared euclidean distances between current and last pointers
- // associated with the current and last pointer indices. Then, we find the best
- // match (by distance) for each current pointer.
- PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
- uint32_t heapSize = 0;
- for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
- currentPointerIndex++) {
- for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
- lastPointerIndex++) {
- int64_t deltaX = currentTouch.pointers[currentPointerIndex].x
- - lastTouch.pointers[lastPointerIndex].x;
- int64_t deltaY = currentTouch.pointers[currentPointerIndex].y
- - lastTouch.pointers[lastPointerIndex].y;
-
- uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
- // Insert new element into the heap (sift up).
- heap[heapSize].currentPointerIndex = currentPointerIndex;
- heap[heapSize].lastPointerIndex = lastPointerIndex;
- heap[heapSize].distance = distance;
- heapSize += 1;
- }
- }
-
- // Heapify
- for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
- startIndex -= 1;
- for (uint32_t parentIndex = startIndex; ;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize
- && heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
- i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
- heap[i].distance);
- }
-#endif
-
- // Pull matches out by increasing order of distance.
- // To avoid reassigning pointers that have already been matched, the loop keeps track
- // of which last and current pointers have been matched using the matchedXXXBits variables.
- // It also tracks the used pointer id bits.
- BitSet32 matchedLastBits(0);
- BitSet32 matchedCurrentBits(0);
- BitSet32 usedIdBits(0);
- bool first = true;
- for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
- for (;;) {
- if (first) {
- // The first time through the loop, we just consume the root element of
- // the heap (the one with smallest distance).
- first = false;
- } else {
- // Previous iterations consumed the root element of the heap.
- // Pop root element off of the heap (sift down).
- heapSize -= 1;
- assert(heapSize > 0);
-
- // Sift down.
- heap[0] = heap[heapSize];
- for (uint32_t parentIndex = 0; ;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize
- && heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
- i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
- heap[i].distance);
- }
-#endif
- }
-
- uint32_t currentPointerIndex = heap[0].currentPointerIndex;
- if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
- uint32_t lastPointerIndex = heap[0].lastPointerIndex;
- if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
- matchedCurrentBits.markBit(currentPointerIndex);
- matchedLastBits.markBit(lastPointerIndex);
-
- uint32_t id = lastTouch.pointers[lastPointerIndex].id;
- currentTouch.pointers[currentPointerIndex].id = id;
- currentTouch.idToIndex[id] = currentPointerIndex;
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
- lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
- break;
- }
- }
-
- // Assign fresh ids to new pointers.
- if (currentPointerCount > lastPointerCount) {
- for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
- uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
- uint32_t id = usedIdBits.firstUnmarkedBit();
-
- currentTouch.pointers[currentPointerIndex].id = id;
- currentTouch.idToIndex[id] = currentPointerIndex;
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
- currentPointerIndex, id);
-#endif
-
- if (--i == 0) break; // done
- matchedCurrentBits.markBit(currentPointerIndex);
- }
- }
-
- // Fix id bits.
- currentTouch.idBits = usedIdBits;
- }
-}
-
-/* Special hack for devices that have bad screen data: if one of the
- * points has moved more than a screen height from the last position,
- * then drop it. */
-bool InputDevice::TouchScreenState::applyBadTouchFilter() {
- // This hack requires valid axis parameters.
- if (! parameters.yAxis.valid) {
- return false;
- }
-
- uint32_t pointerCount = currentTouch.pointerCount;
-
- // Nothing to do if there are no points.
- if (pointerCount == 0) {
- return false;
- }
-
- // Don't do anything if a finger is going down or up. We run
- // here before assigning pointer IDs, so there isn't a good
- // way to do per-finger matching.
- if (pointerCount != lastTouch.pointerCount) {
- return false;
- }
-
- // We consider a single movement across more than a 7/16 of
- // the long size of the screen to be bad. This was a magic value
- // determined by looking at the maximum distance it is feasible
- // to actually move in one sample.
- int32_t maxDeltaY = parameters.yAxis.range * 7 / 16;
-
- // XXX The original code in InputDevice.java included commented out
- // code for testing the X axis. Note that when we drop a point
- // we don't actually restore the old X either. Strange.
- // The old code also tries to track when bad points were previously
- // detected but it turns out that due to the placement of a "break"
- // at the end of the loop, we never set mDroppedBadPoint to true
- // so it is effectively dead code.
- // Need to figure out if the old code is busted or just overcomplicated
- // but working as intended.
-
- // Look through all new points and see if any are farther than
- // acceptable from all previous points.
- for (uint32_t i = pointerCount; i-- > 0; ) {
- int32_t y = currentTouch.pointers[i].y;
- int32_t closestY = INT_MAX;
- int32_t closestDeltaY = 0;
-
-#if DEBUG_HACKS
- LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
-#endif
-
- for (uint32_t j = pointerCount; j-- > 0; ) {
- int32_t lastY = lastTouch.pointers[j].y;
- int32_t deltaY = abs(y - lastY);
-
-#if DEBUG_HACKS
- LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
- j, lastY, deltaY);
-#endif
-
- if (deltaY < maxDeltaY) {
- goto SkipSufficientlyClosePoint;
- }
- if (deltaY < closestDeltaY) {
- closestDeltaY = deltaY;
- closestY = lastY;
- }
- }
-
- // Must not have found a close enough match.
-#if DEBUG_HACKS
- LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
- i, y, closestY, closestDeltaY, maxDeltaY);
-#endif
-
- currentTouch.pointers[i].y = closestY;
- return true; // XXX original code only corrects one point
-
- SkipSufficientlyClosePoint: ;
- }
-
- // No change.
- return false;
-}
-
-/* Special hack for devices that have bad screen data: drop points where
- * the coordinate value for one axis has jumped to the other pointer's location.
- */
-bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
- // This hack requires valid axis parameters.
- if (! parameters.yAxis.valid) {
- return false;
- }
-
- uint32_t pointerCount = currentTouch.pointerCount;
- if (lastTouch.pointerCount != pointerCount) {
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
- lastTouch.pointerCount, pointerCount);
- for (uint32_t i = 0; i < pointerCount; i++) {
- LOGD(" Pointer %d (%d, %d)", i,
- currentTouch.pointers[i].x, currentTouch.pointers[i].y);
- }
-#endif
-
- if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
- if (lastTouch.pointerCount == 1 && pointerCount == 2) {
- // Just drop the first few events going from 1 to 2 pointers.
- // They're bad often enough that they're not worth considering.
- currentTouch.pointerCount = 1;
- jumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Pointer 2 dropped");
-#endif
- return true;
- } else if (lastTouch.pointerCount == 2 && pointerCount == 1) {
- // The event when we go from 2 -> 1 tends to be messed up too
- currentTouch.pointerCount = 2;
- currentTouch.pointers[0] = lastTouch.pointers[0];
- currentTouch.pointers[1] = lastTouch.pointers[1];
- jumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
- for (int32_t i = 0; i < 2; i++) {
- LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
- currentTouch.pointers[i].x, currentTouch.pointers[i].y);
- }
-#endif
- return true;
- }
- }
- // Reset jumpy points dropped on other transitions or if limit exceeded.
- jumpyTouchFilter.jumpyPointsDropped = 0;
-
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Transition - drop limit reset");
-#endif
- return false;
- }
-
- // We have the same number of pointers as last time.
- // A 'jumpy' point is one where the coordinate value for one axis
- // has jumped to the other pointer's location. No need to do anything
- // else if we only have one pointer.
- if (pointerCount < 2) {
- return false;
- }
-
- if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
- int jumpyEpsilon = parameters.yAxis.range / JUMPY_EPSILON_DIVISOR;
-
- // We only replace the single worst jumpy point as characterized by pointer distance
- // in a single axis.
- int32_t badPointerIndex = -1;
- int32_t badPointerReplacementIndex = -1;
- int32_t badPointerDistance = INT_MIN; // distance to be corrected
-
- for (uint32_t i = pointerCount; i-- > 0; ) {
- int32_t x = currentTouch.pointers[i].x;
- int32_t y = currentTouch.pointers[i].y;
-
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
-#endif
-
- // Check if a touch point is too close to another's coordinates
- bool dropX = false, dropY = false;
- for (uint32_t j = 0; j < pointerCount; j++) {
- if (i == j) {
- continue;
- }
-
- if (abs(x - currentTouch.pointers[j].x) <= jumpyEpsilon) {
- dropX = true;
- break;
- }
-
- if (abs(y - currentTouch.pointers[j].y) <= jumpyEpsilon) {
- dropY = true;
- break;
- }
- }
- if (! dropX && ! dropY) {
- continue; // not jumpy
- }
-
- // Find a replacement candidate by comparing with older points on the
- // complementary (non-jumpy) axis.
- int32_t distance = INT_MIN; // distance to be corrected
- int32_t replacementIndex = -1;
-
- if (dropX) {
- // X looks too close. Find an older replacement point with a close Y.
- int32_t smallestDeltaY = INT_MAX;
- for (uint32_t j = 0; j < pointerCount; j++) {
- int32_t deltaY = abs(y - lastTouch.pointers[j].y);
- if (deltaY < smallestDeltaY) {
- smallestDeltaY = deltaY;
- replacementIndex = j;
- }
- }
- distance = abs(x - lastTouch.pointers[replacementIndex].x);
- } else {
- // Y looks too close. Find an older replacement point with a close X.
- int32_t smallestDeltaX = INT_MAX;
- for (uint32_t j = 0; j < pointerCount; j++) {
- int32_t deltaX = abs(x - lastTouch.pointers[j].x);
- if (deltaX < smallestDeltaX) {
- smallestDeltaX = deltaX;
- replacementIndex = j;
- }
- }
- distance = abs(y - lastTouch.pointers[replacementIndex].y);
- }
-
- // If replacing this pointer would correct a worse error than the previous ones
- // considered, then use this replacement instead.
- if (distance > badPointerDistance) {
- badPointerIndex = i;
- badPointerReplacementIndex = replacementIndex;
- badPointerDistance = distance;
- }
- }
-
- // Correct the jumpy pointer if one was found.
- if (badPointerIndex >= 0) {
-#if DEBUG_HACKS
- LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
- badPointerIndex,
- lastTouch.pointers[badPointerReplacementIndex].x,
- lastTouch.pointers[badPointerReplacementIndex].y);
-#endif
-
- currentTouch.pointers[badPointerIndex].x =
- lastTouch.pointers[badPointerReplacementIndex].x;
- currentTouch.pointers[badPointerIndex].y =
- lastTouch.pointers[badPointerReplacementIndex].y;
- jumpyTouchFilter.jumpyPointsDropped += 1;
- return true;
- }
- }
-
- jumpyTouchFilter.jumpyPointsDropped = 0;
- return false;
-}
-
-/* Special hack for devices that have bad screen data: aggregate and
- * compute averages of the coordinate data, to reduce the amount of
- * jitter seen by applications. */
-void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
- for (uint32_t currentIndex = 0; currentIndex < currentTouch.pointerCount; currentIndex++) {
- uint32_t id = currentTouch.pointers[currentIndex].id;
- int32_t x = currentTouch.pointers[currentIndex].x;
- int32_t y = currentTouch.pointers[currentIndex].y;
- int32_t pressure = currentTouch.pointers[currentIndex].pressure;
-
- if (lastTouch.idBits.hasBit(id)) {
- // Pointer was down before and is still down now.
- // Compute average over history trace.
- uint32_t start = averagingTouchFilter.historyStart[id];
- uint32_t end = averagingTouchFilter.historyEnd[id];
-
- int64_t deltaX = x - averagingTouchFilter.historyData[end].pointers[id].x;
- int64_t deltaY = y - averagingTouchFilter.historyData[end].pointers[id].y;
- uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
- id, distance);
-#endif
-
- if (distance < AVERAGING_DISTANCE_LIMIT) {
- // Increment end index in preparation for recording new historical data.
- end += 1;
- if (end > AVERAGING_HISTORY_SIZE) {
- end = 0;
- }
-
- // If the end index has looped back to the start index then we have filled
- // the historical trace up to the desired size so we drop the historical
- // data at the start of the trace.
- if (end == start) {
- start += 1;
- if (start > AVERAGING_HISTORY_SIZE) {
- start = 0;
- }
- }
-
- // Add the raw data to the historical trace.
- averagingTouchFilter.historyStart[id] = start;
- averagingTouchFilter.historyEnd[id] = end;
- averagingTouchFilter.historyData[end].pointers[id].x = x;
- averagingTouchFilter.historyData[end].pointers[id].y = y;
- averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
-
- // Average over all historical positions in the trace by total pressure.
- int32_t averagedX = 0;
- int32_t averagedY = 0;
- int32_t totalPressure = 0;
- for (;;) {
- int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
- int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].y;
- int32_t historicalPressure = averagingTouchFilter.historyData[start]
- .pointers[id].pressure;
-
- averagedX += historicalX * historicalPressure;
- averagedY += historicalY * historicalPressure;
- totalPressure += historicalPressure;
-
- if (start == end) {
- break;
- }
-
- start += 1;
- if (start > AVERAGING_HISTORY_SIZE) {
- start = 0;
- }
- }
-
- averagedX /= totalPressure;
- averagedY /= totalPressure;
-
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - "
- "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
- averagedX, averagedY);
-#endif
-
- currentTouch.pointers[currentIndex].x = averagedX;
- currentTouch.pointers[currentIndex].y = averagedY;
- } else {
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
-#endif
- }
- } else {
-#if DEBUG_HACKS
- LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
-#endif
- }
-
- // Reset pointer history.
- averagingTouchFilter.historyStart[id] = 0;
- averagingTouchFilter.historyEnd[id] = 0;
- averagingTouchFilter.historyData[0].pointers[id].x = x;
- averagingTouchFilter.historyData[0].pointers[id].y = y;
- averagingTouchFilter.historyData[0].pointers[id].pressure = pressure;
- }
-}
-
-bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
- if (! parameters.xAxis.valid || ! parameters.yAxis.valid) {
- // Assume all points on a touch screen without valid axis parameters are
- // inside the display.
- return true;
- }
-
- return x >= parameters.xAxis.minValue
- && x <= parameters.xAxis.maxValue
- && y >= parameters.yAxis.minValue
- && y <= parameters.yAxis.maxValue;
-}
-
-const InputDevice::VirtualKey* InputDevice::TouchScreenState::findVirtualKeyHit() const {
- int32_t x = currentTouch.pointers[0].x;
- int32_t y = currentTouch.pointers[0].y;
- for (size_t i = 0; i < virtualKeys.size(); i++) {
- const InputDevice::VirtualKey& virtualKey = virtualKeys[i];
-
-#if DEBUG_VIRTUAL_KEYS
- LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
- "left=%d, top=%d, right=%d, bottom=%d",
- x, y,
- virtualKey.keyCode, virtualKey.scanCode,
- virtualKey.hitLeft, virtualKey.hitTop,
- virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
- if (virtualKey.isHit(x, y)) {
- return & virtualKey;
- }
- }
-
- return NULL;
-}
-
-
-// --- InputDevice::SingleTouchScreenState ---
-
-void InputDevice::SingleTouchScreenState::reset() {
- accumulator.clear();
- current.down = false;
- current.x = 0;
- current.y = 0;
- current.pressure = 0;
- current.size = 0;
-}
-
-
-// --- InputDevice::MultiTouchScreenState ---
-
-void InputDevice::MultiTouchScreenState::reset() {
- accumulator.clear();
-}
-
-
// --- InputReader ---
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
@@ -927,32 +253,30 @@ void InputReader::handleKey(const RawEvent* rawEvent) {
bool down = rawEvent->value != 0;
int32_t scanCode = rawEvent->scanCode;
- if (device->isKeyboard() && (scanCode < BTN_FIRST || scanCode > BTN_LAST)) {
- int32_t keyCode = rawEvent->keyCode;
- onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
- } else if (device->isSingleTouchScreen()) {
+ if (device->isSingleTouchScreen()) {
switch (rawEvent->scanCode) {
case BTN_TOUCH:
device->singleTouchScreen.accumulator.fields |=
InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
device->singleTouchScreen.accumulator.btnTouch = down;
- break;
+ return;
}
- } else if (device->isTrackball()) {
+ }
+
+ if (device->isTrackball()) {
switch (rawEvent->scanCode) {
case BTN_MOUSE:
device->trackball.accumulator.fields |=
InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
device->trackball.accumulator.btnMouse = down;
-
- // send the down immediately
- // XXX this emulates the old behavior of KeyInputQueue, unclear whether it is
- // necessary or if we can wait until the next sync
- onTrackballStateChanged(rawEvent->when, device);
- device->trackball.accumulator.clear();
- break;
+ return;
}
}
+
+ if (device->isKeyboard()) {
+ int32_t keyCode = rawEvent->keyCode;
+ onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
+ }
}
void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 2d6b531..55504f2 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -76,7 +76,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {
const int32_t nature = INPUT_EVENT_NATURE_KEY;
const int32_t action = KEY_EVENT_ACTION_DOWN;
const int32_t flags = KEY_EVENT_FLAG_FROM_SYSTEM;
- const int32_t keyCode = KEYCODE_ENTER;
+ const int32_t keyCode = AKEYCODE_ENTER;
const int32_t scanCode = 13;
const int32_t metaState = META_ALT_LEFT_ON | META_ALT_ON;
const int32_t repeatCount = 1;