File indexing completed on 2024-04-28 03:58:57

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2021 Steffen Hartleib <steffenhartleib@t-online.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include <ktwofingerswipe.h>
0009 
0010 #include <QTest>
0011 #include <QSignalSpy>
0012 #include <QWidget>
0013 #include <QMainWindow>
0014 
0015 class KTwoFingerSwipeTest : public QObject
0016 {
0017     Q_OBJECT
0018 
0019     QPointingDevice *mDev = nullptr;
0020 
0021     QMainWindow mMainWindow;
0022     QWidget mWidget;
0023     KTwoFingerSwipeRecognizer *mTwoFingerRec = nullptr;
0024     Qt::GestureType mKTwoFingerSwipeGesture;
0025     QPoint mTouchPointPos = QPoint(200, 200);
0026     QSignalSpy *mSpySwipeFinished = nullptr;
0027     QSignalSpy *mSpySwipeStarted = nullptr;
0028     QSignalSpy *mSpySwipeUpdated = nullptr;
0029     QSignalSpy *mSpySwipeCanceled = nullptr;
0030     qreal mAngel = 0.0;
0031 
0032 Q_SIGNALS:
0033     void swipeStarted(KTwoFingerSwipe *);
0034     void swipeFinished(KTwoFingerSwipe *);
0035     void swipeUpdated(KTwoFingerSwipe *);
0036     void swipeCanceled(KTwoFingerSwipe *);
0037 
0038 protected:
0039     bool eventFilter(QObject *watched, QEvent *e) override
0040     {
0041         if (e->type() == QEvent::Gesture) {
0042             QGestureEvent *gEvent = static_cast<QGestureEvent *>(e);
0043             KTwoFingerSwipe *swipe = static_cast<KTwoFingerSwipe *>(gEvent->gesture(mKTwoFingerSwipeGesture));
0044             if (swipe) {
0045                 const Qt::GestureState state = swipe->state();
0046                 if (state == Qt::GestureFinished) {
0047                     Q_EMIT swipeFinished(swipe);
0048                 } else if (state == Qt::GestureStarted) {
0049                     Q_EMIT swipeStarted(swipe);
0050                 } else if (state == Qt::GestureUpdated) {
0051                     Q_EMIT swipeUpdated(swipe);
0052                 } else if (state == Qt::GestureCanceled) {
0053                     Q_EMIT swipeCanceled(swipe);
0054                 }
0055             }
0056             e->accept();
0057             return true;
0058         }
0059         return QObject::eventFilter(watched, e);
0060     }
0061 
0062 protected Q_SLOTS:
0063     void slotSwipeFinished (KTwoFingerSwipe *swipe)
0064     {
0065         compareGesturePositions(swipe);
0066     }
0067     void slotSwipeStarted (KTwoFingerSwipe *swipe)
0068     {
0069         compareGesturePositions(swipe);
0070     }
0071     void slotSwipeUpdated (KTwoFingerSwipe *swipe)
0072     {
0073         compareGesturePositions(swipe);
0074     }
0075     void slotSwipeCanceled (KTwoFingerSwipe *swipe)
0076     {
0077         compareGesturePositions(swipe);
0078     }
0079 private:
0080     void compareGesturePositions(KTwoFingerSwipe *swipe)
0081     {
0082         QCOMPARE(swipe->pos(), mTouchPointPos);
0083         QCOMPARE(swipe->screenPos(), mWidget.mapToGlobal(mTouchPointPos));
0084         QCOMPARE(swipe->hotSpot(), mWidget.mapToGlobal(mTouchPointPos));
0085         QCOMPARE(swipe->scenePos(), mWidget.mapToGlobal(mTouchPointPos));
0086         QVERIFY(swipe->hasHotSpot());
0087         mAngel = swipe->swipeAngle();
0088     }
0089 
0090     void clearSignalSpys()
0091     {
0092         mSpySwipeFinished->clear();
0093         mSpySwipeCanceled->clear();
0094         mSpySwipeUpdated->clear();
0095         mSpySwipeStarted->clear();
0096     }
0097 
0098 private Q_SLOTS:
0099     void cleanupTestCase()
0100     {
0101         delete mSpySwipeFinished;
0102         delete mSpySwipeCanceled;
0103         delete mSpySwipeUpdated;
0104         delete mSpySwipeStarted;
0105     }
0106     void initTestCase()
0107     {
0108         mDev = QTest::createTouchDevice();
0109 
0110         mMainWindow.setGeometry(0, 0, 500, 500);
0111         mMainWindow.setCentralWidget(&mWidget);
0112         mMainWindow.show();
0113 
0114         mWidget.installEventFilter(this);
0115         mWidget.setAttribute(Qt::WA_AcceptTouchEvents);
0116 
0117         QVERIFY(QTest::qWaitForWindowActive(&mMainWindow));
0118         QVERIFY(QTest::qWaitForWindowActive(&mWidget));
0119 
0120         mTwoFingerRec = new KTwoFingerSwipeRecognizer();
0121         QVERIFY(mTwoFingerRec);
0122 
0123         mKTwoFingerSwipeGesture = QGestureRecognizer::registerRecognizer(mTwoFingerRec);
0124         QVERIFY(mKTwoFingerSwipeGesture & Qt::CustomGesture);
0125 
0126         mWidget.grabGesture(mKTwoFingerSwipeGesture);
0127 
0128         connect(this, &KTwoFingerSwipeTest::swipeFinished, this, &KTwoFingerSwipeTest::slotSwipeFinished);
0129         connect(this, &KTwoFingerSwipeTest::swipeStarted, this, &KTwoFingerSwipeTest::slotSwipeStarted);
0130         connect(this, &KTwoFingerSwipeTest::swipeUpdated, this, &KTwoFingerSwipeTest::slotSwipeUpdated);
0131         connect(this, &KTwoFingerSwipeTest::swipeCanceled, this, &KTwoFingerSwipeTest::slotSwipeCanceled);
0132 
0133         mSpySwipeFinished = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeFinished);
0134         QVERIFY(mSpySwipeFinished->isValid());
0135 
0136         mSpySwipeStarted = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeStarted);
0137         QVERIFY(mSpySwipeStarted->isValid());
0138 
0139         mSpySwipeUpdated = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeUpdated);
0140         QVERIFY(mSpySwipeUpdated->isValid());
0141 
0142         mSpySwipeCanceled = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeCanceled);
0143         QVERIFY(mSpySwipeCanceled->isValid());
0144 
0145         QTest::qWait(1000);
0146     }
0147 
0148     void testChangeTimeAndDistance()
0149     {
0150         QVERIFY(mTwoFingerRec->maxSwipeTime() >= 0);
0151         mTwoFingerRec->setMaxSwipeTime(10);
0152         QCOMPARE(mTwoFingerRec->maxSwipeTime(), 10);
0153         mTwoFingerRec->setMaxSwipeTime(-10);
0154         QCOMPARE(mTwoFingerRec->maxSwipeTime(), 0);
0155         mTwoFingerRec->setMaxSwipeTime(90);
0156         QCOMPARE(mTwoFingerRec->maxSwipeTime(), 90);
0157 
0158         QVERIFY(mTwoFingerRec->minSswipeDistance() >= 0);
0159         mTwoFingerRec->setSwipeDistance(10);
0160         QCOMPARE(mTwoFingerRec->minSswipeDistance(), 10);
0161         mTwoFingerRec->setSwipeDistance(-10);
0162         QCOMPARE(mTwoFingerRec->minSswipeDistance(), 0);
0163         mTwoFingerRec->setSwipeDistance(30);
0164         QCOMPARE(mTwoFingerRec->minSswipeDistance(), 30);
0165     }
0166 
0167     void testSuccessfulGesture_right()
0168     {
0169         clearSignalSpys();
0170 
0171         const int length = mTwoFingerRec->minSswipeDistance();
0172         const QPoint swipeDistance = QPoint(length, 0);
0173 
0174         QTest::touchEvent(&mWidget, mDev)
0175             .press(0, mTouchPointPos, (QWidget *) nullptr)
0176             .press(1, mTouchPointPos, (QWidget *) nullptr);
0177 
0178         QTest::touchEvent(&mWidget, mDev)
0179             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0180             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0181 
0182 
0183         QTest::touchEvent(&mWidget, mDev)
0184             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0185             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0186 
0187         QTest::touchEvent(&mWidget, mDev)
0188             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0189             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0190 
0191         QTest::touchEvent(&mWidget, mDev)
0192             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0193             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0194 
0195         if (mSpySwipeStarted->count() == 0) {
0196             QVERIFY(mSpySwipeStarted->wait(1000));
0197         }
0198 
0199         QCOMPARE(mSpySwipeStarted->count(), 1);
0200         QCOMPARE(mSpySwipeFinished->count(), 1);
0201         QCOMPARE(mSpySwipeCanceled->count(), 0);
0202         QVERIFY(mSpySwipeUpdated->count() > 0);
0203         QCOMPARE(mAngel, 0);
0204     }
0205 
0206     void testSuccessfulGesture_left()
0207     {
0208         clearSignalSpys();
0209 
0210         const int length = mTwoFingerRec->minSswipeDistance();
0211         const QPoint swipeDistance = QPoint(-length, 0);
0212 
0213         QTest::touchEvent(&mWidget, mDev)
0214             .press(0, mTouchPointPos, (QWidget *) nullptr)
0215             .press(1, mTouchPointPos, (QWidget *) nullptr);
0216 
0217         QTest::touchEvent(&mWidget, mDev)
0218             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0219             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0220 
0221 
0222         QTest::touchEvent(&mWidget, mDev)
0223             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0224             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0225 
0226         QTest::touchEvent(&mWidget, mDev)
0227             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0228             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0229 
0230         QTest::touchEvent(&mWidget, mDev)
0231             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0232             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0233 
0234         if (mSpySwipeStarted->count() == 0) {
0235             QVERIFY(mSpySwipeStarted->wait(1000));
0236         }
0237 
0238         QCOMPARE(mSpySwipeStarted->count(), 1);
0239         QCOMPARE(mSpySwipeFinished->count(), 1);
0240         QCOMPARE(mSpySwipeCanceled->count(), 0);
0241         QVERIFY(mSpySwipeUpdated->count() > 0);
0242         QCOMPARE(mAngel, 180);
0243     }
0244 
0245     void testSuccessfulGesture_up()
0246     {
0247         clearSignalSpys();
0248 
0249         const int length = mTwoFingerRec->minSswipeDistance();
0250         const QPoint swipeDistance = QPoint(0, -length);
0251 
0252         QTest::touchEvent(&mWidget, mDev)
0253             .press(0, mTouchPointPos, (QWidget *) nullptr)
0254             .press(1, mTouchPointPos, (QWidget *) nullptr);
0255 
0256         QTest::touchEvent(&mWidget, mDev)
0257             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0258             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0259 
0260 
0261         QTest::touchEvent(&mWidget, mDev)
0262             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0263             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0264 
0265         QTest::touchEvent(&mWidget, mDev)
0266             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0267             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0268 
0269         QTest::touchEvent(&mWidget, mDev)
0270             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0271             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0272 
0273         if (mSpySwipeStarted->count() == 0) {
0274             QVERIFY(mSpySwipeStarted->wait(1000));
0275         }
0276 
0277         QCOMPARE(mSpySwipeStarted->count(), 1);
0278         QCOMPARE(mSpySwipeFinished->count(), 1);
0279         QCOMPARE(mSpySwipeCanceled->count(), 0);
0280         QVERIFY(mSpySwipeUpdated->count() > 0);
0281         QCOMPARE(mAngel, 90);
0282     }
0283 
0284     void testSuccessfulGesture_down()
0285     {
0286         clearSignalSpys();
0287 
0288         const int length = mTwoFingerRec->minSswipeDistance();
0289         const QPoint swipeDistance = QPoint(0, length);
0290 
0291         QTest::touchEvent(&mWidget, mDev)
0292             .press(0, mTouchPointPos, (QWidget *) nullptr)
0293             .press(1, mTouchPointPos, (QWidget *) nullptr);
0294 
0295         QTest::touchEvent(&mWidget, mDev)
0296             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0297             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0298 
0299 
0300         QTest::touchEvent(&mWidget, mDev)
0301             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0302             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0303 
0304         QTest::touchEvent(&mWidget, mDev)
0305             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0306             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0307 
0308         QTest::touchEvent(&mWidget, mDev)
0309             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0310             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0311 
0312         if (mSpySwipeStarted->count() == 0) {
0313             QVERIFY(mSpySwipeStarted->wait(1000));
0314         }
0315 
0316         QCOMPARE(mSpySwipeStarted->count(), 1);
0317         QCOMPARE(mSpySwipeFinished->count(), 1);
0318         QCOMPARE(mSpySwipeCanceled->count(), 0);
0319         QVERIFY(mSpySwipeUpdated->count() > 0);
0320         QCOMPARE(mAngel, 270);
0321     }
0322 
0323     void testFailingGesture_toSlow()
0324     {
0325         clearSignalSpys();
0326 
0327         const int length = mTwoFingerRec->minSswipeDistance() / 3;
0328         const QPoint swipeDistance = QPoint(length, 0);
0329 
0330         QTest::touchEvent(&mWidget, mDev)
0331             .press(0, mTouchPointPos, (QWidget *) nullptr)
0332             .press(1, mTouchPointPos, (QWidget *) nullptr);
0333 
0334         QTest::touchEvent(&mWidget, mDev)
0335             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0336             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0337 
0338 
0339         QTest::touchEvent(&mWidget, mDev)
0340             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0341             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0342 
0343         QTest::touchEvent(&mWidget, mDev)
0344             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0345             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0346 
0347         QTest::touchEvent(&mWidget, mDev)
0348             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0349             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0350 
0351         if (mSpySwipeStarted->count() == 0) {
0352             QVERIFY(mSpySwipeStarted->wait(1000));
0353         }
0354 
0355         QCOMPARE(mSpySwipeStarted->count(), 1);
0356         QCOMPARE(mSpySwipeFinished->count(), 0);
0357         QCOMPARE(mSpySwipeCanceled->count(), 1);
0358         QVERIFY(mSpySwipeUpdated->count() > 0);
0359         QCOMPARE(mAngel, 0);
0360     }
0361 
0362 
0363     void testFailingGesture_threeFingers()
0364     {
0365         clearSignalSpys();
0366 
0367         const int length = mTwoFingerRec->minSswipeDistance();
0368         const QPoint swipeDistance = QPoint(length, 0);
0369 
0370         QTest::touchEvent(&mWidget, mDev)
0371             .press(0, mTouchPointPos, (QWidget *) nullptr)
0372             .press(1, mTouchPointPos, (QWidget *) nullptr);
0373 
0374         QTest::touchEvent(&mWidget, mDev)
0375             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0376             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0377 
0378         QTest::touchEvent(&mWidget, mDev)
0379             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0380             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0381             .press(2, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0382 
0383         QTest::touchEvent(&mWidget, mDev)
0384             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0385             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0386             .move(2, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0387 
0388         QTest::touchEvent(&mWidget, mDev)
0389             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0390             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0391             .release(2, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0392 
0393         if (mSpySwipeCanceled->count() == 0) {
0394             QVERIFY(mSpySwipeCanceled->wait(1000));
0395         }
0396 
0397         QCOMPARE(mSpySwipeStarted->count(), 1);
0398         QCOMPARE(mSpySwipeFinished->count(), 0);
0399         QCOMPARE(mSpySwipeCanceled->count(), 1);
0400         QVERIFY(mSpySwipeUpdated->count() >= 0);
0401         QCOMPARE(mAngel, 0);
0402     }
0403 
0404     void testFailingGesture_oneFinger()
0405     {
0406         clearSignalSpys();
0407 
0408         const int length = mTwoFingerRec->minSswipeDistance();
0409         const QPoint swipeDistance = QPoint(length, 0);
0410 
0411         QTest::touchEvent(&mWidget, mDev)
0412             .press(0, mTouchPointPos, (QWidget *) nullptr);
0413 
0414         QTest::touchEvent(&mWidget, mDev)
0415             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0416 
0417         QTest::touchEvent(&mWidget, mDev)
0418             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0419 
0420         QTest::touchEvent(&mWidget, mDev)
0421             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0422 
0423         QTest::touchEvent(&mWidget, mDev)
0424             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0425 
0426         QCOMPARE(mSpySwipeStarted->count(), 0);
0427         QCOMPARE(mSpySwipeFinished->count(), 0);
0428         QCOMPARE(mSpySwipeCanceled->count(), 0);
0429         QVERIFY(mSpySwipeUpdated->count() == 0);
0430     }
0431 
0432     void testSomeRandomSwipes()
0433     {
0434         for (int i = 0; i < 50; ++i) {
0435             const int x = rand() % 200 + 150;
0436             const int y = rand() % 200 + 150;
0437             mTouchPointPos = QPoint(x, y);
0438             testSuccessfulGesture_right();
0439             testSuccessfulGesture_up();
0440         }
0441     }
0442 };
0443 
0444 QTEST_MAIN(KTwoFingerSwipeTest)
0445 
0446 #include "ktwofingerswipetest.moc"