diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 4848a7accf72c..85f435c761163 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -167,6 +167,19 @@ public final class InputDevice implements Parcelable { /** * The input source is a stylus pointing device. + *
+ * Note that this bit merely indicates that an input device is capable of obtaining + * input from a stylus. To determine whether a given touch event was produced + * by a stylus, examine the tool type returned by {@link MotionEvent#getToolType(int)} + * for each individual pointer. + *
+ * A single touch event may multiple pointers with different tool types, + * such as an event that has one pointer with tool type + * {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type + * {@link MotionEvent#TOOL_TYPE_STYLUS}. So it is important to examine + * the tool type of each pointer, regardless of the source reported + * by {@link MotionEvent#getSource()}. + *
* * @see #SOURCE_CLASS_POINTER */ diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 4cc3d44623f30..3a48b1607130a 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -1292,12 +1292,17 @@ void CursorScrollAccumulator::finishSync() { // --- TouchButtonAccumulator --- TouchButtonAccumulator::TouchButtonAccumulator() : - mHaveBtnTouch(false) { + mHaveBtnTouch(false), mHaveStylus(false) { clearButtons(); } void TouchButtonAccumulator::configure(InputDevice* device) { mHaveBtnTouch = device->hasKey(BTN_TOUCH); + mHaveStylus = device->hasKey(BTN_TOOL_PEN) + || device->hasKey(BTN_TOOL_RUBBER) + || device->hasKey(BTN_TOOL_BRUSH) + || device->hasKey(BTN_TOOL_PENCIL) + || device->hasKey(BTN_TOOL_AIRBRUSH); } void TouchButtonAccumulator::reset(InputDevice* device) { @@ -1421,6 +1426,10 @@ bool TouchButtonAccumulator::isHovering() const { return mHaveBtnTouch && !mBtnTouch; } +bool TouchButtonAccumulator::hasStylus() const { + return mHaveStylus; +} + // --- RawPointerAxes --- @@ -1572,16 +1581,19 @@ void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { // --- MultiTouchMotionAccumulator --- MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() : - mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) { + mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false), + mHaveStylus(false) { } MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() { delete[] mSlots; } -void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) { +void MultiTouchMotionAccumulator::configure(InputDevice* device, + size_t slotCount, bool usingSlotsProtocol) { mSlotCount = slotCount; mUsingSlotsProtocol = usingSlotsProtocol; + mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE); delete[] mSlots; mSlots = new Slot[slotCount]; @@ -1713,6 +1725,10 @@ void MultiTouchMotionAccumulator::finishSync() { } } +bool MultiTouchMotionAccumulator::hasStylus() const { + return mHaveStylus; +} + // --- MultiTouchMotionAccumulator::Slot --- @@ -2872,10 +2888,16 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { && mConfig.pointerGesturesEnabled) { mSource = AINPUT_SOURCE_MOUSE; mDeviceMode = DEVICE_MODE_POINTER; + if (hasStylus()) { + mSource |= AINPUT_SOURCE_STYLUS; + } } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN && mParameters.associatedDisplayId >= 0) { mSource = AINPUT_SOURCE_TOUCHSCREEN; mDeviceMode = DEVICE_MODE_DIRECT; + if (hasStylus()) { + mSource |= AINPUT_SOURCE_STYLUS; + } } else { mSource = AINPUT_SOURCE_TOUCHPAD; mDeviceMode = DEVICE_MODE_UNSCALED; @@ -5786,6 +5808,10 @@ void SingleTouchInputMapper::configureRawPointerAxes() { getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY); } +bool SingleTouchInputMapper::hasStylus() const { + return mTouchButtonAccumulator.hasStylus(); +} + // --- MultiTouchInputMapper --- @@ -5920,12 +5946,19 @@ void MultiTouchInputMapper::configureRawPointerAxes() { getDeviceName().string(), slotCount, MAX_SLOTS); slotCount = MAX_SLOTS; } - mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/); + mMultiTouchMotionAccumulator.configure(getDevice(), + slotCount, true /*usingSlotsProtocol*/); } else { - mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/); + mMultiTouchMotionAccumulator.configure(getDevice(), + MAX_POINTERS, false /*usingSlotsProtocol*/); } } +bool MultiTouchInputMapper::hasStylus() const { + return mMultiTouchMotionAccumulator.hasStylus() + || mTouchButtonAccumulator.hasStylus(); +} + // --- JoystickInputMapper --- diff --git a/services/input/InputReader.h b/services/input/InputReader.h index e5897e7051eec..acdec85a6ae5c 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -507,6 +507,12 @@ public: return getEventHub()->hasScanCode(mId, code); } + bool hasAbsoluteAxis(int32_t code) { + RawAbsoluteAxisInfo info; + getEventHub()->getAbsoluteAxisInfo(mId, code, &info); + return info.valid; + } + bool isKeyPressed(int32_t code) { return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN; } @@ -627,9 +633,11 @@ public: int32_t getToolType() const; bool isToolActive() const; bool isHovering() const; + bool hasStylus() const; private: bool mHaveBtnTouch; + bool mHaveStylus; bool mBtnTouch; bool mBtnStylus; @@ -817,10 +825,11 @@ public: MultiTouchMotionAccumulator(); ~MultiTouchMotionAccumulator(); - void configure(size_t slotCount, bool usingSlotsProtocol); + void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol); void reset(InputDevice* device); void process(const RawEvent* rawEvent); void finishSync(); + bool hasStylus() const; inline size_t getSlotCount() const { return mSlotCount; } inline const Slot* getSlot(size_t index) const { return &mSlots[index]; } @@ -830,6 +839,7 @@ private: Slot* mSlots; size_t mSlotCount; bool mUsingSlotsProtocol; + bool mHaveStylus; void clearSlots(int32_t initialSlot); }; @@ -1257,6 +1267,7 @@ protected: virtual void parseCalibration(); virtual void resolveCalibration(); virtual void dumpCalibration(String8& dump); + virtual bool hasStylus() const = 0; virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0; @@ -1605,6 +1616,7 @@ public: protected: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); virtual void configureRawPointerAxes(); + virtual bool hasStylus() const; private: SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; @@ -1622,6 +1634,7 @@ public: protected: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); virtual void configureRawPointerAxes(); + virtual bool hasStylus() const; private: MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;