[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
This commit is contained in:
parent
b6af777230
commit
de89176cd2
5 changed files with 579 additions and 16 deletions
|
@ -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)
|
||||
|
|
|
@ -21,6 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "../../libinput/device.h"
|
||||
#include <config-kwin.h>
|
||||
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
@ -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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<bool>("initValue");
|
||||
QTest::addColumn<bool>("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<quint32>("initValue");
|
||||
QTest::addColumn<quint32>("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"
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include <config-kwin.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
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<void (Device*, bool)> setter;
|
||||
std::function<bool (Device*)> defaultValue;
|
||||
} booleanSetter;
|
||||
struct UintSetter {
|
||||
std::function<void (Device*, quint32)> setter;
|
||||
std::function<quint32 (Device*)> defaultValue;
|
||||
} quint32Setter;
|
||||
};
|
||||
|
||||
static const QMap<ConfigKey, ConfigData> s_configData {
|
||||
{ConfigKey::Enabled, {QByteArrayLiteral("Enabled"), {&Device::setEnabled, std::function<bool (Device*)>()}, {}}},
|
||||
{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 <typename T>
|
||||
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 <typename T, typename Setter>
|
||||
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
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include <libinput.h>
|
||||
|
||||
#include <KConfigGroup>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSizeF>
|
||||
#include <QVector>
|
||||
|
@ -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 <typename T>
|
||||
void writeEntry(const ConfigKey &key, const T &value);
|
||||
template <typename T, typename Setter>
|
||||
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<Device*> s_devices;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue