From 43fd19fd1a22d95ed985a0680fd8806d918f3ba7 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 21 Apr 2015 19:02:58 +0100 Subject: [PATCH] Synthesize events for pressure and button changes. Even when there isn't movement on the touchscreen we should produce events for pressure and button state changes generated by external stylii. Change-Id: I9fd7ba85902d5d6bfb28d5e5ff5d8f340a94c2bf --- services/inputflinger/InputReader.cpp | 58 ++++++++++++++++++--------- services/inputflinger/InputReader.h | 3 +- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index 870969206..c6389a9c9 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -73,6 +73,13 @@ static const size_t MAX_SLOTS = 32; // external stylus. static const nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72); +// Maximum amount of time to wait on touch data before pushing out new pressure data. +static const nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); + +// Artificial latency on synthetic events created from stylus data without corresponding touch +// data. +static const nsecs_t STYLUS_DATA_LATENCY = ms2ns(10); + // --- Static Functions --- template @@ -2827,7 +2834,7 @@ void TouchInputMapper::dump(String8& dump) { toString(mExternalStylusConnected)); dump.appendFormat(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId); dump.appendFormat(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n", - mExternalStylusDataTimeout); + mExternalStylusFusionTimeout); dump.append(INDENT3 "External Stylus State:\n"); dumpStylusState(dump, mExternalStylusState); @@ -3836,10 +3843,15 @@ void TouchInputMapper::reset(nsecs_t when) { void TouchInputMapper::resetExternalStylus() { mExternalStylusState.clear(); mExternalStylusId = -1; - mExternalStylusDataTimeout = LLONG_MAX; + mExternalStylusFusionTimeout = LLONG_MAX; mExternalStylusDataPending = false; } +void TouchInputMapper::clearStylusDataPendingFlags() { + mExternalStylusDataPending = false; + mExternalStylusFusionTimeout = LLONG_MAX; +} + void TouchInputMapper::process(const RawEvent* rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); @@ -3915,19 +3927,30 @@ void TouchInputMapper::processRawTouches(bool timeout) { } // All ready to go. - mExternalStylusDataPending = false; + clearStylusDataPendingFlags(); mCurrentRawState.copyFrom(next); + if (mCurrentRawState.when < mLastRawState.when) { + mCurrentRawState.when = mLastRawState.when; + } cookAndDispatch(mCurrentRawState.when); } if (count != 0) { mRawStatesPending.removeItemsAt(0, count); } - // TODO: If we still have pending stylus data that hasn't been mapped to a touch yet - // then set a timeout to synthesize a new touch event with the new data. Otherwise - // we will lose button and pressure information while the touch is stationary. if (mExternalStylusDataPending) { - ALOGD("STYLUS TODO: Wiggle wiggle wiggle."); + if (timeout) { + nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY; + clearStylusDataPendingFlags(); + mCurrentRawState.copyFrom(mLastRawState); +#if DEBUG_STYLUS_FUSION + ALOGD("Timeout expired, synthesizing event with new stylus data"); +#endif + cookAndDispatch(when); + } else if (mExternalStylusFusionTimeout == LLONG_MAX) { + mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT; + getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout); + } } } @@ -4086,15 +4109,14 @@ bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeou #endif resetExternalStylus(); } else { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (mExternalStylusDataTimeout == LLONG_MAX) { - mExternalStylusDataTimeout = now + EXTERNAL_STYLUS_DATA_TIMEOUT; + if (mExternalStylusFusionTimeout == LLONG_MAX) { + mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT; } #if DEBUG_STYLUS_FUSION ALOGD("No stylus data but stylus is connected, requesting timeout " - "(%" PRId64 "ms)", mExternalStylusDataTimeout); + "(%" PRId64 "ms)", mExternalStylusFusionTimeout); #endif - getContext()->requestTimeoutAtTime(mExternalStylusDataTimeout); + getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout); return true; } } @@ -4117,22 +4139,20 @@ void TouchInputMapper::timeoutExpired(nsecs_t when) { dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/); } } else if (mDeviceMode == DEVICE_MODE_DIRECT) { - if (mExternalStylusDataTimeout < when) { - mExternalStylusDataTimeout = LLONG_MAX; + if (mExternalStylusFusionTimeout < when) { processRawTouches(true /*timeout*/); - } else if (mExternalStylusDataTimeout != LLONG_MAX) { - getContext()->requestTimeoutAtTime(mExternalStylusDataTimeout); + } else if (mExternalStylusFusionTimeout != LLONG_MAX) { + getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout); } } } void TouchInputMapper::updateExternalStylusState(const StylusState& state) { mExternalStylusState.copyFrom(state); - if (mExternalStylusId != -1 || mExternalStylusDataTimeout != LLONG_MAX) { + if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) { // We're either in the middle of a fused stream of data or we're waiting on data before // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus // data. - mExternalStylusDataTimeout = LLONG_MAX; mExternalStylusDataPending = true; processRawTouches(false /*timeout*/); } @@ -4310,7 +4330,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { // Dispatch move events if any of the remaining pointers moved from their old locations. // Although applications receive new locations as part of individual pointer up // events, they do not generally handle them except when presented in a move event. - if (moveNeeded) { + if (moveNeeded && !moveIdBits.isEmpty()) { ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value); dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0, diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 451a20fc0..aadc37fb4 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -1456,7 +1456,7 @@ protected: // State provided by an external stylus StylusState mExternalStylusState; int64_t mExternalStylusId; - nsecs_t mExternalStylusDataTimeout; + nsecs_t mExternalStylusFusionTimeout; bool mExternalStylusDataPending; // True if we sent a HOVER_ENTER event. @@ -1781,6 +1781,7 @@ private: VelocityControl mWheelYVelocityControl; void resetExternalStylus(); + void clearStylusDataPendingFlags(); void sync(nsecs_t when);