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