inputflinger: disable touch input while using a stylus

Android 5.0 cannot form multitouch events from multiple input
devices. So it is not possible to report one touchpoint from the
stylus position and, at the same time, another touchpoint from a
finger touch. Instead, when a new input device starts up the currently
active input is cancelled. This is highly undesirable while writing
with the pen.

The easiest solution is to ignore non-stylus touch events while the
stylus is within range (hovering) of the touchscreen. For example,
N-trig digitizers implement this in hardware. But wacom digitizers do
report pen data simultaneously with touch data. This patch disables
(non-stylus) touch input within 50ms of stylus data. On my Galaxy
Note this is necessary to make stylus input usable.

Original commit by vbraun:
b9cb296130

Change-Id: I97f26369826e96c97461c8ae188f1c64dec1b4d3
This commit is contained in:
Christopher N. Hesse 2014-12-05 21:38:51 +01:00 committed by Steve Kondik
parent bd33987d72
commit 00888b7eee
2 changed files with 25 additions and 0 deletions

View File

@ -5843,6 +5843,7 @@ void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags)
mPointerSimple.currentProperties.id = 0;
mPointerSimple.currentProperties.toolType =
mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
mLastStylusTime = when;
} else {
down = false;
hovering = false;
@ -5924,6 +5925,11 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
}
}
if (rejectPalm(when)) { // stylus is currently active
mPointerSimple.reset();
return;
}
if (mPointerSimple.down && !down) {
mPointerSimple.down = false;
@ -6045,6 +6051,9 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32
const PointerProperties* properties, const PointerCoords* coords,
const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
float xPrecision, float yPrecision, nsecs_t downTime) {
if (rejectPalm(when)) return;
PointerCoords pointerCoords[MAX_POINTERS];
PointerProperties pointerProperties[MAX_POINTERS];
uint32_t pointerCount = 0;
@ -6118,6 +6127,13 @@ void TouchInputMapper::fadePointer() {
}
}
nsecs_t TouchInputMapper::mLastStylusTime = 0;
bool TouchInputMapper::rejectPalm(nsecs_t when) {
return (when - mLastStylusTime < mConfig.stylusPalmRejectionTime) &&
mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS;
}
void TouchInputMapper::cancelTouch(nsecs_t when) {
abortPointerUsage(when, 0 /*policyFlags*/);
abortTouches(when, 0 /* policyFlags*/);

View File

@ -230,6 +230,9 @@ struct InputReaderConfiguration {
// True to show the location of touches on the touch screen as spots.
bool showTouches;
// Ignore finger touches this long after the stylus has been used (including hover)
nsecs_t stylusPalmRejectionTime;
InputReaderConfiguration() :
virtualKeyQuietTime(0),
@ -247,6 +250,7 @@ struct InputReaderConfiguration {
pointerGestureSwipeMaxWidthRatio(0.25f),
pointerGestureMovementSpeedRatio(0.8f),
pointerGestureZoomSpeedRatio(0.3f),
stylusPalmRejectionTime(50 * 10000000LL), // 50 ms
showTouches(false) { }
bool getDisplayInfo(bool external, DisplayViewport* outViewport) const;
@ -1787,6 +1791,9 @@ private:
VelocityControl mPointerVelocityControl;
VelocityControl mWheelXVelocityControl;
VelocityControl mWheelYVelocityControl;
// The time the stylus event was processed by any TouchInputMapper
static nsecs_t mLastStylusTime;
void resetExternalStylus();
void clearStylusDataPendingFlags();
@ -1853,6 +1860,8 @@ private:
const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
static void assignPointerIds(const RawState* last, RawState* current);
bool rejectPalm(nsecs_t when);
};