From 9a53b55af5228baef78a965d191dec83310009dc Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Tue, 4 Jun 2024 02:59:40 +0000 Subject: MotionEvent: Differentiate directional support for AXIS_ORIENTATION We have three cases for handling AXIS_ORIENTATION: 1. Orientation is not supported by the input device, so the value for AXIS_ORIENTATION should always be 0, regardless of display rotation. 2. Orientation is supported, but a "direction" is not specified, like for touchscreens and touchpads. The orientation must be in the range [-pi/2, pi/2] for all display rotations. 3. Orientation is fully supported, and the value is in the range [-pi, pi] for all display rotations. It is insufficient to rely on whether or not the PointerCoords has the bit for AXIS_ORIENTATION set to determine whether the event has a valid orientation. This is because we always skip setting values of 0 for any axis in PointerCoords to save space during serialization. To support these three cases, we introduce two new MotionEvent private flags. These are flags that are not exposed to Java and to the public APIs. Bug: 263310669 Test: atest TouchScreenTest libinput_tests inputflinger_tests Change-Id: Iaa38afe35b00de74fbc5eefce25191bea52c2ea6 --- libs/input/Input.cpp | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'libs/input/Input.cpp') diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index ee121d53fe..0a3f1fd463 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -96,6 +96,19 @@ int32_t resolveActionForSplitMotionEvent( return AMOTION_EVENT_ACTION_DOWN; } +float transformOrientation(const ui::Transform& transform, const PointerCoords& coords, + int32_t motionEventFlags) { + if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) == 0) { + return 0; + } + + const bool isDirectionalAngle = + (motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION) != 0; + + return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), + isDirectionalAngle); +} + } // namespace const char* motionClassificationToString(MotionClassification classification) { @@ -187,7 +200,7 @@ vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) return roundTransformedCoords(transformedXy - transformedOrigin); } -float transformAngle(const ui::Transform& transform, float angleRadians) { +float transformAngle(const ui::Transform& transform, float angleRadians, bool isDirectional) { // Construct and transform a vector oriented at the specified clockwise angle from vertical. // Coordinate system: down is increasing Y, right is increasing X. float x = sinf(angleRadians); @@ -201,6 +214,11 @@ float transformAngle(const ui::Transform& transform, float angleRadians) { transformedPoint.x -= origin.x; transformedPoint.y -= origin.y; + if (!isDirectional && transformedPoint.y > 0) { + // Limit the range of atan2f to [-pi/2, pi/2] by reversing the direction of the vector. + transformedPoint *= -1; + } + // Derive the transformed vector's clockwise angle from vertical. // The return value of atan2f is in range [-pi, pi] which conforms to the orientation API. return atan2f(transformedPoint.x, -transformedPoint.y); @@ -530,7 +548,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const { return true; } -void PointerCoords::transform(const ui::Transform& transform) { +void PointerCoords::transform(const ui::Transform& transform, int32_t motionEventFlags) { const vec2 xy = transform.transform(getXYValue()); setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); @@ -544,9 +562,9 @@ void PointerCoords::transform(const ui::Transform& transform) { setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); } - if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_ORIENTATION)) { - const float val = getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); - setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, val)); + if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) != 0) { + setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, + transformOrientation(transform, *this, motionEventFlags)); } } @@ -723,13 +741,13 @@ const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex); - return calculateTransformedAxisValue(axis, mSource, mRawTransform, coords); + return calculateTransformedAxisValue(axis, mSource, mFlags, mRawTransform, coords); } float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex); - return calculateTransformedAxisValue(axis, mSource, mTransform, coords); + return calculateTransformedAxisValue(axis, mSource, mFlags, mTransform, coords); } ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { @@ -787,7 +805,7 @@ void MotionEvent::applyTransform(const std::array& matrix) { // Apply the transformation to all samples. std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(), - [&transform](PointerCoords& c) { c.transform(transform); }); + [&](PointerCoords& c) { c.transform(transform, mFlags); }); if (mRawXCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION && mRawYCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) { @@ -1059,7 +1077,7 @@ vec2 MotionEvent::calculateTransformedXY(uint32_t source, const ui::Transform& t } // Keep in sync with calculateTransformedCoords. -float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, +float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, int32_t flags, const ui::Transform& transform, const PointerCoords& coords) { if (shouldDisregardTransformation(source)) { @@ -1081,7 +1099,7 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, } if (axis == AMOTION_EVENT_AXIS_ORIENTATION) { - return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); + return transformOrientation(transform, coords, flags); } return coords.getAxisValue(axis); @@ -1089,7 +1107,7 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, // Keep in sync with calculateTransformedAxisValue. This is an optimization of // calculateTransformedAxisValue for all PointerCoords axes. -PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, +PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, int32_t flags, const ui::Transform& transform, const PointerCoords& coords) { if (shouldDisregardTransformation(source)) { @@ -1109,8 +1127,7 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, - transformAngle(transform, - coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION))); + transformOrientation(transform, coords, flags)); return out; } -- cgit v1.2.3-59-g8ed1b From 4b8d36c0e1cbeaee7b23a3a1dd65eddb0fae11fa Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Fri, 7 Jun 2024 15:10:46 +0000 Subject: MotionEvent: Consolidate functions to transform PointerCoords Remove PointerCoords::transform(), which is a duplicate of MotionEvent::calculateTranformedCoords(). Bug: 342349872 Test: atest inputflinger_tests libinput_tests Change-Id: I7610a0475a16e9964817f63efa67b291cb7aaf0a --- include/input/Input.h | 4 +- libs/input/Input.cpp | 51 ++++++++-------------- .../inputflinger/dispatcher/InputDispatcher.cpp | 6 ++- 3 files changed, 24 insertions(+), 37 deletions(-) (limited to 'libs/input/Input.cpp') diff --git a/include/input/Input.h b/include/input/Input.h index a96dae2510..3e7a6fd1c5 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -478,8 +478,6 @@ struct PointerCoords { // axes, however the window scaling will not. void scale(float globalScale, float windowXScale, float windowYScale); - void transform(const ui::Transform& transform, int32_t motionEventFlags); - inline float getX() const { return getAxisValue(AMOTION_EVENT_AXIS_X); } @@ -948,6 +946,8 @@ public: static vec2 calculateTransformedXY(uint32_t source, const ui::Transform&, const vec2& xy); static float calculateTransformedAxisValue(int32_t axis, uint32_t source, int32_t flags, const ui::Transform&, const PointerCoords&); + static void calculateTransformedCoordsInPlace(PointerCoords& coords, uint32_t source, + int32_t flags, const ui::Transform&); static PointerCoords calculateTransformedCoords(uint32_t source, int32_t flags, const ui::Transform&, const PointerCoords&); // The rounding precision for transformed motion events. diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 0a3f1fd463..b09814797f 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -548,26 +548,6 @@ bool PointerCoords::operator==(const PointerCoords& other) const { return true; } -void PointerCoords::transform(const ui::Transform& transform, int32_t motionEventFlags) { - const vec2 xy = transform.transform(getXYValue()); - setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); - setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); - - if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_X) || - BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_Y)) { - const ui::Transform rotation(transform.getOrientation()); - const vec2 relativeXy = rotation.transform(getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), - getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)); - setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x); - setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); - } - - if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) != 0) { - setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, - transformOrientation(transform, *this, motionEventFlags)); - } -} - // --- MotionEvent --- void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, @@ -804,8 +784,9 @@ void MotionEvent::applyTransform(const std::array& matrix) { transform.set(matrix); // Apply the transformation to all samples. - std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(), - [&](PointerCoords& c) { c.transform(transform, mFlags); }); + std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(), [&](PointerCoords& c) { + calculateTransformedCoordsInPlace(c, mSource, mFlags, transform); + }); if (mRawXCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION && mRawYCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) { @@ -1107,28 +1088,32 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, // Keep in sync with calculateTransformedAxisValue. This is an optimization of // calculateTransformedAxisValue for all PointerCoords axes. -PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, int32_t flags, - const ui::Transform& transform, - const PointerCoords& coords) { +void MotionEvent::calculateTransformedCoordsInPlace(PointerCoords& coords, uint32_t source, + int32_t flags, const ui::Transform& transform) { if (shouldDisregardTransformation(source)) { - return coords; + return; } - PointerCoords out = coords; const vec2 xy = calculateTransformedXYUnchecked(source, transform, coords.getXYValue()); - out.setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); - out.setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); + coords.setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); + coords.setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); const vec2 relativeXy = transformWithoutTranslation(transform, {coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X), coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)}); - out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x); - out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); + coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x); + coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); - out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, - transformOrientation(transform, coords, flags)); + coords.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, + transformOrientation(transform, coords, flags)); +} +PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, int32_t flags, + const ui::Transform& transform, + const PointerCoords& coords) { + PointerCoords out = coords; + calculateTransformedCoordsInPlace(out, source, flags, transform); return out; } diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8b38874afa..96d9dc1e1a 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -444,10 +444,12 @@ std::unique_ptr createDispatchEntry(const IdGenerator& idGenerato newCoords.copyFrom(motionEntry.pointerCoords[i]); // First, apply the current pointer's transform to update the coordinates into // window space. - newCoords.transform(currTransform, motionEntry.flags); + MotionEvent::calculateTransformedCoordsInPlace(newCoords, motionEntry.source, + motionEntry.flags, currTransform); // Next, apply the inverse transform of the normalized coordinates so the // current coordinates are transformed into the normalized coordinate space. - newCoords.transform(inverseTransform, motionEntry.flags); + MotionEvent::calculateTransformedCoordsInPlace(newCoords, motionEntry.source, + motionEntry.flags, inverseTransform); } } -- cgit v1.2.3-59-g8ed1b