File indexing completed on 2024-04-28 15:31:54

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     QTouchDevice *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 initTestCase()
0100     {
0101         mDev = QTest::createTouchDevice();
0102 
0103         mMainWindow.setGeometry(0, 0, 500, 500);
0104         mMainWindow.setCentralWidget(&mWidget);
0105         mMainWindow.show();
0106 
0107         mWidget.installEventFilter(this);
0108         mWidget.setAttribute(Qt::WA_AcceptTouchEvents);
0109 
0110         QVERIFY(QTest::qWaitForWindowActive(&mMainWindow));
0111         QVERIFY(QTest::qWaitForWindowActive(&mWidget));
0112 
0113         mTwoFingerRec = new KTwoFingerSwipeRecognizer();
0114         QVERIFY(mTwoFingerRec);
0115 
0116         mKTwoFingerSwipeGesture = QGestureRecognizer::registerRecognizer(mTwoFingerRec);
0117         QVERIFY(mKTwoFingerSwipeGesture & Qt::CustomGesture);
0118 
0119         mWidget.grabGesture(mKTwoFingerSwipeGesture);
0120 
0121         connect(this, &KTwoFingerSwipeTest::swipeFinished, this, &KTwoFingerSwipeTest::slotSwipeFinished);
0122         connect(this, &KTwoFingerSwipeTest::swipeStarted, this, &KTwoFingerSwipeTest::slotSwipeStarted);
0123         connect(this, &KTwoFingerSwipeTest::swipeUpdated, this, &KTwoFingerSwipeTest::slotSwipeUpdated);
0124         connect(this, &KTwoFingerSwipeTest::swipeCanceled, this, &KTwoFingerSwipeTest::slotSwipeCanceled);
0125 
0126         mSpySwipeFinished = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeFinished);
0127         QVERIFY(mSpySwipeFinished->isValid());
0128 
0129         mSpySwipeStarted = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeStarted);
0130         QVERIFY(mSpySwipeStarted->isValid());
0131 
0132         mSpySwipeUpdated = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeUpdated);
0133         QVERIFY(mSpySwipeUpdated->isValid());
0134 
0135         mSpySwipeCanceled = new QSignalSpy(this, &KTwoFingerSwipeTest::swipeCanceled);
0136         QVERIFY(mSpySwipeCanceled->isValid());
0137 
0138         QTest::qWait(1000);
0139     }
0140 
0141     void testChangeTimeAndDistance()
0142     {
0143         QVERIFY(mTwoFingerRec->maxSwipeTime() >= 0);
0144         mTwoFingerRec->setMaxSwipeTime(10);
0145         QCOMPARE(mTwoFingerRec->maxSwipeTime(), 10);
0146         mTwoFingerRec->setMaxSwipeTime(-10);
0147         QCOMPARE(mTwoFingerRec->maxSwipeTime(), 0);
0148         mTwoFingerRec->setMaxSwipeTime(90);
0149         QCOMPARE(mTwoFingerRec->maxSwipeTime(), 90);
0150 
0151         QVERIFY(mTwoFingerRec->minSswipeDistance() >= 0);
0152         mTwoFingerRec->setSwipeDistance(10);
0153         QCOMPARE(mTwoFingerRec->minSswipeDistance(), 10);
0154         mTwoFingerRec->setSwipeDistance(-10);
0155         QCOMPARE(mTwoFingerRec->minSswipeDistance(), 0);
0156         mTwoFingerRec->setSwipeDistance(30);
0157         QCOMPARE(mTwoFingerRec->minSswipeDistance(), 30);
0158     }
0159 
0160     void testSuccessfulGesture_right()
0161     {
0162         clearSignalSpys();
0163 
0164         const int length = mTwoFingerRec->minSswipeDistance();
0165         const QPoint swipeDistance = QPoint(length, 0);
0166 
0167         QTest::touchEvent(&mWidget, mDev)
0168             .press(0, mTouchPointPos, (QWidget *) nullptr)
0169             .press(1, mTouchPointPos, (QWidget *) nullptr);
0170 
0171         QTest::touchEvent(&mWidget, mDev)
0172             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0173             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0174 
0175 
0176         QTest::touchEvent(&mWidget, mDev)
0177             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0178             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0179 
0180         QTest::touchEvent(&mWidget, mDev)
0181             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0182             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0183 
0184         QTest::touchEvent(&mWidget, mDev)
0185             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0186             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0187 
0188         if (mSpySwipeStarted->count() == 0) {
0189             QVERIFY(mSpySwipeStarted->wait(1000));
0190         }
0191 
0192         QCOMPARE(mSpySwipeStarted->count(), 1);
0193         QCOMPARE(mSpySwipeFinished->count(), 1);
0194         QCOMPARE(mSpySwipeCanceled->count(), 0);
0195         QVERIFY(mSpySwipeUpdated->count() > 0);
0196         QCOMPARE(mAngel, 0);
0197     }
0198 
0199     void testSuccessfulGesture_left()
0200     {
0201         clearSignalSpys();
0202 
0203         const int length = mTwoFingerRec->minSswipeDistance();
0204         const QPoint swipeDistance = QPoint(-length, 0);
0205 
0206         QTest::touchEvent(&mWidget, mDev)
0207             .press(0, mTouchPointPos, (QWidget *) nullptr)
0208             .press(1, mTouchPointPos, (QWidget *) nullptr);
0209 
0210         QTest::touchEvent(&mWidget, mDev)
0211             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0212             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0213 
0214 
0215         QTest::touchEvent(&mWidget, mDev)
0216             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0217             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0218 
0219         QTest::touchEvent(&mWidget, mDev)
0220             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0221             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0222 
0223         QTest::touchEvent(&mWidget, mDev)
0224             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0225             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0226 
0227         if (mSpySwipeStarted->count() == 0) {
0228             QVERIFY(mSpySwipeStarted->wait(1000));
0229         }
0230 
0231         QCOMPARE(mSpySwipeStarted->count(), 1);
0232         QCOMPARE(mSpySwipeFinished->count(), 1);
0233         QCOMPARE(mSpySwipeCanceled->count(), 0);
0234         QVERIFY(mSpySwipeUpdated->count() > 0);
0235         QCOMPARE(mAngel, 180);
0236     }
0237 
0238     void testSuccessfulGesture_up()
0239     {
0240         clearSignalSpys();
0241 
0242         const int length = mTwoFingerRec->minSswipeDistance();
0243         const QPoint swipeDistance = QPoint(0, -length);
0244 
0245         QTest::touchEvent(&mWidget, mDev)
0246             .press(0, mTouchPointPos, (QWidget *) nullptr)
0247             .press(1, mTouchPointPos, (QWidget *) nullptr);
0248 
0249         QTest::touchEvent(&mWidget, mDev)
0250             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0251             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0252 
0253 
0254         QTest::touchEvent(&mWidget, mDev)
0255             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0256             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0257 
0258         QTest::touchEvent(&mWidget, mDev)
0259             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0260             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0261 
0262         QTest::touchEvent(&mWidget, mDev)
0263             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0264             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0265 
0266         if (mSpySwipeStarted->count() == 0) {
0267             QVERIFY(mSpySwipeStarted->wait(1000));
0268         }
0269 
0270         QCOMPARE(mSpySwipeStarted->count(), 1);
0271         QCOMPARE(mSpySwipeFinished->count(), 1);
0272         QCOMPARE(mSpySwipeCanceled->count(), 0);
0273         QVERIFY(mSpySwipeUpdated->count() > 0);
0274         QCOMPARE(mAngel, 90);
0275     }
0276 
0277     void testSuccessfulGesture_down()
0278     {
0279         clearSignalSpys();
0280 
0281         const int length = mTwoFingerRec->minSswipeDistance();
0282         const QPoint swipeDistance = QPoint(0, length);
0283 
0284         QTest::touchEvent(&mWidget, mDev)
0285             .press(0, mTouchPointPos, (QWidget *) nullptr)
0286             .press(1, mTouchPointPos, (QWidget *) nullptr);
0287 
0288         QTest::touchEvent(&mWidget, mDev)
0289             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0290             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0291 
0292 
0293         QTest::touchEvent(&mWidget, mDev)
0294             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0295             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0296 
0297         QTest::touchEvent(&mWidget, mDev)
0298             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0299             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0300 
0301         QTest::touchEvent(&mWidget, mDev)
0302             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0303             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0304 
0305         if (mSpySwipeStarted->count() == 0) {
0306             QVERIFY(mSpySwipeStarted->wait(1000));
0307         }
0308 
0309         QCOMPARE(mSpySwipeStarted->count(), 1);
0310         QCOMPARE(mSpySwipeFinished->count(), 1);
0311         QCOMPARE(mSpySwipeCanceled->count(), 0);
0312         QVERIFY(mSpySwipeUpdated->count() > 0);
0313         QCOMPARE(mAngel, 270);
0314     }
0315 
0316     void testFailingGesture_toSlow()
0317     {
0318         clearSignalSpys();
0319 
0320         const int length = mTwoFingerRec->minSswipeDistance() / 3;
0321         const QPoint swipeDistance = QPoint(length, 0);
0322 
0323         QTest::touchEvent(&mWidget, mDev)
0324             .press(0, mTouchPointPos, (QWidget *) nullptr)
0325             .press(1, mTouchPointPos, (QWidget *) nullptr);
0326 
0327         QTest::touchEvent(&mWidget, mDev)
0328             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0329             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0330 
0331 
0332         QTest::touchEvent(&mWidget, mDev)
0333             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0334             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0335 
0336         QTest::touchEvent(&mWidget, mDev)
0337             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0338             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0339 
0340         QTest::touchEvent(&mWidget, mDev)
0341             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0342             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0343 
0344         if (mSpySwipeStarted->count() == 0) {
0345             QVERIFY(mSpySwipeStarted->wait(1000));
0346         }
0347 
0348         QCOMPARE(mSpySwipeStarted->count(), 1);
0349         QCOMPARE(mSpySwipeFinished->count(), 0);
0350         QCOMPARE(mSpySwipeCanceled->count(), 1);
0351         QVERIFY(mSpySwipeUpdated->count() > 0);
0352         QCOMPARE(mAngel, 0);
0353     }
0354 
0355 
0356     void testFailingGesture_threeFingers()
0357     {
0358         clearSignalSpys();
0359 
0360         const int length = mTwoFingerRec->minSswipeDistance();
0361         const QPoint swipeDistance = QPoint(length, 0);
0362 
0363         QTest::touchEvent(&mWidget, mDev)
0364             .press(0, mTouchPointPos, (QWidget *) nullptr)
0365             .press(1, mTouchPointPos, (QWidget *) nullptr);
0366 
0367         QTest::touchEvent(&mWidget, mDev)
0368             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr)
0369             .move(1, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0370 
0371         QTest::touchEvent(&mWidget, mDev)
0372             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0373             .move(1, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr)
0374             .press(2, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0375 
0376         QTest::touchEvent(&mWidget, mDev)
0377             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0378             .move(1, mTouchPointPos + swipeDistance, (QWidget *) nullptr)
0379             .move(2, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0380 
0381         QTest::touchEvent(&mWidget, mDev)
0382             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0383             .release(1, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr)
0384             .release(2, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0385 
0386         if (mSpySwipeCanceled->count() == 0) {
0387             QVERIFY(mSpySwipeCanceled->wait(1000));
0388         }
0389 
0390         QCOMPARE(mSpySwipeStarted->count(), 1);
0391         QCOMPARE(mSpySwipeFinished->count(), 0);
0392         QCOMPARE(mSpySwipeCanceled->count(), 1);
0393         QVERIFY(mSpySwipeUpdated->count() >= 0);
0394         QCOMPARE(mAngel, 0);
0395     }
0396 
0397     void testFailingGesture_oneFinger()
0398     {
0399         clearSignalSpys();
0400 
0401         const int length = mTwoFingerRec->minSswipeDistance();
0402         const QPoint swipeDistance = QPoint(length, 0);
0403 
0404         QTest::touchEvent(&mWidget, mDev)
0405             .press(0, mTouchPointPos, (QWidget *) nullptr);
0406 
0407         QTest::touchEvent(&mWidget, mDev)
0408             .move(0, mTouchPointPos + swipeDistance / 3, (QWidget *) nullptr);
0409 
0410         QTest::touchEvent(&mWidget, mDev)
0411             .move(0, mTouchPointPos + swipeDistance / 2, (QWidget *) nullptr);
0412 
0413         QTest::touchEvent(&mWidget, mDev)
0414             .move(0, mTouchPointPos + swipeDistance, (QWidget *) nullptr);
0415 
0416         QTest::touchEvent(&mWidget, mDev)
0417             .release(0, mTouchPointPos + swipeDistance * 1.5, (QWidget *) nullptr);
0418 
0419         QCOMPARE(mSpySwipeStarted->count(), 0);
0420         QCOMPARE(mSpySwipeFinished->count(), 0);
0421         QCOMPARE(mSpySwipeCanceled->count(), 0);
0422         QVERIFY(mSpySwipeUpdated->count() == 0);
0423     }
0424 
0425     void testSomeRandomSwipes()
0426     {
0427         for (int i = 0; i < 50; ++i) {
0428             const int x = rand() % 200 + 150;
0429             const int y = rand() % 200 + 150;
0430             mTouchPointPos = QPoint(x, y);
0431             testSuccessfulGesture_right();
0432             testSuccessfulGesture_up();
0433         }
0434     }
0435 };
0436 
0437 QTEST_MAIN(KTwoFingerSwipeTest)
0438 
0439 #include "ktwofingerswipetest.moc"