diff --git a/autotests/libinput/device_test.cpp b/autotests/libinput/device_test.cpp --- a/autotests/libinput/device_test.cpp +++ b/autotests/libinput/device_test.cpp @@ -124,6 +124,7 @@ void testMiddleEmulation(); void testNaturalScroll_data(); void testNaturalScroll(); + void testScrollFactor(); void testScrollTwoFinger_data(); void testScrollTwoFinger(); void testScrollEdge_data(); @@ -1353,6 +1354,29 @@ QCOMPARE(dbusProperty(d.sysName(), "naturalScroll"), expectedValue); } +void TestLibinputDevice::testScrollFactor() +{ + libinput_device device; + + qreal initValue = 1.0; + + Device d(&device); + QCOMPARE(d.scrollFactor(), initValue); + QCOMPARE(d.property("scrollFactor").toReal(), initValue); + QCOMPARE(dbusProperty(d.sysName(), "scrollFactor"), initValue); + + QSignalSpy scrollFactorChangedSpy(&d, &Device::scrollFactorChanged); + QVERIFY(scrollFactorChangedSpy.isValid()); + + qreal expectedValue = 2.0; + + d.setScrollFactor(expectedValue); + QCOMPARE(d.scrollFactor(), expectedValue); + QCOMPARE(d.property("scrollFactor").toReal(), expectedValue); + QCOMPARE(scrollFactorChangedSpy.isEmpty(), false); + QCOMPARE(dbusProperty(d.sysName(), "scrollFactor"), expectedValue); +} + void TestLibinputDevice::testScrollTwoFinger_data() { QTest::addColumn("initValue"); diff --git a/libinput/device.h b/libinput/device.h --- a/libinput/device.h +++ b/libinput/device.h @@ -125,6 +125,8 @@ Q_PROPERTY(bool scrollOnButtonDown READ isScrollOnButtonDown WRITE setScrollOnButtonDown NOTIFY scrollMethodChanged) Q_PROPERTY(quint32 scrollButton READ scrollButton WRITE setScrollButton NOTIFY scrollButtonChanged) + Q_PROPERTY(qreal scrollFactor READ scrollFactor WRITE setScrollFactor NOTIFY scrollFactorChanged) + // switches Q_PROPERTY(bool switchDevice READ isSwitch CONSTANT) Q_PROPERTY(bool lidSwitch READ isLidSwitch CONSTANT) @@ -330,6 +332,14 @@ } void setScrollButton(quint32 button); + qreal scrollFactorDefault() const { + return 1.0; + } + qreal scrollFactor() const { + return m_scrollFactor; + } + void setScrollFactor(qreal factor); + void setDisableWhileTyping(bool set); bool isDisableWhileTyping() const { return m_disableWhileTyping; @@ -500,6 +510,7 @@ void naturalScrollChanged(); void scrollMethodChanged(); void scrollButtonChanged(); + void scrollFactorChanged(); void clickMethodChanged(); private: @@ -559,6 +570,7 @@ quint32 m_scrollButton; qreal m_defaultPointerAcceleration; qreal m_pointerAcceleration; + qreal m_scrollFactor; quint32 m_supportedPointerAccelerationProfiles; enum libinput_config_accel_profile m_defaultPointerAccelerationProfile; enum libinput_config_accel_profile m_pointerAccelerationProfile; diff --git a/libinput/device.cpp b/libinput/device.cpp --- a/libinput/device.cpp +++ b/libinput/device.cpp @@ -84,7 +84,8 @@ NaturalScroll, ScrollMethod, ScrollButton, - ClickMethod + ClickMethod, + ScrollFactor }; struct ConfigData { @@ -100,6 +101,10 @@ : key(_key) { stringSetter.setter = _setter; stringSetter.defaultValue = _defaultValue; } + explicit ConfigData(QByteArray _key, void (Device::*_setter)(qreal), qreal (Device::*_defaultValue)() const = nullptr) + : key(_key) + { qrealSetter.setter = _setter; qrealSetter.defaultValue = _defaultValue; } + QByteArray key; struct { @@ -115,6 +120,10 @@ void (Device::*setter)(QString) = nullptr; QString (Device::*defaultValue)() const; } stringSetter; + struct { + void (Device::*setter)(qreal) = nullptr; + qreal (Device::*defaultValue)() const; + } qrealSetter; }; static const QMap s_configData { @@ -131,7 +140,8 @@ {ConfigKey::NaturalScroll, ConfigData(QByteArrayLiteral("NaturalScroll"), &Device::setNaturalScroll, &Device::naturalScrollEnabledByDefault)}, {ConfigKey::ScrollMethod, ConfigData(QByteArrayLiteral("ScrollMethod"), &Device::activateScrollMethodFromInt, &Device::defaultScrollMethodToInt)}, {ConfigKey::ScrollButton, ConfigData(QByteArrayLiteral("ScrollButton"), &Device::setScrollButton, &Device::defaultScrollButton)}, - {ConfigKey::ClickMethod, ConfigData(QByteArrayLiteral("ClickMethod"), &Device::setClickMethodFromInt, &Device::defaultClickMethodToInt)} + {ConfigKey::ClickMethod, ConfigData(QByteArrayLiteral("ClickMethod"), &Device::setClickMethodFromInt, &Device::defaultClickMethodToInt)}, + {ConfigKey::ScrollFactor, ConfigData(QByteArrayLiteral("ScrollFactor"), &Device::setScrollFactor, &Device::scrollFactorDefault)} }; namespace { @@ -209,6 +219,7 @@ , m_supportedClickMethods(libinput_device_config_click_get_methods(m_device)) , m_defaultClickMethod(libinput_device_config_click_get_default_method(m_device)) , m_clickMethod(libinput_device_config_click_get_method(m_device)) + , m_scrollFactor(scrollFactorDefault()) { libinput_device_ref(m_device); @@ -301,6 +312,7 @@ readEntry(key, it.value().booleanSetter, true); readEntry(key, it.value().quint32Setter, 0); readEntry(key, it.value().stringSetter, ""); + readEntry(key, it.value().qrealSetter, 1.0); }; m_loading = false; @@ -476,6 +488,15 @@ #undef CONFIG +void Device::setScrollFactor(qreal factor) +{ + if (m_scrollFactor != factor) { + m_scrollFactor = factor; + writeEntry(ConfigKey::ScrollFactor, m_scrollFactor); + emit scrollFactorChanged(); + } +} + void Device::setOrientation(Qt::ScreenOrientation orientation) { if (!m_supportsCalibrationMatrix) { diff --git a/libinput/events.cpp b/libinput/events.cpp --- a/libinput/events.cpp +++ b/libinput/events.cpp @@ -214,16 +214,16 @@ const libinput_pointer_axis a = axis == InputRedirection::PointerAxisHorizontal ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - return libinput_event_pointer_get_axis_value(m_pointerEvent, a); + return libinput_event_pointer_get_axis_value(m_pointerEvent, a) * device()->scrollFactor(); } qint32 PointerEvent::discreteAxisValue(InputRedirection::PointerAxis axis) const { Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS); const libinput_pointer_axis a = (axis == InputRedirection::PointerAxisHorizontal) ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - return libinput_event_pointer_get_axis_value_discrete(m_pointerEvent, a); + return libinput_event_pointer_get_axis_value_discrete(m_pointerEvent, a) * device()->scrollFactor(); } InputRedirection::PointerAxisSource PointerEvent::axisSource() const