Loading include/android/input.h +8 −0 Original line number Diff line number Diff line Loading @@ -870,6 +870,14 @@ enum AMotionClassification : uint32_t { * The current event stream represents the user swiping with two fingers on a touchpad. */ AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE = 3, /** * Classification constant: multi-finger swipe. * * The current event stream represents the user swiping with three or more fingers on a * touchpad. Unlike two-finger swipes, these are only to be handled by the system UI, which is * why they have a separate constant from two-finger swipes. */ AMOTION_EVENT_CLASSIFICATION_MULTI_FINGER_SWIPE = 4, }; /** Loading include/input/Input.h +6 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,12 @@ enum class MotionClassification : uint8_t { * The current gesture represents the user swiping with two fingers on a touchpad. */ TWO_FINGER_SWIPE = AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE, /** * The current gesture represents the user swiping with three or more fingers on a touchpad. * Unlike two-finger swipes, these are only to be handled by the system UI, which is why they * have a separate constant from two-finger swipes. */ MULTI_FINGER_SWIPE = AMOTION_EVENT_CLASSIFICATION_MULTI_FINGER_SWIPE, }; /** Loading libs/input/Input.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ const char* motionClassificationToString(MotionClassification classification) { return "DEEP_PRESS"; case MotionClassification::TWO_FINGER_SWIPE: return "TWO_FINGER_SWIPE"; case MotionClassification::MULTI_FINGER_SWIPE: return "MULTI_FINGER_SWIPE"; } } Loading services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext) mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter), mPointerController(getContext()->getPointerController(getDeviceId())), mStateConverter(deviceContext), mGestureConverter(*getContext(), getDeviceId()) { mGestureConverter(*getContext(), deviceContext, getDeviceId()) { mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD); mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext)); // Even though we don't explicitly delete copy/move semantics, it's safe to Loading services/inputflinger/reader/mapper/gestures/GestureConverter.cpp +119 −23 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "gestures/GestureConverter.h" #include <android/input.h> #include <linux/input-event-codes.h> #include "TouchCursorInputMapperCommon.h" #include "input/Input.h" Loading Loading @@ -44,10 +45,14 @@ uint32_t gesturesButtonToMotionEventButton(uint32_t gesturesButton) { } // namespace GestureConverter::GestureConverter(InputReaderContext& readerContext, int32_t deviceId) GestureConverter::GestureConverter(InputReaderContext& readerContext, const InputDeviceContext& deviceContext, int32_t deviceId) : mDeviceId(deviceId), mReaderContext(readerContext), mPointerController(readerContext.getPointerController(deviceId)) {} mPointerController(readerContext.getPointerController(deviceId)) { deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo); deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo); } void GestureConverter::reset() { mButtonState = 0; Loading @@ -60,6 +65,15 @@ std::list<NotifyArgs> GestureConverter::handleGesture(nsecs_t when, nsecs_t read return {handleMove(when, readTime, gesture)}; case kGestureTypeButtonsChange: return handleButtonsChange(when, readTime, gesture); case kGestureTypeSwipe: return handleMultiFingerSwipe(when, readTime, 3, gesture.details.swipe.dx, gesture.details.swipe.dy); case kGestureTypeFourFingerSwipe: return handleMultiFingerSwipe(when, readTime, 4, gesture.details.four_finger_swipe.dx, gesture.details.four_finger_swipe.dy); case kGestureTypeSwipeLift: case kGestureTypeFourFingerSwipeLift: return handleMultiFingerSwipeLift(when, readTime); default: // TODO(b/251196347): handle more gesture types. return {}; Loading @@ -67,11 +81,6 @@ std::list<NotifyArgs> GestureConverter::handleGesture(nsecs_t when, nsecs_t read } NotifyArgs GestureConverter::handleMove(nsecs_t when, nsecs_t readTime, const Gesture& gesture) { PointerProperties props; props.clear(); props.id = 0; props.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; float deltaX = gesture.details.move.dx; float deltaY = gesture.details.move.dy; rotateDelta(mOrientation, &deltaX, &deltaY); Loading @@ -93,7 +102,8 @@ NotifyArgs GestureConverter::handleMove(nsecs_t when, nsecs_t readTime, const Ge const int32_t action = down ? AMOTION_EVENT_ACTION_MOVE : AMOTION_EVENT_ACTION_HOVER_MOVE; return makeMotionArgs(when, readTime, action, /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition); /* pointerCount= */ 1, mFingerProps.data(), &coords, xCursorPosition, yCursorPosition); } std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_t readTime, Loading @@ -103,11 +113,6 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER); mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE); PointerProperties props; props.clear(); props.id = 0; props.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; float xCursorPosition, yCursorPosition; mPointerController->getPosition(&xCursorPosition, &yCursorPosition); Loading @@ -131,15 +136,16 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ newButtonState |= actionButton; pressEvents.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); /* pointerCount= */ 1, mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } } if (!isPointerDown(mButtonState) && isPointerDown(newButtonState)) { mDownTime = when; out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN, /* actionButton= */ 0, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } out.splice(out.end(), pressEvents); Loading @@ -155,19 +161,109 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ newButtonState &= ~actionButton; out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } } if (isPointerDown(mButtonState) && !isPointerDown(newButtonState)) { coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f); out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); newButtonState, /* pointerCount= */ 1, mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } mButtonState = newButtonState; return out; } [[nodiscard]] std::list<NotifyArgs> GestureConverter::handleMultiFingerSwipe(nsecs_t when, nsecs_t readTime, uint32_t fingerCount, float dx, float dy) { std::list<NotifyArgs> out = {}; float xCursorPosition, yCursorPosition; mPointerController->getPosition(&xCursorPosition, &yCursorPosition); if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) { // If the user changes the number of fingers mid-way through a swipe (e.g. they start with // three and then put a fourth finger down), the gesture library will treat it as two // separate swipes with an appropriate lift event between them, so we don't have to worry // about the finger count changing mid-swipe. mCurrentClassification = MotionClassification::MULTI_FINGER_SWIPE; mSwipeFingerCount = fingerCount; constexpr float FAKE_FINGER_SPACING = 100; float xCoord = xCursorPosition - FAKE_FINGER_SPACING * (mSwipeFingerCount - 1) / 2; for (size_t i = 0; i < mSwipeFingerCount; i++) { PointerCoords& coords = mFakeFingerCoords[i]; coords.clear(); coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCoord); coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition); coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); xCoord += FAKE_FINGER_SPACING; } mDownTime = when; out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN, /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); for (size_t i = 1; i < mSwipeFingerCount; i++) { out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_POINTER_DOWN | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), /* actionButton= */ 0, mButtonState, /* pointerCount= */ i + 1, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); } } for (size_t i = 0; i < mSwipeFingerCount; i++) { PointerCoords& coords = mFakeFingerCoords[i]; coords.setAxisValue(AMOTION_EVENT_AXIS_X, coords.getAxisValue(AMOTION_EVENT_AXIS_X) + dx); // TODO(b/251196347): Set the gesture properties appropriately to avoid needing to negate // the Y values. coords.setAxisValue(AMOTION_EVENT_AXIS_Y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y) - dy); } float xOffset = dx / (mXAxisInfo.maxValue - mXAxisInfo.minValue); // TODO(b/251196347): Set the gesture properties appropriately to avoid needing to negate the Y // values. float yOffset = -dy / (mYAxisInfo.maxValue - mYAxisInfo.minValue); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, xOffset); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset); out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, /* actionButton= */ 0, mButtonState, /* pointerCount= */ mSwipeFingerCount, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); return out; } [[nodiscard]] std::list<NotifyArgs> GestureConverter::handleMultiFingerSwipeLift(nsecs_t when, nsecs_t readTime) { std::list<NotifyArgs> out = {}; if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) { return out; } float xCursorPosition, yCursorPosition; mPointerController->getPosition(&xCursorPosition, &yCursorPosition); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, 0); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, 0); for (size_t i = mSwipeFingerCount; i > 1; i--) { out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_POINTER_UP | ((i - 1) << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), /* actionButton= */ 0, mButtonState, /* pointerCount= */ i, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); } out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); mCurrentClassification = MotionClassification::NONE; mSwipeFingerCount = 0; return out; } NotifyMotionArgs GestureConverter::makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action, int32_t actionButton, int32_t buttonState, uint32_t pointerCount, Loading @@ -181,10 +277,10 @@ NotifyMotionArgs GestureConverter::makeMotionArgs(nsecs_t when, nsecs_t readTime mPointerController->getDisplayId(), /* policyFlags= */ 0, action, /* actionButton= */ actionButton, /* flags= */ 0, mReaderContext.getGlobalMetaState(), buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties, pointerCoords, /* xPrecision= */ 1.0f, /* yPrecision= */ 1.0f, xCursorPosition, yCursorPosition, /* downTime= */ mDownTime, /* videoFrames= */ {}); mCurrentClassification, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties, pointerCoords, /* xPrecision= */ 1.0f, /* yPrecision= */ 1.0f, xCursorPosition, yCursorPosition, /* downTime= */ mDownTime, /* videoFrames= */ {}); } } // namespace android Loading
include/android/input.h +8 −0 Original line number Diff line number Diff line Loading @@ -870,6 +870,14 @@ enum AMotionClassification : uint32_t { * The current event stream represents the user swiping with two fingers on a touchpad. */ AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE = 3, /** * Classification constant: multi-finger swipe. * * The current event stream represents the user swiping with three or more fingers on a * touchpad. Unlike two-finger swipes, these are only to be handled by the system UI, which is * why they have a separate constant from two-finger swipes. */ AMOTION_EVENT_CLASSIFICATION_MULTI_FINGER_SWIPE = 4, }; /** Loading
include/input/Input.h +6 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,12 @@ enum class MotionClassification : uint8_t { * The current gesture represents the user swiping with two fingers on a touchpad. */ TWO_FINGER_SWIPE = AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE, /** * The current gesture represents the user swiping with three or more fingers on a touchpad. * Unlike two-finger swipes, these are only to be handled by the system UI, which is why they * have a separate constant from two-finger swipes. */ MULTI_FINGER_SWIPE = AMOTION_EVENT_CLASSIFICATION_MULTI_FINGER_SWIPE, }; /** Loading
libs/input/Input.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ const char* motionClassificationToString(MotionClassification classification) { return "DEEP_PRESS"; case MotionClassification::TWO_FINGER_SWIPE: return "TWO_FINGER_SWIPE"; case MotionClassification::MULTI_FINGER_SWIPE: return "MULTI_FINGER_SWIPE"; } } Loading
services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext) mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter), mPointerController(getContext()->getPointerController(getDeviceId())), mStateConverter(deviceContext), mGestureConverter(*getContext(), getDeviceId()) { mGestureConverter(*getContext(), deviceContext, getDeviceId()) { mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD); mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext)); // Even though we don't explicitly delete copy/move semantics, it's safe to Loading
services/inputflinger/reader/mapper/gestures/GestureConverter.cpp +119 −23 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "gestures/GestureConverter.h" #include <android/input.h> #include <linux/input-event-codes.h> #include "TouchCursorInputMapperCommon.h" #include "input/Input.h" Loading Loading @@ -44,10 +45,14 @@ uint32_t gesturesButtonToMotionEventButton(uint32_t gesturesButton) { } // namespace GestureConverter::GestureConverter(InputReaderContext& readerContext, int32_t deviceId) GestureConverter::GestureConverter(InputReaderContext& readerContext, const InputDeviceContext& deviceContext, int32_t deviceId) : mDeviceId(deviceId), mReaderContext(readerContext), mPointerController(readerContext.getPointerController(deviceId)) {} mPointerController(readerContext.getPointerController(deviceId)) { deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo); deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo); } void GestureConverter::reset() { mButtonState = 0; Loading @@ -60,6 +65,15 @@ std::list<NotifyArgs> GestureConverter::handleGesture(nsecs_t when, nsecs_t read return {handleMove(when, readTime, gesture)}; case kGestureTypeButtonsChange: return handleButtonsChange(when, readTime, gesture); case kGestureTypeSwipe: return handleMultiFingerSwipe(when, readTime, 3, gesture.details.swipe.dx, gesture.details.swipe.dy); case kGestureTypeFourFingerSwipe: return handleMultiFingerSwipe(when, readTime, 4, gesture.details.four_finger_swipe.dx, gesture.details.four_finger_swipe.dy); case kGestureTypeSwipeLift: case kGestureTypeFourFingerSwipeLift: return handleMultiFingerSwipeLift(when, readTime); default: // TODO(b/251196347): handle more gesture types. return {}; Loading @@ -67,11 +81,6 @@ std::list<NotifyArgs> GestureConverter::handleGesture(nsecs_t when, nsecs_t read } NotifyArgs GestureConverter::handleMove(nsecs_t when, nsecs_t readTime, const Gesture& gesture) { PointerProperties props; props.clear(); props.id = 0; props.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; float deltaX = gesture.details.move.dx; float deltaY = gesture.details.move.dy; rotateDelta(mOrientation, &deltaX, &deltaY); Loading @@ -93,7 +102,8 @@ NotifyArgs GestureConverter::handleMove(nsecs_t when, nsecs_t readTime, const Ge const int32_t action = down ? AMOTION_EVENT_ACTION_MOVE : AMOTION_EVENT_ACTION_HOVER_MOVE; return makeMotionArgs(when, readTime, action, /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition); /* pointerCount= */ 1, mFingerProps.data(), &coords, xCursorPosition, yCursorPosition); } std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_t readTime, Loading @@ -103,11 +113,6 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER); mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE); PointerProperties props; props.clear(); props.id = 0; props.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; float xCursorPosition, yCursorPosition; mPointerController->getPosition(&xCursorPosition, &yCursorPosition); Loading @@ -131,15 +136,16 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ newButtonState |= actionButton; pressEvents.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); /* pointerCount= */ 1, mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } } if (!isPointerDown(mButtonState) && isPointerDown(newButtonState)) { mDownTime = when; out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN, /* actionButton= */ 0, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } out.splice(out.end(), pressEvents); Loading @@ -155,19 +161,109 @@ std::list<NotifyArgs> GestureConverter::handleButtonsChange(nsecs_t when, nsecs_ newButtonState &= ~actionButton; out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } } if (isPointerDown(mButtonState) && !isPointerDown(newButtonState)) { coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f); out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0, newButtonState, /* pointerCount= */ 1, &props, &coords, xCursorPosition, yCursorPosition)); newButtonState, /* pointerCount= */ 1, mFingerProps.data(), &coords, xCursorPosition, yCursorPosition)); } mButtonState = newButtonState; return out; } [[nodiscard]] std::list<NotifyArgs> GestureConverter::handleMultiFingerSwipe(nsecs_t when, nsecs_t readTime, uint32_t fingerCount, float dx, float dy) { std::list<NotifyArgs> out = {}; float xCursorPosition, yCursorPosition; mPointerController->getPosition(&xCursorPosition, &yCursorPosition); if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) { // If the user changes the number of fingers mid-way through a swipe (e.g. they start with // three and then put a fourth finger down), the gesture library will treat it as two // separate swipes with an appropriate lift event between them, so we don't have to worry // about the finger count changing mid-swipe. mCurrentClassification = MotionClassification::MULTI_FINGER_SWIPE; mSwipeFingerCount = fingerCount; constexpr float FAKE_FINGER_SPACING = 100; float xCoord = xCursorPosition - FAKE_FINGER_SPACING * (mSwipeFingerCount - 1) / 2; for (size_t i = 0; i < mSwipeFingerCount; i++) { PointerCoords& coords = mFakeFingerCoords[i]; coords.clear(); coords.setAxisValue(AMOTION_EVENT_AXIS_X, xCoord); coords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition); coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); xCoord += FAKE_FINGER_SPACING; } mDownTime = when; out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN, /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); for (size_t i = 1; i < mSwipeFingerCount; i++) { out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_POINTER_DOWN | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), /* actionButton= */ 0, mButtonState, /* pointerCount= */ i + 1, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); } } for (size_t i = 0; i < mSwipeFingerCount; i++) { PointerCoords& coords = mFakeFingerCoords[i]; coords.setAxisValue(AMOTION_EVENT_AXIS_X, coords.getAxisValue(AMOTION_EVENT_AXIS_X) + dx); // TODO(b/251196347): Set the gesture properties appropriately to avoid needing to negate // the Y values. coords.setAxisValue(AMOTION_EVENT_AXIS_Y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y) - dy); } float xOffset = dx / (mXAxisInfo.maxValue - mXAxisInfo.minValue); // TODO(b/251196347): Set the gesture properties appropriately to avoid needing to negate the Y // values. float yOffset = -dy / (mYAxisInfo.maxValue - mYAxisInfo.minValue); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, xOffset); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset); out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, /* actionButton= */ 0, mButtonState, /* pointerCount= */ mSwipeFingerCount, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); return out; } [[nodiscard]] std::list<NotifyArgs> GestureConverter::handleMultiFingerSwipeLift(nsecs_t when, nsecs_t readTime) { std::list<NotifyArgs> out = {}; if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) { return out; } float xCursorPosition, yCursorPosition; mPointerController->getPosition(&xCursorPosition, &yCursorPosition); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, 0); mFakeFingerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, 0); for (size_t i = mSwipeFingerCount; i > 1; i--) { out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_POINTER_UP | ((i - 1) << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), /* actionButton= */ 0, mButtonState, /* pointerCount= */ i, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); } out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_UP, /* actionButton= */ 0, mButtonState, /* pointerCount= */ 1, mFingerProps.data(), mFakeFingerCoords.data(), xCursorPosition, yCursorPosition)); mCurrentClassification = MotionClassification::NONE; mSwipeFingerCount = 0; return out; } NotifyMotionArgs GestureConverter::makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action, int32_t actionButton, int32_t buttonState, uint32_t pointerCount, Loading @@ -181,10 +277,10 @@ NotifyMotionArgs GestureConverter::makeMotionArgs(nsecs_t when, nsecs_t readTime mPointerController->getDisplayId(), /* policyFlags= */ 0, action, /* actionButton= */ actionButton, /* flags= */ 0, mReaderContext.getGlobalMetaState(), buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties, pointerCoords, /* xPrecision= */ 1.0f, /* yPrecision= */ 1.0f, xCursorPosition, yCursorPosition, /* downTime= */ mDownTime, /* videoFrames= */ {}); mCurrentClassification, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties, pointerCoords, /* xPrecision= */ 1.0f, /* yPrecision= */ 1.0f, xCursorPosition, yCursorPosition, /* downTime= */ mDownTime, /* videoFrames= */ {}); } } // namespace android