Loading services/inputflinger/include/InputReaderBase.h +9 −1 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ struct InputReaderConfiguration { // The key remapping has changed. KEY_REMAPPING = 1u << 14, // The mouse settings changed, this includes mouse reverse vertical scrolling. MOUSE_SETTINGS = 1u << 15, // All devices must be reopened. MUST_REOPEN = 1u << 31, }; Loading Loading @@ -252,6 +255,10 @@ struct InputReaderConfiguration { // Keycodes to be remapped. std::map<int32_t /* fromKeyCode */, int32_t /* toKeyCode */> keyRemapping; // True if the external mouse should have its vertical scrolling reversed, so that rotating the // wheel downwards scrolls the content upwards. bool mouseReverseVerticalScrollingEnabled; InputReaderConfiguration() : virtualKeyQuietTime(0), defaultPointerDisplayId(ui::LogicalDisplayId::DEFAULT), Loading Loading @@ -282,7 +289,8 @@ struct InputReaderConfiguration { shouldNotifyTouchpadHardwareState(false), touchpadRightClickZoneEnabled(false), stylusButtonMotionEventsEnabled(true), stylusPointerIconEnabled(false) {} stylusPointerIconEnabled(false), mouseReverseVerticalScrollingEnabled(false) {} std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const; std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId) Loading services/inputflinger/reader/mapper/CursorInputMapper.cpp +14 −1 Original line number Diff line number Diff line Loading @@ -164,6 +164,10 @@ std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when, changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) { configureOnChangePointerSpeed(readerConfig); } if (!changes.any() || changes.test(InputReaderConfiguration::Change::MOUSE_SETTINGS)) { configureOnChangeMouseSettings(readerConfig); } return out; } Loading Loading @@ -275,7 +279,12 @@ std::list<NotifyArgs> CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) { PointerCoords pointerCoords; pointerCoords.clear(); float vscroll = mCursorScrollAccumulator.getRelativeVWheel(); // A negative value represents inverted scrolling direction. // Applies only if the source is a mouse. const bool isMouse = (mSource == AINPUT_SOURCE_MOUSE) || (mSource == AINPUT_SOURCE_MOUSE_RELATIVE); const int scrollingDirection = (mMouseReverseVerticalScrolling && isMouse) ? -1 : 1; float vscroll = scrollingDirection * mCursorScrollAccumulator.getRelativeVWheel(); float hscroll = mCursorScrollAccumulator.getRelativeHWheel(); bool scrolled = vscroll != 0 || hscroll != 0; Loading Loading @@ -537,4 +546,8 @@ void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfigurat bumpGeneration(); } void CursorInputMapper::configureOnChangeMouseSettings(const InputReaderConfiguration& config) { mMouseReverseVerticalScrolling = config.mouseReverseVerticalScrollingEnabled; } } // namespace android services/inputflinger/reader/mapper/CursorInputMapper.h +2 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,7 @@ private: nsecs_t mLastEventTime; const bool mEnableNewMousePointerBallistics; bool mMouseReverseVerticalScrolling = false; explicit CursorInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig); Loading @@ -129,6 +130,7 @@ private: void configureOnPointerCapture(const InputReaderConfiguration& config); void configureOnChangePointerSpeed(const InputReaderConfiguration& config); void configureOnChangeDisplayInfo(const InputReaderConfiguration& config); void configureOnChangeMouseSettings(const InputReaderConfiguration& config); [[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime); Loading services/inputflinger/tests/CursorInputMapper_test.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -882,6 +882,51 @@ TEST_F(CursorInputMapperUnitTest, HighResScrollIgnoresRegularScroll) { WithScroll(0.5f, 0.5f))))); } TEST_F(CursorInputMapperUnitTest, ProcessReversedVerticalScroll) { mReaderConfiguration.mouseReverseVerticalScrollingEnabled = true; createMapper(); std::list<NotifyArgs> args; args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1); args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); // Reversed vertical scrolling only affects the y-axis, expect it to be -1.0f to indicate the // inverted scroll direction. EXPECT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), WithScroll(1.0f, -1.0f))))); } TEST_F(CursorInputMapperUnitTest, ProcessHighResReversedVerticalScroll) { mReaderConfiguration.mouseReverseVerticalScrollingEnabled = true; vd_flags::high_resolution_scroll(true); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) .WillRepeatedly(Return(true)); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) .WillRepeatedly(Return(true)); createMapper(); std::list<NotifyArgs> args; args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60); args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60); args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); EXPECT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), WithScroll(0.5f, -0.5f))))); } /** * When Pointer Capture is enabled, we expect to report unprocessed relative movements, so any * pointer acceleration or speed processing should not be applied. Loading Loading
services/inputflinger/include/InputReaderBase.h +9 −1 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ struct InputReaderConfiguration { // The key remapping has changed. KEY_REMAPPING = 1u << 14, // The mouse settings changed, this includes mouse reverse vertical scrolling. MOUSE_SETTINGS = 1u << 15, // All devices must be reopened. MUST_REOPEN = 1u << 31, }; Loading Loading @@ -252,6 +255,10 @@ struct InputReaderConfiguration { // Keycodes to be remapped. std::map<int32_t /* fromKeyCode */, int32_t /* toKeyCode */> keyRemapping; // True if the external mouse should have its vertical scrolling reversed, so that rotating the // wheel downwards scrolls the content upwards. bool mouseReverseVerticalScrollingEnabled; InputReaderConfiguration() : virtualKeyQuietTime(0), defaultPointerDisplayId(ui::LogicalDisplayId::DEFAULT), Loading Loading @@ -282,7 +289,8 @@ struct InputReaderConfiguration { shouldNotifyTouchpadHardwareState(false), touchpadRightClickZoneEnabled(false), stylusButtonMotionEventsEnabled(true), stylusPointerIconEnabled(false) {} stylusPointerIconEnabled(false), mouseReverseVerticalScrollingEnabled(false) {} std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const; std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId) Loading
services/inputflinger/reader/mapper/CursorInputMapper.cpp +14 −1 Original line number Diff line number Diff line Loading @@ -164,6 +164,10 @@ std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when, changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) { configureOnChangePointerSpeed(readerConfig); } if (!changes.any() || changes.test(InputReaderConfiguration::Change::MOUSE_SETTINGS)) { configureOnChangeMouseSettings(readerConfig); } return out; } Loading Loading @@ -275,7 +279,12 @@ std::list<NotifyArgs> CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) { PointerCoords pointerCoords; pointerCoords.clear(); float vscroll = mCursorScrollAccumulator.getRelativeVWheel(); // A negative value represents inverted scrolling direction. // Applies only if the source is a mouse. const bool isMouse = (mSource == AINPUT_SOURCE_MOUSE) || (mSource == AINPUT_SOURCE_MOUSE_RELATIVE); const int scrollingDirection = (mMouseReverseVerticalScrolling && isMouse) ? -1 : 1; float vscroll = scrollingDirection * mCursorScrollAccumulator.getRelativeVWheel(); float hscroll = mCursorScrollAccumulator.getRelativeHWheel(); bool scrolled = vscroll != 0 || hscroll != 0; Loading Loading @@ -537,4 +546,8 @@ void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfigurat bumpGeneration(); } void CursorInputMapper::configureOnChangeMouseSettings(const InputReaderConfiguration& config) { mMouseReverseVerticalScrolling = config.mouseReverseVerticalScrollingEnabled; } } // namespace android
services/inputflinger/reader/mapper/CursorInputMapper.h +2 −0 Original line number Diff line number Diff line Loading @@ -121,6 +121,7 @@ private: nsecs_t mLastEventTime; const bool mEnableNewMousePointerBallistics; bool mMouseReverseVerticalScrolling = false; explicit CursorInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig); Loading @@ -129,6 +130,7 @@ private: void configureOnPointerCapture(const InputReaderConfiguration& config); void configureOnChangePointerSpeed(const InputReaderConfiguration& config); void configureOnChangeDisplayInfo(const InputReaderConfiguration& config); void configureOnChangeMouseSettings(const InputReaderConfiguration& config); [[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime); Loading
services/inputflinger/tests/CursorInputMapper_test.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -882,6 +882,51 @@ TEST_F(CursorInputMapperUnitTest, HighResScrollIgnoresRegularScroll) { WithScroll(0.5f, 0.5f))))); } TEST_F(CursorInputMapperUnitTest, ProcessReversedVerticalScroll) { mReaderConfiguration.mouseReverseVerticalScrollingEnabled = true; createMapper(); std::list<NotifyArgs> args; args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1); args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); // Reversed vertical scrolling only affects the y-axis, expect it to be -1.0f to indicate the // inverted scroll direction. EXPECT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), WithScroll(1.0f, -1.0f))))); } TEST_F(CursorInputMapperUnitTest, ProcessHighResReversedVerticalScroll) { mReaderConfiguration.mouseReverseVerticalScrollingEnabled = true; vd_flags::high_resolution_scroll(true); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) .WillRepeatedly(Return(true)); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) .WillRepeatedly(Return(true)); createMapper(); std::list<NotifyArgs> args; args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60); args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60); args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); EXPECT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), VariantWith<NotifyMotionArgs>( AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), WithScroll(0.5f, -0.5f))))); } /** * When Pointer Capture is enabled, we expect to report unprocessed relative movements, so any * pointer acceleration or speed processing should not be applied. Loading