File indexing completed on 2024-04-28 03:59:16

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 // Self
0009 #include "ktwofingerswipe.h"
0010 
0011 // Qt
0012 #include <QGraphicsWidget>
0013 #include <QLineF>
0014 #include <QTouchEvent>
0015 #include <QDebug>
0016 class KTwoFingerSwipeRecognizerPrivate
0017 {
0018 public:
0019     KTwoFingerSwipeRecognizerPrivate(KTwoFingerSwipeRecognizer *parent)
0020         : q(parent)
0021     {
0022     }
0023     KTwoFingerSwipeRecognizer *const q;
0024     qint64 mTouchBeginnTimestamp = 0;
0025     bool mGestureAlreadyFinished = false;
0026     int mMaxSwipeTime = 90;
0027     int mMinSwipeDistance = 30;
0028 };
0029 
0030 KTwoFingerSwipeRecognizer::KTwoFingerSwipeRecognizer()
0031     : QGestureRecognizer()
0032     , d(new KTwoFingerSwipeRecognizerPrivate(this))
0033 {
0034 }
0035 
0036 KTwoFingerSwipeRecognizer::~KTwoFingerSwipeRecognizer()
0037 {
0038 }
0039 
0040 QGesture* KTwoFingerSwipeRecognizer::create(QObject *target)
0041 {
0042     Q_UNUSED(target);
0043     return static_cast<QGesture *>(new KTwoFingerSwipe());
0044 }
0045 
0046 QGestureRecognizer::Result KTwoFingerSwipeRecognizer::recognize(QGesture *gesture, QObject *watched, QEvent *event)
0047 {
0048     Q_UNUSED(watched)
0049 
0050     KTwoFingerSwipe *kTwoFingerSwipe = static_cast<KTwoFingerSwipe *>(gesture);
0051     const QTouchEvent *touchEvent = static_cast<const QTouchEvent *>(event);
0052 
0053     switch (event->type()) {
0054     case QEvent::TouchBegin: {
0055         d->mTouchBeginnTimestamp = touchEvent->timestamp();
0056         d->mGestureAlreadyFinished = false;
0057         const QTouchEvent::TouchPoint tp = touchEvent->points().first();
0058         kTwoFingerSwipe->setHotSpot(tp.globalPressPosition());
0059         kTwoFingerSwipe->setPos(tp.pressPosition());
0060         kTwoFingerSwipe->setScreenPos(tp.globalPressPosition());
0061         kTwoFingerSwipe->setScenePos(tp.scenePressPosition());
0062         kTwoFingerSwipe->setSwipeAngle(0.0);
0063         return MayBeGesture;
0064     }
0065 
0066     case QEvent::TouchUpdate: {
0067         // The gesture was already canceled or finished, so we will ignore this event.
0068         if (d->mGestureAlreadyFinished) {
0069             return Ignore;
0070         }
0071 
0072         const qint64 now = touchEvent->timestamp();
0073         const qint64 elapsedTime = now - d->mTouchBeginnTimestamp;
0074         const QLineF ql = QLineF(touchEvent->points().first().pressPosition(), touchEvent->points().first().position());
0075         const qreal length = ql.length();
0076         const int touchPointSize = touchEvent->points().size();
0077 
0078         kTwoFingerSwipe->setSwipeAngle(ql.angle());
0079 
0080         if (touchPointSize > 2) {
0081                 d->mGestureAlreadyFinished = true;
0082                 return CancelGesture;
0083         }
0084 
0085         if (touchPointSize == 2) {
0086             if (elapsedTime > d->mMaxSwipeTime) {
0087                 d->mGestureAlreadyFinished = true;
0088                 return CancelGesture;
0089             }
0090             if (length >= d->mMinSwipeDistance && elapsedTime <= d->mMaxSwipeTime && !d->mGestureAlreadyFinished) {
0091                 d->mGestureAlreadyFinished = true;
0092                 return FinishGesture;
0093             } else if (elapsedTime <= d->mMaxSwipeTime && !d->mGestureAlreadyFinished) {
0094                 return TriggerGesture;
0095             }
0096         }
0097         break;
0098     }
0099 
0100     case QEvent::TouchEnd: {
0101         if (gesture->state() == Qt::GestureUpdated || gesture->state() == Qt::GestureStarted) {
0102             if (!d->mGestureAlreadyFinished) {
0103                 return CancelGesture;
0104             }
0105         }
0106         break;
0107     }
0108 
0109     default:
0110         return Ignore;
0111     }
0112     return Ignore;
0113 }
0114 
0115 int KTwoFingerSwipeRecognizer::maxSwipeTime() const
0116 {
0117     return d->mMaxSwipeTime;
0118 }
0119 
0120 void KTwoFingerSwipeRecognizer::setMaxSwipeTime(int i)
0121 {
0122     if (i < 0) {
0123         i = 0;
0124     }
0125 
0126     d->mMaxSwipeTime = i;
0127 }
0128 
0129 int KTwoFingerSwipeRecognizer::minSswipeDistance() const
0130 {
0131     return d->mMinSwipeDistance;
0132 }
0133 
0134 void KTwoFingerSwipeRecognizer::setSwipeDistance(int i)
0135 {
0136     if (i < 0) {
0137         i = 0;
0138     }
0139 
0140     d->mMinSwipeDistance = i;
0141 }
0142 
0143 
0144 
0145 class KTwoFingerSwipePrivate
0146 {
0147 public:
0148     KTwoFingerSwipePrivate(KTwoFingerSwipe *parent)
0149         : q(parent)
0150     {
0151     }
0152     KTwoFingerSwipe *const q;
0153     QPointF mPos = QPointF(-1, -1);
0154     QPointF mScreenPos = QPointF(-1, -1);
0155     QPointF mScenePos = QPointF(-1, -1);
0156     qreal mSwipeAngle = 0.0;
0157 };
0158 
0159 KTwoFingerSwipe::KTwoFingerSwipe(QObject *parent)
0160     : QGesture(parent)
0161     , d(new KTwoFingerSwipePrivate(this))
0162 {
0163 }
0164 
0165 KTwoFingerSwipe::~KTwoFingerSwipe()
0166 {
0167 }
0168 
0169 QPointF KTwoFingerSwipe::pos() const
0170 {
0171     return d->mPos;
0172 }
0173 
0174 void KTwoFingerSwipe::setPos(QPointF _pos)
0175 {
0176     d->mPos = _pos;
0177 }
0178 
0179 QPointF KTwoFingerSwipe::screenPos() const
0180 {
0181     return d->mScreenPos;
0182 }
0183 
0184 void KTwoFingerSwipe::setScreenPos(QPointF _screenPos)
0185 {
0186     d->mScreenPos = _screenPos;
0187 }
0188 
0189 QPointF KTwoFingerSwipe::scenePos() const
0190 {
0191     return d->mScenePos;
0192 }
0193 
0194 void KTwoFingerSwipe::setScenePos(QPointF _scenePos)
0195 {
0196     d->mScenePos = _scenePos;
0197 }
0198 
0199 qreal KTwoFingerSwipe::swipeAngle() const
0200 {
0201     return d->mSwipeAngle;
0202 }
0203  void KTwoFingerSwipe::setSwipeAngle(qreal _swipeAngle)
0204 {
0205     d->mSwipeAngle = _swipeAngle;
0206 }
0207 
0208 #include "moc_ktwofingerswipe.cpp"