From de89176cd2a9977e4e5f6bac0bbcf2da9d1e5197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 4 Nov 2016 15:31:35 +0100 Subject: [PATCH] [libinput] Load/store device configuration Summary: Device gets a KConfigGroup injected and supports loading device-specific settings. This is invoked from Libinput::Connection when adding a new Device. Whenever a Device option is changed successfully through the DBus interface it gets synced into the KConfigGroup, thus on next loading of the Device it gets restored. The config group follows a pattern of: [libinput][vendor][product][name] Thus every device has a specific and persistent configuration. Test Plan: So far only tested through autotests Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D3264 --- autotests/libinput/CMakeLists.txt | 4 +- autotests/libinput/device_test.cpp | 442 +++++++++++++++++++++++++++++ libinput/connection.cpp | 4 + libinput/device.cpp | 120 +++++++- libinput/device.h | 25 +- 5 files changed, 579 insertions(+), 16 deletions(-) diff --git a/autotests/libinput/CMakeLists.txt b/autotests/libinput/CMakeLists.txt index 225f5733ea..79686097ac 100644 --- a/autotests/libinput/CMakeLists.txt +++ b/autotests/libinput/CMakeLists.txt @@ -5,7 +5,7 @@ include_directories(${UDEV_INCLUDE_DIR}) ######################################################## set( testLibinputDevice_SRCS device_test.cpp mock_libinput.cpp ../../libinput/device.cpp ) add_executable(testLibinputDevice ${testLibinputDevice_SRCS}) -target_link_libraries( testLibinputDevice Qt5::Test Qt5::DBus) +target_link_libraries( testLibinputDevice Qt5::Test Qt5::DBus KF5::ConfigCore) add_test(kwin-testLibinputDevice testLibinputDevice) ecm_mark_as_test(testLibinputDevice) @@ -94,6 +94,6 @@ ecm_mark_as_test(testLibinputContext) ######################################################## set( testInputEvents_SRCS input_event_test.cpp mock_libinput.cpp ../../libinput/device.cpp ../../input_event.cpp ) add_executable(testInputEvents ${testInputEvents_SRCS}) -target_link_libraries( testInputEvents Qt5::Test Qt5::DBus Qt5::Gui) +target_link_libraries( testInputEvents Qt5::Test Qt5::DBus Qt5::Gui KF5::ConfigCore) add_test(kwin-testInputEvents testInputEvents) ecm_mark_as_test(testInputEvents) diff --git a/autotests/libinput/device_test.cpp b/autotests/libinput/device_test.cpp index cfdc10931f..57d5a24a4e 100644 --- a/autotests/libinput/device_test.cpp +++ b/autotests/libinput/device_test.cpp @@ -21,6 +21,8 @@ along with this program. If not, see . #include "../../libinput/device.h" #include +#include + #include #include @@ -111,6 +113,26 @@ private Q_SLOTS: void testScrollButtonDown(); void testScrollButton_data(); void testScrollButton(); + void testLoadEnabled_data(); + void testLoadEnabled(); + void testLoadTapToClick_data(); + void testLoadTapToClick(); + void testLoadTapAndDrag_data(); + void testLoadTapAndDrag(); + void testLoadTapDragLock_data(); + void testLoadTapDragLock(); + void testLoadMiddleButtonEmulation_data(); + void testLoadMiddleButtonEmulation(); + void testLoadNaturalScroll_data(); + void testLoadNaturalScroll(); + void testLoadScrollTwoFinger_data(); + void testLoadScrollTwoFinger(); + void testLoadScrollEdge_data(); + void testLoadScrollEdge(); + void testLoadScrollOnButton_data(); + void testLoadScrollOnButton(); + void testLoadScrollButton_data(); + void testLoadScrollButton(); }; void TestLibinputDevice::testStaticGetter() @@ -1257,5 +1279,425 @@ void TestLibinputDevice::testScrollButton() QCOMPARE(scrollButtonChangedSpy.isEmpty(), initValue == expectedValue); } +void TestLibinputDevice::testLoadEnabled_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadEnabled() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("Enabled", configValue); + + libinput_device device; + device.supportsDisableEvents = true; + device.enabled = initValue; + device.setEnableModeReturnValue = false; + + Device d(&device); + QCOMPARE(d.isEnabled(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isEnabled(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isEnabled(), configValue); + + // and try to store + if (configValue != initValue) { + d.setEnabled(initValue); + QCOMPARE(inputConfig.readEntry("Enabled", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadTapToClick_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadTapToClick() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("TapToClick", configValue); + + libinput_device device; + device.tapFingerCount = 2; + device.tapToClick = initValue; + device.setTapToClickReturnValue = false; + + Device d(&device); + QCOMPARE(d.isTapToClick(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isTapToClick(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isTapToClick(), configValue); + + // and try to store + if (configValue != initValue) { + d.setTapToClick(initValue); + QCOMPARE(inputConfig.readEntry("TapToClick", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadTapAndDrag_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadTapAndDrag() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("TapAndDrag", configValue); + + libinput_device device; + device.tapAndDrag = initValue; + device.setTapAndDragReturnValue = false; + + Device d(&device); + QCOMPARE(d.isTapAndDrag(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isTapAndDrag(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isTapAndDrag(), configValue); + + // and try to store + if (configValue != initValue) { + d.setTapAndDrag(initValue); + QCOMPARE(inputConfig.readEntry("TapAndDrag", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadTapDragLock_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadTapDragLock() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("TapDragLock", configValue); + + libinput_device device; + device.tapDragLock = initValue; + device.setTapDragLockReturnValue = false; + + Device d(&device); + QCOMPARE(d.isTapDragLock(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isTapDragLock(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isTapDragLock(), configValue); + + // and try to store + if (configValue != initValue) { + d.setTapDragLock(initValue); + QCOMPARE(inputConfig.readEntry("TapDragLock", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadMiddleButtonEmulation_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadMiddleButtonEmulation() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("MiddleButtonEmulation", configValue); + + libinput_device device; + device.supportsMiddleEmulation = true; + device.middleEmulation = initValue; + device.setMiddleEmulationReturnValue = false; + + Device d(&device); + QCOMPARE(d.isMiddleEmulation(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isMiddleEmulation(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isMiddleEmulation(), configValue); + + // and try to store + if (configValue != initValue) { + d.setMiddleEmulation(initValue); + QCOMPARE(inputConfig.readEntry("MiddleButtonEmulation", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadNaturalScroll_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadNaturalScroll() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("NaturalScroll", configValue); + + libinput_device device; + device.supportsNaturalScroll = true; + device.naturalScroll = initValue; + device.setNaturalScrollReturnValue = false; + + Device d(&device); + QCOMPARE(d.isNaturalScroll(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isNaturalScroll(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isNaturalScroll(), configValue); + + // and try to store + if (configValue != initValue) { + d.setNaturalScroll(initValue); + QCOMPARE(inputConfig.readEntry("NaturalScroll", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadScrollTwoFinger_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadScrollTwoFinger() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("ScrollTwoFinger", configValue); + + libinput_device device; + device.supportedScrollMethods = LIBINPUT_CONFIG_SCROLL_2FG; + device.scrollMethod = initValue ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + device.setScrollMethodReturnValue = false; + + Device d(&device); + QCOMPARE(d.isScrollTwoFinger(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isScrollTwoFinger(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isScrollTwoFinger(), configValue); + + // and try to store + if (configValue != initValue) { + d.setScrollTwoFinger(initValue); + QCOMPARE(inputConfig.readEntry("ScrollTwoFinger", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadScrollEdge_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadScrollEdge() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("ScrollEdge", configValue); + + libinput_device device; + device.supportedScrollMethods = LIBINPUT_CONFIG_SCROLL_EDGE; + device.scrollMethod = initValue ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + device.setScrollMethodReturnValue = false; + + Device d(&device); + QCOMPARE(d.isScrollEdge(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isScrollEdge(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isScrollEdge(), configValue); + + // and try to store + if (configValue != initValue) { + d.setScrollEdge(initValue); + QCOMPARE(inputConfig.readEntry("ScrollEdge", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadScrollOnButton_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("false -> true") << false << true; + QTest::newRow("true -> false") << true << false; + QTest::newRow("true -> true") << true << true; + QTest::newRow("false -> false") << false << false; +} + +void TestLibinputDevice::testLoadScrollOnButton() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(bool, configValue); + QFETCH(bool, initValue); + inputConfig.writeEntry("ScrollOnButton", configValue); + + libinput_device device; + device.supportedScrollMethods = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + device.scrollMethod = initValue ? LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + device.setScrollMethodReturnValue = false; + + Device d(&device); + QCOMPARE(d.isScrollOnButtonDown(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isScrollOnButtonDown(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isScrollOnButtonDown(), configValue); + + // and try to store + if (configValue != initValue) { + d.setScrollOnButtonDown(initValue); + QCOMPARE(inputConfig.readEntry("ScrollOnButton", configValue), initValue); + } +} + +void TestLibinputDevice::testLoadScrollButton_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("configValue"); + + QTest::newRow("BTN_LEFT -> BTN_RIGHT") << quint32(BTN_LEFT) << quint32(BTN_RIGHT); + QTest::newRow("BTN_LEFT -> BTN_LEFT") << quint32(BTN_LEFT) << quint32(BTN_LEFT); +} + +void TestLibinputDevice::testLoadScrollButton() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(quint32, configValue); + QFETCH(quint32, initValue); + inputConfig.writeEntry("ScrollButton", configValue); + + libinput_device device; + device.supportedScrollMethods = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + device.scrollMethod = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; + device.scrollButton = initValue; + device.setScrollButtonReturnValue = false; + + Device d(&device); + QCOMPARE(d.isScrollOnButtonDown(), true); + QCOMPARE(d.scrollButton(), initValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.isScrollOnButtonDown(), true); + QCOMPARE(d.scrollButton(), initValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.isScrollOnButtonDown(), true); + QCOMPARE(d.scrollButton(), configValue); + + // and try to store + if (configValue != initValue) { + d.setScrollButton(initValue); + QCOMPARE(inputConfig.readEntry("ScrollButton", configValue), initValue); + } +} + QTEST_GUILESS_MAIN(TestLibinputDevice) #include "device_test.moc" diff --git a/libinput/connection.cpp b/libinput/connection.cpp index fece61797b..6964c891ae 100644 --- a/libinput/connection.cpp +++ b/libinput/connection.cpp @@ -471,6 +471,10 @@ bool Connection::isSuspended() const void Connection::applyDeviceConfig(Device *device) { + // pass configuration to Device + device->setConfig(m_config->group("Libinput").group(QString::number(device->vendor())).group(QString::number(device->product())).group(device->name())); + device->loadConfiguration(); + if (device->isPointer()) { const KConfigGroup group = m_config->group("Mouse"); device->setLeftHanded(group.readEntry("MouseButtonMapping", "RightHanded") == QLatin1String("LeftHanded")); diff --git a/libinput/device.cpp b/libinput/device.cpp index c9884e7012..ad43c02802 100644 --- a/libinput/device.cpp +++ b/libinput/device.cpp @@ -25,6 +25,8 @@ along with this program. If not, see . #include +#include + namespace KWin { namespace LibInput @@ -70,6 +72,44 @@ Device *Device::getDevice(libinput_device *native) return nullptr; } +enum class ConfigKey { + Enabled, + TapToClick, + TapAndDrag, + TapDragLock, + MiddleButtonEmulation, + NaturalScroll, + ScrollTwoFinger, + ScrollEdge, + ScrollOnButton, + ScrollButton +}; + +struct ConfigData { + QByteArray key; + struct BooleanSetter { + std::function setter; + std::function defaultValue; + } booleanSetter; + struct UintSetter { + std::function setter; + std::function defaultValue; + } quint32Setter; +}; + +static const QMap s_configData { + {ConfigKey::Enabled, {QByteArrayLiteral("Enabled"), {&Device::setEnabled, std::function()}, {}}}, + {ConfigKey::TapToClick, {QByteArrayLiteral("TapToClick"), {&Device::setTapToClick, &Device::tapToClickEnabledByDefault}, {}}}, + {ConfigKey::TapAndDrag, {QByteArrayLiteral("TapAndDrag"), {&Device::setTapAndDrag, &Device::tapAndDragEnabledByDefault}, {}}}, + {ConfigKey::TapDragLock, {QByteArrayLiteral("TapDragLock"), {&Device::setTapDragLock, &Device::tapDragLockEnabledByDefault}, {}}}, + {ConfigKey::MiddleButtonEmulation, {QByteArrayLiteral("MiddleButtonEmulation"), {&Device::setMiddleEmulation, &Device::middleEmulationEnabledByDefault}, {}}}, + {ConfigKey::NaturalScroll, {QByteArrayLiteral("NaturalScroll"), {&Device::setNaturalScroll, &Device::naturalScrollEnabledByDefault}, {}}}, + {ConfigKey::ScrollTwoFinger, {QByteArrayLiteral("ScrollTwoFinger"), {&Device::setScrollTwoFinger, &Device::scrollTwoFingerEnabledByDefault}, {}}}, + {ConfigKey::ScrollEdge, {QByteArrayLiteral("ScrollEdge"), {&Device::setScrollEdge, &Device::scrollEdgeEnabledByDefault}, {}}}, + {ConfigKey::ScrollOnButton, {QByteArrayLiteral("ScrollOnButton"), {&Device::setScrollOnButtonDown, &Device::scrollOnButtonDownEnabledByDefault}, {}}}, + {ConfigKey::ScrollButton, {QByteArrayLiteral("ScrollButton"), {}, {&Device::setScrollButton, &Device::defaultScrollButton}}} +}; + Device::Device(libinput_device *device, QObject *parent) : QObject(parent) , m_device(device) @@ -116,6 +156,7 @@ Device::Device(libinput_device *device, QObject *parent) , m_scrollButton(libinput_device_config_scroll_get_button(m_device)) , m_pointerAcceleration(libinput_device_config_accel_get_speed(m_device)) , m_enabled(m_supportsDisableEvents ? libinput_device_config_send_events_get_mode(m_device) == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : true) + , m_config() { libinput_device_ref(m_device); @@ -169,6 +210,48 @@ Device::~Device() libinput_device_unref(m_device); } +template +void Device::writeEntry(const ConfigKey &key, const T &value) +{ + if (!m_config.isValid()) { + return; + } + if (m_loading) { + return; + } + auto it = s_configData.find(key); + Q_ASSERT(it != s_configData.end()); + m_config.writeEntry(it.value().key.constData(), value); + m_config.sync(); +} + +template +void Device::readEntry(const QByteArray &key, const Setter &s, const T &defaultValue) +{ + if (!s.setter) { + return; + } + s.setter(this, m_config.readEntry(key.constData(), s.defaultValue ? s.defaultValue(this) : defaultValue)); +} + +void Device::loadConfiguration() +{ + if (!m_config.isValid()) { + return; + } + m_loading = true; + for (auto it = s_configData.begin(), end = s_configData.end(); it != end; ++it) { + const auto key = it.value().key; + if (!m_config.hasKey(key.constData())) { + continue; + } + readEntry(key, it.value().booleanSetter, true); + readEntry(key, it.value().quint32Setter, 0); + }; + + m_loading = false; +} + void Device::setLeftHanded(bool set) { if (!m_supportsLeftHanded) { @@ -204,23 +287,24 @@ void Device::setNaturalScroll(bool set) if (libinput_device_config_scroll_set_natural_scroll_enabled(m_device, set) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_naturalScroll != set) { m_naturalScroll = set; + writeEntry(ConfigKey::NaturalScroll, m_naturalScroll); emit naturalScrollChanged(); } } } -void Device::setScrollMethod(bool set, enum libinput_config_scroll_method method) +bool Device::setScrollMethod(bool set, enum libinput_config_scroll_method method) { if (!(m_supportedScrollMethods & method)) { - return; + return false; } if (set) { if (m_scrollMethod == method) { - return; + return false; } } else { if (m_scrollMethod != method) { - return; + return false; } method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; } @@ -228,19 +312,27 @@ void Device::setScrollMethod(bool set, enum libinput_config_scroll_method method if (libinput_device_config_scroll_set_method(m_device, method) == LIBINPUT_CONFIG_STATUS_SUCCESS) { m_scrollMethod = method; emit scrollMethodChanged(); + return true; } + return false; } void Device::setScrollTwoFinger(bool set) { - setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_2FG); + if (setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_2FG)) { + writeEntry(ConfigKey::ScrollTwoFinger, set); + } } void Device::setScrollEdge(bool set) { - setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_EDGE); + if (setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_EDGE)) { + writeEntry(ConfigKey::ScrollEdge, set); + } } void Device::setScrollOnButtonDown(bool set) { - setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); + if (setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)) { + writeEntry(ConfigKey::ScrollOnButton, set); + } } void Device::setScrollButton(quint32 button) @@ -251,12 +343,13 @@ void Device::setScrollButton(quint32 button) if (libinput_device_config_scroll_set_button(m_device, button) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_scrollButton != button) { m_scrollButton = button; + writeEntry(ConfigKey::ScrollButton, m_scrollButton); emit scrollButtonChanged(); } } } -#define CONFIG(method, condition, function, enum, variable) \ +#define CONFIG(method, condition, function, enum, variable, key) \ void Device::method(bool set) \ { \ if (condition) { \ @@ -265,16 +358,17 @@ void Device::method(bool set) \ if (libinput_device_config_##function(m_device, set ? LIBINPUT_CONFIG_##enum##_ENABLED : LIBINPUT_CONFIG_##enum##_DISABLED) == LIBINPUT_CONFIG_STATUS_SUCCESS) { \ if (m_##variable != set) { \ m_##variable = set; \ + writeEntry(ConfigKey::key, m_##variable); \ emit variable##Changed(); \ }\ } \ } -CONFIG(setEnabled, !m_supportsDisableEvents, send_events_set_mode, SEND_EVENTS, enabled) -CONFIG(setTapToClick, m_tapFingerCount == 0, tap_set_enabled, TAP, tapToClick) -CONFIG(setTapAndDrag, false, tap_set_drag_enabled, DRAG, tapAndDrag) -CONFIG(setTapDragLock, false, tap_set_drag_lock_enabled, DRAG_LOCK, tapDragLock) -CONFIG(setMiddleEmulation, m_supportsMiddleEmulation == false, middle_emulation_set_enabled, MIDDLE_EMULATION, middleEmulation) +CONFIG(setEnabled, !m_supportsDisableEvents, send_events_set_mode, SEND_EVENTS, enabled, Enabled) +CONFIG(setTapToClick, m_tapFingerCount == 0, tap_set_enabled, TAP, tapToClick, TapToClick) +CONFIG(setTapAndDrag, false, tap_set_drag_enabled, DRAG, tapAndDrag, TapAndDrag) +CONFIG(setTapDragLock, false, tap_set_drag_lock_enabled, DRAG_LOCK, tapDragLock, TapDragLock) +CONFIG(setMiddleEmulation, m_supportsMiddleEmulation == false, middle_emulation_set_enabled, MIDDLE_EMULATION, middleEmulation, MiddleButtonEmulation) #undef CONFIG diff --git a/libinput/device.h b/libinput/device.h index f0e08a4684..21955383f9 100644 --- a/libinput/device.h +++ b/libinput/device.h @@ -22,6 +22,8 @@ along with this program. If not, see . #include +#include + #include #include #include @@ -32,6 +34,7 @@ namespace KWin { namespace LibInput { +enum class ConfigKey; class Device : public QObject { @@ -216,7 +219,7 @@ public: return m_naturalScroll; } void setNaturalScroll(bool set); - void setScrollMethod(bool set, enum libinput_config_scroll_method method); + bool setScrollMethod(bool set, enum libinput_config_scroll_method method); bool isScrollTwoFinger() const { return m_scrollMethod & LIBINPUT_CONFIG_SCROLL_2FG; } @@ -260,6 +263,19 @@ public: return m_device; } + /** + * Sets the @p config to load the Device configuration from and to store each + * successful Device configuration. + **/ + void setConfig(const KConfigGroup &config) { + m_config = config; + } + + /** + * Loads the configuration and applies it to the Device + **/ + void loadConfiguration(); + /** * All created Devices **/ @@ -284,6 +300,10 @@ Q_SIGNALS: void scrollButtonChanged(); private: + template + void writeEntry(const ConfigKey &key, const T &value); + template + void readEntry(const QByteArray &key, const Setter &s, const T &defaultValue = T()); libinput_device *m_device; bool m_keyboard; bool m_alphaNumericKeyboard = false; @@ -329,6 +349,9 @@ private: qreal m_pointerAcceleration; bool m_enabled; + KConfigGroup m_config; + bool m_loading = false; + static QVector s_devices; };