Handle stylus buttons and tool types.
Added TOOL_TYPE_ERASER.
Refactored the InputReader to share more code between the
various input mappers that handle button states and to
simplify the accumulator implementations by having each
one only handle a single type of input.
Removed the concept of direct/indirect tool types from the API.
If we add it back, it should be done in a manner that is orthogonal
to the tool type itself, perhaps as a flags field on the pointer.
The device source may well provide sufficient information anyhow.
Change-Id: I811c22d95e8304269b6ee4f6d11a6b04f3cfc1b2
diff --git a/api/current.txt b/api/current.txt
index db7713a..dfc1c47 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21919,9 +21919,8 @@
field public static final int EDGE_TOP = 1; // 0x1
field public static final int FLAG_WINDOW_IS_OBSCURED = 1; // 0x1
field public static final int INVALID_POINTER_ID = -1; // 0xffffffff
+ field public static final int TOOL_TYPE_ERASER = 4; // 0x4
field public static final int TOOL_TYPE_FINGER = 1; // 0x1
- field public static final int TOOL_TYPE_INDIRECT_FINGER = 4; // 0x4
- field public static final int TOOL_TYPE_INDIRECT_STYLUS = 5; // 0x5
field public static final int TOOL_TYPE_MOUSE = 3; // 0x3
field public static final int TOOL_TYPE_STYLUS = 2; // 0x2
field public static final int TOOL_TYPE_UNKNOWN = 0; // 0x0
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 88f59d4..da5c7b2 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1123,7 +1123,10 @@
}
/**
- * Button constant: Primary button (left mouse button, stylus tip).
+ * Button constant: Primary button (left mouse button).
+ *
+ * This button constant is not set in response to simple touches with a finger
+ * or stylus tip. The user must actually push a button.
*
* @see #getButtonState
*/
@@ -1215,55 +1218,32 @@
public static final int TOOL_TYPE_UNKNOWN = 0;
/**
- * Tool type constant: The tool is a finger directly touching the display.
- *
- * This is a <em>direct</em> positioning tool.
+ * Tool type constant: The tool is a finger.
*
* @see #getToolType
*/
public static final int TOOL_TYPE_FINGER = 1;
/**
- * Tool type constant: The tool is a stylus directly touching the display
- * or hovering slightly above it.
- *
- * This is a <em>direct</em> positioning tool.
+ * Tool type constant: The tool is a stylus.
*
* @see #getToolType
*/
public static final int TOOL_TYPE_STYLUS = 2;
/**
- * Tool type constant: The tool is a mouse or trackpad that translates
- * relative motions into cursor movements on the display.
- *
- * This is an <em>indirect</em> positioning tool.
+ * Tool type constant: The tool is a mouse or trackpad.
*
* @see #getToolType
*/
public static final int TOOL_TYPE_MOUSE = 3;
/**
- * Tool type constant: The tool is a finger on a touch pad that is not
- * directly attached to the display. Finger movements on the touch pad
- * may be translated into touches on the display, possibly with visual feedback.
- *
- * This is an <em>indirect</em> positioning tool.
+ * Tool type constant: The tool is an eraser or a stylus being used in an inverted posture.
*
* @see #getToolType
*/
- public static final int TOOL_TYPE_INDIRECT_FINGER = 4;
-
- /**
- * Tool type constant: The tool is a stylus on a digitizer tablet that is not
- * attached to the display. Stylus movements on the digitizer may be translated
- * into touches on the display, possibly with visual feedback.
- *
- * This is an <em>indirect</em> positioning tool.
- *
- * @see #getToolType
- */
- public static final int TOOL_TYPE_INDIRECT_STYLUS = 5;
+ public static final int TOOL_TYPE_ERASER = 4;
// NOTE: If you add a new tool type here you must also add it to:
// native/include/android/input.h
@@ -1276,8 +1256,7 @@
names.append(TOOL_TYPE_FINGER, "TOOL_TYPE_FINGER");
names.append(TOOL_TYPE_STYLUS, "TOOL_TYPE_STYLUS");
names.append(TOOL_TYPE_MOUSE, "TOOL_TYPE_MOUSE");
- names.append(TOOL_TYPE_INDIRECT_FINGER, "TOOL_TYPE_INDIRECT_FINGER");
- names.append(TOOL_TYPE_INDIRECT_STYLUS, "TOOL_TYPE_INDIRECT_STYLUS");
+ names.append(TOOL_TYPE_ERASER, "TOOL_TYPE_ERASER");
}
// Private value for history pos that obtains the current sample.
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 0d8ea28..7a0dcd3 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -415,8 +415,7 @@
AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER = 4,
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS = 5,
+ AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
};
/*
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index ca2540b..7ea3de2 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -460,6 +460,17 @@
mExcludedDevices = devices;
}
+bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ if (device && scanCode >= 0 && scanCode <= KEY_MAX) {
+ if (test_bit(scanCode, device->keyBitmask)) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 695dfdf..293a1a0 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -195,6 +195,7 @@
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
uint8_t* outFlags) const = 0;
+ virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
@@ -246,6 +247,7 @@
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
+ virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
virtual bool hasLed(int32_t deviceId, int32_t led) const;
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 3e041f3..9d69c60 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -151,30 +151,6 @@
return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
}
-static uint32_t getButtonStateForScanCode(int32_t scanCode) {
- // Currently all buttons are mapped to the primary button.
- switch (scanCode) {
- case BTN_LEFT:
- return AMOTION_EVENT_BUTTON_PRIMARY;
- case BTN_RIGHT:
- case BTN_STYLUS:
- return AMOTION_EVENT_BUTTON_SECONDARY;
- case BTN_MIDDLE:
- case BTN_STYLUS2:
- return AMOTION_EVENT_BUTTON_TERTIARY;
- case BTN_SIDE:
- return AMOTION_EVENT_BUTTON_BACK;
- case BTN_FORWARD:
- case BTN_EXTRA:
- return AMOTION_EVENT_BUTTON_FORWARD;
- case BTN_BACK:
- return AMOTION_EVENT_BUTTON_BACK;
- case BTN_TASK:
- default:
- return 0;
- }
-}
-
// Returns true if the pointer should be reported as being down given the specified
// button states. This determines whether the event is reported as a touch event.
static bool isPointerDown(int32_t buttonState) {
@@ -1007,6 +983,378 @@
}
+// --- CursorButtonAccumulator ---
+
+CursorButtonAccumulator::CursorButtonAccumulator() {
+ clearButtons();
+}
+
+void CursorButtonAccumulator::clearButtons() {
+ mBtnLeft = 0;
+ mBtnRight = 0;
+ mBtnMiddle = 0;
+ mBtnBack = 0;
+ mBtnSide = 0;
+ mBtnForward = 0;
+ mBtnExtra = 0;
+ mBtnTask = 0;
+}
+
+void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_KEY) {
+ switch (rawEvent->scanCode) {
+ case BTN_LEFT:
+ mBtnLeft = rawEvent->value;
+ break;
+ case BTN_RIGHT:
+ mBtnRight = rawEvent->value;
+ break;
+ case BTN_MIDDLE:
+ mBtnMiddle = rawEvent->value;
+ break;
+ case BTN_BACK:
+ mBtnBack = rawEvent->value;
+ break;
+ case BTN_SIDE:
+ mBtnSide = rawEvent->value;
+ break;
+ case BTN_FORWARD:
+ mBtnForward = rawEvent->value;
+ break;
+ case BTN_EXTRA:
+ mBtnExtra = rawEvent->value;
+ break;
+ case BTN_TASK:
+ mBtnTask = rawEvent->value;
+ break;
+ }
+ }
+}
+
+uint32_t CursorButtonAccumulator::getButtonState() const {
+ uint32_t result = 0;
+ if (mBtnLeft) {
+ result |= AMOTION_EVENT_BUTTON_PRIMARY;
+ }
+ if (mBtnRight) {
+ result |= AMOTION_EVENT_BUTTON_SECONDARY;
+ }
+ if (mBtnMiddle) {
+ result |= AMOTION_EVENT_BUTTON_TERTIARY;
+ }
+ if (mBtnBack || mBtnSide) {
+ result |= AMOTION_EVENT_BUTTON_BACK;
+ }
+ if (mBtnForward || mBtnExtra) {
+ result |= AMOTION_EVENT_BUTTON_FORWARD;
+ }
+ return result;
+}
+
+
+// --- CursorMotionAccumulator ---
+
+CursorMotionAccumulator::CursorMotionAccumulator() :
+ mHaveRelWheel(false), mHaveRelHWheel(false) {
+ clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::configure(InputDevice* device) {
+ mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
+ mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+}
+
+void CursorMotionAccumulator::clearRelativeAxes() {
+ mRelX = 0;
+ mRelY = 0;
+ mRelWheel = 0;
+ mRelHWheel = 0;
+}
+
+void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_REL) {
+ switch (rawEvent->scanCode) {
+ case REL_X:
+ mRelX = rawEvent->value;
+ break;
+ case REL_Y:
+ mRelY = rawEvent->value;
+ break;
+ case REL_WHEEL:
+ mRelWheel = rawEvent->value;
+ break;
+ case REL_HWHEEL:
+ mRelHWheel = rawEvent->value;
+ break;
+ }
+ }
+}
+
+
+// --- TouchButtonAccumulator ---
+
+TouchButtonAccumulator::TouchButtonAccumulator() :
+ mHaveBtnTouch(false) {
+ clearButtons();
+}
+
+void TouchButtonAccumulator::configure(InputDevice* device) {
+ mHaveBtnTouch = device->getEventHub()->hasScanCode(device->getId(), BTN_TOUCH);
+}
+
+void TouchButtonAccumulator::clearButtons() {
+ mBtnTouch = 0;
+ mBtnStylus = 0;
+ mBtnStylus2 = 0;
+ mBtnToolFinger = 0;
+ mBtnToolPen = 0;
+ mBtnToolRubber = 0;
+}
+
+void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_KEY) {
+ switch (rawEvent->scanCode) {
+ case BTN_TOUCH:
+ mBtnTouch = rawEvent->value;
+ break;
+ case BTN_STYLUS:
+ mBtnStylus = rawEvent->value;
+ break;
+ case BTN_STYLUS2:
+ mBtnStylus2 = rawEvent->value;
+ break;
+ case BTN_TOOL_FINGER:
+ mBtnToolFinger = rawEvent->value;
+ break;
+ case BTN_TOOL_PEN:
+ mBtnToolPen = rawEvent->value;
+ break;
+ case BTN_TOOL_RUBBER:
+ mBtnToolRubber = rawEvent->value;
+ break;
+ }
+ }
+}
+
+uint32_t TouchButtonAccumulator::getButtonState() const {
+ uint32_t result = 0;
+ if (mBtnStylus) {
+ result |= AMOTION_EVENT_BUTTON_SECONDARY;
+ }
+ if (mBtnStylus2) {
+ result |= AMOTION_EVENT_BUTTON_TERTIARY;
+ }
+ return result;
+}
+
+int32_t TouchButtonAccumulator::getToolType() const {
+ if (mBtnToolRubber) {
+ return AMOTION_EVENT_TOOL_TYPE_ERASER;
+ }
+ if (mBtnToolPen) {
+ return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+ if (mBtnToolFinger) {
+ return AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+bool TouchButtonAccumulator::isActive() const {
+ return mBtnTouch || mBtnToolFinger || mBtnToolPen
+ || mBtnToolRubber || mBtnStylus || mBtnStylus2;
+}
+
+bool TouchButtonAccumulator::isHovering() const {
+ return mHaveBtnTouch && !mBtnTouch;
+}
+
+
+// --- SingleTouchMotionAccumulator ---
+
+SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
+ clearAbsoluteAxes();
+}
+
+void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
+ mAbsX = 0;
+ mAbsY = 0;
+ mAbsPressure = 0;
+ mAbsToolWidth = 0;
+ mAbsDistance = 0;
+}
+
+void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_ABS) {
+ switch (rawEvent->scanCode) {
+ case ABS_X:
+ mAbsX = rawEvent->value;
+ break;
+ case ABS_Y:
+ mAbsY = rawEvent->value;
+ break;
+ case ABS_PRESSURE:
+ mAbsPressure = rawEvent->value;
+ break;
+ case ABS_TOOL_WIDTH:
+ mAbsToolWidth = rawEvent->value;
+ break;
+ case ABS_DISTANCE:
+ mAbsDistance = rawEvent->value;
+ break;
+ }
+ }
+}
+
+
+// --- MultiTouchMotionAccumulator ---
+
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
+ mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
+}
+
+MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
+ delete[] mSlots;
+}
+
+void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
+ mSlotCount = slotCount;
+ mUsingSlotsProtocol = usingSlotsProtocol;
+
+ delete[] mSlots;
+ mSlots = new Slot[slotCount];
+}
+
+void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
+ for (size_t i = 0; i < mSlotCount; i++) {
+ mSlots[i].clearIfInUse();
+ }
+ mCurrentSlot = initialSlot;
+}
+
+void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_ABS) {
+ bool newSlot = false;
+ if (mUsingSlotsProtocol) {
+ if (rawEvent->scanCode == ABS_MT_SLOT) {
+ mCurrentSlot = rawEvent->value;
+ newSlot = true;
+ }
+ } else if (mCurrentSlot < 0) {
+ mCurrentSlot = 0;
+ }
+
+ if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+#if DEBUG_POINTERS
+ if (newSlot) {
+ LOGW("MultiTouch device emitted invalid slot index %d but it "
+ "should be between 0 and %d; ignoring this slot.",
+ mCurrentSlot, mSlotCount - 1);
+ }
+#endif
+ } else {
+ Slot* slot = &mSlots[mCurrentSlot];
+
+ switch (rawEvent->scanCode) {
+ case ABS_MT_POSITION_X:
+ slot->mInUse = true;
+ slot->mAbsMTPositionX = rawEvent->value;
+ break;
+ case ABS_MT_POSITION_Y:
+ slot->mInUse = true;
+ slot->mAbsMTPositionY = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MAJOR:
+ slot->mInUse = true;
+ slot->mAbsMTTouchMajor = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MINOR:
+ slot->mInUse = true;
+ slot->mAbsMTTouchMinor = rawEvent->value;
+ slot->mHaveAbsMTTouchMinor = true;
+ break;
+ case ABS_MT_WIDTH_MAJOR:
+ slot->mInUse = true;
+ slot->mAbsMTWidthMajor = rawEvent->value;
+ break;
+ case ABS_MT_WIDTH_MINOR:
+ slot->mInUse = true;
+ slot->mAbsMTWidthMinor = rawEvent->value;
+ slot->mHaveAbsMTWidthMinor = true;
+ break;
+ case ABS_MT_ORIENTATION:
+ slot->mInUse = true;
+ slot->mAbsMTOrientation = rawEvent->value;
+ break;
+ case ABS_MT_TRACKING_ID:
+ if (mUsingSlotsProtocol && rawEvent->value < 0) {
+ slot->clearIfInUse();
+ } else {
+ slot->mInUse = true;
+ slot->mAbsMTTrackingId = rawEvent->value;
+ }
+ break;
+ case ABS_MT_PRESSURE:
+ slot->mInUse = true;
+ slot->mAbsMTPressure = rawEvent->value;
+ break;
+ case ABS_MT_TOOL_TYPE:
+ slot->mInUse = true;
+ slot->mAbsMTToolType = rawEvent->value;
+ slot->mHaveAbsMTToolType = true;
+ break;
+ }
+ }
+ } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) {
+ // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+ mCurrentSlot += 1;
+ }
+}
+
+
+// --- MultiTouchMotionAccumulator::Slot ---
+
+MultiTouchMotionAccumulator::Slot::Slot() {
+ clear();
+}
+
+void MultiTouchMotionAccumulator::Slot::clearIfInUse() {
+ if (mInUse) {
+ clear();
+ }
+}
+
+void MultiTouchMotionAccumulator::Slot::clear() {
+ mInUse = false;
+ mHaveAbsMTTouchMinor = false;
+ mHaveAbsMTWidthMinor = false;
+ mHaveAbsMTToolType = false;
+ mAbsMTPositionX = 0;
+ mAbsMTPositionY = 0;
+ mAbsMTTouchMajor = 0;
+ mAbsMTTouchMinor = 0;
+ mAbsMTWidthMajor = 0;
+ mAbsMTWidthMinor = 0;
+ mAbsMTOrientation = 0;
+ mAbsMTTrackingId = -1;
+ mAbsMTPressure = 0;
+ mAbsMTToolType = 0;
+ mAbsMTDistance = 0;
+}
+
+int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
+ if (mHaveAbsMTToolType) {
+ switch (mAbsMTToolType) {
+ case MT_TOOL_FINGER:
+ return AMOTION_EVENT_TOOL_TYPE_FINGER;
+ case MT_TOOL_PEN:
+ return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+ }
+ return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+
// --- InputMapper ---
InputMapper::InputMapper(InputDevice* device) :
@@ -1399,10 +1747,10 @@
}
info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
- if (mHaveVWheel) {
+ if (mCursorMotionAccumulator.haveRelativeVWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
- if (mHaveHWheel) {
+ if (mCursorMotionAccumulator.haveRelativeHWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
}
@@ -1416,8 +1764,10 @@
dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
- dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
+ dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
+ toString(mCursorMotionAccumulator.haveRelativeVWheel()));
+ dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
+ toString(mCursorMotionAccumulator.haveRelativeHWheel()));
dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
@@ -1430,6 +1780,8 @@
InputMapper::configure(config, changes);
if (!changes) { // first time only
+ mCursorMotionAccumulator.configure(getDevice());
+
// Configure basic parameters.
configureParameters();
@@ -1454,9 +1806,6 @@
mVWheelScale = 1.0f;
mHWheelScale = 1.0f;
-
- mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
- mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
@@ -1506,7 +1855,8 @@
}
void CursorInputMapper::initializeLocked() {
- mAccumulator.clear();
+ mCursorButtonAccumulator.clearButtons();
+ mCursorMotionAccumulator.clearRelativeAxes();
mLocked.buttonState = 0;
mLocked.downTime = 0;
@@ -1532,10 +1882,8 @@
// Synthesize button up event on reset.
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- mAccumulator.clear();
- mAccumulator.buttonDown = 0;
- mAccumulator.buttonUp = buttonState;
- mAccumulator.fields = Accumulator::FIELD_BUTTONS;
+ mCursorButtonAccumulator.clearButtons();
+ mCursorMotionAccumulator.clearRelativeAxes();
sync(when);
}
@@ -1543,64 +1891,15 @@
}
void CursorInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
- if (buttonState) {
- if (rawEvent->value) {
- mAccumulator.buttonDown = buttonState;
- mAccumulator.buttonUp = 0;
- } else {
- mAccumulator.buttonDown = 0;
- mAccumulator.buttonUp = buttonState;
- }
- mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
+ mCursorButtonAccumulator.process(rawEvent);
+ mCursorMotionAccumulator.process(rawEvent);
- // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
- // we need to ensure that we report the up/down promptly.
- sync(rawEvent->when);
- break;
- }
- break;
- }
-
- case EV_REL:
- switch (rawEvent->scanCode) {
- case REL_X:
- mAccumulator.fields |= Accumulator::FIELD_REL_X;
- mAccumulator.relX = rawEvent->value;
- break;
- case REL_Y:
- mAccumulator.fields |= Accumulator::FIELD_REL_Y;
- mAccumulator.relY = rawEvent->value;
- break;
- case REL_WHEEL:
- mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
- mAccumulator.relWheel = rawEvent->value;
- break;
- case REL_HWHEEL:
- mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
- mAccumulator.relHWheel = rawEvent->value;
- break;
- }
- break;
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
}
}
void CursorInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
- }
-
int32_t motionEventAction;
int32_t lastButtonState, currentButtonState;
PointerProperties pointerProperties;
@@ -1611,34 +1910,21 @@
AutoMutex _l(mLock);
lastButtonState = mLocked.buttonState;
+ currentButtonState = mCursorButtonAccumulator.getButtonState();
+ mLocked.buttonState = currentButtonState;
- bool down, downChanged;
- bool wasDown = isPointerDown(mLocked.buttonState);
- bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
- if (buttonsChanged) {
- mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
- & ~mAccumulator.buttonUp;
-
- down = isPointerDown(mLocked.buttonState);
-
- if (!wasDown && down) {
- mLocked.downTime = when;
- downChanged = true;
- } else if (wasDown && !down) {
- downChanged = true;
- } else {
- downChanged = false;
- }
+ bool wasDown = isPointerDown(lastButtonState);
+ bool down = isPointerDown(currentButtonState);
+ bool downChanged;
+ if (!wasDown && down) {
+ mLocked.downTime = when;
+ downChanged = true;
+ } else if (wasDown && !down) {
+ downChanged = true;
} else {
- down = wasDown;
downChanged = false;
}
-
- currentButtonState = mLocked.buttonState;
-
downTime = mLocked.downTime;
- float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
- float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
if (downChanged) {
motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
@@ -1648,6 +1934,9 @@
motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
}
+ float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
+ float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
+
if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
&& (deltaX != 0.0f || deltaY != 0.0f)) {
// Rotate motion based on display orientation if needed.
@@ -1667,25 +1956,17 @@
pointerCoords.clear();
- if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
- vscroll = mAccumulator.relWheel;
- } else {
- vscroll = 0;
- }
- mWheelYVelocityControl.move(when, NULL, &vscroll);
+ vscroll = mCursorMotionAccumulator.getRelativeVWheel();
+ hscroll = mCursorMotionAccumulator.getRelativeHWheel();
- if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
- hscroll = mAccumulator.relHWheel;
- } else {
- hscroll = 0;
- }
+ mWheelYVelocityControl.move(when, NULL, &vscroll);
mWheelXVelocityControl.move(when, &hscroll, NULL);
mPointerVelocityControl.move(when, &deltaX, &deltaY);
if (mPointerController != NULL) {
if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
- || buttonsChanged) {
+ || currentButtonState != lastButtonState) {
mPointerController->setPresentation(
PointerControllerInterface::PRESENTATION_POINTER);
@@ -1693,8 +1974,8 @@
mPointerController->move(deltaX, deltaY);
}
- if (buttonsChanged) {
- mPointerController->setButtonState(mLocked.buttonState);
+ if (currentButtonState != lastButtonState) {
+ mPointerController->setButtonState(currentButtonState);
}
mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
@@ -1755,7 +2036,7 @@
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
policyFlags, lastButtonState, currentButtonState);
- mAccumulator.clear();
+ mCursorMotionAccumulator.clearRelativeAxes();
}
int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
@@ -1881,10 +2162,11 @@
const PointerData& pointer = mLastTouch.pointers[i];
dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
"touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
- "orientation=%d, distance=%d, isStylus=%s\n", i,
+ "orientation=%d, distance=%d, toolType=%d, isHovering=%s\n", i,
pointer.id, pointer.x, pointer.y, pointer.pressure,
pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, pointer.toolMinor,
- pointer.orientation, pointer.distance, toString(pointer.isStylus));
+ pointer.orientation, pointer.distance,
+ pointer.toolType, toString(pointer.isHovering));
}
if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
@@ -2924,6 +3206,7 @@
calculatePointerIds();
}
+ // Handle initial down events.
uint32_t policyFlags = 0;
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
@@ -3420,7 +3703,7 @@
PointerProperties& properties = mCurrentTouchProperties[i];
properties.clear();
properties.id = mCurrentTouch.pointers[i].id;
- properties.toolType = getTouchToolType(mCurrentTouch.pointers[i].isStylus);
+ properties.toolType = mCurrentTouch.pointers[i].toolType;
}
*outXPrecision = mLocked.orientedXPrecision;
@@ -3604,7 +3887,7 @@
PointerProperties pointerProperties;
pointerProperties.clear();
pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
PointerCoords pointerCoords;
pointerCoords.clear();
@@ -3838,8 +4121,7 @@
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
mPointerGesture.currentGestureProperties[0].clear();
mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -3880,7 +4162,7 @@
mPointerGesture.currentGestureProperties[0].id =
mPointerGesture.activeGestureId;
mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(
AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
@@ -3993,7 +4275,7 @@
mPointerGesture.currentGestureProperties[0].clear();
mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -4240,7 +4522,7 @@
mPointerGesture.currentGestureProperties[0].clear();
mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
mPointerGesture.referenceGestureX);
@@ -4331,7 +4613,7 @@
mPointerGesture.currentGestureProperties[i].clear();
mPointerGesture.currentGestureProperties[i].id = gestureId;
mPointerGesture.currentGestureProperties[i].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[i].clear();
mPointerGesture.currentGestureCoords[i].setAxisValue(
AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
@@ -4473,15 +4755,6 @@
} // release lock
}
-int32_t TouchInputMapper::getTouchToolType(bool isStylus) const {
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
- return isStylus ? AMOTION_EVENT_TOOL_TYPE_STYLUS : AMOTION_EVENT_TOOL_TYPE_FINGER;
- } else {
- return isStylus ? AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS
- : AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
- }
-}
-
bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
&& y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
@@ -4760,14 +5033,9 @@
}
void SingleTouchInputMapper::clearState() {
- mAccumulator.clear();
-
- mDown = false;
- mX = 0;
- mY = 0;
- mPressure = 0; // default to 0 for devices that don't report pressure
- mToolWidth = 0; // default to 0 for devices that don't report tool width
- mButtonState = 0;
+ mCursorButtonAccumulator.clearButtons();
+ mTouchButtonAccumulator.clearButtons();
+ mSingleTouchMotionAccumulator.clearAbsoluteAxes();
}
void SingleTouchInputMapper::reset() {
@@ -4777,144 +5045,79 @@
}
void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY:
- switch (rawEvent->scanCode) {
- case BTN_TOUCH:
- mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
- mAccumulator.btnTouch = rawEvent->value != 0;
- // Don't sync immediately. Wait until the next SYN_REPORT since we might
- // not have received valid position information yet. This logic assumes that
- // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
- break;
- default:
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
- if (buttonState) {
- if (rawEvent->value) {
- mAccumulator.buttonDown |= buttonState;
- } else {
- mAccumulator.buttonUp |= buttonState;
- }
- mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
- }
- }
- break;
- }
- break;
+ mCursorButtonAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+ mSingleTouchMotionAccumulator.process(rawEvent);
- case EV_ABS:
- switch (rawEvent->scanCode) {
- case ABS_X:
- mAccumulator.fields |= Accumulator::FIELD_ABS_X;
- mAccumulator.absX = rawEvent->value;
- break;
- case ABS_Y:
- mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
- mAccumulator.absY = rawEvent->value;
- break;
- case ABS_PRESSURE:
- mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
- mAccumulator.absPressure = rawEvent->value;
- break;
- case ABS_TOOL_WIDTH:
- mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
- mAccumulator.absToolWidth = rawEvent->value;
- break;
- }
- break;
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
}
}
void SingleTouchInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
- }
-
- if (fields & Accumulator::FIELD_BTN_TOUCH) {
- mDown = mAccumulator.btnTouch;
- }
-
- if (fields & Accumulator::FIELD_ABS_X) {
- mX = mAccumulator.absX;
- }
-
- if (fields & Accumulator::FIELD_ABS_Y) {
- mY = mAccumulator.absY;
- }
-
- if (fields & Accumulator::FIELD_ABS_PRESSURE) {
- mPressure = mAccumulator.absPressure;
- }
-
- if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
- mToolWidth = mAccumulator.absToolWidth;
- }
-
- if (fields & Accumulator::FIELD_BUTTONS) {
- mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
- }
-
mCurrentTouch.clear();
- if (mDown) {
+ if (mTouchButtonAccumulator.isActive()) {
+ uint32_t buttonState = mTouchButtonAccumulator.getButtonState();
+ bool isHovering = mTouchButtonAccumulator.isHovering();
+ if (mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0) {
+ isHovering = true;
+ }
+
mCurrentTouch.pointerCount = 1;
- mCurrentTouch.pointers[0].id = 0;
- mCurrentTouch.pointers[0].x = mX;
- mCurrentTouch.pointers[0].y = mY;
- mCurrentTouch.pointers[0].pressure = mPressure;
- mCurrentTouch.pointers[0].touchMajor = 0;
- mCurrentTouch.pointers[0].touchMinor = 0;
- mCurrentTouch.pointers[0].toolMajor = mToolWidth;
- mCurrentTouch.pointers[0].toolMinor = mToolWidth;
- mCurrentTouch.pointers[0].orientation = 0;
- mCurrentTouch.pointers[0].distance = 0;
- mCurrentTouch.pointers[0].isStylus = false; // TODO: Set stylus
mCurrentTouch.idToIndex[0] = 0;
mCurrentTouch.idBits.markBit(0);
- mCurrentTouch.buttonState = mButtonState;
+ mCurrentTouch.buttonState = buttonState;
+
+ PointerData& outPointer = mCurrentTouch.pointers[0];
+ outPointer.id = 0;
+ outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
+ outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
+ outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+ outPointer.touchMajor = 0;
+ outPointer.touchMinor = 0;
+ outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+ outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+ outPointer.orientation = 0;
+ outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
+ outPointer.toolType = mTouchButtonAccumulator.getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ outPointer.isHovering = isHovering;
}
syncTouch(when, true);
-
- mAccumulator.clear();
}
void SingleTouchInputMapper::configureRawAxes() {
TouchInputMapper::configureRawAxes();
+ mTouchButtonAccumulator.configure(getDevice());
+
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
+ getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_DISTANCE, & mRawAxes.distance);
}
// --- MultiTouchInputMapper ---
MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
- TouchInputMapper(device), mSlotCount(0), mUsingSlotsProtocol(false) {
+ TouchInputMapper(device) {
}
MultiTouchInputMapper::~MultiTouchInputMapper() {
}
void MultiTouchInputMapper::clearState() {
- mAccumulator.clearSlots(mSlotCount);
- mAccumulator.clearButtons();
- mButtonState = 0;
+ mCursorButtonAccumulator.clearButtons();
+ mTouchButtonAccumulator.clearButtons();
mPointerIdBits.clear();
- if (mUsingSlotsProtocol) {
+ if (mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
// Query the driver for the current slot index and use it as the initial slot
// before we start reading events from the device. It is possible that the
// current slot index will not be the same as it was when the first event was
@@ -4924,12 +5127,16 @@
// two slots will be confused until the next ABS_MT_SLOT event is received.
// This can cause the touch point to "jump", but at least there will be
// no stuck touches.
+ int32_t initialSlot;
status_t status = getEventHub()->getAbsoluteAxisValue(getDeviceId(), ABS_MT_SLOT,
- &mAccumulator.currentSlot);
+ &initialSlot);
if (status) {
LOGW("Could not retrieve current multitouch slot index. status=%d", status);
- mAccumulator.currentSlot = -1;
+ initialSlot = -1;
}
+ mMultiTouchMotionAccumulator.clearSlots(initialSlot);
+ } else {
+ mMultiTouchMotionAccumulator.clearSlots(-1);
}
}
@@ -4940,124 +5147,26 @@
}
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
- if (buttonState) {
- if (rawEvent->value) {
- mAccumulator.buttonDown |= buttonState;
- } else {
- mAccumulator.buttonUp |= buttonState;
- }
- }
- }
- break;
- }
+ mCursorButtonAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+ mMultiTouchMotionAccumulator.process(rawEvent);
- case EV_ABS: {
- bool newSlot = false;
- if (mUsingSlotsProtocol && rawEvent->scanCode == ABS_MT_SLOT) {
- mAccumulator.currentSlot = rawEvent->value;
- newSlot = true;
- }
-
- if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
- if (newSlot) {
- LOGW("MultiTouch device %s emitted invalid slot index %d but it "
- "should be between 0 and %d; ignoring this slot.",
- getDeviceName().string(), mAccumulator.currentSlot, mSlotCount);
- }
-#endif
- break;
- }
-
- Accumulator::Slot* slot = &mAccumulator.slots[mAccumulator.currentSlot];
-
- switch (rawEvent->scanCode) {
- case ABS_MT_POSITION_X:
- slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
- slot->absMTPositionX = rawEvent->value;
- break;
- case ABS_MT_POSITION_Y:
- slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
- slot->absMTPositionY = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MAJOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
- slot->absMTTouchMajor = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MINOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
- slot->absMTTouchMinor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MAJOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
- slot->absMTWidthMajor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MINOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
- slot->absMTWidthMinor = rawEvent->value;
- break;
- case ABS_MT_ORIENTATION:
- slot->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
- slot->absMTOrientation = rawEvent->value;
- break;
- case ABS_MT_TRACKING_ID:
- if (mUsingSlotsProtocol && rawEvent->value < 0) {
- slot->clear();
- } else {
- slot->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
- slot->absMTTrackingId = rawEvent->value;
- }
- break;
- case ABS_MT_PRESSURE:
- slot->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
- slot->absMTPressure = rawEvent->value;
- break;
- case ABS_MT_TOOL_TYPE:
- slot->fields |= Accumulator::FIELD_ABS_MT_TOOL_TYPE;
- slot->absMTToolType = rawEvent->value;
- break;
- }
- break;
- }
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_MT_REPORT: {
- // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
- mAccumulator.currentSlot += 1;
- break;
- }
-
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
}
}
void MultiTouchInputMapper::sync(nsecs_t when) {
- static const uint32_t REQUIRED_FIELDS =
- Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
-
- size_t inCount = mSlotCount;
+ size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
size_t outCount = 0;
bool havePointerIds = true;
mCurrentTouch.clear();
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
- const Accumulator::Slot& inSlot = mAccumulator.slots[inIndex];
- uint32_t fields = inSlot.fields;
-
- if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
- // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
- // This may also indicate an unused slot.
- // Drop this finger.
+ const MultiTouchMotionAccumulator::Slot* inSlot =
+ mMultiTouchMotionAccumulator.getSlot(inIndex);
+ if (!inSlot->isInUse()) {
continue;
}
@@ -5071,71 +5180,32 @@
}
PointerData& outPointer = mCurrentTouch.pointers[outCount];
- outPointer.x = inSlot.absMTPositionX;
- outPointer.y = inSlot.absMTPositionY;
+ outPointer.x = inSlot->getX();
+ outPointer.y = inSlot->getY();
+ outPointer.pressure = inSlot->getPressure();
+ outPointer.touchMajor = inSlot->getTouchMajor();
+ outPointer.touchMinor = inSlot->getTouchMinor();
+ outPointer.toolMajor = inSlot->getToolMajor();
+ outPointer.toolMinor = inSlot->getToolMinor();
+ outPointer.orientation = inSlot->getOrientation();
+ outPointer.distance = inSlot->getDistance();
- if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
- outPointer.pressure = inSlot.absMTPressure;
- } else {
- // Default pressure to 0 if absent.
- outPointer.pressure = 0;
+ outPointer.toolType = inSlot->getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = mTouchButtonAccumulator.getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
}
- if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
- outPointer.touchMajor = inSlot.absMTTouchMajor;
- } else {
- // Default touch area to 0 if absent.
- outPointer.touchMajor = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
- outPointer.touchMinor = inSlot.absMTTouchMinor;
- } else {
- // Assume touch area is circular.
- outPointer.touchMinor = outPointer.touchMajor;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
- outPointer.toolMajor = inSlot.absMTWidthMajor;
- } else {
- // Default tool area to 0 if absent.
- outPointer.toolMajor = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
- outPointer.toolMinor = inSlot.absMTWidthMinor;
- } else {
- // Assume tool area is circular.
- outPointer.toolMinor = outPointer.toolMajor;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
- outPointer.orientation = inSlot.absMTOrientation;
- } else {
- // Default orientation to vertical if absent.
- outPointer.orientation = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_DISTANCE) {
- outPointer.distance = inSlot.absMTDistance;
- } else {
- // Default distance is 0 (direct contact).
- outPointer.distance = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_TOOL_TYPE) {
- outPointer.isStylus = (inSlot.absMTToolType == MT_TOOL_PEN);
- } else {
- // Assume this is not a stylus.
- outPointer.isStylus = false;
- }
+ outPointer.isHovering = mTouchButtonAccumulator.isHovering()
+ || inSlot->getDistance() > 0;
// Assign pointer id using tracking id if available.
if (havePointerIds) {
+ int32_t trackingId = inSlot->getTrackingId();
int32_t id = -1;
- if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
- int32_t trackingId = inSlot.absMTTrackingId;
-
+ if (trackingId >= 0) {
for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
uint32_t n = idBits.firstMarkedBit();
idBits.clearBit(n);
@@ -5165,23 +5235,22 @@
}
mCurrentTouch.pointerCount = outCount;
-
- mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
- mCurrentTouch.buttonState = mButtonState;
+ mCurrentTouch.buttonState = mTouchButtonAccumulator.getButtonState();
mPointerIdBits = mCurrentTouch.idBits;
syncTouch(when, havePointerIds);
- if (!mUsingSlotsProtocol) {
- mAccumulator.clearSlots(mSlotCount);
+ if (!mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
+ mMultiTouchMotionAccumulator.clearSlots(-1);
}
- mAccumulator.clearButtons();
}
void MultiTouchInputMapper::configureRawAxes() {
TouchInputMapper::configureRawAxes();
+ mTouchButtonAccumulator.configure(getDevice());
+
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor);
@@ -5196,21 +5265,18 @@
if (mRawAxes.trackingId.valid
&& mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) {
- mSlotCount = mRawAxes.slot.maxValue + 1;
- if (mSlotCount > MAX_SLOTS) {
+ size_t slotCount = mRawAxes.slot.maxValue + 1;
+ if (slotCount > MAX_SLOTS) {
LOGW("MultiTouch Device %s reported %d slots but the framework "
"only supports a maximum of %d slots at this time.",
- getDeviceName().string(), mSlotCount, MAX_SLOTS);
- mSlotCount = MAX_SLOTS;
+ getDeviceName().string(), slotCount, MAX_SLOTS);
+ slotCount = MAX_SLOTS;
}
- mUsingSlotsProtocol = true;
+ mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
} else {
- mSlotCount = MAX_POINTERS;
- mUsingSlotsProtocol = false;
+ mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
}
- mAccumulator.allocateSlots(mSlotCount);
-
clearState();
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index b1fdcf2..f9750d0 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -430,9 +430,8 @@
void fadePointer();
- inline const PropertyMap& getConfiguration() {
- return mConfiguration;
- }
+ inline const PropertyMap& getConfiguration() { return mConfiguration; }
+ inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
private:
InputReaderContext* mContext;
@@ -452,6 +451,171 @@
};
+/* Keeps track of the state of mouse or touch pad buttons. */
+class CursorButtonAccumulator {
+public:
+ CursorButtonAccumulator();
+
+ void clearButtons();
+ void process(const RawEvent* rawEvent);
+
+ uint32_t getButtonState() const;
+
+private:
+ bool mBtnLeft;
+ bool mBtnRight;
+ bool mBtnMiddle;
+ bool mBtnBack;
+ bool mBtnSide;
+ bool mBtnForward;
+ bool mBtnExtra;
+ bool mBtnTask;
+};
+
+
+/* Keeps track of cursor movements. */
+
+class CursorMotionAccumulator {
+public:
+ CursorMotionAccumulator();
+ void configure(InputDevice* device);
+
+ void clearRelativeAxes();
+ void process(const RawEvent* rawEvent);
+
+ inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
+ inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
+
+ inline int32_t getRelativeX() const { return mRelX; }
+ inline int32_t getRelativeY() const { return mRelY; }
+ inline int32_t getRelativeVWheel() const { return mRelWheel; }
+ inline int32_t getRelativeHWheel() const { return mRelHWheel; }
+
+private:
+ bool mHaveRelWheel;
+ bool mHaveRelHWheel;
+
+ int32_t mRelX;
+ int32_t mRelY;
+ int32_t mRelWheel;
+ int32_t mRelHWheel;
+};
+
+
+/* Keeps track of the state of touch, stylus and tool buttons. */
+class TouchButtonAccumulator {
+public:
+ TouchButtonAccumulator();
+ void configure(InputDevice* device);
+
+ void clearButtons();
+ void process(const RawEvent* rawEvent);
+
+ uint32_t getButtonState() const;
+ int32_t getToolType() const;
+ bool isActive() const;
+ bool isHovering() const;
+
+private:
+ bool mHaveBtnTouch;
+
+ bool mBtnTouch;
+ bool mBtnStylus;
+ bool mBtnStylus2;
+ bool mBtnToolFinger;
+ bool mBtnToolPen;
+ bool mBtnToolRubber;
+};
+
+
+/* Keeps track of the state of single-touch protocol. */
+class SingleTouchMotionAccumulator {
+public:
+ SingleTouchMotionAccumulator();
+
+ void clearAbsoluteAxes();
+ void process(const RawEvent* rawEvent);
+
+ inline int32_t getAbsoluteX() const { return mAbsX; }
+ inline int32_t getAbsoluteY() const { return mAbsY; }
+ inline int32_t getAbsolutePressure() const { return mAbsPressure; }
+ inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
+ inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
+
+private:
+ int32_t mAbsX;
+ int32_t mAbsY;
+ int32_t mAbsPressure;
+ int32_t mAbsToolWidth;
+ int32_t mAbsDistance;
+};
+
+
+/* Keeps track of the state of multi-touch protocol. */
+class MultiTouchMotionAccumulator {
+public:
+ class Slot {
+ public:
+ inline bool isInUse() const { return mInUse; }
+ inline int32_t getX() const { return mAbsMTPositionX; }
+ inline int32_t getY() const { return mAbsMTPositionY; }
+ inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
+ inline int32_t getTouchMinor() const {
+ return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; }
+ inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
+ inline int32_t getToolMinor() const {
+ return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; }
+ inline int32_t getOrientation() const { return mAbsMTOrientation; }
+ inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
+ inline int32_t getPressure() const { return mAbsMTPressure; }
+ inline int32_t getDistance() const { return mAbsMTDistance; }
+ inline int32_t getToolType() const;
+
+ private:
+ friend class MultiTouchMotionAccumulator;
+
+ bool mInUse;
+ bool mHaveAbsMTTouchMinor;
+ bool mHaveAbsMTWidthMinor;
+ bool mHaveAbsMTToolType;
+
+ int32_t mAbsMTPositionX;
+ int32_t mAbsMTPositionY;
+ int32_t mAbsMTTouchMajor;
+ int32_t mAbsMTTouchMinor;
+ int32_t mAbsMTWidthMajor;
+ int32_t mAbsMTWidthMinor;
+ int32_t mAbsMTOrientation;
+ int32_t mAbsMTTrackingId;
+ int32_t mAbsMTPressure;
+ int32_t mAbsMTToolType;
+ int32_t mAbsMTDistance;
+
+ Slot();
+ void clearIfInUse();
+ void clear();
+ };
+
+ MultiTouchMotionAccumulator();
+ ~MultiTouchMotionAccumulator();
+
+ void configure(size_t slotCount, bool usingSlotsProtocol);
+ void process(const RawEvent* rawEvent);
+
+ void clearSlots(int32_t initialSlot);
+
+ inline bool isUsingSlotsProtocol() const { return mUsingSlotsProtocol; }
+ inline size_t getSlotCount() const { return mSlotCount; }
+ inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+
+private:
+ int32_t mCurrentSlot;
+ Slot* mSlots;
+ size_t mSlotCount;
+ bool mUsingSlotsProtocol;
+};
+
+
/* An input mapper transforms raw input events into cooked event data.
* A single input device can have multiple associated input mappers in order to interpret
* different classes of events.
@@ -615,29 +779,8 @@
bool orientationAware;
} mParameters;
- struct Accumulator {
- enum {
- FIELD_BUTTONS = 1,
- FIELD_REL_X = 2,
- FIELD_REL_Y = 4,
- FIELD_REL_WHEEL = 8,
- FIELD_REL_HWHEEL = 16,
- };
-
- uint32_t fields;
-
- uint32_t buttonDown;
- uint32_t buttonUp;
-
- int32_t relX;
- int32_t relY;
- int32_t relWheel;
- int32_t relHWheel;
-
- inline void clear() {
- fields = 0;
- }
- } mAccumulator;
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ CursorMotionAccumulator mCursorMotionAccumulator;
int32_t mSource;
float mXScale;
@@ -645,8 +788,6 @@
float mXPrecision;
float mYPrecision;
- bool mHaveVWheel;
- bool mHaveHWheel;
float mVWheelScale;
float mHWheelScale;
@@ -722,7 +863,8 @@
int32_t toolMinor;
int32_t orientation;
int32_t distance;
- bool isStylus;
+ int32_t toolType; // AMOTION_EVENT_TOOL_TYPE constant
+ bool isHovering;
inline bool operator== (const PointerData& other) const {
return id == other.id
@@ -734,7 +876,9 @@
&& toolMajor == other.toolMajor
&& toolMinor == other.toolMinor
&& orientation == other.orientation
- && distance == other.distance;
+ && distance == other.distance
+ && toolType == other.toolType
+ && isHovering == other.isHovering;
}
inline bool operator!= (const PointerData& other) const {
return !(*this == other);
@@ -1201,7 +1345,6 @@
void suppressSwipeOntoVirtualKeys(nsecs_t when);
- int32_t getTouchToolType(bool isStylus) const;
bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
@@ -1221,40 +1364,9 @@
virtual void configureRawAxes();
private:
- struct Accumulator {
- enum {
- FIELD_BTN_TOUCH = 1,
- FIELD_ABS_X = 2,
- FIELD_ABS_Y = 4,
- FIELD_ABS_PRESSURE = 8,
- FIELD_ABS_TOOL_WIDTH = 16,
- FIELD_BUTTONS = 32,
- };
-
- uint32_t fields;
-
- bool btnTouch;
- int32_t absX;
- int32_t absY;
- int32_t absPressure;
- int32_t absToolWidth;
-
- uint32_t buttonDown;
- uint32_t buttonUp;
-
- inline void clear() {
- fields = 0;
- buttonDown = 0;
- buttonUp = 0;
- }
- } mAccumulator;
-
- bool mDown;
- int32_t mX;
- int32_t mY;
- int32_t mPressure;
- int32_t mToolWidth;
- int32_t mButtonState;
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+ SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
void clearState();
@@ -1274,83 +1386,9 @@
virtual void configureRawAxes();
private:
- struct Accumulator {
- enum {
- FIELD_ABS_MT_POSITION_X = 1 << 0,
- FIELD_ABS_MT_POSITION_Y = 1 << 1,
- FIELD_ABS_MT_TOUCH_MAJOR = 1 << 2,
- FIELD_ABS_MT_TOUCH_MINOR = 1 << 3,
- FIELD_ABS_MT_WIDTH_MAJOR = 1 << 4,
- FIELD_ABS_MT_WIDTH_MINOR = 1 << 5,
- FIELD_ABS_MT_ORIENTATION = 1 << 6,
- FIELD_ABS_MT_TRACKING_ID = 1 << 7,
- FIELD_ABS_MT_PRESSURE = 1 << 8,
- FIELD_ABS_MT_TOOL_TYPE = 1 << 9,
- FIELD_ABS_MT_DISTANCE = 1 << 10,
- };
-
- struct Slot {
- uint32_t fields; // 0 if slot is unused
-
- int32_t absMTPositionX;
- int32_t absMTPositionY;
- int32_t absMTTouchMajor;
- int32_t absMTTouchMinor;
- int32_t absMTWidthMajor;
- int32_t absMTWidthMinor;
- int32_t absMTOrientation;
- int32_t absMTTrackingId;
- int32_t absMTPressure;
- int32_t absMTToolType;
- int32_t absMTDistance;
-
- inline Slot() {
- clear();
- }
-
- inline void clear() {
- fields = 0;
- }
- };
-
- // Current slot index.
- int32_t currentSlot;
-
- // Array of slots.
- Slot* slots;
-
- // Bitfield of buttons that went down or up.
- uint32_t buttonDown;
- uint32_t buttonUp;
-
- Accumulator() : currentSlot(0), slots(NULL), buttonDown(0), buttonUp(0) {
- }
-
- ~Accumulator() {
- delete[] slots;
- }
-
- void allocateSlots(size_t slotCount) {
- slots = new Slot[slotCount];
- }
-
- void clearSlots(size_t slotCount) {
- for (size_t i = 0; i < slotCount; i++) {
- slots[i].clear();
- }
- currentSlot = 0;
- }
-
- void clearButtons() {
- buttonDown = 0;
- buttonUp = 0;
- }
- } mAccumulator;
-
- size_t mSlotCount;
- bool mUsingSlotsProtocol;
-
- int32_t mButtonState;
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+ MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
// Specifies the pointer id bits that are in use, and their associated tracking id.
BitSet32 mPointerIdBits;
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 131894a..7a6af25 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -707,6 +707,15 @@
return result;
}
+ virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->keys.indexOfKey(scanCode);
+ return index >= 0;
+ }
+ return false;
+ }
+
virtual bool hasLed(int32_t deviceId, int32_t led) const {
Device* device = getDevice(deviceId);
return device && device->leds.indexOfKey(led) >= 0;
@@ -2116,6 +2125,7 @@
// Button press.
// Mostly testing non x/y behavior here so we don't need to check again elsewhere.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2137,6 +2147,7 @@
// Button release. Should have same down time.
process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2190,6 +2201,7 @@
// Button press without following sync.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2197,6 +2209,7 @@
// Button release without following sync.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2233,6 +2246,7 @@
// Release Button.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2248,10 +2262,12 @@
// Button press.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
// Button release.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
// Reset. Should not synthesize button up since button is not pressed.
@@ -2269,6 +2285,7 @@
// Button press.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
// Reset. Should synthesize button up.
@@ -2445,6 +2462,7 @@
class SingleTouchInputMapperTest : public TouchInputMapperTest {
protected:
+ void prepareButtons();
void prepareAxes(int axes);
void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
@@ -2455,6 +2473,10 @@
void processSync(SingleTouchInputMapper* mapper);
};
+void SingleTouchInputMapperTest::prepareButtons() {
+ mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0);
+}
+
void SingleTouchInputMapperTest::prepareAxes(int axes) {
if (axes & POSITION) {
mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X,
@@ -2504,6 +2526,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+ prepareButtons();
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
@@ -2514,6 +2537,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X);
mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y);
+ prepareButtons();
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
@@ -2522,6 +2546,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+ prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchPad");
addMapperAndConfigure(mapper);
@@ -2531,6 +2556,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+ prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
addMapperAndConfigure(mapper);
@@ -2542,6 +2568,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2570,6 +2597,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2598,6 +2626,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2615,6 +2644,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2649,6 +2679,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2676,6 +2707,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2726,6 +2758,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2847,6 +2880,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2920,6 +2954,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -3009,6 +3044,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.orientationAware", "0");
addMapperAndConfigure(mapper);
@@ -3032,6 +3068,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareButtons();
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
@@ -3094,6 +3131,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION | PRESSURE | TOOL);
addMapperAndConfigure(mapper);
@@ -3815,6 +3853,7 @@
FakeInputDispatcher::NotifyMotionArgs args;
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
args.action);