| 1 | /* |
|---|---|
| 2 | This file is part of the KDE libraries |
| 3 | SPDX-FileCopyrightText: 2021 Steffen Hartleib <steffenhartleib@t-online.de> |
| 4 | |
| 5 | SPDX-License-Identifier: LGPL-2.1-or-later |
| 6 | */ |
| 7 | |
| 8 | // Self |
| 9 | #include "ktwofingertap.h" |
| 10 | |
| 11 | // Qt |
| 12 | #include <QApplication> |
| 13 | #include <QGraphicsWidget> |
| 14 | #include <QTouchEvent> |
| 15 | |
| 16 | class KTwoFingerTapRecognizerPrivate |
| 17 | { |
| 18 | public: |
| 19 | KTwoFingerTapRecognizerPrivate(KTwoFingerTapRecognizer *parent) |
| 20 | : q(parent) |
| 21 | { |
| 22 | } |
| 23 | KTwoFingerTapRecognizer *const q; |
| 24 | bool mGestureTriggered = false; |
| 25 | int mTapRadius = 40; // same as Qt::TapGesture |
| 26 | Qt::GestureState mLastState = Qt::NoGesture; |
| 27 | }; |
| 28 | |
| 29 | KTwoFingerTapRecognizer::KTwoFingerTapRecognizer() |
| 30 | : QGestureRecognizer() |
| 31 | , d(new KTwoFingerTapRecognizerPrivate(this)) |
| 32 | { |
| 33 | } |
| 34 | |
| 35 | KTwoFingerTapRecognizer::~KTwoFingerTapRecognizer() |
| 36 | { |
| 37 | } |
| 38 | |
| 39 | QGesture *KTwoFingerTapRecognizer::create(QObject *target) |
| 40 | { |
| 41 | Q_UNUSED(target) |
| 42 | return static_cast<QGesture *>(new KTwoFingerTap()); |
| 43 | } |
| 44 | |
| 45 | QGestureRecognizer::Result KTwoFingerTapRecognizer::recognize(QGesture *gesture, QObject *watched, QEvent *event) |
| 46 | { |
| 47 | Q_UNUSED(watched) |
| 48 | |
| 49 | KTwoFingerTap *ktwoFingerTap = static_cast<KTwoFingerTap *>(gesture); |
| 50 | const QTouchEvent *touchEvent = static_cast<const QTouchEvent *>(event); |
| 51 | |
| 52 | switch (event->type()) { |
| 53 | case QEvent::TouchBegin: { |
| 54 | const QTouchEvent::TouchPoint tp = touchEvent->points().first(); |
| 55 | ktwoFingerTap->setHotSpot(tp.globalPressPosition()); |
| 56 | ktwoFingerTap->setPos(tp.pressPosition()); |
| 57 | ktwoFingerTap->setScreenPos(tp.globalPressPosition()); |
| 58 | ktwoFingerTap->setScenePos(tp.scenePressPosition()); |
| 59 | d->mLastState = Qt::NoGesture; |
| 60 | return MayBeGesture; |
| 61 | } |
| 62 | |
| 63 | case QEvent::TouchUpdate: { |
| 64 | // The gesture was already canceled or finished, so we will ignore this event. |
| 65 | if (d->mLastState == Qt::GestureCanceled || d->mLastState == Qt::GestureFinished) { |
| 66 | return Ignore; |
| 67 | } |
| 68 | |
| 69 | const int touchPointSize = touchEvent->points().size(); |
| 70 | |
| 71 | if (touchPointSize > 2) { |
| 72 | d->mLastState = Qt::GestureCanceled; |
| 73 | return CancelGesture; |
| 74 | } |
| 75 | |
| 76 | if (touchPointSize == 2) { |
| 77 | if ((touchEvent->points().first().pressPosition() - touchEvent->points().first().position()).manhattanLength() > d->mTapRadius) { |
| 78 | d->mLastState = Qt::GestureCanceled; |
| 79 | return CancelGesture; |
| 80 | } |
| 81 | if ((touchEvent->points().at(i: 1).pressPosition() - touchEvent->points().at(i: 1).position()).manhattanLength() > d->mTapRadius) { |
| 82 | d->mLastState = Qt::GestureCanceled; |
| 83 | return CancelGesture; |
| 84 | } |
| 85 | if (touchEvent->touchPointStates() & Qt::TouchPointPressed) { |
| 86 | d->mLastState = gesture->state() == Qt::NoGesture ? Qt::GestureStarted : Qt::GestureUpdated; |
| 87 | return TriggerGesture; |
| 88 | } |
| 89 | if (touchEvent->touchPointStates() & Qt::TouchPointMoved) { |
| 90 | d->mLastState = gesture->state() == Qt::NoGesture ? Qt::GestureStarted : Qt::GestureUpdated; |
| 91 | return TriggerGesture; |
| 92 | } |
| 93 | if (touchEvent->touchPointStates() & Qt::TouchPointReleased) { |
| 94 | d->mLastState = Qt::GestureFinished; |
| 95 | return FinishGesture; |
| 96 | } |
| 97 | } |
| 98 | break; |
| 99 | } |
| 100 | |
| 101 | case QEvent::TouchEnd: { |
| 102 | if (d->mLastState == Qt::GestureStarted || d->mLastState == Qt::GestureUpdated) { |
| 103 | return FinishGesture; |
| 104 | } |
| 105 | break; |
| 106 | } |
| 107 | |
| 108 | default: |
| 109 | return Ignore; |
| 110 | } |
| 111 | return Ignore; |
| 112 | } |
| 113 | |
| 114 | void KTwoFingerTapRecognizer::setTapRadius(int i) |
| 115 | { |
| 116 | if (i < 0) { |
| 117 | i = 0; |
| 118 | } |
| 119 | |
| 120 | d->mTapRadius = i; |
| 121 | } |
| 122 | |
| 123 | int KTwoFingerTapRecognizer::tapRadius() const |
| 124 | { |
| 125 | return d->mTapRadius; |
| 126 | } |
| 127 | |
| 128 | class KTwoFingerTapPrivate |
| 129 | { |
| 130 | public: |
| 131 | KTwoFingerTapPrivate(KTwoFingerTap *parent) |
| 132 | : q(parent) |
| 133 | { |
| 134 | } |
| 135 | KTwoFingerTap *const q; |
| 136 | QPointF mPos = QPointF(-1, -1); |
| 137 | QPointF mScreenPos = QPointF(-1, -1); |
| 138 | QPointF mScenePos = QPointF(-1, -1); |
| 139 | }; |
| 140 | |
| 141 | KTwoFingerTap::KTwoFingerTap(QObject *parent) |
| 142 | : QGesture(parent) |
| 143 | , d(new KTwoFingerTapPrivate(this)) |
| 144 | { |
| 145 | } |
| 146 | |
| 147 | KTwoFingerTap::~KTwoFingerTap() |
| 148 | { |
| 149 | } |
| 150 | |
| 151 | QPointF KTwoFingerTap::pos() const |
| 152 | { |
| 153 | return d->mPos; |
| 154 | } |
| 155 | |
| 156 | void KTwoFingerTap::setPos(QPointF _pos) |
| 157 | { |
| 158 | d->mPos = _pos; |
| 159 | } |
| 160 | |
| 161 | QPointF KTwoFingerTap::screenPos() const |
| 162 | { |
| 163 | return d->mScreenPos; |
| 164 | } |
| 165 | |
| 166 | void KTwoFingerTap::setScreenPos(QPointF _screenPos) |
| 167 | { |
| 168 | d->mScreenPos = _screenPos; |
| 169 | } |
| 170 | |
| 171 | QPointF KTwoFingerTap::scenePos() const |
| 172 | { |
| 173 | return d->mScenePos; |
| 174 | } |
| 175 | |
| 176 | void KTwoFingerTap::setScenePos(QPointF _scenePos) |
| 177 | { |
| 178 | d->mScenePos = _scenePos; |
| 179 | } |
| 180 | |
| 181 | #include "moc_ktwofingertap.cpp" |
| 182 |
