File indexing completed on 2024-04-28 15:31:55
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 <ktwofingertap.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 KTwoFingerTapRecognizer *mTwoFingerRec = nullptr; 0024 Qt::GestureType mKTwoFingerTapGesture; 0025 QPoint mTouchPointPos = QPoint(100, 100); 0026 QSignalSpy *mSpyTapFinished = nullptr; 0027 QSignalSpy *mSpyTapStarted = nullptr; 0028 QSignalSpy *mSpyTapUpdated = nullptr; 0029 QSignalSpy *mSpyTapCanceled = nullptr; 0030 0031 Q_SIGNALS: 0032 void tapStarted(KTwoFingerTap *); 0033 void tapFinished(KTwoFingerTap *); 0034 void tapUpdated(KTwoFingerTap *); 0035 void tapCanceled(KTwoFingerTap *); 0036 0037 protected: 0038 bool eventFilter(QObject *watched, QEvent *e) override 0039 { 0040 if (e->type() == QEvent::Gesture) { 0041 QGestureEvent *gEvent = static_cast<QGestureEvent *>(e); 0042 KTwoFingerTap *tap = static_cast<KTwoFingerTap *>(gEvent->gesture(mKTwoFingerTapGesture)); 0043 if (tap) { 0044 const Qt::GestureState state = tap->state(); 0045 if (state == Qt::GestureFinished) { 0046 Q_EMIT tapFinished(tap); 0047 } else if (state == Qt::GestureStarted) { 0048 Q_EMIT tapStarted(tap); 0049 } else if (state == Qt::GestureUpdated) { 0050 Q_EMIT tapUpdated(tap); 0051 } else if (state == Qt::GestureCanceled) { 0052 Q_EMIT tapCanceled(tap); 0053 } 0054 } 0055 e->accept(); 0056 return true; 0057 } 0058 return QObject::eventFilter(watched, e); 0059 } 0060 0061 protected Q_SLOTS: 0062 void slotTapFinished (KTwoFingerTap *tap) 0063 { 0064 compareGesturePositions(tap); 0065 } 0066 void slotTapStarted (KTwoFingerTap *tap) 0067 { 0068 compareGesturePositions(tap); 0069 } 0070 void slotTapUpdated (KTwoFingerTap *tap) 0071 { 0072 compareGesturePositions(tap); 0073 } 0074 void slotTapCanceled (KTwoFingerTap *tap) 0075 { 0076 compareGesturePositions(tap); 0077 } 0078 private: 0079 void compareGesturePositions(KTwoFingerTap *tap) 0080 { 0081 QCOMPARE(tap->pos(), mTouchPointPos); 0082 QCOMPARE(tap->screenPos(), mWidget.mapToGlobal(mTouchPointPos)); 0083 QCOMPARE(tap->hotSpot(), mWidget.mapToGlobal(mTouchPointPos)); 0084 QCOMPARE(tap->scenePos(), mWidget.mapToGlobal(mTouchPointPos)); 0085 QVERIFY(tap->hasHotSpot()); 0086 } 0087 0088 void clearSignalSpys() 0089 { 0090 mSpyTapFinished->clear(); 0091 mSpyTapCanceled->clear(); 0092 mSpyTapUpdated->clear(); 0093 mSpyTapStarted->clear(); 0094 } 0095 0096 private Q_SLOTS: 0097 void initTestCase() 0098 { 0099 mDev = QTest::createTouchDevice(); 0100 0101 mMainWindow.setGeometry(0, 0, 500, 500); 0102 mMainWindow.setCentralWidget(&mWidget); 0103 mMainWindow.show(); 0104 0105 mWidget.installEventFilter(this); 0106 mWidget.setAttribute(Qt::WA_AcceptTouchEvents); 0107 0108 QVERIFY(QTest::qWaitForWindowActive(&mMainWindow)); 0109 QVERIFY(QTest::qWaitForWindowActive(&mWidget)); 0110 0111 mTwoFingerRec = new KTwoFingerTapRecognizer(); 0112 QVERIFY(mTwoFingerRec); 0113 0114 mKTwoFingerTapGesture = QGestureRecognizer::registerRecognizer(mTwoFingerRec); 0115 QVERIFY(mKTwoFingerTapGesture & Qt::CustomGesture); 0116 0117 mWidget.grabGesture(mKTwoFingerTapGesture); 0118 0119 connect(this, &KTwoFingerSwipeTest::tapFinished, this, &KTwoFingerSwipeTest::slotTapFinished); 0120 connect(this, &KTwoFingerSwipeTest::tapStarted, this, &KTwoFingerSwipeTest::slotTapStarted); 0121 connect(this, &KTwoFingerSwipeTest::tapUpdated, this, &KTwoFingerSwipeTest::slotTapUpdated); 0122 connect(this, &KTwoFingerSwipeTest::tapCanceled, this, &KTwoFingerSwipeTest::slotTapCanceled); 0123 0124 mSpyTapFinished = new QSignalSpy(this, &KTwoFingerSwipeTest::tapFinished); 0125 QVERIFY(mSpyTapFinished->isValid()); 0126 0127 mSpyTapStarted = new QSignalSpy(this, &KTwoFingerSwipeTest::tapStarted); 0128 QVERIFY(mSpyTapStarted->isValid()); 0129 0130 mSpyTapUpdated = new QSignalSpy(this, &KTwoFingerSwipeTest::tapUpdated); 0131 QVERIFY(mSpyTapUpdated->isValid()); 0132 0133 mSpyTapCanceled = new QSignalSpy(this, &KTwoFingerSwipeTest::tapCanceled); 0134 QVERIFY(mSpyTapCanceled->isValid()); 0135 0136 QTest::qWait(1000); 0137 } 0138 0139 void testChangeTapRadius() 0140 { 0141 QVERIFY(mTwoFingerRec->tapRadius() >= 0); 0142 0143 mTwoFingerRec->setTapRadius(10); 0144 QCOMPARE(mTwoFingerRec->tapRadius(), 10); 0145 0146 mTwoFingerRec->setTapRadius(-100); 0147 QCOMPARE(mTwoFingerRec->tapRadius(), 0); 0148 0149 mTwoFingerRec->setTapRadius(40); 0150 QCOMPARE(mTwoFingerRec->tapRadius(), 40); 0151 } 0152 0153 void testSuccessfulGesture() 0154 { 0155 // Test a successful gesture with two fingers, where the touch points wiggle only a little bit. 0156 0157 clearSignalSpys(); 0158 0159 int tapRadius = mTwoFingerRec->tapRadius(); 0160 QPoint wiggleRoom = QPoint (tapRadius / 2, tapRadius / 2); 0161 0162 QTest::touchEvent(&mWidget, mDev) 0163 .press(0, mTouchPointPos, (QWidget *) nullptr); 0164 0165 QTest::touchEvent(&mWidget, mDev) 0166 .move(0, mTouchPointPos + wiggleRoom, (QWidget *) nullptr) 0167 .press(1, mTouchPointPos, (QWidget *) nullptr); 0168 0169 QTest::touchEvent(&mWidget, mDev) 0170 .move(0, mTouchPointPos, (QWidget *) nullptr) 0171 .move(1, mTouchPointPos + wiggleRoom, (QWidget *) nullptr); 0172 0173 QTest::touchEvent(&mWidget, mDev) 0174 .move(0, mTouchPointPos, (QWidget *) nullptr) 0175 .release(1, mTouchPointPos, (QWidget *) nullptr); 0176 0177 QTest::touchEvent(&mWidget, mDev) 0178 .release(0, mTouchPointPos, (QWidget *) nullptr); 0179 0180 if (mSpyTapStarted->count() == 0) { 0181 QVERIFY(mSpyTapStarted->wait(1000)); 0182 } 0183 if (mSpyTapFinished->count() == 0) { 0184 QVERIFY(mSpyTapFinished->wait(1000)); 0185 } 0186 0187 QCOMPARE(mSpyTapStarted->count(), 1); 0188 QCOMPARE(mSpyTapFinished->count(), 1); 0189 QCOMPARE(mSpyTapCanceled->count(), 0); 0190 QVERIFY(mSpyTapUpdated->count() > 0); 0191 } 0192 0193 void testFailingGesture() 0194 { 0195 // Test a failing gesture with two fingers, where the touch points wiggle too much at beginning. 0196 0197 clearSignalSpys(); 0198 0199 int tapRadius = mTwoFingerRec->tapRadius(); 0200 QPoint wiggleRoom = QPoint (tapRadius, tapRadius); 0201 0202 QTest::touchEvent(&mWidget, mDev) 0203 .press(0, mTouchPointPos, (QWidget *) nullptr); 0204 0205 QTest::touchEvent(&mWidget, mDev) 0206 .move(0, mTouchPointPos + wiggleRoom, (QWidget *) nullptr) 0207 .press(1, mTouchPointPos, (QWidget *) nullptr); 0208 0209 QTest::touchEvent(&mWidget, mDev) 0210 .move(0, mTouchPointPos, (QWidget *) nullptr) 0211 .move(1, mTouchPointPos + wiggleRoom, (QWidget *) nullptr); 0212 0213 QTest::touchEvent(&mWidget, mDev) 0214 .move(0, mTouchPointPos, (QWidget *) nullptr) 0215 .release(1, mTouchPointPos, (QWidget *) nullptr); 0216 0217 QTest::touchEvent(&mWidget, mDev) 0218 .release(0, mTouchPointPos, (QWidget *) nullptr); 0219 0220 QCOMPARE(mSpyTapStarted->count(), 0); 0221 QCOMPARE(mSpyTapFinished->count(), 0); 0222 QCOMPARE(mSpyTapCanceled->count(), 0); 0223 QCOMPARE(mSpyTapUpdated->count(), 0); 0224 } 0225 0226 void testFailingGesture2() 0227 { 0228 // Test a failing gesture with two fingers, where the touch points wiggle too much in the middle. 0229 clearSignalSpys(); 0230 int tapRadius = mTwoFingerRec->tapRadius(); 0231 QPoint wiggleRoom = QPoint (tapRadius, tapRadius); 0232 0233 QTest::touchEvent(&mWidget, mDev) 0234 .press(0, mTouchPointPos, (QWidget *) nullptr); 0235 0236 QTest::touchEvent(&mWidget, mDev) 0237 .move(0, mTouchPointPos, (QWidget *) nullptr) 0238 .press(1, mTouchPointPos, (QWidget *) nullptr); 0239 0240 QTest::touchEvent(&mWidget, mDev) 0241 .move(0, mTouchPointPos, (QWidget *) nullptr) 0242 .move(1, mTouchPointPos + wiggleRoom, (QWidget *) nullptr); 0243 0244 QTest::touchEvent(&mWidget, mDev) 0245 .move(0, mTouchPointPos, (QWidget *) nullptr) 0246 .release(1, mTouchPointPos, (QWidget *) nullptr); 0247 0248 QTest::touchEvent(&mWidget, mDev) 0249 .release(0, mTouchPointPos, (QWidget *) nullptr); 0250 0251 if (mSpyTapStarted->count() == 0) { 0252 QVERIFY(mSpyTapStarted->wait(1000)); 0253 } 0254 QCOMPARE(mSpyTapStarted->count(), 1); 0255 QCOMPARE(mSpyTapFinished->count(), 0); 0256 QCOMPARE(mSpyTapCanceled->count(), 1); 0257 QVERIFY(mSpyTapUpdated->count() >= 0); 0258 } 0259 0260 void testFailingGesture3() 0261 { 0262 // Test a failing gesture with two fingers, where the touch points wiggle too much in the middle, 0263 // and the second finger press and release successively. 0264 0265 clearSignalSpys(); 0266 int tapRadius = mTwoFingerRec->tapRadius(); 0267 QPoint wiggleRoom = QPoint (tapRadius, tapRadius); 0268 0269 QTest::touchEvent(&mWidget, mDev) 0270 .press(0, mTouchPointPos, (QWidget *) nullptr); 0271 0272 QTest::touchEvent(&mWidget, mDev) 0273 .move(0, mTouchPointPos, (QWidget *) nullptr) 0274 .press(1, mTouchPointPos, (QWidget *) nullptr); 0275 0276 QTest::touchEvent(&mWidget, mDev) 0277 .move(0, mTouchPointPos, (QWidget *) nullptr) 0278 .move(1, mTouchPointPos + wiggleRoom, (QWidget *) nullptr); 0279 0280 QTest::touchEvent(&mWidget, mDev) 0281 .move(0, mTouchPointPos, (QWidget *) nullptr) 0282 .release(1, mTouchPointPos, (QWidget *) nullptr); 0283 0284 QTest::touchEvent(&mWidget, mDev) 0285 .move(0, mTouchPointPos, (QWidget *) nullptr) 0286 .press(1, mTouchPointPos, (QWidget *) nullptr); 0287 0288 QTest::touchEvent(&mWidget, mDev) 0289 .move(0, mTouchPointPos, (QWidget *) nullptr) 0290 .release(1, mTouchPointPos, (QWidget *) nullptr); 0291 0292 QTest::touchEvent(&mWidget, mDev) 0293 .release(0, mTouchPointPos, (QWidget *) nullptr); 0294 0295 if (mSpyTapStarted->count() == 0) { 0296 QVERIFY(mSpyTapStarted->wait(1000)); 0297 } 0298 QCOMPARE(mSpyTapStarted->count(), 1); 0299 QCOMPARE(mSpyTapFinished->count(), 0); 0300 QCOMPARE(mSpyTapCanceled->count(), 1); 0301 QVERIFY(mSpyTapUpdated->count() >= 0); 0302 } 0303 0304 void testFailingGesture_threeFingers() 0305 { 0306 // the test a gesture with three fingers should be end with gesture canceled. 0307 clearSignalSpys(); 0308 int tapRadius = mTwoFingerRec->tapRadius(); 0309 QPoint wiggleRoom = QPoint (tapRadius / 2, tapRadius / 2); 0310 0311 QTest::touchEvent(&mWidget, mDev) 0312 .press(0, mTouchPointPos, (QWidget *) nullptr); 0313 0314 QTest::touchEvent(&mWidget, mDev) 0315 .move(0, mTouchPointPos, (QWidget *) nullptr) 0316 .press(1, mTouchPointPos, (QWidget *) nullptr); 0317 0318 QTest::touchEvent(&mWidget, mDev) 0319 .move(0, mTouchPointPos, (QWidget *) nullptr) 0320 .move(1, mTouchPointPos + wiggleRoom, (QWidget *) nullptr) 0321 .press(2, mTouchPointPos, (QWidget *) nullptr); 0322 0323 QTest::touchEvent(&mWidget, mDev) 0324 .move(0, mTouchPointPos, (QWidget *) nullptr) 0325 .release(1, mTouchPointPos, (QWidget *) nullptr); 0326 0327 QTest::touchEvent(&mWidget, mDev) 0328 .release(0, mTouchPointPos, (QWidget *) nullptr); 0329 0330 if (mSpyTapStarted->count() == 0) { 0331 QVERIFY(mSpyTapStarted->wait(1000)); 0332 } 0333 QCOMPARE(mSpyTapStarted->count(), 1); 0334 QCOMPARE(mSpyTapFinished->count(), 0); 0335 QCOMPARE(mSpyTapCanceled->count(), 1); 0336 QVERIFY(mSpyTapUpdated->count() >= 0); 0337 } 0338 0339 void testFailingGesture_threeFingers2() 0340 { 0341 0342 clearSignalSpys(); 0343 0344 QTest::touchEvent(&mWidget, mDev) 0345 .press(0, mTouchPointPos, (QWidget *) nullptr); 0346 0347 QTest::touchEvent(&mWidget, mDev) 0348 .move(0, mTouchPointPos, (QWidget *) nullptr) 0349 .press(1, mTouchPointPos, (QWidget *) nullptr); 0350 0351 QTest::touchEvent(&mWidget, mDev) 0352 .move(0, mTouchPointPos, (QWidget *) nullptr) 0353 .move(1, mTouchPointPos, (QWidget *) nullptr) 0354 .press(2, mTouchPointPos, (QWidget *) nullptr); 0355 0356 QTest::touchEvent(&mWidget, mDev) 0357 .move(0, mTouchPointPos, (QWidget *) nullptr) 0358 .move(1, mTouchPointPos, (QWidget *) nullptr) 0359 .release(3, mTouchPointPos, (QWidget *) nullptr); 0360 0361 QTest::touchEvent(&mWidget, mDev) 0362 .move(0, mTouchPointPos, (QWidget *) nullptr) 0363 .release(1, mTouchPointPos, (QWidget *) nullptr); 0364 0365 QTest::touchEvent(&mWidget, mDev) 0366 .move(0, mTouchPointPos, (QWidget *) nullptr) 0367 .press(1, mTouchPointPos, (QWidget *) nullptr); 0368 0369 QTest::touchEvent(&mWidget, mDev) 0370 .move(0, mTouchPointPos, (QWidget *) nullptr) 0371 .release(1, mTouchPointPos, (QWidget *) nullptr); 0372 0373 QTest::touchEvent(&mWidget, mDev) 0374 .release(1, mTouchPointPos, (QWidget *) nullptr); 0375 0376 if (mSpyTapStarted->count() == 0) { 0377 QVERIFY(mSpyTapStarted->wait(1000)); 0378 } 0379 QCOMPARE(mSpyTapStarted->count(), 1); 0380 QCOMPARE(mSpyTapFinished->count(), 0); 0381 QCOMPARE(mSpyTapCanceled->count(), 1); 0382 QVERIFY(mSpyTapUpdated->count() >= 0); 0383 } 0384 0385 void testFailingGesture_oneFinger() 0386 { 0387 // Test a failing gesture where we use only one finger. 0388 clearSignalSpys(); 0389 int tapRadius = mTwoFingerRec->tapRadius(); 0390 QPoint wiggleRoom = QPoint (tapRadius / 2, tapRadius / 2); 0391 0392 QTest::touchEvent(&mWidget, mDev) 0393 .press(0, mTouchPointPos, (QWidget *) nullptr); 0394 0395 QTest::touchEvent(&mWidget, mDev) 0396 .move(0, mTouchPointPos + wiggleRoom, (QWidget *) nullptr); 0397 0398 QTest::touchEvent(&mWidget, mDev) 0399 .move(0, mTouchPointPos, (QWidget *) nullptr); 0400 0401 QTest::touchEvent(&mWidget, mDev) 0402 .release(0, mTouchPointPos, (QWidget *) nullptr); 0403 0404 QCOMPARE(mSpyTapStarted->count(), 0); 0405 QCOMPARE(mSpyTapFinished->count(), 0); 0406 QCOMPARE(mSpyTapCanceled->count(), 0); 0407 QCOMPARE(mSpyTapUpdated->count(), 0); 0408 } 0409 void testSomeRandomTaps() 0410 { 0411 for (int i = 0; i < 50; ++i) { 0412 int v1 = rand() % 450; 0413 int v2 = rand() % 450; 0414 mTouchPointPos = QPoint(v1, v2); 0415 testSuccessfulGesture(); 0416 } 0417 } 0418 }; 0419 0420 QTEST_MAIN(KTwoFingerSwipeTest) 0421 0422 #include "ktwofingertaptest.moc"