diff options
| author | 2024-06-15 12:58:20 +0000 | |
|---|---|---|
| committer | 2024-07-08 08:18:05 +0000 | |
| commit | 8ff5e5ecde93d80549208f25563f351da90a8dfc (patch) | |
| tree | af7f75b07b7828ad83cbcca4269e8e2ac465a27e /libs/input/VirtualInputDevice.cpp | |
| parent | 9a87716c8a4715332adc8970de44e3f1ea83fb72 (diff) | |
Support high-resolution scroll
VirtualMouse currently supports -1f to 1f float scroll values,
but it worked for integer values only as input framework supported
only REL_HWHEEL and REL_WHEEL events. With the introduction of
high-res scroll event support (REL_HWHEEL_HI_RES and REL_WHEEL_HI_RES),
granular mouse scrolling can be done, and VirtualMouse scroll API
would work for all float values.
Flag: android.companion.virtualdevice.flags.high_resolution_scroll
Test: atest VirtualMouseTest
Bug: 335160780
Change-Id: I7b13ac1722b6fd31736fe1c0117d4de6e838261a
Diffstat (limited to 'libs/input/VirtualInputDevice.cpp')
| -rw-r--r-- | libs/input/VirtualInputDevice.cpp | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp index b73ee65504..2e3e1a09b8 100644 --- a/libs/input/VirtualInputDevice.cpp +++ b/libs/input/VirtualInputDevice.cpp @@ -18,6 +18,7 @@ #include <android/input.h> #include <android/keycodes.h> +#include <android_companion_virtualdevice_flags.h> #include <fcntl.h> #include <input/Input.h> #include <input/VirtualInputDevice.h> @@ -40,6 +41,8 @@ static bool isDebug() { namespace android { +namespace vd_flags = android::companion::virtualdevice::flags; + VirtualInputDevice::VirtualInputDevice(unique_fd fd) : mFd(std::move(fd)) {} VirtualInputDevice::~VirtualInputDevice() { @@ -253,7 +256,10 @@ const std::map<int, int> VirtualMouse::BUTTON_CODE_MAPPING = { // clang-format on }; -VirtualMouse::VirtualMouse(unique_fd fd) : VirtualInputDevice(std::move(fd)) {} +VirtualMouse::VirtualMouse(unique_fd fd) + : VirtualInputDevice(std::move(fd)), + mAccumulatedHighResScrollX(0), + mAccumulatedHighResScrollY(0) {} VirtualMouse::~VirtualMouse() {} @@ -272,9 +278,43 @@ bool VirtualMouse::writeRelativeEvent(float relativeX, float relativeY, bool VirtualMouse::writeScrollEvent(float xAxisMovement, float yAxisMovement, std::chrono::nanoseconds eventTime) { - return writeInputEvent(EV_REL, REL_HWHEEL, xAxisMovement, eventTime) && - writeInputEvent(EV_REL, REL_WHEEL, yAxisMovement, eventTime) && - writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); + if (!vd_flags::high_resolution_scroll()) { + return writeInputEvent(EV_REL, REL_HWHEEL, xAxisMovement, eventTime) && + writeInputEvent(EV_REL, REL_WHEEL, yAxisMovement, eventTime) && + writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); + } + + const int32_t highResScrollX = xAxisMovement * kEvdevMouseHighResScrollUnitsPerDetent; + const int32_t highResScrollY = yAxisMovement * kEvdevMouseHighResScrollUnitsPerDetent; + bool highResScrollResult = + writeInputEvent(EV_REL, REL_HWHEEL_HI_RES, highResScrollX, eventTime) && + writeInputEvent(EV_REL, REL_WHEEL_HI_RES, highResScrollY, eventTime); + if (!highResScrollResult) { + return false; + } + + // According to evdev spec, a high-resolution mouse needs to emit REL_WHEEL / REL_HWHEEL events + // in addition to high-res scroll events. Regular scroll events can approximate high-res scroll + // events, so we send a regular scroll event when the accumulated scroll motion reaches a detent + // (single mouse wheel click). + mAccumulatedHighResScrollX += highResScrollX; + mAccumulatedHighResScrollY += highResScrollY; + const int32_t scrollX = mAccumulatedHighResScrollX / kEvdevMouseHighResScrollUnitsPerDetent; + const int32_t scrollY = mAccumulatedHighResScrollY / kEvdevMouseHighResScrollUnitsPerDetent; + if (scrollX != 0) { + if (!writeInputEvent(EV_REL, REL_HWHEEL, scrollX, eventTime)) { + return false; + } + mAccumulatedHighResScrollX %= kEvdevMouseHighResScrollUnitsPerDetent; + } + if (scrollY != 0) { + if (!writeInputEvent(EV_REL, REL_WHEEL, scrollY, eventTime)) { + return false; + } + mAccumulatedHighResScrollY %= kEvdevMouseHighResScrollUnitsPerDetent; + } + + return writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); } // --- VirtualTouchscreen --- |