1 | /* |
---|---|
2 | This file is part of the KDE project |
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 "ktwofingerswipe.h" |
10 | |
11 | // Qt |
12 | #include <QGraphicsWidget> |
13 | #include <QLineF> |
14 | #include <QTouchEvent> |
15 | #include <QDebug> |
16 | class KTwoFingerSwipeRecognizerPrivate |
17 | { |
18 | public: |
19 | KTwoFingerSwipeRecognizerPrivate(KTwoFingerSwipeRecognizer *parent) |
20 | : q(parent) |
21 | { |
22 | } |
23 | KTwoFingerSwipeRecognizer *const q; |
24 | qint64 mTouchBeginnTimestamp = 0; |
25 | bool mGestureAlreadyFinished = false; |
26 | int mMaxSwipeTime = 90; |
27 | int mMinSwipeDistance = 30; |
28 | }; |
29 | |
30 | KTwoFingerSwipeRecognizer::KTwoFingerSwipeRecognizer() |
31 | : QGestureRecognizer() |
32 | , d(new KTwoFingerSwipeRecognizerPrivate(this)) |
33 | { |
34 | } |
35 | |
36 | KTwoFingerSwipeRecognizer::~KTwoFingerSwipeRecognizer() |
37 | { |
38 | } |
39 | |
40 | QGesture* KTwoFingerSwipeRecognizer::create(QObject *target) |
41 | { |
42 | Q_UNUSED(target); |
43 | return static_cast<QGesture *>(new KTwoFingerSwipe()); |
44 | } |
45 | |
46 | QGestureRecognizer::Result KTwoFingerSwipeRecognizer::recognize(QGesture *gesture, QObject *watched, QEvent *event) |
47 | { |
48 | Q_UNUSED(watched) |
49 | |
50 | KTwoFingerSwipe *kTwoFingerSwipe = static_cast<KTwoFingerSwipe *>(gesture); |
51 | const QTouchEvent *touchEvent = static_cast<const QTouchEvent *>(event); |
52 | |
53 | switch (event->type()) { |
54 | case QEvent::TouchBegin: { |
55 | d->mTouchBeginnTimestamp = touchEvent->timestamp(); |
56 | d->mGestureAlreadyFinished = false; |
57 | const QTouchEvent::TouchPoint tp = touchEvent->points().first(); |
58 | kTwoFingerSwipe->setHotSpot(tp.globalPressPosition()); |
59 | kTwoFingerSwipe->setPos(tp.pressPosition()); |
60 | kTwoFingerSwipe->setScreenPos(tp.globalPressPosition()); |
61 | kTwoFingerSwipe->setScenePos(tp.scenePressPosition()); |
62 | kTwoFingerSwipe->setSwipeAngle(0.0); |
63 | return MayBeGesture; |
64 | } |
65 | |
66 | case QEvent::TouchUpdate: { |
67 | // The gesture was already canceled or finished, so we will ignore this event. |
68 | if (d->mGestureAlreadyFinished) { |
69 | return Ignore; |
70 | } |
71 | |
72 | const qint64 now = touchEvent->timestamp(); |
73 | const qint64 elapsedTime = now - d->mTouchBeginnTimestamp; |
74 | const QLineF ql = QLineF(touchEvent->points().first().pressPosition(), touchEvent->points().first().position()); |
75 | const qreal length = ql.length(); |
76 | const int touchPointSize = touchEvent->points().size(); |
77 | |
78 | kTwoFingerSwipe->setSwipeAngle(ql.angle()); |
79 | |
80 | if (touchPointSize > 2) { |
81 | d->mGestureAlreadyFinished = true; |
82 | return CancelGesture; |
83 | } |
84 | |
85 | if (touchPointSize == 2) { |
86 | if (elapsedTime > d->mMaxSwipeTime) { |
87 | d->mGestureAlreadyFinished = true; |
88 | return CancelGesture; |
89 | } |
90 | if (length >= d->mMinSwipeDistance && elapsedTime <= d->mMaxSwipeTime && !d->mGestureAlreadyFinished) { |
91 | d->mGestureAlreadyFinished = true; |
92 | return FinishGesture; |
93 | } else if (elapsedTime <= d->mMaxSwipeTime && !d->mGestureAlreadyFinished) { |
94 | return TriggerGesture; |
95 | } |
96 | } |
97 | break; |
98 | } |
99 | |
100 | case QEvent::TouchEnd: { |
101 | if (gesture->state() == Qt::GestureUpdated || gesture->state() == Qt::GestureStarted) { |
102 | if (!d->mGestureAlreadyFinished) { |
103 | return CancelGesture; |
104 | } |
105 | } |
106 | break; |
107 | } |
108 | |
109 | default: |
110 | return Ignore; |
111 | } |
112 | return Ignore; |
113 | } |
114 | |
115 | int KTwoFingerSwipeRecognizer::maxSwipeTime() const |
116 | { |
117 | return d->mMaxSwipeTime; |
118 | } |
119 | |
120 | void KTwoFingerSwipeRecognizer::setMaxSwipeTime(int i) |
121 | { |
122 | if (i < 0) { |
123 | i = 0; |
124 | } |
125 | |
126 | d->mMaxSwipeTime = i; |
127 | } |
128 | |
129 | int KTwoFingerSwipeRecognizer::minSswipeDistance() const |
130 | { |
131 | return d->mMinSwipeDistance; |
132 | } |
133 | |
134 | void KTwoFingerSwipeRecognizer::setSwipeDistance(int i) |
135 | { |
136 | if (i < 0) { |
137 | i = 0; |
138 | } |
139 | |
140 | d->mMinSwipeDistance = i; |
141 | } |
142 | |
143 | |
144 | |
145 | class KTwoFingerSwipePrivate |
146 | { |
147 | public: |
148 | KTwoFingerSwipePrivate(KTwoFingerSwipe *parent) |
149 | : q(parent) |
150 | { |
151 | } |
152 | KTwoFingerSwipe *const q; |
153 | QPointF mPos = QPointF(-1, -1); |
154 | QPointF mScreenPos = QPointF(-1, -1); |
155 | QPointF mScenePos = QPointF(-1, -1); |
156 | qreal mSwipeAngle = 0.0; |
157 | }; |
158 | |
159 | KTwoFingerSwipe::KTwoFingerSwipe(QObject *parent) |
160 | : QGesture(parent) |
161 | , d(new KTwoFingerSwipePrivate(this)) |
162 | { |
163 | } |
164 | |
165 | KTwoFingerSwipe::~KTwoFingerSwipe() |
166 | { |
167 | } |
168 | |
169 | QPointF KTwoFingerSwipe::pos() const |
170 | { |
171 | return d->mPos; |
172 | } |
173 | |
174 | void KTwoFingerSwipe::setPos(QPointF _pos) |
175 | { |
176 | d->mPos = _pos; |
177 | } |
178 | |
179 | QPointF KTwoFingerSwipe::screenPos() const |
180 | { |
181 | return d->mScreenPos; |
182 | } |
183 | |
184 | void KTwoFingerSwipe::setScreenPos(QPointF _screenPos) |
185 | { |
186 | d->mScreenPos = _screenPos; |
187 | } |
188 | |
189 | QPointF KTwoFingerSwipe::scenePos() const |
190 | { |
191 | return d->mScenePos; |
192 | } |
193 | |
194 | void KTwoFingerSwipe::setScenePos(QPointF _scenePos) |
195 | { |
196 | d->mScenePos = _scenePos; |
197 | } |
198 | |
199 | qreal KTwoFingerSwipe::swipeAngle() const |
200 | { |
201 | return d->mSwipeAngle; |
202 | } |
203 | void KTwoFingerSwipe::setSwipeAngle(qreal _swipeAngle) |
204 | { |
205 | d->mSwipeAngle = _swipeAngle; |
206 | } |
207 | |
208 | #include "moc_ktwofingerswipe.cpp" |
209 |