Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qstandardgestures.cpp
Go to the documentation of this file.
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
5#include "qgesture.h"
6#include "qgesture_p.h"
7#include "qevent.h"
8#include "qwidget.h"
10#if QT_CONFIG(graphicsview)
11#include <qgraphicssceneevent.h>
12#endif
13#include "qdebug.h"
14
15#ifndef QT_NO_GESTURES
16
18
19// If the change in scale for a single touch event is out of this range,
20// we consider it to be spurious.
21static const qreal kSingleStepScaleMax = 2.0;
22static const qreal kSingleStepScaleMin = 0.1;
23
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()))
31#else
33#endif
34 }
35 return new QPanGesture;
36}
37
38static QPointF panOffset(const QList<QEventPoint> &touchPoints, int maxCount)
39{
41 const int count = qMin(touchPoints.size(), maxCount);
42 for (int p = 0; p < count; ++p)
43 result += touchPoints.at(p).position() - touchPoints.at(p).pressPosition();
44 return result / qreal(count);
45}
46
48 QObject *,
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: {
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(ev->points(), d->pointCount);
68 }
70 } else {
72 }
73 break;
74 }
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(ev->points(), 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());
84 } else {
86 }
87 }
88 break;
89 }
90 default:
91 break;
92 }
93 return result;
94}
95
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
105}
106
107
108//
109// QPinchGestureRecognizer
110//
111
115
117{
118 if (target && target->isWidgetType()) {
120 }
121 return new QPinchGesture;
122}
123
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: {
136 break;
137 }
138 case QEvent::TouchEnd: {
139 if (q->state() != Qt::NoGesture) {
141 } else {
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(0);
151 const QEventPoint &p2 = ev->points().at(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)
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;
197
198 d->totalChangeFlags |= d->changeFlags;
199 d->isNewSequence = false;
201 } else {
202 d->isNewSequence = true;
203 if (q->state() == Qt::NoGesture)
205 else
207 }
208 break;
209 }
210 default:
211 break;
212 }
213 return result;
214}
215
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
231}
232
233//
234// QSwipeGestureRecognizer
235//
236
240
242{
243 if (target && target->isWidgetType()) {
245 }
246 return new QSwipeGesture;
247}
248
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();
264 break;
265 }
266 case QEvent::TouchEnd: {
267 if (q->state() != Qt::NoGesture) {
269 } else {
271 }
272 break;
273 }
274 case QEvent::TouchUpdate: {
275 const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
278 else if (ev->points().size() == 3) {
280 const QEventPoint &p1 = ev->points().at(0);
281 const QEventPoint &p2 = ev->points().at(1);
282 const QEventPoint &p3 = ev->points().at(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(xDistance) > MoveThreshold || qAbs(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();
314 // QTBUG-46195, small changes in direction should not cause the gesture to be canceled.
315 if (d->verticalDirection == QSwipeGesture::NoDirection || qAbs(yDistance) > directionChangeThreshold) {
316 const QSwipeGesture::SwipeDirection vertical = yDistance > 0
318 if (d->verticalDirection != QSwipeGesture::NoDirection && d->verticalDirection != vertical)
320 d->verticalDirection = vertical;
321 }
322 if (d->horizontalDirection == QSwipeGesture::NoDirection || qAbs(xDistance) > directionChangeThreshold) {
323 const QSwipeGesture::SwipeDirection horizontal = xDistance > 0
325 if (d->horizontalDirection != QSwipeGesture::NoDirection && d->horizontalDirection != horizontal)
327 d->horizontalDirection = horizontal;
328 }
329 } else {
330 if (q->state() != Qt::NoGesture)
332 else
334 }
335 } else if (ev->points().size() > 3) {
337 } else { // less than 3 touch points
338 switch (d->state) {
341 break;
344 break;
346 result = (ev->touchPointStates() & QEventPoint::State::Pressed)
348 break;
349 }
350 }
351 break;
352 }
353 default:
354 break;
355 }
356 return result;
357}
358
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();
369 d->velocityValue = 0;
370 d->time.invalidate();
371
373}
374
375//
376// QTapGestureRecognizer
377//
378
382
384{
385 if (target && target->isWidgetType()) {
387 }
388 return new QTapGesture;
389}
390
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(0).position();
405 q->setHotSpot(ev->points().at(0).globalPosition());
407 break;
408 }
410 case QEvent::TouchEnd: {
411 if (q->state() != Qt::NoGesture && ev->points().size() == 1) {
412 const QEventPoint &p = ev->points().at(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)
418 else
420 }
421 }
422 break;
423 }
428 break;
429 default:
431 break;
432 }
433 return result;
434}
435
437{
438 QTapGesture *q = static_cast<QTapGesture *>(state);
439 QTapGesturePrivate *d = q->d_func();
440
441 d->position = QPointF();
442
444}
445
446//
447// QTapAndHoldGestureRecognizer
448//
449
453
455{
456 if (target && target->isWidgetType()) {
458 }
459 return new QTapAndHoldGesture;
460}
461
462QGestureRecognizer::Result
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(d->timerId);
471 d->timerId = 0;
473 }
474
475 enum { TapRadius = 40 };
476
477 switch (event->type()) {
478#if QT_CONFIG(graphicsview)
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(d->timerId);
485 d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout);
486 return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
487 }
488#endif
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(d->timerId);
495 d->timerId = q->startTimer(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(0).globalPressPosition();
501 q->setHotSpot(d->position);
502 if (d->timerId)
503 q->killTimer(d->timerId);
504 d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout);
505 return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
506 }
507#if QT_CONFIG(graphicsview)
509#endif
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(0);
517 QPoint delta = p.position().toPoint() - p.pressPosition().toPoint();
518 if (delta.manhattanLength() <= TapRadius)
520 }
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)
529 }
530#if QT_CONFIG(graphicsview)
532 const QGraphicsSceneMouseEvent *gsme = static_cast<const QGraphicsSceneMouseEvent *>(event);
533 QPoint delta = gsme->screenPos() - d->position.toPoint();
534 if (d->timerId && delta.manhattanLength() <= TapRadius)
537 }
538#endif
539 default:
541 }
542}
543
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(d->timerId);
552 d->timerId = 0;
553
555}
556
558
559#endif // QT_NO_GESTURES
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
QPointF globalPressPosition
the global position at which this point was pressed.
Definition qeventpoint.h:44
QPointF position
the position of this point.
Definition qeventpoint.h:35
\inmodule QtCore
Definition qcoreevent.h:45
@ GraphicsSceneMouseMove
Definition qcoreevent.h:189
@ GraphicsSceneMouseRelease
Definition qcoreevent.h:191
@ GraphicsSceneMousePress
Definition qcoreevent.h:190
@ MouseMove
Definition qcoreevent.h:63
@ MouseButtonPress
Definition qcoreevent.h:60
@ TouchUpdate
Definition qcoreevent.h:242
@ TouchBegin
Definition qcoreevent.h:241
@ MouseButtonRelease
Definition qcoreevent.h:61
virtual void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
The QGesture class represents a gesture, containing properties that describe the corresponding user i...
Definition qgesture.h:29
The QGraphicsSceneMouseEvent class provides mouse events in the graphics view framework.
QPoint screenPos() const
Returns the mouse cursor position in screen coordinates.
\inmodule QtCore\compares equality \compareswith equality QLine \endcompareswith
Definition qline.h:192
qreal angle() const
Definition qline.cpp:564
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
\inmodule QtGui
Definition qevent.h:196
\inmodule QtCore
Definition qobject.h:103
QGesture * create(QObject *target) override
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
void reset(QGesture *state) override
This function is called by the framework to reset a given gesture.
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event) override
Handles the given event for the watched object, updating the state of the gesture object as required,...
The QPanGesture class describes a panning gesture made by the user.\inmodule QtWidgets.
Definition qgesture.h:73
QPointF lastOffset
the last offset recorded for this gesture
Definition qgesture.h:77
QGesture * create(QObject *target) override
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event) override
Handles the given event for the watched object, updating the state of the gesture object as required,...
void reset(QGesture *state) override
This function is called by the framework to reset a given gesture.
The QPinchGesture class describes a pinch gesture made by the user.\inmodule QtWidgets.
Definition qgesture.h:103
@ RotationAngleChanged
Definition qgesture.h:110
ChangeFlags totalChangeFlags
the property of the gesture that has change
Definition qgesture.h:117
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int manhattanLength() const
Returns the sum of the absolute values of x() and y(), traditionally known as the "Manhattan length" ...
Definition qpoint.h:150
const QList< QEventPoint > & points() const
Returns a list of points in this pointer event.
Definition qevent.h:87
QPointF globalPosition() const
Returns the position of the point in this event on the screen or virtual desktop.
Definition qevent.h:123
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:119
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
QSwipeGesture::SwipeDirection verticalDirection
Definition qgesture_p.h:126
QGesture * create(QObject *target) override
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event) override
Handles the given event for the watched object, updating the state of the gesture object as required,...
void reset(QGesture *state) override
This function is called by the framework to reset a given gesture.
The QSwipeGesture class describes a swipe gesture made by the user.\inmodule QtWidgets.
Definition qgesture.h:177
SwipeDirection
This enum describes the possible directions for the gesture's motion along the horizontal and vertica...
Definition qgesture.h:187
void reset(QGesture *state) override
This function is called by the framework to reset a given gesture.
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event) override
Handles the given event for the watched object, updating the state of the gesture object as required,...
QGesture * create(QObject *target) override
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
The QTapAndHoldGesture class describes a tap-and-hold (aka LongTap) gesture made by the user....
Definition qgesture.h:222
void reset(QGesture *state) override
This function is called by the framework to reset a given gesture.
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event) override
Handles the given event for the watched object, updating the state of the gesture object as required,...
QGesture * create(QObject *target) override
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
The QTapGesture class describes a tap gesture made by the user.\inmodule QtWidgets.
Definition qgesture.h:204
The QTouchEvent class contains parameters that describe a touch event.
Definition qevent.h:917
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
QPixmap p2
QPixmap p1
[0]
else opt state
[0]
Combined button and popup list for selecting options.
@ WA_AcceptTouchEvents
Definition qnamespace.h:404
@ NoGesture
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLenum GLenum GLsizei count
GLsizei GLsizei GLfloat distance
GLfloat angle
GLenum target
struct _cl_event * event
GLsizei maxCount
Definition qopenglext.h:677
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
static QPointF panOffset(const QList< QEventPoint > &touchPoints, int maxCount)
static QT_BEGIN_NAMESPACE const qreal kSingleStepScaleMax
static const qreal kSingleStepScaleMin
double qreal
Definition qtypes.h:187
app setAttribute(Qt::AA_DontShowIconsInMenus)