diff --git a/autotests/libinput/device_test.cpp b/autotests/libinput/device_test.cpp index 7e9b1140f..0dfae64ec 100644 --- a/autotests/libinput/device_test.cpp +++ b/autotests/libinput/device_test.cpp @@ -1,2295 +1,2404 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "mock_libinput.h" #include "../../libinput/device.h" #include #include #include #include #include #include using namespace KWin::LibInput; class TestLibinputDevice : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testStaticGetter(); void testDeviceType_data(); void testDeviceType(); void testGestureSupport_data(); void testGestureSupport(); void testNames_data(); void testNames(); void testProduct(); void testVendor(); void testTapFingerCount(); void testSize_data(); void testSize(); void testDefaultPointerAcceleration_data(); void testDefaultPointerAcceleration(); void testDefaultPointerAccelerationProfileFlat_data(); void testDefaultPointerAccelerationProfileFlat(); void testDefaultPointerAccelerationProfileAdaptive_data(); void testDefaultPointerAccelerationProfileAdaptive(); + void testDefaultClickMethodAreas_data(); + void testDefaultClickMethodAreas(); + void testDefaultClickMethodClickfinger_data(); + void testDefaultClickMethodClickfinger(); void testLeftHandedEnabledByDefault_data(); void testLeftHandedEnabledByDefault(); void testTapEnabledByDefault_data(); void testTapEnabledByDefault(); void testMiddleEmulationEnabledByDefault_data(); void testMiddleEmulationEnabledByDefault(); void testNaturalScrollEnabledByDefault_data(); void testNaturalScrollEnabledByDefault(); void testScrollTwoFingerEnabledByDefault_data(); void testScrollTwoFingerEnabledByDefault(); void testScrollEdgeEnabledByDefault_data(); void testScrollEdgeEnabledByDefault(); void testScrollOnButtonDownEnabledByDefault_data(); void testScrollOnButtonDownEnabledByDefault(); void testDisableWhileTypingEnabledByDefault_data(); void testDisableWhileTypingEnabledByDefault(); void testLmrTapButtonMapEnabledByDefault_data(); void testLmrTapButtonMapEnabledByDefault(); void testSupportsDisableWhileTyping_data(); void testSupportsDisableWhileTyping(); void testSupportsPointerAcceleration_data(); void testSupportsPointerAcceleration(); void testSupportsLeftHanded_data(); void testSupportsLeftHanded(); void testSupportsCalibrationMatrix_data(); void testSupportsCalibrationMatrix(); void testSupportsDisableEvents_data(); void testSupportsDisableEvents(); void testSupportsDisableEventsOnExternalMouse_data(); void testSupportsDisableEventsOnExternalMouse(); void testSupportsMiddleEmulation_data(); void testSupportsMiddleEmulation(); void testSupportsNaturalScroll_data(); void testSupportsNaturalScroll(); void testSupportsScrollTwoFinger_data(); void testSupportsScrollTwoFinger(); void testSupportsScrollEdge_data(); void testSupportsScrollEdge(); void testSupportsScrollOnButtonDown_data(); void testSupportsScrollOnButtonDown(); void testDefaultScrollButton_data(); void testDefaultScrollButton(); void testPointerAcceleration_data(); void testPointerAcceleration(); void testLeftHanded_data(); void testLeftHanded(); void testSupportedButtons_data(); void testSupportedButtons(); void testAlphaNumericKeyboard_data(); void testAlphaNumericKeyboard(); void testEnabled_data(); void testEnabled(); void testTapToClick_data(); void testTapToClick(); void testTapAndDragEnabledByDefault_data(); void testTapAndDragEnabledByDefault(); void testTapAndDrag_data(); void testTapAndDrag(); void testTapDragLockEnabledByDefault_data(); void testTapDragLockEnabledByDefault(); void testTapDragLock_data(); void testTapDragLock(); void testMiddleEmulation_data(); void testMiddleEmulation(); void testNaturalScroll_data(); void testNaturalScroll(); void testScrollTwoFinger_data(); void testScrollTwoFinger(); void testScrollEdge_data(); void testScrollEdge(); void testScrollButtonDown_data(); void testScrollButtonDown(); void testScrollButton_data(); void testScrollButton(); void testDisableWhileTyping_data(); void testDisableWhileTyping(); void testLmrTapButtonMap_data(); void testLmrTapButtonMap(); void testLoadEnabled_data(); void testLoadEnabled(); void testLoadPointerAcceleration_data(); void testLoadPointerAcceleration(); void testLoadPointerAccelerationProfile_data(); void testLoadPointerAccelerationProfile(); + void testLoadClickMethod_data(); + void testLoadClickMethod(); 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 testLoadScrollMethod_data(); void testLoadScrollMethod(); void testLoadScrollButton_data(); void testLoadScrollButton(); void testLoadDisableWhileTyping_data(); void testLoadDisableWhileTyping(); void testLoadLmrTapButtonMap_data(); void testLoadLmrTapButtonMap(); void testLoadLeftHanded_data(); void testLoadLeftHanded(); void testScreenId(); void testOrientation_data(); void testOrientation(); void testCalibrationWithDefault(); void testSwitch_data(); void testSwitch(); }; namespace { template T dbusProperty(const QString &name, const char *property) { QDBusInterface interface{QStringLiteral("org.kde.kwin.tests.libinputdevice"), QStringLiteral("/org/kde/KWin/InputDevice/") + name, QStringLiteral("org.kde.KWin.InputDevice")}; return interface.property(property).value(); } } void TestLibinputDevice::initTestCase() { QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kwin.tests.libinputdevice")); } void TestLibinputDevice::testStaticGetter() { // this test verifies that the static getter for Device works as expected QVERIFY(Device::devices().isEmpty()); // create some device libinput_device device1; libinput_device device2; // at the moment not yet known to Device QVERIFY(!Device::getDevice(&device1)); QVERIFY(!Device::getDevice(&device2)); QVERIFY(Device::devices().isEmpty()); // now create a Device for one Device *d1 = new Device(&device1); QCOMPARE(Device::devices().count(), 1); QCOMPARE(Device::devices().first(), d1); QCOMPARE(Device::getDevice(&device1), d1); QVERIFY(!Device::getDevice(&device2)); // and a second Device Device *d2 = new Device(&device2); QCOMPARE(Device::devices().count(), 2); QCOMPARE(Device::devices().first(), d1); QCOMPARE(Device::devices().last(), d2); QCOMPARE(Device::getDevice(&device1), d1); QCOMPARE(Device::getDevice(&device2), d2); // now delete d1 delete d1; QCOMPARE(Device::devices().count(), 1); QCOMPARE(Device::devices().first(), d2); QCOMPARE(Device::getDevice(&device2), d2); QVERIFY(!Device::getDevice(&device1)); // and delete d2 delete d2; QVERIFY(!Device::getDevice(&device1)); QVERIFY(!Device::getDevice(&device2)); QVERIFY(Device::devices().isEmpty()); } void TestLibinputDevice::testDeviceType_data() { QTest::addColumn("keyboard"); QTest::addColumn("pointer"); QTest::addColumn("touch"); QTest::addColumn("tabletTool"); QTest::addColumn("switchDevice"); QTest::newRow("keyboard") << true << false << false << false << false; QTest::newRow("pointer") << false << true << false << false << false; QTest::newRow("touch") << false << false << true << false << false; QTest::newRow("keyboard/pointer") << true << true << false << false << false; QTest::newRow("keyboard/touch") << true << false << true << false << false; QTest::newRow("pointer/touch") << false << true << true << false << false; QTest::newRow("keyboard/pointer/touch") << true << true << true << false << false; QTest::newRow("tabletTool") << false << false << false << true << false; QTest::newRow("switch") << false << false << false << false << true; } void TestLibinputDevice::testDeviceType() { // this test verifies that the device type is recognized correctly QFETCH(bool, keyboard); QFETCH(bool, pointer); QFETCH(bool, touch); QFETCH(bool, tabletTool); QFETCH(bool, switchDevice); libinput_device device; device.keyboard = keyboard; device.pointer = pointer; device.touch = touch; device.tabletTool = tabletTool; device.switchDevice = switchDevice; Device d(&device); QCOMPARE(d.isKeyboard(), keyboard); QCOMPARE(d.property("keyboard").toBool(), keyboard); QCOMPARE(dbusProperty(d.sysName(), "keyboard"), keyboard); QCOMPARE(d.isPointer(), pointer); QCOMPARE(d.property("pointer").toBool(), pointer); QCOMPARE(dbusProperty(d.sysName(), "pointer"), pointer); QCOMPARE(d.isTouch(), touch); QCOMPARE(d.property("touch").toBool(), touch); QCOMPARE(dbusProperty(d.sysName(), "touch"), touch); QCOMPARE(d.isTabletPad(), false); QCOMPARE(d.property("tabletPad").toBool(), false); QCOMPARE(dbusProperty(d.sysName(), "tabletPad"), false); QCOMPARE(d.isTabletTool(), tabletTool); QCOMPARE(d.property("tabletTool").toBool(), tabletTool); QCOMPARE(dbusProperty(d.sysName(), "tabletTool"), tabletTool); QCOMPARE(d.isSwitch(), switchDevice); QCOMPARE(d.property("switchDevice").toBool(), switchDevice); QCOMPARE(dbusProperty(d.sysName(), "switchDevice"), switchDevice); QCOMPARE(d.device(), &device); } void TestLibinputDevice::testGestureSupport_data() { QTest::addColumn("supported"); QTest::newRow("supported") << true; QTest::newRow("not supported") << false; } void TestLibinputDevice::testGestureSupport() { // this test verifies whether the Device supports gestures QFETCH(bool, supported); libinput_device device; device.gestureSupported = supported; Device d(&device); QCOMPARE(d.supportsGesture(), supported); QCOMPARE(d.property("gestureSupport").toBool(), supported); QCOMPARE(dbusProperty(d.sysName(), "gestureSupport"), supported); } void TestLibinputDevice::testNames_data() { QTest::addColumn("name"); QTest::addColumn("sysName"); QTest::addColumn("outputName"); QTest::newRow("empty") << QByteArray() << QByteArrayLiteral("event1") << QByteArray(); QTest::newRow("set") << QByteArrayLiteral("awesome test device") << QByteArrayLiteral("event0") << QByteArrayLiteral("hdmi0"); } void TestLibinputDevice::testNames() { // this test verifies the various name properties of the Device QFETCH(QByteArray, name); QFETCH(QByteArray, sysName); QFETCH(QByteArray, outputName); libinput_device device; device.name = name; device.sysName = sysName; device.outputName = outputName; Device d(&device); QCOMPARE(d.name().toUtf8(), name); QCOMPARE(d.property("name").toString().toUtf8(), name); QCOMPARE(dbusProperty(d.sysName(), "name"), name); QCOMPARE(d.sysName().toUtf8(), sysName); QCOMPARE(d.property("sysName").toString().toUtf8(), sysName); QCOMPARE(dbusProperty(d.sysName(), "sysName"), sysName); QCOMPARE(d.outputName().toUtf8(), outputName); QCOMPARE(d.property("outputName").toString().toUtf8(), outputName); QCOMPARE(dbusProperty(d.sysName(), "outputName"), outputName); } void TestLibinputDevice::testProduct() { // this test verifies the product property libinput_device device; device.product = 100u; Device d(&device); QCOMPARE(d.product(), 100u); QCOMPARE(d.property("product").toUInt(), 100u); QCOMPARE(dbusProperty(d.sysName(), "product"), 100u); } void TestLibinputDevice::testVendor() { // this test verifies the vendor property libinput_device device; device.vendor = 200u; Device d(&device); QCOMPARE(d.vendor(), 200u); QCOMPARE(d.property("vendor").toUInt(), 200u); QCOMPARE(dbusProperty(d.sysName(), "vendor"), 200u); } void TestLibinputDevice::testTapFingerCount() { // this test verifies the tap finger count property libinput_device device; device.tapFingerCount = 3; Device d(&device); QCOMPARE(d.tapFingerCount(), 3); QCOMPARE(d.property("tapFingerCount").toInt(), 3); QCOMPARE(dbusProperty(d.sysName(), "tapFingerCount"), 3); } void TestLibinputDevice::testSize_data() { QTest::addColumn("setSize"); QTest::addColumn("returnValue"); QTest::addColumn("expectedSize"); QTest::newRow("10/20") << QSizeF(10.5, 20.2) << 0 << QSizeF(10.5, 20.2); QTest::newRow("failure") << QSizeF(10, 20) << 1 << QSizeF(); } void TestLibinputDevice::testSize() { // this test verifies that getting the size works correctly including failures QFETCH(QSizeF, setSize); QFETCH(int, returnValue); libinput_device device; device.deviceSize = setSize; device.deviceSizeReturnValue = returnValue; Device d(&device); QTEST(d.size(), "expectedSize"); QTEST(d.property("size").toSizeF(), "expectedSize"); QTEST(dbusProperty(d.sysName(), "size"), "expectedSize"); } void TestLibinputDevice::testLeftHandedEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testLeftHandedEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.leftHandedEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.leftHandedEnabledByDefault(), enabled); QCOMPARE(d.property("leftHandedEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "leftHandedEnabledByDefault"), enabled); } void TestLibinputDevice::testTapEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testTapEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.tapEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.tapToClickEnabledByDefault(), enabled); QCOMPARE(d.property("tapToClickEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "tapToClickEnabledByDefault"), enabled); } void TestLibinputDevice::testMiddleEmulationEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testMiddleEmulationEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.middleEmulationEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.middleEmulationEnabledByDefault(), enabled); QCOMPARE(d.property("middleEmulationEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "middleEmulationEnabledByDefault"), enabled); } void TestLibinputDevice::testNaturalScrollEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testNaturalScrollEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.naturalScrollEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.naturalScrollEnabledByDefault(), enabled); QCOMPARE(d.property("naturalScrollEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "naturalScrollEnabledByDefault"), enabled); } void TestLibinputDevice::testScrollTwoFingerEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testScrollTwoFingerEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.defaultScrollMethod = enabled ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; Device d(&device); QCOMPARE(d.scrollTwoFingerEnabledByDefault(), enabled); QCOMPARE(d.property("scrollTwoFingerEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "scrollTwoFingerEnabledByDefault"), enabled); } void TestLibinputDevice::testScrollEdgeEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testScrollEdgeEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.defaultScrollMethod = enabled ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; Device d(&device); QCOMPARE(d.scrollEdgeEnabledByDefault(), enabled); QCOMPARE(d.property("scrollEdgeEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "scrollEdgeEnabledByDefault"), enabled); } void TestLibinputDevice::testDefaultPointerAccelerationProfileFlat_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testDefaultPointerAccelerationProfileFlat() { QFETCH(bool, enabled); libinput_device device; device.defaultPointerAccelerationProfile = enabled ? LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT : LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; Device d(&device); QCOMPARE(d.defaultPointerAccelerationProfileFlat(), enabled); QCOMPARE(d.property("defaultPointerAccelerationProfileFlat").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "defaultPointerAccelerationProfileFlat"), enabled); } void TestLibinputDevice::testDefaultPointerAccelerationProfileAdaptive_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testDefaultPointerAccelerationProfileAdaptive() { QFETCH(bool, enabled); libinput_device device; device.defaultPointerAccelerationProfile = enabled ? LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE : LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; Device d(&device); QCOMPARE(d.defaultPointerAccelerationProfileAdaptive(), enabled); QCOMPARE(d.property("defaultPointerAccelerationProfileAdaptive").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "defaultPointerAccelerationProfileAdaptive"), enabled); } +void TestLibinputDevice::testDefaultClickMethodAreas_data() +{ + QTest::addColumn("enabled"); + + QTest::addRow("enabled") << true; + QTest::addRow("disabled") << false; +} + +void TestLibinputDevice::testDefaultClickMethodAreas() +{ + QFETCH(bool, enabled); + libinput_device device; + device.defaultClickMethod = enabled ? LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS : LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; + + Device d(&device); + QCOMPARE(d.defaultClickMethodAreas(), enabled); + QCOMPARE(d.property("defaultClickMethodAreas").toBool(), enabled); + QCOMPARE(dbusProperty(d.sysName(), "defaultClickMethodAreas"), enabled); +} + +void TestLibinputDevice::testDefaultClickMethodClickfinger_data() +{ + QTest::addColumn("enabled"); + + QTest::addRow("enabled") << true; + QTest::addRow("disabled") << false; +} + +void TestLibinputDevice::testDefaultClickMethodClickfinger() +{ + QFETCH(bool, enabled); + libinput_device device; + device.defaultClickMethod = enabled ? LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER : LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + + Device d(&device); + QCOMPARE(d.defaultClickMethodClickfinger(), enabled); + QCOMPARE(d.property("defaultClickMethodClickfinger").toBool(), enabled); + QCOMPARE(dbusProperty(d.sysName(), "defaultClickMethodClickfinger"), enabled); +} + void TestLibinputDevice::testScrollOnButtonDownEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testScrollOnButtonDownEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.defaultScrollMethod = enabled ? LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; Device d(&device); QCOMPARE(d.scrollOnButtonDownEnabledByDefault(), enabled); QCOMPARE(d.property("scrollOnButtonDownEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "scrollOnButtonDownEnabledByDefault"), enabled); } void TestLibinputDevice::testDefaultScrollButton_data() { QTest::addColumn("button"); QTest::newRow("0") << 0u; QTest::newRow("BTN_LEFT") << quint32(BTN_LEFT); QTest::newRow("BTN_RIGHT") << quint32(BTN_RIGHT); QTest::newRow("BTN_MIDDLE") << quint32(BTN_MIDDLE); QTest::newRow("BTN_SIDE") << quint32(BTN_SIDE); QTest::newRow("BTN_EXTRA") << quint32(BTN_EXTRA); QTest::newRow("BTN_FORWARD") << quint32(BTN_FORWARD); QTest::newRow("BTN_BACK") << quint32(BTN_BACK); QTest::newRow("BTN_TASK") << quint32(BTN_TASK); } void TestLibinputDevice::testDefaultScrollButton() { libinput_device device; QFETCH(quint32, button); device.defaultScrollButton = button; Device d(&device); QCOMPARE(d.defaultScrollButton(), button); QCOMPARE(d.property("defaultScrollButton").value(), button); QCOMPARE(dbusProperty(d.sysName(), "defaultScrollButton"), button); } void TestLibinputDevice::testSupportsDisableWhileTyping_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsDisableWhileTyping() { QFETCH(bool, enabled); libinput_device device; device.supportsDisableWhileTyping = enabled; Device d(&device); QCOMPARE(d.supportsDisableWhileTyping(), enabled); QCOMPARE(d.property("supportsDisableWhileTyping").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsDisableWhileTyping"), enabled); } void TestLibinputDevice::testSupportsPointerAcceleration_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsPointerAcceleration() { QFETCH(bool, enabled); libinput_device device; device.supportsPointerAcceleration = enabled; Device d(&device); QCOMPARE(d.supportsPointerAcceleration(), enabled); QCOMPARE(d.property("supportsPointerAcceleration").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsPointerAcceleration"), enabled); } void TestLibinputDevice::testSupportsLeftHanded_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsLeftHanded() { QFETCH(bool, enabled); libinput_device device; device.supportsLeftHanded = enabled; Device d(&device); QCOMPARE(d.supportsLeftHanded(), enabled); QCOMPARE(d.property("supportsLeftHanded").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsLeftHanded"), enabled); } void TestLibinputDevice::testSupportsCalibrationMatrix_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsCalibrationMatrix() { QFETCH(bool, enabled); libinput_device device; device.supportsCalibrationMatrix = enabled; Device d(&device); QCOMPARE(d.supportsCalibrationMatrix(), enabled); QCOMPARE(d.property("supportsCalibrationMatrix").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsCalibrationMatrix"), enabled); } void TestLibinputDevice::testSupportsDisableEvents_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsDisableEvents() { QFETCH(bool, enabled); libinput_device device; device.supportsDisableEvents = enabled; Device d(&device); QCOMPARE(d.supportsDisableEvents(), enabled); QCOMPARE(d.property("supportsDisableEvents").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsDisableEvents"), enabled); } void TestLibinputDevice::testSupportsDisableEventsOnExternalMouse_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsDisableEventsOnExternalMouse() { QFETCH(bool, enabled); libinput_device device; device.supportsDisableEventsOnExternalMouse = enabled; Device d(&device); QCOMPARE(d.supportsDisableEventsOnExternalMouse(), enabled); QCOMPARE(d.property("supportsDisableEventsOnExternalMouse").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsDisableEventsOnExternalMouse"), enabled); } void TestLibinputDevice::testSupportsMiddleEmulation_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsMiddleEmulation() { QFETCH(bool, enabled); libinput_device device; device.supportsMiddleEmulation = enabled; Device d(&device); QCOMPARE(d.supportsMiddleEmulation(), enabled); QCOMPARE(d.property("supportsMiddleEmulation").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsMiddleEmulation"), enabled); } void TestLibinputDevice::testSupportsNaturalScroll_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsNaturalScroll() { QFETCH(bool, enabled); libinput_device device; device.supportsNaturalScroll = enabled; Device d(&device); QCOMPARE(d.supportsNaturalScroll(), enabled); QCOMPARE(d.property("supportsNaturalScroll").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsNaturalScroll"), enabled); } void TestLibinputDevice::testSupportsScrollTwoFinger_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsScrollTwoFinger() { QFETCH(bool, enabled); libinput_device device; device.supportedScrollMethods = enabled ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; Device d(&device); QCOMPARE(d.supportsScrollTwoFinger(), enabled); QCOMPARE(d.property("supportsScrollTwoFinger").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsScrollTwoFinger"), enabled); } void TestLibinputDevice::testSupportsScrollEdge_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsScrollEdge() { QFETCH(bool, enabled); libinput_device device; device.supportedScrollMethods = enabled ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; Device d(&device); QCOMPARE(d.supportsScrollEdge(), enabled); QCOMPARE(d.property("supportsScrollEdge").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsScrollEdge"), enabled); } void TestLibinputDevice::testSupportsScrollOnButtonDown_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsScrollOnButtonDown() { QFETCH(bool, enabled); libinput_device device; device.supportedScrollMethods = enabled ? LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; Device d(&device); QCOMPARE(d.supportsScrollOnButtonDown(), enabled); QCOMPARE(d.property("supportsScrollOnButtonDown").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "supportsScrollOnButtonDown"), enabled); } void TestLibinputDevice::testDefaultPointerAcceleration_data() { QTest::addColumn("accel"); QTest::newRow("-1.0") << -1.0; QTest::newRow("-0.5") << -0.5; QTest::newRow("0.0") << 0.0; QTest::newRow("0.3") << 0.3; QTest::newRow("1.0") << 1.0; } void TestLibinputDevice::testDefaultPointerAcceleration() { QFETCH(qreal, accel); libinput_device device; device.defaultPointerAcceleration = accel; Device d(&device); QCOMPARE(d.defaultPointerAcceleration(), accel); QCOMPARE(d.property("defaultPointerAcceleration").toReal(), accel); QCOMPARE(dbusProperty(d.sysName(), "defaultPointerAcceleration"), accel); } void TestLibinputDevice::testPointerAcceleration_data() { QTest::addColumn("supported"); QTest::addColumn("setShouldFail"); QTest::addColumn("accel"); QTest::addColumn("setAccel"); QTest::addColumn("expectedAccel"); QTest::addColumn("expectedChanged"); QTest::newRow("-1 -> 2.0") << true << false << -1.0 << 2.0 << 1.0 << true; QTest::newRow("0 -> -1.0") << true << false << 0.0 << -1.0 << -1.0 << true; QTest::newRow("1 -> 1") << true << false << 1.0 << 1.0 << 1.0 << false; QTest::newRow("unsupported") << false << false << 0.0 << 1.0 << 0.0 << false; QTest::newRow("set fails") << true << true << -1.0 << 1.0 << -1.0 << false; } void TestLibinputDevice::testPointerAcceleration() { QFETCH(bool, supported); QFETCH(bool, setShouldFail); QFETCH(qreal, accel); libinput_device device; device.supportsPointerAcceleration = supported; device.pointerAcceleration = accel; device.setPointerAccelerationReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.pointerAcceleration(), accel); QCOMPARE(d.property("pointerAcceleration").toReal(), accel); QCOMPARE(dbusProperty(d.sysName(), "pointerAcceleration"), accel); QSignalSpy pointerAccelChangedSpy(&d, &Device::pointerAccelerationChanged); QVERIFY(pointerAccelChangedSpy.isValid()); QFETCH(qreal, setAccel); d.setPointerAcceleration(setAccel); QTEST(d.pointerAcceleration(), "expectedAccel"); QTEST(!pointerAccelChangedSpy.isEmpty(), "expectedChanged"); QTEST(dbusProperty(d.sysName(), "pointerAcceleration"), "expectedAccel"); } void TestLibinputDevice::testLeftHanded_data() { QTest::addColumn("supported"); QTest::addColumn("setShouldFail"); QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("expectedValue"); QTest::newRow("unsupported/true") << false << false << true << false << false; QTest::newRow("unsupported/false") << false << false << false << true << false; QTest::newRow("true -> false") << true << false << true << false << false; QTest::newRow("false -> true") << true << false << false << true << true; QTest::newRow("set fails") << true << true << true << false << true; QTest::newRow("true -> true") << true << false << true << true << true; QTest::newRow("false -> false") << true << false << false << false << false; } void TestLibinputDevice::testLeftHanded() { QFETCH(bool, supported); QFETCH(bool, setShouldFail); QFETCH(bool, initValue); libinput_device device; device.supportsLeftHanded = supported; device.leftHanded = initValue; device.setLeftHandedReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isLeftHanded(), supported && initValue); QCOMPARE(d.property("leftHanded").toBool(), supported && initValue); QCOMPARE(dbusProperty(d.sysName(), "leftHanded"), supported && initValue); QSignalSpy leftHandedChangedSpy(&d, &Device::leftHandedChanged); QVERIFY(leftHandedChangedSpy.isValid()); QFETCH(bool, setValue); d.setLeftHanded(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isLeftHanded(), expectedValue); QCOMPARE(leftHandedChangedSpy.isEmpty(), (supported && initValue) == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "leftHanded"), expectedValue); } void TestLibinputDevice::testSupportedButtons_data() { QTest::addColumn("isPointer"); QTest::addColumn("setButtons"); QTest::addColumn("expectedButtons"); QTest::newRow("left") << true << Qt::MouseButtons(Qt::LeftButton) << Qt::MouseButtons(Qt::LeftButton); QTest::newRow("right") << true << Qt::MouseButtons(Qt::RightButton) << Qt::MouseButtons(Qt::RightButton); QTest::newRow("middle") << true << Qt::MouseButtons(Qt::MiddleButton) << Qt::MouseButtons(Qt::MiddleButton); QTest::newRow("extra1") << true << Qt::MouseButtons(Qt::ExtraButton1) << Qt::MouseButtons(Qt::ExtraButton1); QTest::newRow("extra2") << true << Qt::MouseButtons(Qt::ExtraButton2) << Qt::MouseButtons(Qt::ExtraButton2); QTest::newRow("back") << true << Qt::MouseButtons(Qt::BackButton) << Qt::MouseButtons(Qt::BackButton); QTest::newRow("forward") << true << Qt::MouseButtons(Qt::ForwardButton) << Qt::MouseButtons(Qt::ForwardButton); QTest::newRow("task") << true << Qt::MouseButtons(Qt::TaskButton) << Qt::MouseButtons(Qt::TaskButton); QTest::newRow("no pointer/left") << false << Qt::MouseButtons(Qt::LeftButton) << Qt::MouseButtons(); QTest::newRow("no pointer/right") << false << Qt::MouseButtons(Qt::RightButton) << Qt::MouseButtons(); QTest::newRow("no pointer/middle") << false << Qt::MouseButtons(Qt::MiddleButton) << Qt::MouseButtons(); QTest::newRow("no pointer/extra1") << false << Qt::MouseButtons(Qt::ExtraButton1) << Qt::MouseButtons(); QTest::newRow("no pointer/extra2") << false << Qt::MouseButtons(Qt::ExtraButton2) << Qt::MouseButtons(); QTest::newRow("no pointer/back") << false << Qt::MouseButtons(Qt::BackButton) << Qt::MouseButtons(); QTest::newRow("no pointer/forward") << false << Qt::MouseButtons(Qt::ForwardButton) << Qt::MouseButtons(); QTest::newRow("no pointer/task") << false << Qt::MouseButtons(Qt::TaskButton) << Qt::MouseButtons(); QTest::newRow("all") << true << Qt::MouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton | Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::BackButton | Qt::ForwardButton | Qt::TaskButton) << Qt::MouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton | Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::BackButton | Qt::ForwardButton | Qt::TaskButton); } void TestLibinputDevice::testSupportedButtons() { libinput_device device; QFETCH(bool, isPointer); device.pointer = isPointer; QFETCH(Qt::MouseButtons, setButtons); device.supportedButtons = setButtons; Device d(&device); QCOMPARE(d.isPointer(), isPointer); QTEST(d.supportedButtons(), "expectedButtons"); QTEST(Qt::MouseButtons(dbusProperty(d.sysName(), "supportedButtons")), "expectedButtons"); } void TestLibinputDevice::testAlphaNumericKeyboard_data() { QTest::addColumn>("supportedKeys"); QTest::addColumn("isAlpha"); QVector keys; for (int i = KEY_1; i <= KEY_0; i++) { keys << i; QByteArray row = QByteArrayLiteral("number"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } for (int i = KEY_Q; i <= KEY_P; i++) { keys << i; QByteArray row = QByteArrayLiteral("alpha"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } for (int i = KEY_A; i <= KEY_L; i++) { keys << i; QByteArray row = QByteArrayLiteral("alpha"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } for (int i = KEY_Z; i < KEY_M; i++) { keys << i; QByteArray row = QByteArrayLiteral("alpha"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } // adding a different key should not result in it becoming alphanumeric keyboard keys << KEY_SEMICOLON; QTest::newRow("semicolon") << keys << false; // last but not least the M which should turn everything on keys << KEY_M; QTest::newRow("alphanumeric") << keys << true; } void TestLibinputDevice::testAlphaNumericKeyboard() { QFETCH(QVector, supportedKeys); libinput_device device; device.keyboard = true; device.keys = supportedKeys; Device d(&device); QCOMPARE(d.isKeyboard(), true); QTEST(d.isAlphaNumericKeyboard(), "isAlpha"); QTEST(dbusProperty(d.sysName(), "alphaNumericKeyboard"), "isAlpha"); } void TestLibinputDevice::testEnabled_data() { QTest::addColumn("supported"); QTest::addColumn("setShouldFail"); QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("expectedValue"); QTest::newRow("unsupported/true") << false << false << true << false << true; QTest::newRow("unsupported/false") << false << false << false << true << true; QTest::newRow("true -> false") << true << false << true << false << false; QTest::newRow("false -> true") << true << false << false << true << true; QTest::newRow("set fails") << true << true << true << false << true; QTest::newRow("true -> true") << true << false << true << true << true; QTest::newRow("false -> false") << true << false << false << false << false; } void TestLibinputDevice::testEnabled() { libinput_device device; QFETCH(bool, supported); QFETCH(bool, setShouldFail); QFETCH(bool, initValue); device.supportsDisableEvents = supported; device.enabled = initValue; device.setEnableModeReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isEnabled(), !supported || initValue); QCOMPARE(d.property("enabled").toBool(), !supported || initValue); QCOMPARE(dbusProperty(d.sysName(), "enabled"), !supported || initValue); QSignalSpy enabledChangedSpy(&d, &Device::enabledChanged); QVERIFY(enabledChangedSpy.isValid()); QFETCH(bool, setValue); d.setEnabled(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isEnabled(), expectedValue); QCOMPARE(dbusProperty(d.sysName(), "enabled"), expectedValue); } void TestLibinputDevice::testTapToClick_data() { QTest::addColumn("fingerCount"); QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::newRow("unsupported") << 0 << false << true << true << false; QTest::newRow("true -> false") << 1 << true << false << false << false; QTest::newRow("false -> true") << 2 << false << true << false << true; QTest::newRow("set fails") << 3 << true << false << true << true; QTest::newRow("true -> true") << 2 << true << true << false << true; QTest::newRow("false -> false") << 1 << false << false << false << false; } void TestLibinputDevice::testTapToClick() { libinput_device device; QFETCH(int, fingerCount); QFETCH(bool, initValue); QFETCH(bool, setShouldFail); device.tapFingerCount = fingerCount; device.tapToClick = initValue; device.setTapToClickReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.tapFingerCount(), fingerCount); QCOMPARE(d.isTapToClick(), initValue); QCOMPARE(d.property("tapToClick").toBool(), initValue); QCOMPARE(dbusProperty(d.sysName(), "tapToClick"), initValue); QSignalSpy tapToClickChangedSpy(&d, &Device::tapToClickChanged); QVERIFY(tapToClickChangedSpy.isValid()); QFETCH(bool, setValue); d.setTapToClick(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isTapToClick(), expectedValue); QCOMPARE(tapToClickChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "tapToClick"), expectedValue); } void TestLibinputDevice::testTapAndDragEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testTapAndDragEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.tapAndDragEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.tapAndDragEnabledByDefault(), enabled); QCOMPARE(d.property("tapAndDragEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "tapAndDragEnabledByDefault"), enabled); } void TestLibinputDevice::testTapAndDrag_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::newRow("true -> false") << true << false << false << false; QTest::newRow("false -> true") << false << true << false << true; QTest::newRow("set fails") << true << false << true << true; QTest::newRow("true -> true") << true << true << false << true; QTest::newRow("false -> false") << false << false << false << false; } void TestLibinputDevice::testTapAndDrag() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, setShouldFail); device.tapAndDrag = initValue; device.setTapAndDragReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isTapAndDrag(), initValue); QCOMPARE(d.property("tapAndDrag").toBool(), initValue); QCOMPARE(dbusProperty(d.sysName(), "tapAndDrag"), initValue); QSignalSpy tapAndDragChangedSpy(&d, &Device::tapAndDragChanged); QVERIFY(tapAndDragChangedSpy.isValid()); QFETCH(bool, setValue); d.setTapAndDrag(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isTapAndDrag(), expectedValue); QCOMPARE(tapAndDragChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "tapAndDrag"), expectedValue); } void TestLibinputDevice::testTapDragLockEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testTapDragLockEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.tapDragLockEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.tapDragLockEnabledByDefault(), enabled); QCOMPARE(d.property("tapDragLockEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "tapDragLockEnabledByDefault"), enabled); } void TestLibinputDevice::testTapDragLock_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::newRow("true -> false") << true << false << false << false; QTest::newRow("false -> true") << false << true << false << true; QTest::newRow("set fails") << true << false << true << true; QTest::newRow("true -> true") << true << true << false << true; QTest::newRow("false -> false") << false << false << false << false; } void TestLibinputDevice::testTapDragLock() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, setShouldFail); device.tapDragLock = initValue; device.setTapDragLockReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isTapDragLock(), initValue); QCOMPARE(d.property("tapDragLock").toBool(), initValue); QCOMPARE(dbusProperty(d.sysName(), "tapDragLock"), initValue); QSignalSpy tapDragLockChangedSpy(&d, &Device::tapDragLockChanged); QVERIFY(tapDragLockChangedSpy.isValid()); QFETCH(bool, setValue); d.setTapDragLock(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isTapDragLock(), expectedValue); QCOMPARE(tapDragLockChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "tapDragLock"), expectedValue); } void TestLibinputDevice::testMiddleEmulation_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("supportsMiddleButton"); QTest::newRow("true -> false") << true << false << false << false << true; QTest::newRow("false -> true") << false << true << false << true << true; QTest::newRow("set fails") << true << false << true << true << true; QTest::newRow("true -> true") << true << true << false << true << true; QTest::newRow("false -> false") << false << false << false << false << true; QTest::newRow("false -> true, unsupported") << false << true << true << false << false; } void TestLibinputDevice::testMiddleEmulation() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, setShouldFail); QFETCH(bool, supportsMiddleButton); device.supportsMiddleEmulation = supportsMiddleButton; device.middleEmulation = initValue; device.setMiddleEmulationReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isMiddleEmulation(), initValue); QCOMPARE(d.property("middleEmulation").toBool(), initValue); QCOMPARE(dbusProperty(d.sysName(), "middleEmulation"), initValue); QSignalSpy middleEmulationChangedSpy(&d, &Device::middleEmulationChanged); QVERIFY(middleEmulationChangedSpy.isValid()); QFETCH(bool, setValue); d.setMiddleEmulation(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isMiddleEmulation(), expectedValue); QCOMPARE(d.property("middleEmulation").toBool(), expectedValue); QCOMPARE(middleEmulationChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "middleEmulation"), expectedValue); } void TestLibinputDevice::testNaturalScroll_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("supportsNaturalScroll"); QTest::newRow("true -> false") << true << false << false << false << true; QTest::newRow("false -> true") << false << true << false << true << true; QTest::newRow("set fails") << true << false << true << true << true; QTest::newRow("true -> true") << true << true << false << true << true; QTest::newRow("false -> false") << false << false << false << false << true; QTest::newRow("false -> true, unsupported") << false << true << true << false << false; } void TestLibinputDevice::testNaturalScroll() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, setShouldFail); QFETCH(bool, supportsNaturalScroll); device.supportsNaturalScroll = supportsNaturalScroll; device.naturalScroll = initValue; device.setNaturalScrollReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isNaturalScroll(), initValue); QCOMPARE(d.property("naturalScroll").toBool(), initValue); QCOMPARE(dbusProperty(d.sysName(), "naturalScroll"), initValue); QSignalSpy naturalScrollChangedSpy(&d, &Device::naturalScrollChanged); QVERIFY(naturalScrollChangedSpy.isValid()); QFETCH(bool, setValue); d.setNaturalScroll(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isNaturalScroll(), expectedValue); QCOMPARE(d.property("naturalScroll").toBool(), expectedValue); QCOMPARE(naturalScrollChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "naturalScroll"), expectedValue); } void TestLibinputDevice::testScrollTwoFinger_data() { QTest::addColumn("initValue"); QTest::addColumn("otherValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("supportsScrollTwoFinger"); QTest::newRow("true -> false") << true << false << false << false << false << true; QTest::newRow("other -> false") << false << true << false << false << false << true; QTest::newRow("false -> true") << false << false << true << false << true << true; QTest::newRow("set fails") << true << false << false << true << true << true; QTest::newRow("true -> true") << true << false << true << false << true << true; QTest::newRow("false -> false") << false << false << false << false << false << true; QTest::newRow("false -> true, unsupported") << false << false << true << true << false << false; } void TestLibinputDevice::testScrollTwoFinger() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, otherValue); QFETCH(bool, setShouldFail); QFETCH(bool, supportsScrollTwoFinger); device.supportedScrollMethods = (supportsScrollTwoFinger ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL) | LIBINPUT_CONFIG_SCROLL_EDGE; device.scrollMethod = initValue ? LIBINPUT_CONFIG_SCROLL_2FG : otherValue ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; device.setScrollMethodReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isScrollTwoFinger(), initValue); QCOMPARE(d.property("scrollTwoFinger").toBool(), initValue); QCOMPARE(d.property("scrollEdge").toBool(), otherValue); QCOMPARE(dbusProperty(d.sysName(), "scrollTwoFinger"), initValue); QCOMPARE(dbusProperty(d.sysName(), "scrollEdge"), otherValue); QSignalSpy scrollMethodChangedSpy(&d, &Device::scrollMethodChanged); QVERIFY(scrollMethodChangedSpy.isValid()); QFETCH(bool, setValue); d.setScrollTwoFinger(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isScrollTwoFinger(), expectedValue); QCOMPARE(d.property("scrollTwoFinger").toBool(), expectedValue); QCOMPARE(scrollMethodChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "scrollTwoFinger"), expectedValue); } void TestLibinputDevice::testScrollEdge_data() { QTest::addColumn("initValue"); QTest::addColumn("otherValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("supportsScrollEdge"); QTest::newRow("true -> false") << true << false << false << false << false << true; QTest::newRow("other -> false") << false << true << false << false << false << true; QTest::newRow("false -> true") << false << false << true << false << true << true; QTest::newRow("set fails") << true << false << false << true << true << true; QTest::newRow("true -> true") << true << false << true << false << true << true; QTest::newRow("false -> false") << false << false << false << false << false << true; QTest::newRow("false -> true, unsupported") << false << false << true << true << false << false; } void TestLibinputDevice::testScrollEdge() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, otherValue); QFETCH(bool, setShouldFail); QFETCH(bool, supportsScrollEdge); device.supportedScrollMethods = (supportsScrollEdge ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL) | LIBINPUT_CONFIG_SCROLL_2FG; device.scrollMethod = initValue ? LIBINPUT_CONFIG_SCROLL_EDGE : otherValue ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; device.setScrollMethodReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isScrollEdge(), initValue); QCOMPARE(d.property("scrollEdge").toBool(), initValue); QCOMPARE(d.property("scrollTwoFinger").toBool(), otherValue); QCOMPARE(dbusProperty(d.sysName(), "scrollEdge"), initValue); QCOMPARE(dbusProperty(d.sysName(), "scrollTwoFinger"), otherValue); QSignalSpy scrollMethodChangedSpy(&d, &Device::scrollMethodChanged); QVERIFY(scrollMethodChangedSpy.isValid()); QFETCH(bool, setValue); d.setScrollEdge(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isScrollEdge(), expectedValue); QCOMPARE(d.property("scrollEdge").toBool(), expectedValue); QCOMPARE(scrollMethodChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "scrollEdge"), expectedValue); } void TestLibinputDevice::testScrollButtonDown_data() { QTest::addColumn("initValue"); QTest::addColumn("otherValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("supportsScrollButtonDown"); QTest::newRow("true -> false") << true << false << false << false << false << true; QTest::newRow("other -> false") << false << true << false << false << false << true; QTest::newRow("false -> true") << false << false << true << false << true << true; QTest::newRow("set fails") << true << false << false << true << true << true; QTest::newRow("true -> true") << true << false << true << false << true << true; QTest::newRow("false -> false") << false << false << false << false << false << true; QTest::newRow("false -> true, unsupported") << false << false << true << true << false << false; } void TestLibinputDevice::testScrollButtonDown() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, otherValue); QFETCH(bool, setShouldFail); QFETCH(bool, supportsScrollButtonDown); device.supportedScrollMethods = (supportsScrollButtonDown ? LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN : LIBINPUT_CONFIG_SCROLL_NO_SCROLL) | LIBINPUT_CONFIG_SCROLL_2FG; device.scrollMethod = initValue ? LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN : otherValue ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; device.setScrollMethodReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isScrollOnButtonDown(), initValue); QCOMPARE(d.property("scrollOnButtonDown").toBool(), initValue); QCOMPARE(d.property("scrollTwoFinger").toBool(), otherValue); QCOMPARE(dbusProperty(d.sysName(), "scrollOnButtonDown"), initValue); QCOMPARE(dbusProperty(d.sysName(), "scrollTwoFinger"), otherValue); QSignalSpy scrollMethodChangedSpy(&d, &Device::scrollMethodChanged); QVERIFY(scrollMethodChangedSpy.isValid()); QFETCH(bool, setValue); d.setScrollOnButtonDown(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isScrollOnButtonDown(), expectedValue); QCOMPARE(d.property("scrollOnButtonDown").toBool(), expectedValue); QCOMPARE(scrollMethodChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "scrollOnButtonDown"), expectedValue); } void TestLibinputDevice::testScrollButton_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("expectedValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("scrollOnButton"); QTest::newRow("BTN_LEFT -> BTN_RIGHT") << quint32(BTN_LEFT) << quint32(BTN_RIGHT) << quint32(BTN_RIGHT) << false << true; QTest::newRow("BTN_LEFT -> BTN_LEFT") << quint32(BTN_LEFT) << quint32(BTN_LEFT) << quint32(BTN_LEFT) << false << true; QTest::newRow("set should fail") << quint32(BTN_LEFT) << quint32(BTN_RIGHT) << quint32(BTN_LEFT) << true << true; QTest::newRow("not scroll on button") << quint32(BTN_LEFT) << quint32(BTN_RIGHT) << quint32(BTN_LEFT) << false << false; } void TestLibinputDevice::testScrollButton() { libinput_device device; QFETCH(quint32, initValue); QFETCH(bool, setShouldFail); QFETCH(bool, scrollOnButton); device.scrollButton = initValue; device.supportedScrollMethods = scrollOnButton ? LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; device.setScrollButtonReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.scrollButton(), initValue); QCOMPARE(d.property("scrollButton").value(), initValue); QCOMPARE(dbusProperty(d.sysName(), "scrollButton"), initValue); QSignalSpy scrollButtonChangedSpy(&d, &Device::scrollButtonChanged); QVERIFY(scrollButtonChangedSpy.isValid()); QFETCH(quint32, setValue); d.setScrollButton(setValue); QFETCH(quint32, expectedValue); QCOMPARE(d.scrollButton(), expectedValue); QCOMPARE(d.property("scrollButton").value(), expectedValue); QCOMPARE(scrollButtonChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "scrollButton"), expectedValue); } void TestLibinputDevice::testDisableWhileTypingEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testDisableWhileTypingEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.disableWhileTypingEnabledByDefault = enabled ? LIBINPUT_CONFIG_DWT_ENABLED : LIBINPUT_CONFIG_DWT_DISABLED; Device d(&device); QCOMPARE(d.disableWhileTypingEnabledByDefault(), enabled); QCOMPARE(d.property("disableWhileTypingEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "disableWhileTypingEnabledByDefault"), enabled); } void TestLibinputDevice::testLmrTapButtonMapEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testLmrTapButtonMapEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.defaultTapButtonMap = enabled ? LIBINPUT_CONFIG_TAP_MAP_LMR : LIBINPUT_CONFIG_TAP_MAP_LRM; Device d(&device); QCOMPARE(d.lmrTapButtonMapEnabledByDefault(), enabled); QCOMPARE(d.property("lmrTapButtonMapEnabledByDefault").toBool(), enabled); QCOMPARE(dbusProperty(d.sysName(), "lmrTapButtonMapEnabledByDefault"), enabled); } void TestLibinputDevice::testLmrTapButtonMap_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("fingerCount"); QTest::newRow("true -> false") << true << false << false << false << 3; QTest::newRow("false -> true") << false << true << false << true << 3; QTest::newRow("true -> false") << true << false << false << false << 2; QTest::newRow("false -> true") << false << true << false << true << 2; QTest::newRow("set fails") << true << false << true << true << 3; QTest::newRow("true -> true") << true << true << false << true << 3; QTest::newRow("false -> false") << false << false << false << false << 3; QTest::newRow("true -> true") << true << true << false << true << 2; QTest::newRow("false -> false") << false << false << false << false << 2; QTest::newRow("false -> true, fingerCount 0") << false << true << true << false << 0; // TODO: is this a fail in libinput? //QTest::newRow("false -> true, fingerCount 1") << false << true << true << false << 1; } void TestLibinputDevice::testLmrTapButtonMap() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, setShouldFail); QFETCH(int, fingerCount); device.tapFingerCount = fingerCount; device.tapButtonMap = initValue ? LIBINPUT_CONFIG_TAP_MAP_LMR : LIBINPUT_CONFIG_TAP_MAP_LRM; device.setTapButtonMapReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.lmrTapButtonMap(), initValue); QCOMPARE(d.property("lmrTapButtonMap").toBool(), initValue); QSignalSpy tapButtonMapChangedSpy(&d, &Device::tapButtonMapChanged); QVERIFY(tapButtonMapChangedSpy.isValid()); QFETCH(bool, setValue); d.setLmrTapButtonMap(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.lmrTapButtonMap(), expectedValue); QCOMPARE(d.property("lmrTapButtonMap").toBool(), expectedValue); QCOMPARE(tapButtonMapChangedSpy.isEmpty(), initValue == expectedValue); } void TestLibinputDevice::testDisableWhileTyping_data() { QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("setShouldFail"); QTest::addColumn("expectedValue"); QTest::addColumn("supportsDisableWhileTyping"); QTest::newRow("true -> false") << true << false << false << false << true; QTest::newRow("false -> true") << false << true << false << true << true; QTest::newRow("set fails") << true << false << true << true << true; QTest::newRow("true -> true") << true << true << false << true << true; QTest::newRow("false -> false") << false << false << false << false << true; QTest::newRow("false -> true, unsupported") << false << true << true << false << false; } void TestLibinputDevice::testDisableWhileTyping() { libinput_device device; QFETCH(bool, initValue); QFETCH(bool, setShouldFail); QFETCH(bool, supportsDisableWhileTyping); device.supportsDisableWhileTyping = supportsDisableWhileTyping; device.disableWhileTyping = initValue ? LIBINPUT_CONFIG_DWT_ENABLED : LIBINPUT_CONFIG_DWT_DISABLED; device.setDisableWhileTypingReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isDisableWhileTyping(), initValue); QCOMPARE(d.property("disableWhileTyping").toBool(), initValue); QCOMPARE(dbusProperty(d.sysName(), "disableWhileTyping"), initValue); QSignalSpy disableWhileTypingChangedSpy(&d, &Device::disableWhileTypingChanged); QVERIFY(disableWhileTypingChangedSpy.isValid()); QFETCH(bool, setValue); d.setDisableWhileTyping(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isDisableWhileTyping(), expectedValue); QCOMPARE(d.property("disableWhileTyping").toBool(), expectedValue); QCOMPARE(disableWhileTypingChangedSpy.isEmpty(), initValue == expectedValue); QCOMPARE(dbusProperty(d.sysName(), "disableWhileTyping"), 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::testLoadPointerAcceleration_data() { QTest::addColumn("initValue"); QTest::addColumn("configValue"); QTest::newRow("-0.2 -> 0.9") << -0.2 << 0.9; QTest::newRow("0.0 -> -1.0") << 0.0 << -1.0; QTest::newRow("0.123 -> -0.456") << 0.123 << -0.456; QTest::newRow("0.7 -> 0.7") << 0.7 << 0.7; } void TestLibinputDevice::testLoadPointerAcceleration() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup inputConfig(config, QStringLiteral("Test")); QFETCH(qreal, configValue); QFETCH(qreal, initValue); inputConfig.writeEntry("PointerAcceleration", configValue); libinput_device device; device.supportsPointerAcceleration = true; device.pointerAcceleration = initValue; device.setPointerAccelerationReturnValue = false; Device d(&device); QCOMPARE(d.pointerAcceleration(), initValue); QCOMPARE(d.property("pointerAcceleration").toReal(), initValue); // no config group set, should not change d.loadConfiguration(); QCOMPARE(d.pointerAcceleration(), initValue); QCOMPARE(d.property("pointerAcceleration").toReal(), initValue); // set the group d.setConfig(inputConfig); d.loadConfiguration(); QCOMPARE(d.pointerAcceleration(), configValue); QCOMPARE(d.property("pointerAcceleration").toReal(), configValue); // and try to store if (configValue != initValue) { d.setPointerAcceleration(initValue); QCOMPARE(inputConfig.readEntry("PointerAcceleration", configValue), initValue); } } void TestLibinputDevice::testLoadPointerAccelerationProfile_data() { QTest::addColumn("initValue"); QTest::addColumn("initValuePropNameString"); QTest::addColumn("configValue"); QTest::addColumn("configValuePropNameString"); QTest::newRow("pointerAccelerationProfileFlat -> pointerAccelerationProfileAdaptive") << (quint32) LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT << "pointerAccelerationProfileFlat" << (quint32) LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE << "pointerAccelerationProfileAdaptive"; QTest::newRow("pointerAccelerationProfileAdaptive -> pointerAccelerationProfileFlat") << (quint32) LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE << "pointerAccelerationProfileAdaptive" << (quint32) LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT << "pointerAccelerationProfileFlat"; QTest::newRow("pointerAccelerationProfileAdaptive -> pointerAccelerationProfileAdaptive") << (quint32) LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE << "pointerAccelerationProfileAdaptive" << (quint32) LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE << "pointerAccelerationProfileAdaptive"; } void TestLibinputDevice::testLoadPointerAccelerationProfile() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup inputConfig(config, QStringLiteral("Test")); QFETCH(quint32, initValue); QFETCH(quint32, configValue); QFETCH(QString, initValuePropNameString); QFETCH(QString, configValuePropNameString); QByteArray initValuePropName = initValuePropNameString.toLatin1(); QByteArray configValuePropName = configValuePropNameString.toLatin1(); inputConfig.writeEntry("PointerAccelerationProfile", configValue); libinput_device device; device.supportedPointerAccelerationProfiles = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT | LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; device.pointerAccelerationProfile = (libinput_config_accel_profile) initValue; device.setPointerAccelerationProfileReturnValue = false; Device d(&device); QCOMPARE(d.property(initValuePropName).toBool(), true); QCOMPARE(d.property(configValuePropName).toBool(), initValue == configValue); // no config group set, should not change d.loadConfiguration(); QCOMPARE(d.property(initValuePropName).toBool(), true); QCOMPARE(d.property(configValuePropName).toBool(), initValue == configValue); // set the group d.setConfig(inputConfig); d.loadConfiguration(); QCOMPARE(d.property(initValuePropName).toBool(), initValue == configValue); QCOMPARE(d.property(configValuePropName).toBool(), true); QCOMPARE(dbusProperty(d.sysName(), initValuePropName), initValue == configValue); QCOMPARE(dbusProperty(d.sysName(), configValuePropName), true); // and try to store if (configValue != initValue) { d.setProperty(initValuePropName, true); QCOMPARE(inputConfig.readEntry("PointerAccelerationProfile", configValue), initValue); } } +void TestLibinputDevice::testLoadClickMethod_data() +{ + QTest::addColumn("initValue"); + QTest::addColumn("initValuePropNameString"); + QTest::addColumn("configValue"); + QTest::addColumn("configValuePropNameString"); + + QTest::newRow("clickMethodAreas -> clickMethodClickfinger") + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) << "clickMethodAreas" + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) << "clickMethodClickfinger"; + QTest::newRow("clickMethodClickfinger -> clickMethodAreas") + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) << "clickMethodClickfinger" + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) << "clickMethodAreas"; + QTest::newRow("clickMethodAreas -> clickMethodAreas") + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) << "clickMethodAreas" + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) << "clickMethodAreas"; + QTest::newRow("clickMethodClickfinger -> clickMethodClickfinger") + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) << "clickMethodClickfinger" + << static_cast(LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) << "clickMethodClickfinger"; +} + +void TestLibinputDevice::testLoadClickMethod() +{ + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + KConfigGroup inputConfig(config, QStringLiteral("Test")); + QFETCH(quint32, initValue); + QFETCH(quint32, configValue); + QFETCH(QString, initValuePropNameString); + QFETCH(QString, configValuePropNameString); + + QByteArray initValuePropName = initValuePropNameString.toLatin1(); + QByteArray configValuePropName = configValuePropNameString.toLatin1(); + + inputConfig.writeEntry("ClickMethod", configValue); + + libinput_device device; + device.supportedClickMethods = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS | LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; + device.clickMethod = (libinput_config_click_method) initValue; + device.setClickMethodReturnValue = false; + + Device d(&device); + QCOMPARE(d.property(initValuePropName).toBool(), true); + QCOMPARE(d.property(configValuePropName).toBool(), initValue == configValue); + // no config group set, should not change + d.loadConfiguration(); + QCOMPARE(d.property(initValuePropName).toBool(), true); + QCOMPARE(d.property(configValuePropName).toBool(), initValue == configValue); + + // set the group + d.setConfig(inputConfig); + d.loadConfiguration(); + QCOMPARE(d.property(initValuePropName).toBool(), initValue == configValue); + QCOMPARE(d.property(configValuePropName).toBool(), true); + QCOMPARE(dbusProperty(d.sysName(), initValuePropName), initValue == configValue); + QCOMPARE(dbusProperty(d.sysName(), configValuePropName), true); + + // and try to store + if (configValue != initValue) { + d.setProperty(initValuePropName, true); + QCOMPARE(inputConfig.readEntry("ClickMethod", 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::testLoadScrollMethod_data() { QTest::addColumn("initValue"); QTest::addColumn("initValuePropNameString"); QTest::addColumn("configValue"); QTest::addColumn("configValuePropNameString"); QTest::newRow("scrollTwoFinger -> scrollEdge") << (quint32) LIBINPUT_CONFIG_SCROLL_2FG << "scrollTwoFinger" << (quint32) LIBINPUT_CONFIG_SCROLL_EDGE << "scrollEdge"; QTest::newRow("scrollOnButtonDown -> scrollTwoFinger") << (quint32) LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN << "scrollOnButtonDown" << (quint32) LIBINPUT_CONFIG_SCROLL_2FG << "scrollTwoFinger"; QTest::newRow("scrollEdge -> scrollEdge") << (quint32) LIBINPUT_CONFIG_SCROLL_EDGE << "scrollEdge" << (quint32) LIBINPUT_CONFIG_SCROLL_EDGE << "scrollEdge"; } void TestLibinputDevice::testLoadScrollMethod() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup inputConfig(config, QStringLiteral("Test")); QFETCH(quint32, initValue); QFETCH(quint32, configValue); QFETCH(QString, initValuePropNameString); QFETCH(QString, configValuePropNameString); QByteArray initValuePropName = initValuePropNameString.toLatin1(); QByteArray configValuePropName = configValuePropNameString.toLatin1(); inputConfig.writeEntry("ScrollMethod", configValue); libinput_device device; device.supportedScrollMethods = LIBINPUT_CONFIG_SCROLL_2FG | LIBINPUT_CONFIG_SCROLL_EDGE | LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; device.scrollMethod = (libinput_config_scroll_method) initValue; device.setScrollMethodReturnValue = false; Device d(&device); QCOMPARE(d.property(initValuePropName).toBool(), true); QCOMPARE(d.property(configValuePropName).toBool(), initValue == configValue); // no config group set, should not change d.loadConfiguration(); QCOMPARE(d.property(initValuePropName).toBool(), true); QCOMPARE(d.property(configValuePropName).toBool(), initValue == configValue); // set the group d.setConfig(inputConfig); d.loadConfiguration(); QCOMPARE(d.property(initValuePropName).toBool(), initValue == configValue); QCOMPARE(d.property(configValuePropName).toBool(), true); // and try to store if (configValue != initValue) { d.setProperty(initValuePropName, true); QCOMPARE(inputConfig.readEntry("ScrollMethod", 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); } } void TestLibinputDevice::testLoadLeftHanded_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::testLoadLeftHanded() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup inputConfig(config, QStringLiteral("Test")); QFETCH(bool, configValue); QFETCH(bool, initValue); inputConfig.writeEntry("LeftHanded", configValue); libinput_device device; device.supportsLeftHanded = true; device.leftHanded = initValue; device.setLeftHandedReturnValue = false; Device d(&device); QCOMPARE(d.isLeftHanded(), initValue); // no config group set, should not change d.loadConfiguration(); QCOMPARE(d.isLeftHanded(), initValue); // set the group d.setConfig(inputConfig); d.loadConfiguration(); QCOMPARE(d.isLeftHanded(), configValue); // and try to store if (configValue != initValue) { d.setLeftHanded(initValue); QCOMPARE(inputConfig.readEntry("LeftHanded", configValue), initValue); } } void TestLibinputDevice::testLoadDisableWhileTyping_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::testLoadDisableWhileTyping() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup inputConfig(config, QStringLiteral("Test")); QFETCH(bool, configValue); QFETCH(bool, initValue); inputConfig.writeEntry("DisableWhileTyping", configValue); libinput_device device; device.supportsDisableWhileTyping = true; device.disableWhileTyping = initValue ? LIBINPUT_CONFIG_DWT_ENABLED : LIBINPUT_CONFIG_DWT_DISABLED; device.setDisableWhileTypingReturnValue = false; Device d(&device); QCOMPARE(d.isDisableWhileTyping(), initValue); // no config group set, should not change d.loadConfiguration(); QCOMPARE(d.isDisableWhileTyping(), initValue); // set the group d.setConfig(inputConfig); d.loadConfiguration(); QCOMPARE(d.isDisableWhileTyping(), configValue); // and try to store if (configValue != initValue) { d.setDisableWhileTyping(initValue); QCOMPARE(inputConfig.readEntry("DisableWhileTyping", configValue), initValue); } } void TestLibinputDevice::testLoadLmrTapButtonMap_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::testLoadLmrTapButtonMap() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup inputConfig(config, QStringLiteral("Test")); QFETCH(bool, configValue); QFETCH(bool, initValue); inputConfig.writeEntry("LmrTapButtonMap", configValue); libinput_device device; device.tapFingerCount = 3; device.tapButtonMap = initValue ? LIBINPUT_CONFIG_TAP_MAP_LMR : LIBINPUT_CONFIG_TAP_MAP_LRM; device.setTapButtonMapReturnValue = false; Device d(&device); QCOMPARE(d.lmrTapButtonMap(), initValue); // no config group set, should not change d.loadConfiguration(); QCOMPARE(d.lmrTapButtonMap(), initValue); QCOMPARE(dbusProperty(d.sysName(), "lmrTapButtonMap"), initValue); // set the group d.setConfig(inputConfig); d.loadConfiguration(); QCOMPARE(d.lmrTapButtonMap(), configValue); QCOMPARE(dbusProperty(d.sysName(), "lmrTapButtonMap"), configValue); // and try to store if (configValue != initValue) { d.setLmrTapButtonMap(initValue); QCOMPARE(inputConfig.readEntry("LmrTapButtonMap", configValue), initValue); } } void TestLibinputDevice::testScreenId() { libinput_device device; Device d(&device); QCOMPARE(d.screenId(), 0); d.setScreenId(1); QCOMPARE(d.screenId(), 1); } void TestLibinputDevice::testOrientation_data() { QTest::addColumn("orientation"); QTest::addColumn("m11"); QTest::addColumn("m12"); QTest::addColumn("m13"); QTest::addColumn("m21"); QTest::addColumn("m22"); QTest::addColumn("m23"); QTest::addColumn("defaultIsIdentity"); QTest::newRow("Primary") << Qt::PrimaryOrientation << 1.0f << 2.0f << 3.0f << 4.0f << 5.0f << 6.0f << false; QTest::newRow("Landscape") << Qt::LandscapeOrientation << 1.0f << 2.0f << 3.0f << 4.0f << 5.0f << 6.0f << false; QTest::newRow("Portrait") << Qt::PortraitOrientation << 0.0f << -1.0f << 1.0f << 1.0f << 0.0f << 0.0f << true; QTest::newRow("InvertedLandscape") << Qt::InvertedLandscapeOrientation << -1.0f << 0.0f << 1.0f << 0.0f << -1.0f << 1.0f << true; QTest::newRow("InvertedPortrait") << Qt::InvertedPortraitOrientation << 0.0f << 1.0f << 0.0f << -1.0f << 0.0f << 1.0f << true; } void TestLibinputDevice::testOrientation() { libinput_device device; device.supportsCalibrationMatrix = true; device.defaultCalibrationMatrix = std::array{{1.0, 2.0, 3.0, 4.0, 5.0, 6.0}}; QFETCH(bool, defaultIsIdentity); device.defaultCalibrationMatrixIsIdentity = defaultIsIdentity; Device d(&device); QFETCH(Qt::ScreenOrientation, orientation); d.setOrientation(orientation); QTEST(device.calibrationMatrix[0], "m11"); QTEST(device.calibrationMatrix[1], "m12"); QTEST(device.calibrationMatrix[2], "m13"); QTEST(device.calibrationMatrix[3], "m21"); QTEST(device.calibrationMatrix[4], "m22"); QTEST(device.calibrationMatrix[5], "m23"); } void TestLibinputDevice::testCalibrationWithDefault() { libinput_device device; device.supportsCalibrationMatrix = true; device.defaultCalibrationMatrix = std::array{{2.0, 3.0, 0.0, 4.0, 5.0, 0.0}}; device.defaultCalibrationMatrixIsIdentity = false; Device d(&device); d.setOrientation(Qt::PortraitOrientation); QCOMPARE(device.calibrationMatrix[0], 3.0f); QCOMPARE(device.calibrationMatrix[1], -2.0f); QCOMPARE(device.calibrationMatrix[2], 2.0f); QCOMPARE(device.calibrationMatrix[3], 5.0f); QCOMPARE(device.calibrationMatrix[4], -4.0f); QCOMPARE(device.calibrationMatrix[5], 4.0f); } void TestLibinputDevice::testSwitch_data() { QTest::addColumn("lid"); QTest::addColumn("tablet"); QTest::newRow("lid") << true << false; QTest::newRow("tablet") << false << true; } void TestLibinputDevice::testSwitch() { libinput_device device; device.switchDevice = true; QFETCH(bool, lid); QFETCH(bool, tablet); device.lidSwitch = lid; device.tabletModeSwitch = tablet; Device d(&device); QCOMPARE(d.isSwitch(), true); QCOMPARE(d.isLidSwitch(), lid); QCOMPARE(d.property("lidSwitch").toBool(), lid); QCOMPARE(dbusProperty(d.sysName(), "lidSwitch"), lid); QCOMPARE(d.isTabletModeSwitch(), tablet); QCOMPARE(d.property("tabletModeSwitch").toBool(), tablet); QCOMPARE(dbusProperty(d.sysName(), "tabletModeSwitch"), tablet); } QTEST_GUILESS_MAIN(TestLibinputDevice) #include "device_test.moc" diff --git a/autotests/libinput/mock_libinput.cpp b/autotests/libinput/mock_libinput.cpp index a412078dd..1dd354261 100644 --- a/autotests/libinput/mock_libinput.cpp +++ b/autotests/libinput/mock_libinput.cpp @@ -1,858 +1,885 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include #include "mock_libinput.h" #include #include int libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code) { return device->keys.contains(code); } int libinput_device_has_capability(struct libinput_device *device, enum libinput_device_capability capability) { switch (capability) { case LIBINPUT_DEVICE_CAP_KEYBOARD: return device->keyboard; case LIBINPUT_DEVICE_CAP_POINTER: return device->pointer; case LIBINPUT_DEVICE_CAP_TOUCH: return device->touch; case LIBINPUT_DEVICE_CAP_GESTURE: return device->gestureSupported; case LIBINPUT_DEVICE_CAP_TABLET_TOOL: return device->tabletTool; case LIBINPUT_DEVICE_CAP_SWITCH: return device->switchDevice; default: return 0; } } const char *libinput_device_get_name(struct libinput_device *device) { return device->name.constData(); } const char *libinput_device_get_sysname(struct libinput_device *device) { return device->sysName.constData(); } const char *libinput_device_get_output_name(struct libinput_device *device) { return device->outputName.constData(); } unsigned int libinput_device_get_id_product(struct libinput_device *device) { return device->product; } unsigned int libinput_device_get_id_vendor(struct libinput_device *device) { return device->vendor; } int libinput_device_config_tap_get_finger_count(struct libinput_device *device) { return device->tapFingerCount; } enum libinput_config_tap_state libinput_device_config_tap_get_enabled(struct libinput_device *device) { if (device->tapToClick) { return LIBINPUT_CONFIG_TAP_ENABLED; } else { return LIBINPUT_CONFIG_TAP_DISABLED; } } enum libinput_config_status libinput_device_config_tap_set_enabled(struct libinput_device *device, enum libinput_config_tap_state enable) { if (device->setTapToClickReturnValue == 0) { device->tapToClick = (enable == LIBINPUT_CONFIG_TAP_ENABLED); return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_tap_state libinput_device_config_tap_get_default_enabled(struct libinput_device *device) { if (device->tapEnabledByDefault) { return LIBINPUT_CONFIG_TAP_ENABLED; } else { return LIBINPUT_CONFIG_TAP_DISABLED; } } enum libinput_config_drag_state libinput_device_config_tap_get_default_drag_enabled(struct libinput_device *device) { if (device->tapAndDragEnabledByDefault) { return LIBINPUT_CONFIG_DRAG_ENABLED; } else { return LIBINPUT_CONFIG_DRAG_DISABLED; } } enum libinput_config_drag_state libinput_device_config_tap_get_drag_enabled(struct libinput_device *device) { if (device->tapAndDrag) { return LIBINPUT_CONFIG_DRAG_ENABLED; } else { return LIBINPUT_CONFIG_DRAG_DISABLED; } } enum libinput_config_status libinput_device_config_tap_set_drag_enabled(struct libinput_device *device, enum libinput_config_drag_state enable) { if (device->setTapAndDragReturnValue == 0) { device->tapAndDrag = (enable == LIBINPUT_CONFIG_DRAG_ENABLED); return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_drag_lock_state libinput_device_config_tap_get_default_drag_lock_enabled(struct libinput_device *device) { if (device->tapDragLockEnabledByDefault) { return LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; } else { return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; } } enum libinput_config_drag_lock_state libinput_device_config_tap_get_drag_lock_enabled(struct libinput_device *device) { if (device->tapDragLock) { return LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; } else { return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; } } enum libinput_config_status libinput_device_config_tap_set_drag_lock_enabled(struct libinput_device *device, enum libinput_config_drag_lock_state enable) { if (device->setTapDragLockReturnValue == 0) { device->tapDragLock = (enable == LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } int libinput_device_config_dwt_is_available(struct libinput_device *device) { return device->supportsDisableWhileTyping; } enum libinput_config_status libinput_device_config_dwt_set_enabled(struct libinput_device *device, enum libinput_config_dwt_state state) { if (device->setDisableWhileTypingReturnValue == 0) { if (!device->supportsDisableWhileTyping) { return LIBINPUT_CONFIG_STATUS_INVALID; } device->disableWhileTyping = state; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_dwt_state libinput_device_config_dwt_get_enabled(struct libinput_device *device) { return device->disableWhileTyping; } enum libinput_config_dwt_state libinput_device_config_dwt_get_default_enabled(struct libinput_device *device) { return device->disableWhileTypingEnabledByDefault; } int libinput_device_config_accel_is_available(struct libinput_device *device) { return device->supportsPointerAcceleration; } int libinput_device_config_calibration_has_matrix(struct libinput_device *device) { return device->supportsCalibrationMatrix; } enum libinput_config_status libinput_device_config_calibration_set_matrix(struct libinput_device *device, const float matrix[6]) { for (std::size_t i = 0; i < 6; i++) { device->calibrationMatrix[i] = matrix[i]; } return LIBINPUT_CONFIG_STATUS_SUCCESS; } int libinput_device_config_calibration_get_default_matrix(struct libinput_device *device, float matrix[6]) { for (std::size_t i = 0; i < 6; i++) { matrix[i] = device->defaultCalibrationMatrix[i]; } return device->defaultCalibrationMatrixIsIdentity ? 0 : 1; } int libinput_device_config_left_handed_is_available(struct libinput_device *device) { return device->supportsLeftHanded; } uint32_t libinput_device_config_send_events_get_modes(struct libinput_device *device) { uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; if (device->supportsDisableEvents) { modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; } if (device->supportsDisableEventsOnExternalMouse) { modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; } return modes; } int libinput_device_config_left_handed_get(struct libinput_device *device) { return device->leftHanded; } double libinput_device_config_accel_get_default_speed(struct libinput_device *device) { return device->defaultPointerAcceleration; } int libinput_device_config_left_handed_get_default(struct libinput_device *device) { return device->leftHandedEnabledByDefault; } double libinput_device_config_accel_get_speed(struct libinput_device *device) { return device->pointerAcceleration; } uint32_t libinput_device_config_accel_get_profiles(struct libinput_device *device) { return device->supportedPointerAccelerationProfiles; } enum libinput_config_accel_profile libinput_device_config_accel_get_default_profile(struct libinput_device *device) { return device->defaultPointerAccelerationProfile; } enum libinput_config_status libinput_device_config_accel_set_profile(struct libinput_device *device, enum libinput_config_accel_profile profile) { if (device->setPointerAccelerationProfileReturnValue == 0) { if (!(device->supportedPointerAccelerationProfiles & profile) && profile!= LIBINPUT_CONFIG_ACCEL_PROFILE_NONE) { return LIBINPUT_CONFIG_STATUS_INVALID; } device->pointerAccelerationProfile = profile; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_accel_profile libinput_device_config_accel_get_profile(struct libinput_device *device) { return device->pointerAccelerationProfile; } +uint32_t libinput_device_config_click_get_methods(struct libinput_device *device) +{ + return device->supportedClickMethods; +} + +enum libinput_config_click_method libinput_device_config_click_get_default_method(struct libinput_device *device) +{ + return device->defaultClickMethod; +} + +enum libinput_config_click_method libinput_device_config_click_get_method(struct libinput_device *device) +{ + return device->clickMethod; +} + +enum libinput_config_status libinput_device_config_click_set_method(struct libinput_device *device, enum libinput_config_click_method method) +{ + if (device->setClickMethodReturnValue == 0) { + if (!(device->supportedClickMethods & method) && method != LIBINPUT_CONFIG_CLICK_METHOD_NONE) { + return LIBINPUT_CONFIG_STATUS_INVALID; + } + device->clickMethod = method; + return LIBINPUT_CONFIG_STATUS_SUCCESS; + } + return LIBINPUT_CONFIG_STATUS_INVALID; +} + uint32_t libinput_device_config_send_events_get_mode(struct libinput_device *device) { if (device->enabled) { return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; } else { // TODO: disabled on eternal mouse return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; } } struct libinput_device *libinput_device_ref(struct libinput_device *device) { return device; } struct libinput_device *libinput_device_unref(struct libinput_device *device) { return device; } int libinput_device_get_size(struct libinput_device *device, double *width, double *height) { if (device->deviceSizeReturnValue) { return device->deviceSizeReturnValue; } if (width) { *width = device->deviceSize.width(); } if (height) { *height = device->deviceSize.height(); } return device->deviceSizeReturnValue; } int libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code) { switch (code) { case BTN_LEFT: return device->supportedButtons.testFlag(Qt::LeftButton); case BTN_MIDDLE: return device->supportedButtons.testFlag(Qt::MiddleButton); case BTN_RIGHT: return device->supportedButtons.testFlag(Qt::RightButton); case BTN_SIDE: return device->supportedButtons.testFlag(Qt::ExtraButton1); case BTN_EXTRA: return device->supportedButtons.testFlag(Qt::ExtraButton2); case BTN_BACK: return device->supportedButtons.testFlag(Qt::BackButton); case BTN_FORWARD: return device->supportedButtons.testFlag(Qt::ForwardButton); case BTN_TASK: return device->supportedButtons.testFlag(Qt::TaskButton); default: return 0; } } enum libinput_config_status libinput_device_config_left_handed_set(struct libinput_device *device, int left_handed) { if (device->setLeftHandedReturnValue == 0) { device->leftHanded = left_handed; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_status libinput_device_config_accel_set_speed(struct libinput_device *device, double speed) { if (device->setPointerAccelerationReturnValue == 0) { device->pointerAcceleration = speed; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_status libinput_device_config_send_events_set_mode(struct libinput_device *device, uint32_t mode) { if (device->setEnableModeReturnValue == 0) { device->enabled = (mode == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED); return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_event_type libinput_event_get_type(struct libinput_event *event) { return event->type; } struct libinput_device *libinput_event_get_device(struct libinput_event *event) { return event->device; } void libinput_event_destroy(struct libinput_event *event) { delete event; } struct libinput_event_keyboard *libinput_event_get_keyboard_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_KEYBOARD_KEY) { return reinterpret_cast(event); } return nullptr; } struct libinput_event_pointer *libinput_event_get_pointer_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_POINTER_MOTION || event->type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE || event->type == LIBINPUT_EVENT_POINTER_BUTTON || event->type == LIBINPUT_EVENT_POINTER_AXIS) { return reinterpret_cast(event); } return nullptr; } struct libinput_event_touch *libinput_event_get_touch_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_TOUCH_DOWN || event->type == LIBINPUT_EVENT_TOUCH_UP || event->type == LIBINPUT_EVENT_TOUCH_MOTION || event->type == LIBINPUT_EVENT_TOUCH_CANCEL || event->type == LIBINPUT_EVENT_TOUCH_FRAME) { return reinterpret_cast(event); } return nullptr; } struct libinput_event_gesture *libinput_event_get_gesture_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN || event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE || event->type == LIBINPUT_EVENT_GESTURE_PINCH_END || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_END) { return reinterpret_cast(event); } return nullptr; } int libinput_event_gesture_get_cancelled(struct libinput_event_gesture *event) { if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_END || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_END) { return event->cancelled; } return 0; } uint32_t libinput_event_gesture_get_time(struct libinput_event_gesture *event) { return event->time; } int libinput_event_gesture_get_finger_count(struct libinput_event_gesture *event) { return event->fingerCount; } double libinput_event_gesture_get_dx(struct libinput_event_gesture *event) { if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE) { return event->delta.width(); } return 0.0; } double libinput_event_gesture_get_dy(struct libinput_event_gesture *event) { if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE) { return event->delta.height(); } return 0.0; } double libinput_event_gesture_get_scale(struct libinput_event_gesture *event) { switch (event->type) { case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: return 1.0; case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: case LIBINPUT_EVENT_GESTURE_PINCH_END: return event->scale; default: return 0.0; } } double libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event) { if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE) { return event->angleDelta; } return 0.0; } uint32_t libinput_event_keyboard_get_key(struct libinput_event_keyboard *event) { return event->key; } enum libinput_key_state libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event) { return event->state; } uint32_t libinput_event_keyboard_get_time(struct libinput_event_keyboard *event) { return event->time; } double libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) { return event->absolutePos.x(); } double libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event) { return event->absolutePos.y(); } double libinput_event_pointer_get_absolute_x_transformed(struct libinput_event_pointer *event, uint32_t width) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.x() / deviceWidth * width; } double libinput_event_pointer_get_absolute_y_transformed(struct libinput_event_pointer *event, uint32_t height) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.y() / deviceHeight * height; } double libinput_event_pointer_get_dx(struct libinput_event_pointer *event) { return event->delta.width(); } double libinput_event_pointer_get_dy(struct libinput_event_pointer *event) { return event->delta.height(); } double libinput_event_pointer_get_dx_unaccelerated(struct libinput_event_pointer *event) { return event->delta.width(); } double libinput_event_pointer_get_dy_unaccelerated(struct libinput_event_pointer *event) { return event->delta.height(); } uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event) { return event->time; } uint64_t libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event) { return quint64(event->time * 1000); } uint32_t libinput_event_pointer_get_button(struct libinput_event_pointer *event) { return event->button; } enum libinput_button_state libinput_event_pointer_get_button_state(struct libinput_event_pointer *event) { return event->buttonState; } int libinput_event_pointer_has_axis(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) { return event->verticalAxis; } else { return event->horizontalAxis; } } double libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) { return event->verticalAxisValue; } else { return event->horizontalAxisValue; } } uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event) { return event->time; } double libinput_event_touch_get_x(struct libinput_event_touch *event) { return event->absolutePos.x(); } double libinput_event_touch_get_y(struct libinput_event_touch *event) { return event->absolutePos.y(); } double libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, uint32_t width) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.x() / deviceWidth * width; } double libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, uint32_t height) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.y() / deviceHeight * height; } int32_t libinput_event_touch_get_slot(struct libinput_event_touch *event) { return event->slot; } struct libinput *libinput_udev_create_context(const struct libinput_interface *interface, void *user_data, struct udev *udev) { if (!udev) { return nullptr; } Q_UNUSED(interface) Q_UNUSED(user_data) return new libinput; } void libinput_log_set_priority(struct libinput *libinput, enum libinput_log_priority priority) { Q_UNUSED(libinput) Q_UNUSED(priority) } void libinput_log_set_handler(struct libinput *libinput, libinput_log_handler log_handler) { Q_UNUSED(libinput) Q_UNUSED(log_handler) } struct libinput *libinput_unref(struct libinput *libinput) { libinput->refCount--; if (libinput->refCount == 0) { delete libinput; return nullptr; } return libinput; } int libinput_udev_assign_seat(struct libinput *libinput, const char *seat_id) { if (libinput->assignSeatRetVal == 0) { libinput->seat = QByteArray(seat_id); } return libinput->assignSeatRetVal; } int libinput_get_fd(struct libinput *libinput) { Q_UNUSED(libinput) return -1; } int libinput_dispatch(struct libinput *libinput) { Q_UNUSED(libinput) return 0; } struct libinput_event *libinput_get_event(struct libinput *libinput) { Q_UNUSED(libinput) return nullptr; } void libinput_suspend(struct libinput *libinput) { Q_UNUSED(libinput) } int libinput_resume(struct libinput *libinput) { Q_UNUSED(libinput) return 0; } int libinput_device_config_middle_emulation_is_available(struct libinput_device *device) { return device->supportsMiddleEmulation; } enum libinput_config_status libinput_device_config_middle_emulation_set_enabled(struct libinput_device *device, enum libinput_config_middle_emulation_state enable) { if (device->setMiddleEmulationReturnValue == 0) { if (!device->supportsMiddleEmulation) { return LIBINPUT_CONFIG_STATUS_INVALID; } device->middleEmulation = (enable == LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED); return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_middle_emulation_state libinput_device_config_middle_emulation_get_enabled(struct libinput_device *device) { if (device->middleEmulation) { return LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; } else { return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; } } enum libinput_config_middle_emulation_state libinput_device_config_middle_emulation_get_default_enabled(struct libinput_device *device) { if (device->middleEmulationEnabledByDefault) { return LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; } else { return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; } } int libinput_device_config_scroll_has_natural_scroll(struct libinput_device *device) { return device->supportsNaturalScroll; } enum libinput_config_status libinput_device_config_scroll_set_natural_scroll_enabled(struct libinput_device *device, int enable) { if (device->setNaturalScrollReturnValue == 0) { if (!device->supportsNaturalScroll) { return LIBINPUT_CONFIG_STATUS_INVALID; } device->naturalScroll = enable; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } int libinput_device_config_scroll_get_natural_scroll_enabled(struct libinput_device *device) { return device->naturalScroll; } int libinput_device_config_scroll_get_default_natural_scroll_enabled(struct libinput_device *device) { return device->naturalScrollEnabledByDefault; } enum libinput_config_tap_button_map libinput_device_config_tap_get_default_button_map(struct libinput_device *device) { return device->defaultTapButtonMap; } enum libinput_config_status libinput_device_config_tap_set_button_map(struct libinput_device *device, enum libinput_config_tap_button_map map) { if (device->setTapButtonMapReturnValue == 0) { if (device->tapFingerCount == 0) { return LIBINPUT_CONFIG_STATUS_INVALID; } device->tapButtonMap = map; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_tap_button_map libinput_device_config_tap_get_button_map(struct libinput_device *device) { return device->tapButtonMap; } uint32_t libinput_device_config_scroll_get_methods(struct libinput_device *device) { return device->supportedScrollMethods; } enum libinput_config_scroll_method libinput_device_config_scroll_get_default_method(struct libinput_device *device) { return device->defaultScrollMethod; } enum libinput_config_status libinput_device_config_scroll_set_method(struct libinput_device *device, enum libinput_config_scroll_method method) { if (device->setScrollMethodReturnValue == 0) { if (!(device->supportedScrollMethods & method) && method != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) { return LIBINPUT_CONFIG_STATUS_INVALID; } device->scrollMethod = method; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_scroll_method libinput_device_config_scroll_get_method(struct libinput_device *device) { return device->scrollMethod; } enum libinput_config_status libinput_device_config_scroll_set_button(struct libinput_device *device, uint32_t button) { if (device->setScrollButtonReturnValue == 0) { if (!(device->supportedScrollMethods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)) { return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; } device->scrollButton = button; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } uint32_t libinput_device_config_scroll_get_button(struct libinput_device *device) { return device->scrollButton; } uint32_t libinput_device_config_scroll_get_default_button(struct libinput_device *device) { return device->defaultScrollButton; } int libinput_device_switch_has_switch(struct libinput_device *device, enum libinput_switch sw) { switch (sw) { case LIBINPUT_SWITCH_LID: return device->lidSwitch; case LIBINPUT_SWITCH_TABLET_MODE: return device->tabletModeSwitch; default: Q_UNREACHABLE(); } return 0; } struct libinput_event_switch *libinput_event_get_switch_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_SWITCH_TOGGLE) { return reinterpret_cast(event); } else { return nullptr; } } enum libinput_switch_state libinput_event_switch_get_switch_state(struct libinput_event_switch *event) { switch (event->state) { case libinput_event_switch::State::On: return LIBINPUT_SWITCH_STATE_ON; case libinput_event_switch::State::Off: return LIBINPUT_SWITCH_STATE_OFF; default: Q_UNREACHABLE(); } } uint32_t libinput_event_switch_get_time(struct libinput_event_switch *event) { return event->time;; } uint64_t libinput_event_switch_get_time_usec(struct libinput_event_switch *event) { return event->timeMicroseconds; } diff --git a/autotests/libinput/mock_libinput.h b/autotests/libinput/mock_libinput.h index 404b0d64f..efbc730aa 100644 --- a/autotests/libinput/mock_libinput.h +++ b/autotests/libinput/mock_libinput.h @@ -1,159 +1,163 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef MOCK_LIBINPUT_H #define MOCK_LIBINPUT_H #include #include #include #include #include #include struct libinput_device { bool keyboard = false; bool pointer = false; bool touch = false; bool tabletTool = false; bool gestureSupported = false; bool switchDevice = false; QByteArray name; QByteArray sysName = QByteArrayLiteral("event0"); QByteArray outputName; quint32 product = 0; quint32 vendor = 0; int tapFingerCount = 0; QSizeF deviceSize; int deviceSizeReturnValue = 0; bool tapEnabledByDefault = false; bool tapToClick = false; bool tapAndDragEnabledByDefault = false; bool tapAndDrag = false; bool tapDragLockEnabledByDefault = false; bool tapDragLock = false; bool supportsDisableWhileTyping = false; bool supportsPointerAcceleration = false; bool supportsLeftHanded = false; bool supportsCalibrationMatrix = false; bool supportsDisableEvents = false; bool supportsDisableEventsOnExternalMouse = false; bool supportsMiddleEmulation = false; bool supportsNaturalScroll = false; quint32 supportedScrollMethods = 0; bool middleEmulationEnabledByDefault = false; bool middleEmulation = false; enum libinput_config_tap_button_map defaultTapButtonMap = LIBINPUT_CONFIG_TAP_MAP_LRM; enum libinput_config_tap_button_map tapButtonMap = LIBINPUT_CONFIG_TAP_MAP_LRM; int setTapButtonMapReturnValue = 0; enum libinput_config_dwt_state disableWhileTypingEnabledByDefault = LIBINPUT_CONFIG_DWT_DISABLED; enum libinput_config_dwt_state disableWhileTyping = LIBINPUT_CONFIG_DWT_DISABLED; int setDisableWhileTypingReturnValue = 0; qreal defaultPointerAcceleration = 0.0; qreal pointerAcceleration = 0.0; int setPointerAccelerationReturnValue = 0; bool leftHandedEnabledByDefault = false; bool leftHanded = false; int setLeftHandedReturnValue = 0; bool naturalScrollEnabledByDefault = false; bool naturalScroll = false; int setNaturalScrollReturnValue = 0; enum libinput_config_scroll_method defaultScrollMethod = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; enum libinput_config_scroll_method scrollMethod = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; int setScrollMethodReturnValue = 0; quint32 defaultScrollButton = 0; quint32 scrollButton = 0; int setScrollButtonReturnValue = 0; Qt::MouseButtons supportedButtons; QVector keys; bool enabled = true; int setEnableModeReturnValue = 0; int setTapToClickReturnValue = 0; int setTapAndDragReturnValue = 0; int setTapDragLockReturnValue = 0; int setMiddleEmulationReturnValue = 0; quint32 supportedPointerAccelerationProfiles = 0; enum libinput_config_accel_profile defaultPointerAccelerationProfile = LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; enum libinput_config_accel_profile pointerAccelerationProfile = LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; bool setPointerAccelerationProfileReturnValue = 0; std::array defaultCalibrationMatrix{{1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}}; std::array calibrationMatrix{{1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}}; bool defaultCalibrationMatrixIsIdentity = true; bool lidSwitch = false; bool tabletModeSwitch = false; + quint32 supportedClickMethods = 0; + enum libinput_config_click_method defaultClickMethod = LIBINPUT_CONFIG_CLICK_METHOD_NONE; + enum libinput_config_click_method clickMethod = LIBINPUT_CONFIG_CLICK_METHOD_NONE; + bool setClickMethodReturnValue = 0; }; struct libinput_event { libinput_device *device = nullptr; libinput_event_type type = LIBINPUT_EVENT_NONE; quint32 time = 0; }; struct libinput_event_keyboard : libinput_event { libinput_event_keyboard() { type = LIBINPUT_EVENT_KEYBOARD_KEY; } libinput_key_state state = LIBINPUT_KEY_STATE_RELEASED; quint32 key = 0; }; struct libinput_event_pointer : libinput_event { libinput_button_state buttonState = LIBINPUT_BUTTON_STATE_RELEASED; quint32 button = 0; bool verticalAxis = false; bool horizontalAxis = false; qreal horizontalAxisValue = 0.0; qreal verticalAxisValue = 0.0; QSizeF delta; QPointF absolutePos; }; struct libinput_event_touch : libinput_event { qint32 slot = -1; QPointF absolutePos; }; struct libinput_event_gesture : libinput_event { int fingerCount = 0; bool cancelled = false; QSizeF delta = QSizeF(0, 0); qreal scale = 0.0; qreal angleDelta = 0.0; }; struct libinput_event_switch : libinput_event { enum class State { Off, On }; State state = State::Off; quint64 timeMicroseconds = 0; }; struct libinput { int refCount = 1; QByteArray seat; int assignSeatRetVal = 0; }; #endif diff --git a/libinput/device.cpp b/libinput/device.cpp index 330499d39..91f00134e 100644 --- a/libinput/device.cpp +++ b/libinput/device.cpp @@ -1,500 +1,526 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "device.h" #include #include #include namespace KWin { namespace LibInput { static bool checkAlphaNumericKeyboard(libinput_device *device) { for (uint i = KEY_1; i <= KEY_0; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } for (uint i = KEY_Q; i <= KEY_P; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } for (uint i = KEY_A; i <= KEY_L; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } for (uint i = KEY_Z; i <= KEY_M; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } return true; } QVector Device::s_devices; Device *Device::getDevice(libinput_device *native) { auto it = std::find_if(s_devices.constBegin(), s_devices.constEnd(), [native] (const Device *d) { return d->device() == native; } ); if (it != s_devices.constEnd()) { return *it; } return nullptr; } enum class ConfigKey { Enabled, LeftHanded, DisableWhileTyping, PointerAcceleration, PointerAccelerationProfile, TapToClick, LmrTapButtonMap, TapAndDrag, TapDragLock, MiddleButtonEmulation, NaturalScroll, ScrollMethod, - ScrollButton + ScrollButton, + ClickMethod }; struct ConfigData { explicit ConfigData(QByteArray _key, void (Device::*_setter)(bool), bool (Device::*_defaultValue)() const = nullptr) : key(_key) { booleanSetter.setter = _setter; booleanSetter.defaultValue = _defaultValue; } explicit ConfigData(QByteArray _key, void (Device::*_setter)(quint32), quint32 (Device::*_defaultValue)() const = nullptr) : key(_key) { quint32Setter.setter = _setter; quint32Setter.defaultValue = _defaultValue; } explicit ConfigData(QByteArray _key, void (Device::*_setter)(QString), QString (Device::*_defaultValue)() const = nullptr) : key(_key) { stringSetter.setter = _setter; stringSetter.defaultValue = _defaultValue; } QByteArray key; struct { void (Device::*setter)(bool) = nullptr; bool (Device::*defaultValue)() const; } booleanSetter; struct { void (Device::*setter)(quint32) = nullptr; quint32 (Device::*defaultValue)() const; } quint32Setter; struct { void (Device::*setter)(QString) = nullptr; QString (Device::*defaultValue)() const; } stringSetter; }; static const QMap s_configData { {ConfigKey::Enabled, ConfigData(QByteArrayLiteral("Enabled"), &Device::setEnabled)}, {ConfigKey::LeftHanded, ConfigData(QByteArrayLiteral("LeftHanded"), &Device::setLeftHanded, &Device::leftHandedEnabledByDefault)}, {ConfigKey::DisableWhileTyping, ConfigData(QByteArrayLiteral("DisableWhileTyping"), &Device::setDisableWhileTyping, &Device::disableWhileTypingEnabledByDefault)}, {ConfigKey::PointerAcceleration, ConfigData(QByteArrayLiteral("PointerAcceleration"), &Device::setPointerAccelerationFromString, &Device::defaultPointerAccelerationToString)}, {ConfigKey::PointerAccelerationProfile, ConfigData(QByteArrayLiteral("PointerAccelerationProfile"), &Device::setPointerAccelerationProfileFromInt, &Device::defaultPointerAccelerationProfileToInt)}, {ConfigKey::TapToClick, ConfigData(QByteArrayLiteral("TapToClick"), &Device::setTapToClick, &Device::tapToClickEnabledByDefault)}, {ConfigKey::TapAndDrag, ConfigData(QByteArrayLiteral("TapAndDrag"), &Device::setTapAndDrag, &Device::tapAndDragEnabledByDefault)}, {ConfigKey::TapDragLock, ConfigData(QByteArrayLiteral("TapDragLock"), &Device::setTapDragLock, &Device::tapDragLockEnabledByDefault)}, {ConfigKey::MiddleButtonEmulation, ConfigData(QByteArrayLiteral("MiddleButtonEmulation"), &Device::setMiddleEmulation, &Device::middleEmulationEnabledByDefault)}, {ConfigKey::LmrTapButtonMap, ConfigData(QByteArrayLiteral("LmrTapButtonMap"), &Device::setLmrTapButtonMap, &Device::lmrTapButtonMapEnabledByDefault)}, {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::ScrollButton, ConfigData(QByteArrayLiteral("ScrollButton"), &Device::setScrollButton, &Device::defaultScrollButton)}, + {ConfigKey::ClickMethod, ConfigData(QByteArrayLiteral("ClickMethod"), &Device::setClickMethodFromInt, &Device::defaultClickMethodToInt)} }; namespace { QMatrix4x4 defaultCalibrationMatrix(libinput_device *device) { float matrix[6]; const int ret = libinput_device_config_calibration_get_default_matrix(device, matrix); if (ret == 0) { return QMatrix4x4(); } return QMatrix4x4{ matrix[0], matrix[1], matrix[2], 0.0f, matrix[3], matrix[4], matrix[5], 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; } } Device::Device(libinput_device *device, QObject *parent) : QObject(parent) , m_device(device) , m_keyboard(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_KEYBOARD)) , m_pointer(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_POINTER)) , m_touch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TOUCH)) , m_tabletTool(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) #if 0 // next libinput version , m_tabletPad(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) #else , m_tabletPad(false) #endif , m_supportsGesture(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_GESTURE)) , m_switch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_SWITCH)) , m_lidSwitch(m_switch ? libinput_device_switch_has_switch(m_device, LIBINPUT_SWITCH_LID) : false) , m_tabletSwitch(m_switch ? libinput_device_switch_has_switch(m_device, LIBINPUT_SWITCH_TABLET_MODE) : false) , m_name(QString::fromLocal8Bit(libinput_device_get_name(m_device))) , m_sysName(QString::fromLocal8Bit(libinput_device_get_sysname(m_device))) , m_outputName(QString::fromLocal8Bit(libinput_device_get_output_name(m_device))) , m_product(libinput_device_get_id_product(m_device)) , m_vendor(libinput_device_get_id_vendor(m_device)) , m_tapFingerCount(libinput_device_config_tap_get_finger_count(m_device)) , m_defaultTapButtonMap(libinput_device_config_tap_get_default_button_map(m_device)) , m_tapButtonMap(libinput_device_config_tap_get_button_map(m_device)) , m_tapToClickEnabledByDefault(libinput_device_config_tap_get_default_enabled(m_device) == LIBINPUT_CONFIG_TAP_ENABLED) , m_tapToClick(libinput_device_config_tap_get_enabled(m_device)) , m_tapAndDragEnabledByDefault(libinput_device_config_tap_get_default_drag_enabled(m_device)) , m_tapAndDrag(libinput_device_config_tap_get_drag_enabled(m_device)) , m_tapDragLockEnabledByDefault(libinput_device_config_tap_get_default_drag_lock_enabled(m_device)) , m_tapDragLock(libinput_device_config_tap_get_drag_lock_enabled(m_device)) , m_supportsDisableWhileTyping(libinput_device_config_dwt_is_available(m_device)) , m_supportsPointerAcceleration(libinput_device_config_accel_is_available(m_device)) , m_supportsLeftHanded(libinput_device_config_left_handed_is_available(m_device)) , m_supportsCalibrationMatrix(libinput_device_config_calibration_has_matrix(m_device)) , m_supportsDisableEvents(libinput_device_config_send_events_get_modes(m_device) & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) , m_supportsDisableEventsOnExternalMouse(libinput_device_config_send_events_get_modes(m_device) & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) , m_supportsMiddleEmulation(libinput_device_config_middle_emulation_is_available(m_device)) , m_supportsNaturalScroll(libinput_device_config_scroll_has_natural_scroll(m_device)) , m_supportedScrollMethods(libinput_device_config_scroll_get_methods(m_device)) , m_leftHandedEnabledByDefault(libinput_device_config_left_handed_get_default(m_device)) , m_middleEmulationEnabledByDefault(libinput_device_config_middle_emulation_get_default_enabled(m_device) == LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED) , m_naturalScrollEnabledByDefault(libinput_device_config_scroll_get_default_natural_scroll_enabled(m_device)) , m_defaultScrollMethod(libinput_device_config_scroll_get_default_method(m_device)) , m_defaultScrollButton(libinput_device_config_scroll_get_default_button(m_device)) , m_disableWhileTypingEnabledByDefault(libinput_device_config_dwt_get_default_enabled(m_device)) , m_disableWhileTyping(m_supportsDisableWhileTyping ? libinput_device_config_dwt_get_enabled(m_device) == LIBINPUT_CONFIG_DWT_ENABLED : false) , m_middleEmulation(libinput_device_config_middle_emulation_get_enabled(m_device) == LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED) , m_leftHanded(m_supportsLeftHanded ? libinput_device_config_left_handed_get(m_device) : false) , m_naturalScroll(m_supportsNaturalScroll ? libinput_device_config_scroll_get_natural_scroll_enabled(m_device) : false) , m_scrollMethod(libinput_device_config_scroll_get_method(m_device)) , m_scrollButton(libinput_device_config_scroll_get_button(m_device)) , m_defaultPointerAcceleration(libinput_device_config_accel_get_default_speed(m_device)) , m_pointerAcceleration(libinput_device_config_accel_get_speed(m_device)) , m_supportedPointerAccelerationProfiles(libinput_device_config_accel_get_profiles(m_device)) , m_defaultPointerAccelerationProfile(libinput_device_config_accel_get_default_profile(m_device)) , m_pointerAccelerationProfile(libinput_device_config_accel_get_profile(m_device)) , m_enabled(m_supportsDisableEvents ? libinput_device_config_send_events_get_mode(m_device) == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : true) , m_config() , m_defaultCalibrationMatrix(m_supportsCalibrationMatrix ? defaultCalibrationMatrix(m_device) : QMatrix4x4{}) + , 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)) { libinput_device_ref(m_device); qreal width = 0; qreal height = 0; if (libinput_device_get_size(m_device, &width, &height) == 0) { m_size = QSizeF(width, height); } if (m_pointer) { if (libinput_device_pointer_has_button(m_device, BTN_LEFT) == 1) { m_supportedButtons |= Qt::LeftButton; } if (libinput_device_pointer_has_button(m_device, BTN_MIDDLE) == 1) { m_supportedButtons |= Qt::MiddleButton; } if (libinput_device_pointer_has_button(m_device, BTN_RIGHT) == 1) { m_supportedButtons |= Qt::RightButton; } if (libinput_device_pointer_has_button(m_device, BTN_SIDE) == 1) { m_supportedButtons |= Qt::ExtraButton1; } if (libinput_device_pointer_has_button(m_device, BTN_EXTRA) == 1) { m_supportedButtons |= Qt::ExtraButton2; } if (libinput_device_pointer_has_button(m_device, BTN_BACK) == 1) { m_supportedButtons |= Qt::BackButton; } if (libinput_device_pointer_has_button(m_device, BTN_FORWARD) == 1) { m_supportedButtons |= Qt::ForwardButton; } if (libinput_device_pointer_has_button(m_device, BTN_TASK) == 1) { m_supportedButtons |= Qt::TaskButton; } } if (m_keyboard) { m_alphaNumericKeyboard = checkAlphaNumericKeyboard(m_device); } s_devices << this; QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/KWin/InputDevice/") + m_sysName, QStringLiteral("org.kde.KWin.InputDevice"), this, QDBusConnection::ExportAllProperties ); } Device::~Device() { s_devices.removeOne(this); QDBusConnection::sessionBus().unregisterObject(QStringLiteral("/org/kde/KWin/InputDevice/") + m_sysName); 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; } (this->*(s.setter))(m_config.readEntry(key.constData(), s.defaultValue ? (this->*(s.defaultValue))() : 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); readEntry(key, it.value().stringSetter, ""); }; m_loading = false; } void Device::setPointerAcceleration(qreal acceleration) { if (!m_supportsPointerAcceleration) { return; } acceleration = qBound(-1.0, acceleration, 1.0); if (libinput_device_config_accel_set_speed(m_device, acceleration) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_pointerAcceleration != acceleration) { m_pointerAcceleration = acceleration; emit pointerAccelerationChanged(); writeEntry(ConfigKey::PointerAcceleration, QString::number(acceleration, 'f', 3)); } } } void Device::setScrollButton(quint32 button) { if (!(m_supportedScrollMethods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)) { return; } 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(); } } } void Device::setPointerAccelerationProfile(bool set, enum libinput_config_accel_profile profile) { if (!(m_supportedPointerAccelerationProfiles & profile)) { return; } if (!set) { profile = (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE : LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; if (!(m_supportedPointerAccelerationProfiles & profile)) { return; } } if (libinput_device_config_accel_set_profile(m_device, profile) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_pointerAccelerationProfile != profile) { m_pointerAccelerationProfile = profile; emit pointerAccelerationProfileChanged(); writeEntry(ConfigKey::PointerAccelerationProfile, (quint32) profile); } } } +void Device::setClickMethod(bool set, enum libinput_config_click_method method) +{ + if (!(m_supportedClickMethods & method)) { + return; + } + if (!set) { + method = (method == LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) ? LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER : LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + if (!(m_supportedClickMethods & method)) { + return; + } + } + + if (libinput_device_config_click_set_method(m_device, method) == LIBINPUT_CONFIG_STATUS_SUCCESS) { + if (m_clickMethod != method) { + m_clickMethod = method; + emit clickMethodChanged(); + writeEntry(ConfigKey::ClickMethod, (quint32) method); + } + } +} + void Device::setScrollMethod(bool set, enum libinput_config_scroll_method method) { if (!(m_supportedScrollMethods & method)) { return; } bool isCurrent = m_scrollMethod == method; if (!set) { if (isCurrent) { method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; isCurrent = false; } else { return; } } if (libinput_device_config_scroll_set_method(m_device, method) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (!isCurrent) { m_scrollMethod = method; emit scrollMethodChanged(); writeEntry(ConfigKey::ScrollMethod, (quint32) method); } } } void Device::setLmrTapButtonMap(bool set) { enum libinput_config_tap_button_map map = set ? LIBINPUT_CONFIG_TAP_MAP_LMR : LIBINPUT_CONFIG_TAP_MAP_LRM; if (m_tapFingerCount < 2) { return; } if (!set) { map = LIBINPUT_CONFIG_TAP_MAP_LRM; } if (libinput_device_config_tap_set_button_map(m_device, map) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_tapButtonMap != map) { m_tapButtonMap = map; writeEntry(ConfigKey::LmrTapButtonMap, set); emit tapButtonMapChanged(); } } } #define CONFIG(method, condition, function, variable, key) \ void Device::method(bool set) \ { \ if (condition) { \ return; \ } \ if (libinput_device_config_##function(m_device, set) == LIBINPUT_CONFIG_STATUS_SUCCESS) { \ if (m_##variable != set) { \ m_##variable = set; \ writeEntry(ConfigKey::key, m_##variable); \ emit variable##Changed(); \ }\ } \ } CONFIG(setLeftHanded, !m_supportsLeftHanded, left_handed_set, leftHanded, LeftHanded) CONFIG(setNaturalScroll, !m_supportsNaturalScroll, scroll_set_natural_scroll_enabled, naturalScroll, NaturalScroll) #undef CONFIG #define CONFIG(method, condition, function, enum, variable, key) \ void Device::method(bool set) \ { \ if (condition) { \ return; \ } \ 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, Enabled) CONFIG(setDisableWhileTyping, !m_supportsDisableWhileTyping, dwt_set_enabled, DWT, disableWhileTyping, DisableWhileTyping) 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 void Device::setOrientation(Qt::ScreenOrientation orientation) { if (!m_supportsCalibrationMatrix) { return; } // 90 deg cw: static const QMatrix4x4 portraitMatrix{ 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; // 180 deg cw: static const QMatrix4x4 invertedLandscapeMatrix{ -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; // 270 deg cw static const QMatrix4x4 invertedPortraitMatrix{ 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; QMatrix4x4 matrix; switch (orientation) { case Qt::PortraitOrientation: matrix = portraitMatrix; break; case Qt::InvertedLandscapeOrientation: matrix = invertedLandscapeMatrix; break; case Qt::InvertedPortraitOrientation: matrix = invertedPortraitMatrix; break; case Qt::PrimaryOrientation: case Qt::LandscapeOrientation: default: break; } const auto combined = m_defaultCalibrationMatrix * matrix; const auto columnOrder = combined.constData(); float m[6] = { columnOrder[0], columnOrder[4], columnOrder[8], columnOrder[1], columnOrder[5], columnOrder[9] }; libinput_device_config_calibration_set_matrix(m_device, m); } } } diff --git a/libinput/device.h b/libinput/device.h index d4f89f8a1..ec5b9a5d5 100644 --- a/libinput/device.h +++ b/libinput/device.h @@ -1,537 +1,581 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_LIBINPUT_DEVICE_H #define KWIN_LIBINPUT_DEVICE_H #include #include #include #include #include #include struct libinput_device; namespace KWin { namespace LibInput { enum class ConfigKey; class Device : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.InputDevice") // // general Q_PROPERTY(bool keyboard READ isKeyboard CONSTANT) Q_PROPERTY(bool alphaNumericKeyboard READ isAlphaNumericKeyboard CONSTANT) Q_PROPERTY(bool pointer READ isPointer CONSTANT) Q_PROPERTY(bool touchpad READ isTouchpad CONSTANT) Q_PROPERTY(bool touch READ isTouch CONSTANT) Q_PROPERTY(bool tabletTool READ isTabletTool CONSTANT) Q_PROPERTY(bool tabletPad READ isTabletPad CONSTANT) Q_PROPERTY(bool gestureSupport READ supportsGesture CONSTANT) Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString sysName READ sysName CONSTANT) Q_PROPERTY(QString outputName READ outputName CONSTANT) Q_PROPERTY(QSizeF size READ size CONSTANT) Q_PROPERTY(quint32 product READ product CONSTANT) Q_PROPERTY(quint32 vendor READ vendor CONSTANT) Q_PROPERTY(bool supportsDisableEvents READ supportsDisableEvents CONSTANT) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) // // advanced Q_PROPERTY(int supportedButtons READ supportedButtons CONSTANT) Q_PROPERTY(bool supportsCalibrationMatrix READ supportsCalibrationMatrix CONSTANT) Q_PROPERTY(bool supportsLeftHanded READ supportsLeftHanded CONSTANT) Q_PROPERTY(bool leftHandedEnabledByDefault READ leftHandedEnabledByDefault CONSTANT) Q_PROPERTY(bool leftHanded READ isLeftHanded WRITE setLeftHanded NOTIFY leftHandedChanged) Q_PROPERTY(bool supportsDisableEventsOnExternalMouse READ supportsDisableEventsOnExternalMouse CONSTANT) Q_PROPERTY(bool supportsDisableWhileTyping READ supportsDisableWhileTyping CONSTANT) Q_PROPERTY(bool disableWhileTypingEnabledByDefault READ disableWhileTypingEnabledByDefault CONSTANT) Q_PROPERTY(bool disableWhileTyping READ isDisableWhileTyping WRITE setDisableWhileTyping NOTIFY disableWhileTypingChanged) // // acceleration speed and profile Q_PROPERTY(bool supportsPointerAcceleration READ supportsPointerAcceleration CONSTANT) Q_PROPERTY(qreal defaultPointerAcceleration READ defaultPointerAcceleration CONSTANT) Q_PROPERTY(qreal pointerAcceleration READ pointerAcceleration WRITE setPointerAcceleration NOTIFY pointerAccelerationChanged) Q_PROPERTY(bool supportsPointerAccelerationProfileFlat READ supportsPointerAccelerationProfileFlat CONSTANT) Q_PROPERTY(bool defaultPointerAccelerationProfileFlat READ defaultPointerAccelerationProfileFlat CONSTANT) Q_PROPERTY(bool pointerAccelerationProfileFlat READ pointerAccelerationProfileFlat WRITE setPointerAccelerationProfileFlat NOTIFY pointerAccelerationProfileChanged) Q_PROPERTY(bool supportsPointerAccelerationProfileAdaptive READ supportsPointerAccelerationProfileAdaptive CONSTANT) Q_PROPERTY(bool defaultPointerAccelerationProfileAdaptive READ defaultPointerAccelerationProfileAdaptive CONSTANT) Q_PROPERTY(bool pointerAccelerationProfileAdaptive READ pointerAccelerationProfileAdaptive WRITE setPointerAccelerationProfileAdaptive NOTIFY pointerAccelerationProfileChanged) // // tapping Q_PROPERTY(int tapFingerCount READ tapFingerCount CONSTANT) Q_PROPERTY(bool tapToClickEnabledByDefault READ tapToClickEnabledByDefault CONSTANT) Q_PROPERTY(bool tapToClick READ isTapToClick WRITE setTapToClick NOTIFY tapToClickChanged) Q_PROPERTY(bool supportsLmrTapButtonMap READ supportsLmrTapButtonMap CONSTANT) Q_PROPERTY(bool lmrTapButtonMapEnabledByDefault READ lmrTapButtonMapEnabledByDefault CONSTANT) Q_PROPERTY(bool lmrTapButtonMap READ lmrTapButtonMap WRITE setLmrTapButtonMap NOTIFY tapButtonMapChanged) Q_PROPERTY(bool tapAndDragEnabledByDefault READ tapAndDragEnabledByDefault CONSTANT) Q_PROPERTY(bool tapAndDrag READ isTapAndDrag WRITE setTapAndDrag NOTIFY tapAndDragChanged) Q_PROPERTY(bool tapDragLockEnabledByDefault READ tapDragLockEnabledByDefault CONSTANT) Q_PROPERTY(bool tapDragLock READ isTapDragLock WRITE setTapDragLock NOTIFY tapDragLockChanged) Q_PROPERTY(bool supportsMiddleEmulation READ supportsMiddleEmulation CONSTANT) Q_PROPERTY(bool middleEmulationEnabledByDefault READ middleEmulationEnabledByDefault CONSTANT) Q_PROPERTY(bool middleEmulation READ isMiddleEmulation WRITE setMiddleEmulation NOTIFY middleEmulationChanged) // // scrolling Q_PROPERTY(bool supportsNaturalScroll READ supportsNaturalScroll CONSTANT) Q_PROPERTY(bool naturalScrollEnabledByDefault READ naturalScrollEnabledByDefault CONSTANT) Q_PROPERTY(bool naturalScroll READ isNaturalScroll WRITE setNaturalScroll NOTIFY naturalScrollChanged) Q_PROPERTY(bool supportsScrollTwoFinger READ supportsScrollTwoFinger CONSTANT) Q_PROPERTY(bool scrollTwoFingerEnabledByDefault READ scrollTwoFingerEnabledByDefault CONSTANT) Q_PROPERTY(bool scrollTwoFinger READ isScrollTwoFinger WRITE setScrollTwoFinger NOTIFY scrollMethodChanged) Q_PROPERTY(bool supportsScrollEdge READ supportsScrollEdge CONSTANT) Q_PROPERTY(bool scrollEdgeEnabledByDefault READ scrollEdgeEnabledByDefault CONSTANT) Q_PROPERTY(bool scrollEdge READ isScrollEdge WRITE setScrollEdge NOTIFY scrollMethodChanged) Q_PROPERTY(bool supportsScrollOnButtonDown READ supportsScrollOnButtonDown CONSTANT) Q_PROPERTY(bool scrollOnButtonDownEnabledByDefault READ scrollOnButtonDownEnabledByDefault CONSTANT) Q_PROPERTY(quint32 defaultScrollButton READ defaultScrollButton CONSTANT) Q_PROPERTY(bool scrollOnButtonDown READ isScrollOnButtonDown WRITE setScrollOnButtonDown NOTIFY scrollMethodChanged) Q_PROPERTY(quint32 scrollButton READ scrollButton WRITE setScrollButton NOTIFY scrollButtonChanged) // switches Q_PROPERTY(bool switchDevice READ isSwitch CONSTANT) Q_PROPERTY(bool lidSwitch READ isLidSwitch CONSTANT) Q_PROPERTY(bool tabletModeSwitch READ isTabletModeSwitch CONSTANT) + // Click Methods + Q_PROPERTY(bool supportsClickMethodAreas READ supportsClickMethodAreas CONSTANT) + Q_PROPERTY(bool defaultClickMethodAreas READ defaultClickMethodAreas CONSTANT) + Q_PROPERTY(bool clickMethodAreas READ isClickMethodAreas WRITE setClickMethodAreas NOTIFY clickMethodChanged) + + Q_PROPERTY(bool supportsClickMethodClickfinger READ supportsClickMethodClickfinger CONSTANT) + Q_PROPERTY(bool defaultClickMethodClickfinger READ defaultClickMethodClickfinger CONSTANT) + Q_PROPERTY(bool clickMethodClickfinger READ isClickMethodClickfinger WRITE setClickMethodClickfinger NOTIFY clickMethodChanged) public: explicit Device(libinput_device *device, QObject *parent = nullptr); virtual ~Device(); bool isKeyboard() const { return m_keyboard; } bool isAlphaNumericKeyboard() const { return m_alphaNumericKeyboard; } bool isPointer() const { return m_pointer; } bool isTouchpad() const{ return m_pointer && // ignore all combined devices. E.g. a touchpad on a keyboard we don't want to toggle // as that would result in the keyboard going off as well !(m_keyboard || m_touch || m_tabletPad || m_tabletTool) && // is this a touch pad? We don't really know, let's do some assumptions (m_tapFingerCount > 0 || m_supportsDisableWhileTyping || m_supportsDisableEventsOnExternalMouse); } bool isTouch() const { return m_touch; } bool isTabletTool() const { return m_tabletTool; } bool isTabletPad() const { return m_tabletPad; } bool supportsGesture() const { return m_supportsGesture; } QString name() const { return m_name; } QString sysName() const { return m_sysName; } QString outputName() const { return m_outputName; } QSizeF size() const { return m_size; } quint32 product() const { return m_product; } quint32 vendor() const { return m_vendor; } Qt::MouseButtons supportedButtons() const { return m_supportedButtons; } int tapFingerCount() const { return m_tapFingerCount; } bool tapToClickEnabledByDefault() const { return m_tapToClickEnabledByDefault; } bool isTapToClick() const { return m_tapToClick; } /** * Set the Device to tap to click if @p set is @c true. **/ void setTapToClick(bool set); bool tapAndDragEnabledByDefault() const { return m_tapAndDragEnabledByDefault; } bool isTapAndDrag() const { return m_tapAndDrag; } void setTapAndDrag(bool set); bool tapDragLockEnabledByDefault() const { return m_tapDragLockEnabledByDefault; } bool isTapDragLock() const { return m_tapDragLock; } void setTapDragLock(bool set); bool supportsDisableWhileTyping() const { return m_supportsDisableWhileTyping; } bool disableWhileTypingEnabledByDefault() const { return m_disableWhileTypingEnabledByDefault; } bool supportsPointerAcceleration() const { return m_supportsPointerAcceleration; } bool supportsLeftHanded() const { return m_supportsLeftHanded; } bool supportsCalibrationMatrix() const { return m_supportsCalibrationMatrix; } bool supportsDisableEvents() const { return m_supportsDisableEvents; } bool supportsDisableEventsOnExternalMouse() const { return m_supportsDisableEventsOnExternalMouse; } bool supportsMiddleEmulation() const { return m_supportsMiddleEmulation; } bool supportsNaturalScroll() const { return m_supportsNaturalScroll; } bool supportsScrollTwoFinger() const { return (m_supportedScrollMethods & LIBINPUT_CONFIG_SCROLL_2FG); } bool supportsScrollEdge() const { return (m_supportedScrollMethods & LIBINPUT_CONFIG_SCROLL_EDGE); } bool supportsScrollOnButtonDown() const { return (m_supportedScrollMethods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); } bool leftHandedEnabledByDefault() const { return m_leftHandedEnabledByDefault; } bool middleEmulationEnabledByDefault() const { return m_middleEmulationEnabledByDefault; } bool naturalScrollEnabledByDefault() const { return m_naturalScrollEnabledByDefault; } enum libinput_config_scroll_method defaultScrollMethod() const { return m_defaultScrollMethod; } quint32 defaultScrollMethodToInt() const { return (quint32) m_defaultScrollMethod; } bool scrollTwoFingerEnabledByDefault() const { return m_defaultScrollMethod == LIBINPUT_CONFIG_SCROLL_2FG; } bool scrollEdgeEnabledByDefault() const { return m_defaultScrollMethod == LIBINPUT_CONFIG_SCROLL_EDGE; } bool scrollOnButtonDownEnabledByDefault() const { return m_defaultScrollMethod == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; } bool supportsLmrTapButtonMap() const { return m_tapFingerCount > 1; } bool lmrTapButtonMapEnabledByDefault() const { return m_defaultTapButtonMap == LIBINPUT_CONFIG_TAP_MAP_LMR; } void setLmrTapButtonMap(bool set); bool lmrTapButtonMap() const { return m_tapButtonMap & LIBINPUT_CONFIG_TAP_MAP_LMR; } quint32 defaultScrollButton() const { return m_defaultScrollButton; } bool isMiddleEmulation() const { return m_middleEmulation; } void setMiddleEmulation(bool set); bool isNaturalScroll() const { return m_naturalScroll; } void setNaturalScroll(bool set); void setScrollMethod(bool set, enum libinput_config_scroll_method method); bool isScrollTwoFinger() const { return m_scrollMethod & LIBINPUT_CONFIG_SCROLL_2FG; } void setScrollTwoFinger(bool set) { setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_2FG); } bool isScrollEdge() const { return m_scrollMethod & LIBINPUT_CONFIG_SCROLL_EDGE; } void setScrollEdge(bool set) { setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_EDGE); } bool isScrollOnButtonDown() const { return m_scrollMethod & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; } void setScrollOnButtonDown(bool set) { setScrollMethod(set, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN); } void activateScrollMethodFromInt(quint32 method) { setScrollMethod(true, (libinput_config_scroll_method) method); } quint32 scrollButton() const { return m_scrollButton; } void setScrollButton(quint32 button); void setDisableWhileTyping(bool set); bool isDisableWhileTyping() const { return m_disableWhileTyping; } bool isLeftHanded() const { return m_leftHanded; } /** * Sets the Device to left handed mode if @p set is @c true. * If @p set is @c false the device is set to right handed mode **/ void setLeftHanded(bool set); qreal defaultPointerAcceleration() const { return m_defaultPointerAcceleration; } qreal pointerAcceleration() const { return m_pointerAcceleration; } /** * @param acceleration mapped to range [-1,1] with -1 being the slowest, 1 being the fastest supported acceleration. **/ void setPointerAcceleration(qreal acceleration); void setPointerAccelerationFromString(QString acceleration) { setPointerAcceleration(acceleration.toDouble()); } QString defaultPointerAccelerationToString() const { return QString::number(m_pointerAcceleration, 'f', 3); } bool supportsPointerAccelerationProfileFlat() const { return (m_supportedPointerAccelerationProfiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT); } bool supportsPointerAccelerationProfileAdaptive() const { return (m_supportedPointerAccelerationProfiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE); } bool defaultPointerAccelerationProfileFlat() const { return (m_defaultPointerAccelerationProfile & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT); } bool defaultPointerAccelerationProfileAdaptive() const { return (m_defaultPointerAccelerationProfile & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE); } bool pointerAccelerationProfileFlat() const { return (m_pointerAccelerationProfile & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT); } bool pointerAccelerationProfileAdaptive() const { return (m_pointerAccelerationProfile & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE); } void setPointerAccelerationProfile(bool set, enum libinput_config_accel_profile profile); void setPointerAccelerationProfileFlat(bool set) { setPointerAccelerationProfile(set, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT); } void setPointerAccelerationProfileAdaptive(bool set) { setPointerAccelerationProfile(set, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE); } void setPointerAccelerationProfileFromInt(quint32 profile) { setPointerAccelerationProfile(true, (libinput_config_accel_profile) profile); } quint32 defaultPointerAccelerationProfileToInt() const { return (quint32) m_defaultPointerAccelerationProfile; } + bool supportsClickMethodAreas() const { + return (m_supportedClickMethods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + } + bool defaultClickMethodAreas() const { + return (m_defaultClickMethod == LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + } + bool isClickMethodAreas() const { + return (m_clickMethod == LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + } + bool supportsClickMethodClickfinger() const { + return (m_supportedClickMethods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + } + bool defaultClickMethodClickfinger() const { + return (m_defaultClickMethod == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + } + bool isClickMethodClickfinger() const { + return (m_clickMethod == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + } + void setClickMethod(bool set, enum libinput_config_click_method method); + void setClickMethodAreas(bool set) { + setClickMethod(set, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + } + void setClickMethodClickfinger(bool set) { + setClickMethod(set, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + } + void setClickMethodFromInt(quint32 method) { + setClickMethod(true, (libinput_config_click_method) method); + } + quint32 defaultClickMethodToInt() const { + return (quint32) m_defaultClickMethod; + } + bool isEnabled() const { return m_enabled; } void setEnabled(bool enabled); libinput_device *device() const { 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; } /** * The id of the screen in KWin identifiers. Set from KWin through @link setScreenId. **/ int screenId() const { return m_screenId; } /** * Sets the KWin screen id for the device **/ void setScreenId(int screenId) { m_screenId = screenId; } void setOrientation(Qt::ScreenOrientation orientation); /** * Loads the configuration and applies it to the Device **/ void loadConfiguration(); bool isSwitch() const { return m_switch; } bool isLidSwitch() const { return m_lidSwitch; } bool isTabletModeSwitch() const { return m_tabletSwitch; } /** * All created Devices **/ static QVector devices() { return s_devices; } /** * Gets the Device for @p native. @c null if there is no Device for @p native. **/ static Device *getDevice(libinput_device *native); Q_SIGNALS: void tapButtonMapChanged(); void leftHandedChanged(); void disableWhileTypingChanged(); void pointerAccelerationChanged(); void pointerAccelerationProfileChanged(); void enabledChanged(); void tapToClickChanged(); void tapAndDragChanged(); void tapDragLockChanged(); void middleEmulationChanged(); void naturalScrollChanged(); void scrollMethodChanged(); void scrollButtonChanged(); + void clickMethodChanged(); 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; bool m_pointer; bool m_touch; bool m_tabletTool; bool m_tabletPad; bool m_supportsGesture; bool m_switch = false; bool m_lidSwitch = false; bool m_tabletSwitch = false; QString m_name; QString m_sysName; QString m_outputName; QSizeF m_size; quint32 m_product; quint32 m_vendor; Qt::MouseButtons m_supportedButtons = Qt::NoButton; int m_tapFingerCount; enum libinput_config_tap_button_map m_defaultTapButtonMap; enum libinput_config_tap_button_map m_tapButtonMap; bool m_tapToClickEnabledByDefault; bool m_tapToClick; bool m_tapAndDragEnabledByDefault; bool m_tapAndDrag; bool m_tapDragLockEnabledByDefault; bool m_tapDragLock; bool m_supportsDisableWhileTyping; bool m_supportsPointerAcceleration; bool m_supportsLeftHanded; bool m_supportsCalibrationMatrix; bool m_supportsDisableEvents; bool m_supportsDisableEventsOnExternalMouse; bool m_supportsMiddleEmulation; bool m_supportsNaturalScroll; quint32 m_supportedScrollMethods; bool m_supportsScrollEdge; bool m_supportsScrollOnButtonDown; bool m_leftHandedEnabledByDefault; bool m_middleEmulationEnabledByDefault; bool m_naturalScrollEnabledByDefault; enum libinput_config_scroll_method m_defaultScrollMethod; quint32 m_defaultScrollButton; bool m_disableWhileTypingEnabledByDefault; bool m_disableWhileTyping; bool m_middleEmulation; bool m_leftHanded; bool m_naturalScroll; enum libinput_config_scroll_method m_scrollMethod; quint32 m_scrollButton; qreal m_defaultPointerAcceleration; qreal m_pointerAcceleration; quint32 m_supportedPointerAccelerationProfiles; enum libinput_config_accel_profile m_defaultPointerAccelerationProfile; enum libinput_config_accel_profile m_pointerAccelerationProfile; bool m_enabled; KConfigGroup m_config; bool m_loading = false; int m_screenId = 0; Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation; QMatrix4x4 m_defaultCalibrationMatrix; + quint32 m_supportedClickMethods; + enum libinput_config_click_method m_defaultClickMethod; + enum libinput_config_click_method m_clickMethod; static QVector s_devices; }; } } Q_DECLARE_METATYPE(KWin::LibInput::Device*) #endif