diff options
author | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2009-09-01 12:25:42 (GMT) |
---|---|---|
committer | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2009-09-03 09:30:54 (GMT) |
commit | 466bc1ed4bf0c466e54732b2f8f7a16a34b716a8 (patch) | |
tree | d84578adfd77b2dd72f16277db3e0c3f1339528e /src/gui/kernel/qstandardgestures.cpp | |
parent | a1a0ea71d8861e2b794f2f9b55447d50fc520de3 (diff) | |
download | Qt-466bc1ed4bf0c466e54732b2f8f7a16a34b716a8.zip Qt-466bc1ed4bf0c466e54732b2f8f7a16a34b716a8.tar.gz Qt-466bc1ed4bf0c466e54732b2f8f7a16a34b716a8.tar.bz2 |
Improved the gesture api.
Made properties in QPanGesture and QPinchGesture more consistent - all of them
have value, lastValue and totalValue. Documented that totalValue means the
value from the beginning of the gesture, while the 'value' - from the beginning
of the current sequence. This is especially useful on Windows when you zoom
with two fingers and then release one finger and touch again to continue
zooming.
Also added a workaround for native Rotate gesture on Windows which contain a
'bad' value in the first WM_GESTURE message in every gesture sequence.
Reviewed-by: Bradley T. Hughes
Diffstat (limited to 'src/gui/kernel/qstandardgestures.cpp')
-rw-r--r-- | src/gui/kernel/qstandardgestures.cpp | 153 |
1 files changed, 123 insertions, 30 deletions
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index f6534d1..783c1d3 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -47,6 +47,7 @@ #include <private/qapplication_p.h> #include <private/qevent_p.h> #include <private/qwidget_p.h> +#include <qmath.h> QT_BEGIN_NAMESPACE @@ -172,11 +173,12 @@ bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) return false; } if (state() == Qt::NoGesture) { - d->lastOffset = d->totalOffset = QSize(); + d->lastOffset = d->totalOffset = d->offset = QSize(); } else { - d->lastOffset = QSize(ev->position.x() - d->lastPosition.x(), - ev->position.y() - d->lastPosition.y()); - d->totalOffset += d->lastOffset; + d->lastOffset = d->offset; + d->offset = QSize(ev->position.x() - d->lastPosition.x(), + ev->position.y() - d->lastPosition.y()); + d->totalOffset += d->offset; } d->lastPosition = ev->position; updateState(nextState); @@ -201,16 +203,17 @@ bool QPanGesture::filterEvent(QEvent *event) if (event->type() == QEvent::TouchBegin) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); d->lastPosition = p.pos().toPoint(); - d->lastOffset = d->totalOffset = QSize(); + d->lastOffset = d->totalOffset = d->offset = QSize(); } else if (event->type() == QEvent::TouchEnd) { if (state() != Qt::NoGesture) { if (ev->touchPoints().size() == 2) { QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); - d->lastOffset = + d->lastOffset = d->offset; + d->offset = QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; - d->totalOffset += d->lastOffset; + d->totalOffset += d->offset; } updateState(Qt::GestureFinished); } @@ -219,10 +222,11 @@ bool QPanGesture::filterEvent(QEvent *event) if (ev->touchPoints().size() == 2) { QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); - d->lastOffset = + d->lastOffset = d->offset; + d->offset = QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; - d->totalOffset += d->lastOffset; + d->totalOffset += d->offset; if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { updateState(Qt::GestureUpdated); @@ -264,8 +268,9 @@ bool QPanGesture::filterEvent(QEvent *event) QPointF mousePos = QCursor::pos(); QPointF dist = mousePos - d->lastPosition; d->lastPosition = mousePos; - d->lastOffset = QSizeF(dist.x(), dist.y()); - d->totalOffset += d->lastOffset; + d->lastOffset = d->offset; + d->offset = QSizeF(dist.x(), dist.y()); + d->totalOffset += d->offset; updateState(Qt::GestureUpdated); } } else if (state() == Qt::NoGesture) { @@ -285,7 +290,7 @@ bool QPanGesture::filterEvent(QEvent *event) void QPanGesture::reset() { Q_D(QPanGesture); - d->lastOffset = d->totalOffset = QSize(0, 0); + d->lastOffset = d->totalOffset = d->offset = QSize(0, 0); d->lastPosition = QPoint(0, 0); #if defined(QT_MAC_USE_COCOA) @@ -310,8 +315,7 @@ QSizeF QPanGesture::totalOffset() const /*! \property QPanGesture::lastOffset - Specifies a pan offset since the last time the gesture was - triggered. + Specifies a pan offset the last time the gesture was triggered. */ QSizeF QPanGesture::lastOffset() const { @@ -319,6 +323,18 @@ QSizeF QPanGesture::lastOffset() const return d->lastOffset; } +/*! + \property QPanGesture::offset + + Specifies the current pan offset since the last time the gesture was + triggered. +*/ +QSizeF QPanGesture::offset() const +{ + Q_D(const QPanGesture); + return d->offset; +} + ////////////////////////////////////////////////////////////////////////////// /*! @@ -397,37 +413,75 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) // next we might receive the first gesture update event, so we // prepare for it. d->state = Qt::NoGesture; - d->scaleFactor = d->lastScaleFactor = 1; - d->rotationAngle = d->lastRotationAngle = 0; + d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.; + d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.; d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF(); #if defined(Q_WS_WIN) d->initialDistance = 0; + d->lastSequenceId = ev->sequenceId; #endif return false; - case QNativeGestureEvent::Rotate: - d->scaleFactor = 0; + case QNativeGestureEvent::Rotate: { + d->lastScaleFactor = d->scaleFactor; d->lastRotationAngle = d->rotationAngle; -#if defined(Q_WS_WIN) - d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument); -#elif defined(Q_WS_MAC) - d->rotationAngle = ev->percentage; -#endif +#if defined(Q_WS_MAC) + d->rotationAngle += ev->percentage; nextState = Qt::GestureUpdated; +#elif defined(Q_WS_WIN) + // This is a workaround for an issue with the native rotation + // gesture on Windows 7. For some reason the rotation angle in the + // first WM_GESTURE message in a sequence contains value that is + // off a little bit and causes the rotating item to "jump", so + // we just ignore the first WM_GESTURE in every sequence. + bool windowsRotateWorkaround = false; + if (!d->lastSequenceId) { + windowsRotateWorkaround = true; + d->lastSequenceId = ev->sequenceId; + } + if (d->lastSequenceId > 0 && d->lastSequenceId != (ulong)-1 && ev->sequenceId != d->lastSequenceId) { + // this is the first WM_GESTURE message in a sequence. + d->totalRotationAngle += d->rotationAngle; + windowsRotateWorkaround = true; + // a magic value to mark that the next WM_GESTURE message is + // the second message in a sequence and we should clear the + // lastRotationAngle + d->lastSequenceId = (ulong)-1; + } + if (!windowsRotateWorkaround) { + d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument) * 180. / M_PI; + if (d->lastSequenceId == (ulong)-1) { + // a special case since we need to set the lastRotationAngle to + // rotationAngle when the first WM_GESTURE is received in each + // sequence. + d->lastRotationAngle = d->rotationAngle; + } + d->lastSequenceId = ev->sequenceId; + } + if (!windowsRotateWorkaround) + nextState = Qt::GestureUpdated; +#endif event->accept(); break; + } case QNativeGestureEvent::Zoom: - d->rotationAngle = 0; + d->lastRotationAngle = d->rotationAngle; + d->lastScaleFactor = d->scaleFactor; #if defined(Q_WS_WIN) if (d->initialDistance != 0) { - d->lastScaleFactor = d->scaleFactor; int distance = int(qint64(ev->argument)); - d->scaleFactor = (qreal) distance / d->initialDistance; + if (d->lastSequenceId && ev->sequenceId != d->lastSequenceId) { + d->totalScaleFactor *= d->scaleFactor; + d->initialDistance = int(qint64(ev->argument)); + d->lastScaleFactor = d->scaleFactor = (qreal) distance / d->initialDistance; + } else { + d->scaleFactor = (qreal) distance / d->initialDistance; + } + d->lastSequenceId = ev->sequenceId; } else { d->initialDistance = int(qint64(ev->argument)); } #elif defined(Q_WS_MAC) - d->lastScaleFactor = d->scaleFactor; - d->scaleFactor = ev->percentage; + d->scaleFactor += ev->percentage; #endif nextState = Qt::GestureUpdated; event->accept(); @@ -469,16 +523,33 @@ bool QPinchGesture::filterEvent(QEvent *event) void QPinchGesture::reset() { Q_D(QPinchGesture); - d->scaleFactor = d->lastScaleFactor = 0; - d->rotationAngle = d->lastRotationAngle = 0; + d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.; + d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.; d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF(); QGesture::reset(); } /*! + \property QPinchGesture::totalScaleFactor + + Specifies a total scale factor of the pinch gesture since the gesture + started. +*/ +qreal QPinchGesture::totalScaleFactor() const +{ + Q_D(const QPinchGesture); + return d->totalScaleFactor * d->scaleFactor; +} + +/*! \property QPinchGesture::scaleFactor Specifies a scale factor of the pinch gesture. + + If the gesture consists of several pinch sequences (i.e. zoom and rotate + sequences), then this property specifies the scale factor in the current + sequence. When pinching changes the rotation angle only, the value of this + property is 1. */ qreal QPinchGesture::scaleFactor() const { @@ -496,9 +567,29 @@ qreal QPinchGesture::lastScaleFactor() const } /*! + \property QPinchGesture::totalRotationAngle + + Specifies a total rotation angle of the gesture since the gesture started. + + The angle is specified in degrees. +*/ +qreal QPinchGesture::totalRotationAngle() const +{ + Q_D(const QPinchGesture); + return d->totalRotationAngle + d->rotationAngle; +} + +/*! \property QPinchGesture::rotationAngle Specifies a rotation angle of the gesture. + + If the gesture consists of several pinch sequences (i.e. zoom and rotate + sequences), then this property specifies the rotation angle in the current + sequence. When pinching changes the scale factor only, the value of this + property is 0. + + The angle is specified in degrees. */ qreal QPinchGesture::rotationAngle() const { @@ -509,6 +600,8 @@ qreal QPinchGesture::rotationAngle() const \property QPinchGesture::lastRotationAngle Specifies a previous rotation angle of the gesture. + + The angle is specified in degrees. */ qreal QPinchGesture::lastRotationAngle() const { |