1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qstandardgestures_p.h" |
5 | #include "qgesture.h" |
6 | #include "qgesture_p.h" |
7 | #include "qevent.h" |
8 | #include "qwidget.h" |
9 | #include "qabstractscrollarea.h" |
10 | #if QT_CONFIG(graphicsview) |
11 | #include <qgraphicssceneevent.h> |
12 | #endif |
13 | #include "qdebug.h" |
14 | |
15 | #ifndef QT_NO_GESTURES |
16 | |
17 | QT_BEGIN_NAMESPACE |
18 | |
19 | // If the change in scale for a single touch event is out of this range, |
20 | // we consider it to be spurious. |
21 | static const qreal kSingleStepScaleMax = 2.0; |
22 | static const qreal kSingleStepScaleMin = 0.1; |
23 | |
24 | QGesture *QPanGestureRecognizer::create(QObject *target) |
25 | { |
26 | if (target && target->isWidgetType()) { |
27 | #if (defined(Q_OS_MACOS) || defined(Q_OS_WIN)) && !defined(QT_NO_NATIVE_GESTURES) |
28 | // for scroll areas on Windows and OS X we want to use native gestures instead |
29 | if (!qobject_cast<QAbstractScrollArea *>(target->parent())) |
30 | static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); |
31 | #else |
32 | static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); |
33 | #endif |
34 | } |
35 | return new QPanGesture; |
36 | } |
37 | |
38 | static QPointF panOffset(const QList<QEventPoint> &touchPoints, int maxCount) |
39 | { |
40 | QPointF result; |
41 | const int count = qMin(a: touchPoints.size(), b: maxCount); |
42 | for (int p = 0; p < count; ++p) |
43 | result += touchPoints.at(i: p).position() - touchPoints.at(i: p).pressPosition(); |
44 | return result / qreal(count); |
45 | } |
46 | |
47 | QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, |
48 | QObject *, |
49 | QEvent *event) |
50 | { |
51 | QPanGesture *q = static_cast<QPanGesture *>(state); |
52 | QPanGesturePrivate *d = q->d_func(); |
53 | |
54 | QGestureRecognizer::Result result = QGestureRecognizer::Ignore; |
55 | switch (event->type()) { |
56 | case QEvent::TouchBegin: { |
57 | result = QGestureRecognizer::MayBeGesture; |
58 | d->lastOffset = d->offset = QPointF(); |
59 | d->pointCount = m_pointCount; |
60 | break; |
61 | } |
62 | case QEvent::TouchEnd: { |
63 | if (q->state() != Qt::NoGesture) { |
64 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
65 | if (ev->points().size() == d->pointCount) { |
66 | d->lastOffset = d->offset; |
67 | d->offset = panOffset(touchPoints: ev->points(), maxCount: d->pointCount); |
68 | } |
69 | result = QGestureRecognizer::FinishGesture; |
70 | } else { |
71 | result = QGestureRecognizer::CancelGesture; |
72 | } |
73 | break; |
74 | } |
75 | case QEvent::TouchUpdate: { |
76 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
77 | if (ev->points().size() >= d->pointCount) { |
78 | d->lastOffset = d->offset; |
79 | d->offset = panOffset(touchPoints: ev->points(), maxCount: d->pointCount); |
80 | if (d->offset.x() > 10 || d->offset.y() > 10 || |
81 | d->offset.x() < -10 || d->offset.y() < -10) { |
82 | q->setHotSpot(ev->points().first().globalPressPosition()); |
83 | result = QGestureRecognizer::TriggerGesture; |
84 | } else { |
85 | result = QGestureRecognizer::MayBeGesture; |
86 | } |
87 | } |
88 | break; |
89 | } |
90 | default: |
91 | break; |
92 | } |
93 | return result; |
94 | } |
95 | |
96 | void QPanGestureRecognizer::reset(QGesture *state) |
97 | { |
98 | QPanGesture *pan = static_cast<QPanGesture*>(state); |
99 | QPanGesturePrivate *d = pan->d_func(); |
100 | |
101 | d->lastOffset = d->offset = QPointF(); |
102 | d->acceleration = 0; |
103 | |
104 | QGestureRecognizer::reset(state); |
105 | } |
106 | |
107 | |
108 | // |
109 | // QPinchGestureRecognizer |
110 | // |
111 | |
112 | QPinchGestureRecognizer::QPinchGestureRecognizer() |
113 | { |
114 | } |
115 | |
116 | QGesture *QPinchGestureRecognizer::create(QObject *target) |
117 | { |
118 | if (target && target->isWidgetType()) { |
119 | static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); |
120 | } |
121 | return new QPinchGesture; |
122 | } |
123 | |
124 | QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, |
125 | QObject *, |
126 | QEvent *event) |
127 | { |
128 | QPinchGesture *q = static_cast<QPinchGesture *>(state); |
129 | QPinchGesturePrivate *d = q->d_func(); |
130 | |
131 | QGestureRecognizer::Result result = QGestureRecognizer::Ignore; |
132 | |
133 | switch (event->type()) { |
134 | case QEvent::TouchBegin: { |
135 | result = QGestureRecognizer::MayBeGesture; |
136 | break; |
137 | } |
138 | case QEvent::TouchEnd: { |
139 | if (q->state() != Qt::NoGesture) { |
140 | result = QGestureRecognizer::FinishGesture; |
141 | } else { |
142 | result = QGestureRecognizer::CancelGesture; |
143 | } |
144 | break; |
145 | } |
146 | case QEvent::TouchUpdate: { |
147 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
148 | d->changeFlags = { }; |
149 | if (ev->points().size() == 2) { |
150 | const QEventPoint &p1 = ev->points().at(i: 0); |
151 | const QEventPoint &p2 = ev->points().at(i: 1); |
152 | |
153 | d->hotSpot = p1.globalPosition(); |
154 | d->isHotSpotSet = true; |
155 | |
156 | QPointF centerPoint = (p1.globalPosition() + p2.globalPosition()) / 2.0; |
157 | if (d->isNewSequence) { |
158 | d->startPosition[0] = p1.globalPosition(); |
159 | d->startPosition[1] = p2.globalPosition(); |
160 | d->lastCenterPoint = centerPoint; |
161 | } else { |
162 | d->lastCenterPoint = d->centerPoint; |
163 | } |
164 | d->centerPoint = centerPoint; |
165 | |
166 | d->changeFlags |= QPinchGesture::CenterPointChanged; |
167 | |
168 | if (d->isNewSequence) { |
169 | d->scaleFactor = 1.0; |
170 | d->lastScaleFactor = 1.0; |
171 | } else { |
172 | d->lastScaleFactor = d->scaleFactor; |
173 | QLineF line(p1.globalPosition(), p2.globalPosition()); |
174 | QLineF lastLine(p1.globalLastPosition(), p2.globalLastPosition()); |
175 | qreal newScaleFactor = line.length() / lastLine.length(); |
176 | if (newScaleFactor > kSingleStepScaleMax || newScaleFactor < kSingleStepScaleMin) |
177 | return QGestureRecognizer::Ignore; |
178 | d->scaleFactor = newScaleFactor; |
179 | } |
180 | d->totalScaleFactor = d->totalScaleFactor * d->scaleFactor; |
181 | d->changeFlags |= QPinchGesture::ScaleFactorChanged; |
182 | |
183 | qreal angle = QLineF(p1.globalPosition(), p2.globalPosition()).angle(); |
184 | if (angle > 180) |
185 | angle -= 360; |
186 | qreal startAngle = QLineF(p1.globalPressPosition(), p2.globalPressPosition()).angle(); |
187 | if (startAngle > 180) |
188 | startAngle -= 360; |
189 | const qreal rotationAngle = startAngle - angle; |
190 | if (d->isNewSequence) |
191 | d->lastRotationAngle = 0.0; |
192 | else |
193 | d->lastRotationAngle = d->rotationAngle; |
194 | d->rotationAngle = rotationAngle; |
195 | d->totalRotationAngle += d->rotationAngle - d->lastRotationAngle; |
196 | d->changeFlags |= QPinchGesture::RotationAngleChanged; |
197 | |
198 | d->totalChangeFlags |= d->changeFlags; |
199 | d->isNewSequence = false; |
200 | result = QGestureRecognizer::TriggerGesture; |
201 | } else { |
202 | d->isNewSequence = true; |
203 | if (q->state() == Qt::NoGesture) |
204 | result = QGestureRecognizer::Ignore; |
205 | else |
206 | result = QGestureRecognizer::FinishGesture; |
207 | } |
208 | break; |
209 | } |
210 | default: |
211 | break; |
212 | } |
213 | return result; |
214 | } |
215 | |
216 | void QPinchGestureRecognizer::reset(QGesture *state) |
217 | { |
218 | QPinchGesture *pinch = static_cast<QPinchGesture *>(state); |
219 | QPinchGesturePrivate *d = pinch->d_func(); |
220 | |
221 | d->totalChangeFlags = d->changeFlags = { }; |
222 | |
223 | d->startCenterPoint = d->lastCenterPoint = d->centerPoint = QPointF(); |
224 | d->totalScaleFactor = d->lastScaleFactor = d->scaleFactor = 1; |
225 | d->totalRotationAngle = d->lastRotationAngle = d->rotationAngle = 0; |
226 | |
227 | d->isNewSequence = true; |
228 | d->startPosition[0] = d->startPosition[1] = QPointF(); |
229 | |
230 | QGestureRecognizer::reset(state); |
231 | } |
232 | |
233 | // |
234 | // QSwipeGestureRecognizer |
235 | // |
236 | |
237 | QSwipeGestureRecognizer::QSwipeGestureRecognizer() |
238 | { |
239 | } |
240 | |
241 | QGesture *QSwipeGestureRecognizer::create(QObject *target) |
242 | { |
243 | if (target && target->isWidgetType()) { |
244 | static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); |
245 | } |
246 | return new QSwipeGesture; |
247 | } |
248 | |
249 | QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, |
250 | QObject *, |
251 | QEvent *event) |
252 | { |
253 | QSwipeGesture *q = static_cast<QSwipeGesture *>(state); |
254 | QSwipeGesturePrivate *d = q->d_func(); |
255 | |
256 | QGestureRecognizer::Result result = QGestureRecognizer::Ignore; |
257 | |
258 | switch (event->type()) { |
259 | case QEvent::TouchBegin: { |
260 | d->velocityValue = 1; |
261 | d->time.start(); |
262 | d->state = QSwipeGesturePrivate::Started; |
263 | result = QGestureRecognizer::MayBeGesture; |
264 | break; |
265 | } |
266 | case QEvent::TouchEnd: { |
267 | if (q->state() != Qt::NoGesture) { |
268 | result = QGestureRecognizer::FinishGesture; |
269 | } else { |
270 | result = QGestureRecognizer::CancelGesture; |
271 | } |
272 | break; |
273 | } |
274 | case QEvent::TouchUpdate: { |
275 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
276 | if (d->state == QSwipeGesturePrivate::NoGesture) |
277 | result = QGestureRecognizer::CancelGesture; |
278 | else if (ev->points().size() == 3) { |
279 | d->state = QSwipeGesturePrivate::ThreePointsReached; |
280 | const QEventPoint &p1 = ev->points().at(i: 0); |
281 | const QEventPoint &p2 = ev->points().at(i: 1); |
282 | const QEventPoint &p3 = ev->points().at(i: 2); |
283 | |
284 | if (d->lastPositions[0].isNull()) { |
285 | d->lastPositions[0] = p1.globalPressPosition().toPoint(); |
286 | d->lastPositions[1] = p2.globalPressPosition().toPoint(); |
287 | d->lastPositions[2] = p3.globalPressPosition().toPoint(); |
288 | } |
289 | d->hotSpot = p1.globalPosition(); |
290 | d->isHotSpotSet = true; |
291 | |
292 | int xDistance = (p1.globalPosition().x() - d->lastPositions[0].x() + |
293 | p2.globalPosition().x() - d->lastPositions[1].x() + |
294 | p3.globalPosition().x() - d->lastPositions[2].x()) / 3; |
295 | int yDistance = (p1.globalPosition().y() - d->lastPositions[0].y() + |
296 | p2.globalPosition().y() - d->lastPositions[1].y() + |
297 | p3.globalPosition().y() - d->lastPositions[2].y()) / 3; |
298 | |
299 | const int distance = xDistance >= yDistance ? xDistance : yDistance; |
300 | int elapsedTime = d->time.restart(); |
301 | if (!elapsedTime) |
302 | elapsedTime = 1; |
303 | d->velocityValue = 0.9 * d->velocityValue + (qreal) distance / elapsedTime; |
304 | d->swipeAngle = QLineF(p1.globalPressPosition(), p1.globalPosition()).angle(); |
305 | |
306 | static const int MoveThreshold = 50; |
307 | static const int directionChangeThreshold = MoveThreshold / 8; |
308 | if (qAbs(t: xDistance) > MoveThreshold || qAbs(t: yDistance) > MoveThreshold) { |
309 | // measure the distance to check if the direction changed |
310 | d->lastPositions[0] = p1.globalPosition().toPoint(); |
311 | d->lastPositions[1] = p2.globalPosition().toPoint(); |
312 | d->lastPositions[2] = p3.globalPosition().toPoint(); |
313 | result = QGestureRecognizer::TriggerGesture; |
314 | // QTBUG-46195, small changes in direction should not cause the gesture to be canceled. |
315 | if (d->verticalDirection == QSwipeGesture::NoDirection || qAbs(t: yDistance) > directionChangeThreshold) { |
316 | const QSwipeGesture::SwipeDirection vertical = yDistance > 0 |
317 | ? QSwipeGesture::Down : QSwipeGesture::Up; |
318 | if (d->verticalDirection != QSwipeGesture::NoDirection && d->verticalDirection != vertical) |
319 | result = QGestureRecognizer::CancelGesture; |
320 | d->verticalDirection = vertical; |
321 | } |
322 | if (d->horizontalDirection == QSwipeGesture::NoDirection || qAbs(t: xDistance) > directionChangeThreshold) { |
323 | const QSwipeGesture::SwipeDirection horizontal = xDistance > 0 |
324 | ? QSwipeGesture::Right : QSwipeGesture::Left; |
325 | if (d->horizontalDirection != QSwipeGesture::NoDirection && d->horizontalDirection != horizontal) |
326 | result = QGestureRecognizer::CancelGesture; |
327 | d->horizontalDirection = horizontal; |
328 | } |
329 | } else { |
330 | if (q->state() != Qt::NoGesture) |
331 | result = QGestureRecognizer::TriggerGesture; |
332 | else |
333 | result = QGestureRecognizer::MayBeGesture; |
334 | } |
335 | } else if (ev->points().size() > 3) { |
336 | result = QGestureRecognizer::CancelGesture; |
337 | } else { // less than 3 touch points |
338 | switch (d->state) { |
339 | case QSwipeGesturePrivate::NoGesture: |
340 | result = QGestureRecognizer::MayBeGesture; |
341 | break; |
342 | case QSwipeGesturePrivate::Started: |
343 | result = QGestureRecognizer::Ignore; |
344 | break; |
345 | case QSwipeGesturePrivate::ThreePointsReached: |
346 | result = (ev->touchPointStates() & QEventPoint::State::Pressed) |
347 | ? QGestureRecognizer::CancelGesture : QGestureRecognizer::Ignore; |
348 | break; |
349 | } |
350 | } |
351 | break; |
352 | } |
353 | default: |
354 | break; |
355 | } |
356 | return result; |
357 | } |
358 | |
359 | void QSwipeGestureRecognizer::reset(QGesture *state) |
360 | { |
361 | QSwipeGesture *q = static_cast<QSwipeGesture *>(state); |
362 | QSwipeGesturePrivate *d = q->d_func(); |
363 | |
364 | d->verticalDirection = d->horizontalDirection = QSwipeGesture::NoDirection; |
365 | d->swipeAngle = 0; |
366 | |
367 | d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint(); |
368 | d->state = QSwipeGesturePrivate::NoGesture; |
369 | d->velocityValue = 0; |
370 | d->time.invalidate(); |
371 | |
372 | QGestureRecognizer::reset(state); |
373 | } |
374 | |
375 | // |
376 | // QTapGestureRecognizer |
377 | // |
378 | |
379 | QTapGestureRecognizer::QTapGestureRecognizer() |
380 | { |
381 | } |
382 | |
383 | QGesture *QTapGestureRecognizer::create(QObject *target) |
384 | { |
385 | if (target && target->isWidgetType()) { |
386 | static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); |
387 | } |
388 | return new QTapGesture; |
389 | } |
390 | |
391 | QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state, |
392 | QObject *, |
393 | QEvent *event) |
394 | { |
395 | QTapGesture *q = static_cast<QTapGesture *>(state); |
396 | QTapGesturePrivate *d = q->d_func(); |
397 | |
398 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
399 | |
400 | QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; |
401 | |
402 | switch (event->type()) { |
403 | case QEvent::TouchBegin: { |
404 | d->position = ev->points().at(i: 0).position(); |
405 | q->setHotSpot(ev->points().at(i: 0).globalPosition()); |
406 | result = QGestureRecognizer::TriggerGesture; |
407 | break; |
408 | } |
409 | case QEvent::TouchUpdate: |
410 | case QEvent::TouchEnd: { |
411 | if (q->state() != Qt::NoGesture && ev->points().size() == 1) { |
412 | const QEventPoint &p = ev->points().at(i: 0); |
413 | QPoint delta = p.position().toPoint() - p.pressPosition().toPoint(); |
414 | enum { TapRadius = 40 }; |
415 | if (delta.manhattanLength() <= TapRadius) { |
416 | if (event->type() == QEvent::TouchEnd) |
417 | result = QGestureRecognizer::FinishGesture; |
418 | else |
419 | result = QGestureRecognizer::TriggerGesture; |
420 | } |
421 | } |
422 | break; |
423 | } |
424 | case QEvent::MouseButtonPress: |
425 | case QEvent::MouseMove: |
426 | case QEvent::MouseButtonRelease: |
427 | result = QGestureRecognizer::Ignore; |
428 | break; |
429 | default: |
430 | result = QGestureRecognizer::Ignore; |
431 | break; |
432 | } |
433 | return result; |
434 | } |
435 | |
436 | void QTapGestureRecognizer::reset(QGesture *state) |
437 | { |
438 | QTapGesture *q = static_cast<QTapGesture *>(state); |
439 | QTapGesturePrivate *d = q->d_func(); |
440 | |
441 | d->position = QPointF(); |
442 | |
443 | QGestureRecognizer::reset(state); |
444 | } |
445 | |
446 | // |
447 | // QTapAndHoldGestureRecognizer |
448 | // |
449 | |
450 | QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer() |
451 | { |
452 | } |
453 | |
454 | QGesture *QTapAndHoldGestureRecognizer::create(QObject *target) |
455 | { |
456 | if (target && target->isWidgetType()) { |
457 | static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); |
458 | } |
459 | return new QTapAndHoldGesture; |
460 | } |
461 | |
462 | QGestureRecognizer::Result |
463 | QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, |
464 | QEvent *event) |
465 | { |
466 | QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); |
467 | QTapAndHoldGesturePrivate *d = q->d_func(); |
468 | |
469 | if (object == state && event->type() == QEvent::Timer) { |
470 | q->killTimer(id: d->timerId); |
471 | d->timerId = 0; |
472 | return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; |
473 | } |
474 | |
475 | enum { TapRadius = 40 }; |
476 | |
477 | switch (event->type()) { |
478 | #if QT_CONFIG(graphicsview) |
479 | case QEvent::GraphicsSceneMousePress: { |
480 | const QGraphicsSceneMouseEvent *gsme = static_cast<const QGraphicsSceneMouseEvent *>(event); |
481 | d->position = gsme->screenPos(); |
482 | q->setHotSpot(d->position); |
483 | if (d->timerId) |
484 | q->killTimer(id: d->timerId); |
485 | d->timerId = q->startTimer(interval: QTapAndHoldGesturePrivate::Timeout); |
486 | return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout |
487 | } |
488 | #endif |
489 | case QEvent::MouseButtonPress: { |
490 | const QMouseEvent *me = static_cast<const QMouseEvent *>(event); |
491 | d->position = me->globalPosition().toPoint(); |
492 | q->setHotSpot(d->position); |
493 | if (d->timerId) |
494 | q->killTimer(id: d->timerId); |
495 | d->timerId = q->startTimer(interval: QTapAndHoldGesturePrivate::Timeout); |
496 | return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout |
497 | } |
498 | case QEvent::TouchBegin: { |
499 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
500 | d->position = ev->points().at(i: 0).globalPressPosition(); |
501 | q->setHotSpot(d->position); |
502 | if (d->timerId) |
503 | q->killTimer(id: d->timerId); |
504 | d->timerId = q->startTimer(interval: QTapAndHoldGesturePrivate::Timeout); |
505 | return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout |
506 | } |
507 | #if QT_CONFIG(graphicsview) |
508 | case QEvent::GraphicsSceneMouseRelease: |
509 | #endif |
510 | case QEvent::MouseButtonRelease: |
511 | case QEvent::TouchEnd: |
512 | return QGestureRecognizer::CancelGesture; // get out of the MayBeGesture state |
513 | case QEvent::TouchUpdate: { |
514 | const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); |
515 | if (d->timerId && ev->points().size() == 1) { |
516 | const QEventPoint &p = ev->points().at(i: 0); |
517 | QPoint delta = p.position().toPoint() - p.pressPosition().toPoint(); |
518 | if (delta.manhattanLength() <= TapRadius) |
519 | return QGestureRecognizer::MayBeGesture; |
520 | } |
521 | return QGestureRecognizer::CancelGesture; |
522 | } |
523 | case QEvent::MouseMove: { |
524 | const QMouseEvent *me = static_cast<const QMouseEvent *>(event); |
525 | QPoint delta = me->globalPosition().toPoint() - d->position.toPoint(); |
526 | if (d->timerId && delta.manhattanLength() <= TapRadius) |
527 | return QGestureRecognizer::MayBeGesture; |
528 | return QGestureRecognizer::CancelGesture; |
529 | } |
530 | #if QT_CONFIG(graphicsview) |
531 | case QEvent::GraphicsSceneMouseMove: { |
532 | const QGraphicsSceneMouseEvent *gsme = static_cast<const QGraphicsSceneMouseEvent *>(event); |
533 | QPoint delta = gsme->screenPos() - d->position.toPoint(); |
534 | if (d->timerId && delta.manhattanLength() <= TapRadius) |
535 | return QGestureRecognizer::MayBeGesture; |
536 | return QGestureRecognizer::CancelGesture; |
537 | } |
538 | #endif |
539 | default: |
540 | return QGestureRecognizer::Ignore; |
541 | } |
542 | } |
543 | |
544 | void QTapAndHoldGestureRecognizer::reset(QGesture *state) |
545 | { |
546 | QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); |
547 | QTapAndHoldGesturePrivate *d = q->d_func(); |
548 | |
549 | d->position = QPointF(); |
550 | if (d->timerId) |
551 | q->killTimer(id: d->timerId); |
552 | d->timerId = 0; |
553 | |
554 | QGestureRecognizer::reset(state); |
555 | } |
556 | |
557 | QT_END_NAMESPACE |
558 | |
559 | #endif // QT_NO_GESTURES |
560 | |