File indexing completed on 2024-11-10 04:56:14

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "mock_libinput.h"
0010 
0011 #include "backends/libinput/device.h"
0012 #include "backends/libinput/events.h"
0013 
0014 #include <QTest>
0015 
0016 #include <linux/input.h>
0017 
0018 Q_DECLARE_METATYPE(libinput_event_type)
0019 Q_DECLARE_METATYPE(libinput_button_state)
0020 
0021 using namespace KWin::LibInput;
0022 using namespace std::literals;
0023 
0024 class TestLibinputPointerEvent : public QObject
0025 {
0026     Q_OBJECT
0027 private Q_SLOTS:
0028     void init();
0029     void cleanup();
0030 
0031     void testType_data();
0032     void testType();
0033     void testButton_data();
0034     void testButton();
0035     void testScrollWheel_data();
0036     void testScrollWheel();
0037     void testScrollFinger_data();
0038     void testScrollFinger();
0039     void testScrollContinuous_data();
0040     void testScrollContinuous();
0041     void testMotion();
0042     void testAbsoluteMotion();
0043 
0044 private:
0045     libinput_device *m_nativeDevice = nullptr;
0046     Device *m_device = nullptr;
0047 };
0048 
0049 void TestLibinputPointerEvent::init()
0050 {
0051     m_nativeDevice = new libinput_device;
0052     m_nativeDevice->pointer = true;
0053     m_nativeDevice->deviceSize = QSizeF(12.5, 13.8);
0054     m_device = new Device(m_nativeDevice);
0055 }
0056 
0057 void TestLibinputPointerEvent::cleanup()
0058 {
0059     delete m_device;
0060     m_device = nullptr;
0061 
0062     delete m_nativeDevice;
0063     m_nativeDevice = nullptr;
0064 }
0065 
0066 void TestLibinputPointerEvent::testType_data()
0067 {
0068     QTest::addColumn<libinput_event_type>("type");
0069 
0070     QTest::newRow("motion") << LIBINPUT_EVENT_POINTER_MOTION;
0071     QTest::newRow("absolute motion") << LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE;
0072     QTest::newRow("button") << LIBINPUT_EVENT_POINTER_BUTTON;
0073     QTest::newRow("scroll wheel") << LIBINPUT_EVENT_POINTER_SCROLL_WHEEL;
0074     QTest::newRow("scroll finger") << LIBINPUT_EVENT_POINTER_SCROLL_FINGER;
0075     QTest::newRow("scroll continuous") << LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS;
0076 }
0077 
0078 void TestLibinputPointerEvent::testType()
0079 {
0080     // this test verifies the initialization of a PointerEvent and the parent Event class
0081     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0082     QFETCH(libinput_event_type, type);
0083     pointerEvent->type = type;
0084     pointerEvent->device = m_nativeDevice;
0085 
0086     std::unique_ptr<Event> event(Event::create(pointerEvent));
0087     // API of event
0088     QCOMPARE(event->type(), type);
0089     QCOMPARE(event->device(), m_device);
0090     QCOMPARE(event->nativeDevice(), m_nativeDevice);
0091     QCOMPARE((libinput_event *)(*event.get()), pointerEvent);
0092     // verify it's a pointer event
0093     QVERIFY(dynamic_cast<PointerEvent *>(event.get()));
0094     QCOMPARE((libinput_event_pointer *)(*dynamic_cast<PointerEvent *>(event.get())), pointerEvent);
0095 }
0096 
0097 void TestLibinputPointerEvent::testButton_data()
0098 {
0099     QTest::addColumn<libinput_button_state>("buttonState");
0100     QTest::addColumn<KWin::InputRedirection::PointerButtonState>("expectedButtonState");
0101     QTest::addColumn<quint32>("button");
0102     QTest::addColumn<quint32>("time");
0103 
0104     QTest::newRow("pressed") << LIBINPUT_BUTTON_STATE_RELEASED << KWin::InputRedirection::PointerButtonReleased << quint32(BTN_RIGHT) << 100u;
0105     QTest::newRow("released") << LIBINPUT_BUTTON_STATE_PRESSED << KWin::InputRedirection::PointerButtonPressed << quint32(BTN_LEFT) << 200u;
0106 }
0107 
0108 void TestLibinputPointerEvent::testButton()
0109 {
0110     // this test verifies the button press/release
0111     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0112     pointerEvent->device = m_nativeDevice;
0113     pointerEvent->type = LIBINPUT_EVENT_POINTER_BUTTON;
0114     QFETCH(libinput_button_state, buttonState);
0115     pointerEvent->buttonState = buttonState;
0116     QFETCH(quint32, button);
0117     pointerEvent->button = button;
0118     QFETCH(quint32, time);
0119     pointerEvent->time = std::chrono::milliseconds(time);
0120 
0121     std::unique_ptr<Event> event(Event::create(pointerEvent));
0122     auto pe = dynamic_cast<PointerEvent *>(event.get());
0123     QVERIFY(pe);
0124     QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_BUTTON);
0125     QTEST(pe->buttonState(), "expectedButtonState");
0126     QCOMPARE(pe->button(), button);
0127     QCOMPARE(pe->time(), pointerEvent->time);
0128 }
0129 
0130 void TestLibinputPointerEvent::testScrollWheel_data()
0131 {
0132     QTest::addColumn<bool>("horizontal");
0133     QTest::addColumn<bool>("vertical");
0134     QTest::addColumn<QPointF>("value");
0135     QTest::addColumn<QPoint>("valueV120");
0136     QTest::addColumn<quint32>("time");
0137 
0138     QTest::newRow("wheel/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(120, 0) << 100u;
0139     QTest::newRow("wheel/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 120) << 200u;
0140     QTest::newRow("wheel/both") << true << true << QPointF(1.1, 4.2) << QPoint(120, 120) << 300u;
0141 }
0142 
0143 void TestLibinputPointerEvent::testScrollWheel()
0144 {
0145     // this test verifies pointer axis functionality
0146     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0147     pointerEvent->device = m_nativeDevice;
0148     pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_WHEEL;
0149     QFETCH(bool, horizontal);
0150     QFETCH(bool, vertical);
0151     QFETCH(QPointF, value);
0152     QFETCH(QPoint, valueV120);
0153     QFETCH(quint32, time);
0154     pointerEvent->horizontalAxis = horizontal;
0155     pointerEvent->verticalAxis = vertical;
0156     pointerEvent->horizontalScrollValue = value.x();
0157     pointerEvent->verticalScrollValue = value.y();
0158     pointerEvent->horizontalScrollValueV120 = valueV120.x();
0159     pointerEvent->verticalScrollValueV120 = valueV120.y();
0160     pointerEvent->time = std::chrono::milliseconds(time);
0161 
0162     std::unique_ptr<Event> event(Event::create(pointerEvent));
0163     auto pe = dynamic_cast<PointerEvent *>(event.get());
0164     QVERIFY(pe);
0165     QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_WHEEL);
0166     QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal);
0167     QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical);
0168     QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
0169     QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y());
0170     QCOMPARE(pe->scrollValueV120(KWin::InputRedirection::PointerAxisHorizontal), valueV120.x());
0171     QCOMPARE(pe->scrollValueV120(KWin::InputRedirection::PointerAxisVertical), valueV120.y());
0172     QCOMPARE(pe->time(), pointerEvent->time);
0173 }
0174 
0175 void TestLibinputPointerEvent::testScrollFinger_data()
0176 {
0177     QTest::addColumn<bool>("horizontal");
0178     QTest::addColumn<bool>("vertical");
0179     QTest::addColumn<QPointF>("value");
0180     QTest::addColumn<quint32>("time");
0181 
0182     QTest::newRow("finger/horizontal") << true << false << QPointF(3.0, 0.0) << 400u;
0183     QTest::newRow("stop finger/horizontal") << true << false << QPointF(0.0, 0.0) << 500u;
0184     QTest::newRow("finger/vertical") << false << true << QPointF(0.0, 2.5) << 600u;
0185     QTest::newRow("stop finger/vertical") << false << true << QPointF(0.0, 0.0) << 700u;
0186     QTest::newRow("finger/both") << true << true << QPointF(1.1, 4.2) << 800u;
0187     QTest::newRow("stop finger/both") << true << true << QPointF(0.0, 0.0) << 900u;
0188 }
0189 
0190 void TestLibinputPointerEvent::testScrollFinger()
0191 {
0192     // this test verifies pointer axis functionality
0193     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0194     pointerEvent->device = m_nativeDevice;
0195     pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_FINGER;
0196     QFETCH(bool, horizontal);
0197     QFETCH(bool, vertical);
0198     QFETCH(QPointF, value);
0199     QFETCH(quint32, time);
0200     pointerEvent->horizontalAxis = horizontal;
0201     pointerEvent->verticalAxis = vertical;
0202     pointerEvent->horizontalScrollValue = value.x();
0203     pointerEvent->verticalScrollValue = value.y();
0204     pointerEvent->time = std::chrono::milliseconds(time);
0205 
0206     std::unique_ptr<Event> event(Event::create(pointerEvent));
0207     auto pe = dynamic_cast<PointerEvent *>(event.get());
0208     QVERIFY(pe);
0209     QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_FINGER);
0210     QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal);
0211     QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical);
0212     QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
0213     QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y());
0214     QCOMPARE(pe->time(), pointerEvent->time);
0215 }
0216 
0217 void TestLibinputPointerEvent::testScrollContinuous_data()
0218 {
0219     QTest::addColumn<bool>("horizontal");
0220     QTest::addColumn<bool>("vertical");
0221     QTest::addColumn<QPointF>("value");
0222     QTest::addColumn<quint32>("time");
0223 
0224     QTest::newRow("continuous/horizontal") << true << false << QPointF(3.0, 0.0) << 1000u;
0225     QTest::newRow("continuous/vertical") << false << true << QPointF(0.0, 2.5) << 1100u;
0226     QTest::newRow("continuous/both") << true << true << QPointF(1.1, 4.2) << 1200u;
0227 }
0228 
0229 void TestLibinputPointerEvent::testScrollContinuous()
0230 {
0231     // this test verifies pointer axis functionality
0232     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0233     pointerEvent->device = m_nativeDevice;
0234     pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS;
0235     QFETCH(bool, horizontal);
0236     QFETCH(bool, vertical);
0237     QFETCH(QPointF, value);
0238     QFETCH(quint32, time);
0239     pointerEvent->horizontalAxis = horizontal;
0240     pointerEvent->verticalAxis = vertical;
0241     pointerEvent->horizontalScrollValue = value.x();
0242     pointerEvent->verticalScrollValue = value.y();
0243     pointerEvent->time = std::chrono::milliseconds(time);
0244 
0245     std::unique_ptr<Event> event(Event::create(pointerEvent));
0246     auto pe = dynamic_cast<PointerEvent *>(event.get());
0247     QVERIFY(pe);
0248     QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
0249     QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal);
0250     QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical);
0251     QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
0252     QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y());
0253     QCOMPARE(pe->time(), pointerEvent->time);
0254 }
0255 
0256 void TestLibinputPointerEvent::testMotion()
0257 {
0258     // this test verifies pointer motion (delta)
0259     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0260     pointerEvent->device = m_nativeDevice;
0261     pointerEvent->type = LIBINPUT_EVENT_POINTER_MOTION;
0262     pointerEvent->delta = QPointF(2.1, 4.5);
0263     pointerEvent->time = 500ms;
0264 
0265     std::unique_ptr<Event> event(Event::create(pointerEvent));
0266     auto pe = dynamic_cast<PointerEvent *>(event.get());
0267     QVERIFY(pe);
0268     QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_MOTION);
0269     QCOMPARE(pe->time(), pointerEvent->time);
0270     QCOMPARE(pe->delta(), QPointF(2.1, 4.5));
0271 }
0272 
0273 void TestLibinputPointerEvent::testAbsoluteMotion()
0274 {
0275     // this test verifies absolute pointer motion
0276     libinput_event_pointer *pointerEvent = new libinput_event_pointer;
0277     pointerEvent->device = m_nativeDevice;
0278     pointerEvent->type = LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE;
0279     pointerEvent->absolutePos = QPointF(6.25, 6.9);
0280     pointerEvent->time = 500ms;
0281 
0282     std::unique_ptr<Event> event(Event::create(pointerEvent));
0283     auto pe = dynamic_cast<PointerEvent *>(event.get());
0284     QVERIFY(pe);
0285     QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
0286     QCOMPARE(pe->time(), pointerEvent->time);
0287     QCOMPARE(pe->absolutePos(), QPointF(6.25, 6.9));
0288     QCOMPARE(pe->absolutePos(QSize(1280, 1024)), QPointF(640, 512));
0289 }
0290 
0291 QTEST_GUILESS_MAIN(TestLibinputPointerEvent)
0292 #include "pointer_event_test.moc"