summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qstandardgestures.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qstandardgestures.cpp')
-rw-r--r--src/gui/kernel/qstandardgestures.cpp231
1 files changed, 185 insertions, 46 deletions
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index d798d32..de6e7c7 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -72,6 +72,7 @@ QWidgetPrivate *qt_widget_private(QWidget *widget);
QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent)
: QGesture(*new QPanGesturePrivate, gestureTarget, parent)
{
+ setObjectName(QLatin1String("QPanGesture"));
}
void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
@@ -80,16 +81,22 @@ void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
if (gestureTarget && gestureTarget->isWidgetType()) {
QWidget *w = static_cast<QWidget*>(gestureTarget.data());
QApplicationPrivate::instance()->widgetGestures[w].pan = 0;
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN)
qt_widget_private(w)->winSetupGestures();
+#elif defined(Q_WS_MAC)
+ w->setAttribute(Qt::WA_AcceptTouchEvents, false);
+ w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents, false);
#endif
}
if (newGestureTarget && newGestureTarget->isWidgetType()) {
QWidget *w = static_cast<QWidget*>(newGestureTarget);
QApplicationPrivate::instance()->widgetGestures[w].pan = q;
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN)
qt_widget_private(w)->winSetupGestures();
+#elif defined(Q_WS_MAC)
+ w->setAttribute(Qt::WA_AcceptTouchEvents);
+ w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
#endif
}
QGesturePrivate::setupGestureTarget(newGestureTarget);
@@ -98,15 +105,13 @@ void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
/*! \internal */
bool QPanGesture::event(QEvent *event)
{
-#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA)
+#if defined(QT_MAC_USE_COCOA)
Q_D(QPanGesture);
if (event->type() == QEvent::Timer) {
const QTimerEvent *te = static_cast<QTimerEvent *>(event);
- if (te->timerId() == d->panFinishedTimer) {
- killTimer(d->panFinishedTimer);
- d->panFinishedTimer = 0;
- d->lastOffset = QSize(0, 0);
- updateState(Qt::GestureFinished);
+ if (te->timerId() == d->singleTouchPanTimer.timerId()) {
+ d->singleTouchPanTimer.stop();
+ updateState(Qt::GestureStarted);
}
}
#endif
@@ -164,8 +169,10 @@ bool QPanGesture::eventFilter(QObject *receiver, QEvent *event)
/*! \internal */
bool QPanGesture::filterEvent(QEvent *event)
{
+#if defined(Q_WS_WIN)
Q_D(QPanGesture);
const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+
if (event->type() == QEvent::TouchBegin) {
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
d->lastPosition = p.pos().toPoint();
@@ -197,33 +204,55 @@ bool QPanGesture::filterEvent(QEvent *event)
}
}
}
-#ifdef Q_OS_MAC
- else if (event->type() == QEvent::Wheel) {
- // On Mac, there is really no native panning gesture. Instead, a two
- // finger pan is delivered as mouse wheel events. Otoh, on Windows, you
- // either get mouse wheel events or pan events. We have decided to make this
- // the Qt behaviour as well, meaning that on Mac, wheel
- // events will be masked away when listening for pan events.
-#ifndef QT_MAC_USE_COCOA
- // In Carbon we receive neither touch-, nor pan gesture events.
- // So we create pan gestures by converting wheel events. After all, this
- // is how things are supposed to work on mac in the first place.
- const QWheelEvent *wev = static_cast<const QWheelEvent*>(event);
- int offset = wev->delta() / -120;
- d->lastOffset = wev->orientation() == Qt::Horizontal ? QSize(offset, 0) : QSize(0, offset);
+#elif defined(QT_MAC_USE_COCOA)
+ // The following implements single touch
+ // panning on Mac:
+ Q_D(QPanGesture);
+ const int panBeginDelay = 300;
+ const int panBeginRadius = 3;
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
- if (state() == Qt::NoGesture) {
- d->totalOffset = d->lastOffset;
- } else {
- d->totalOffset += d->lastOffset;
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ if (ev->touchPoints().size() == 1) {
+ d->lastPosition = QCursor::pos();
+ d->singleTouchPanTimer.start(panBeginDelay, this);
}
-
- killTimer(d->panFinishedTimer);
- d->panFinishedTimer = startTimer(200);
- updateState(Qt::GestureUpdated);
-#endif
- return true;
+ break;}
+ case QEvent::TouchEnd: {
+ if (state() != Qt::NoGesture)
+ updateState(Qt::GestureFinished);
+ reset();
+ break;}
+ case QEvent::TouchUpdate: {
+ if (ev->touchPoints().size() == 1) {
+ if (state() == Qt::NoGesture) {
+ // INVARIANT: The singleTouchTimer has still not fired.
+ // Lets check if the user moved his finger so much from
+ // the starting point that it makes sense to cancel:
+ const QPointF startPos = ev->touchPoints().at(0).startPos().toPoint();
+ const QPointF p = ev->touchPoints().at(0).pos().toPoint();
+ if ((startPos - p).manhattanLength() > panBeginRadius)
+ reset();
+ else
+ d->lastPosition = QCursor::pos();
+ } else {
+ QPointF mousePos = QCursor::pos();
+ QPointF dist = mousePos - d->lastPosition;
+ d->lastPosition = mousePos;
+ d->lastOffset = QSizeF(dist.x(), dist.y());
+ d->totalOffset += d->lastOffset;
+ updateState(Qt::GestureUpdated);
+ }
+ } else if (state() == Qt::NoGesture) {
+ reset();
+ }
+ break;}
+ default:
+ return false;
}
+#else
+ Q_UNUSED(event);
#endif
return false;
}
@@ -232,14 +261,14 @@ bool QPanGesture::filterEvent(QEvent *event)
void QPanGesture::reset()
{
Q_D(QPanGesture);
- d->lastOffset = d->totalOffset = QSize();
- d->lastPosition = QPoint();
-#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA)
- if (d->panFinishedTimer) {
- killTimer(d->panFinishedTimer);
- d->panFinishedTimer = 0;
- }
+ d->lastOffset = d->totalOffset = QSize(0, 0);
+ d->lastPosition = QPoint(0, 0);
+
+#if defined(QT_MAC_USE_COCOA)
+ d->singleTouchPanTimer.stop();
+ d->prevMousePos = QPointF(0, 0);
#endif
+
QGesture::reset();
}
@@ -248,7 +277,7 @@ void QPanGesture::reset()
Specifies a total pan offset since the start of the gesture.
*/
-QSize QPanGesture::totalOffset() const
+QSizeF QPanGesture::totalOffset() const
{
Q_D(const QPanGesture);
return d->totalOffset;
@@ -260,12 +289,13 @@ QSize QPanGesture::totalOffset() const
Specifies a pan offset since the last time the gesture was
triggered.
*/
-QSize QPanGesture::lastOffset() const
+QSizeF QPanGesture::lastOffset() const
{
Q_D(const QPanGesture);
return d->lastOffset;
}
+//////////////////////////////////////////////////////////////////////////////
/*!
\class QPinchGesture
@@ -285,6 +315,7 @@ QSize QPanGesture::lastOffset() const
QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent)
: QGesture(*new QPinchGesturePrivate, gestureTarget, parent)
{
+ setObjectName(QLatin1String("QPinchGesture"));
}
void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
@@ -338,12 +369,13 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event)
d->state = Qt::NoGesture;
d->scaleFactor = d->lastScaleFactor = 1;
d->rotationAngle = d->lastRotationAngle = 0;
- d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPoint();
+ d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF();
#if defined(Q_WS_WIN)
d->initialDistance = 0;
#endif
return false;
case QNativeGestureEvent::Rotate:
+ d->scaleFactor = 0;
d->lastRotationAngle = d->rotationAngle;
#if defined(Q_WS_WIN)
d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument);
@@ -354,6 +386,7 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event)
event->accept();
break;
case QNativeGestureEvent::Zoom:
+ d->rotationAngle = 0;
#if defined(Q_WS_WIN)
if (d->initialDistance != 0) {
d->lastScaleFactor = d->scaleFactor;
@@ -402,7 +435,7 @@ void QPinchGesture::reset()
Q_D(QPinchGesture);
d->scaleFactor = d->lastScaleFactor = 0;
d->rotationAngle = d->lastRotationAngle = 0;
- d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPoint();
+ d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF();
QGesture::reset();
}
@@ -452,7 +485,7 @@ qreal QPinchGesture::lastRotationAngle() const
Specifies a center point of the gesture. The point can be used as a center
point that the object is rotated around.
*/
-QPoint QPinchGesture::centerPoint() const
+QPointF QPinchGesture::centerPoint() const
{
return d_func()->centerPoint;
}
@@ -462,7 +495,7 @@ QPoint QPinchGesture::centerPoint() const
Specifies a previous center point of the gesture.
*/
-QPoint QPinchGesture::lastCenterPoint() const
+QPointF QPinchGesture::lastCenterPoint() const
{
return d_func()->lastCenterPoint;
}
@@ -474,11 +507,117 @@ QPoint QPinchGesture::lastCenterPoint() const
startCenterPoint and the centerPoint is the distance at which pinching
fingers has shifted.
*/
-QPoint QPinchGesture::startCenterPoint() const
+QPointF QPinchGesture::startCenterPoint() const
{
return d_func()->startCenterPoint;
}
+//////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \class QSwipeGesture
+ \since 4.6
+
+ \brief The QSwipeGesture class represents a swipe gesture,
+ providing additional information related to swiping.
+*/
+
+/*!
+ Creates a new Swipe gesture handler object and marks it as a child of \a
+ parent.
+
+ On some platform like Windows it's necessary to provide a non-null widget
+ as \a parent to get native gesture support.
+*/
+QSwipeGesture::QSwipeGesture(QWidget *gestureTarget, QObject *parent)
+ : QGesture(*new QSwipeGesturePrivate, gestureTarget, parent)
+{
+ setObjectName(QLatin1String("QSwipeGesture"));
+}
+
+void QSwipeGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
+{
+ Q_Q(QSwipeGesture);
+ if (gestureTarget && gestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(gestureTarget.data());
+ QApplicationPrivate::instance()->widgetGestures[w].swipe = 0;
+#if defined(Q_WS_WIN)
+ qt_widget_private(w)->winSetupGestures();
+#endif
+ }
+
+ if (newGestureTarget && newGestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(newGestureTarget);
+ QApplicationPrivate::instance()->widgetGestures[w].swipe = q;
+#if defined(Q_WS_WIN)
+ qt_widget_private(w)->winSetupGestures();
+#endif
+ }
+ QGesturePrivate::setupGestureTarget(newGestureTarget);
+}
+
+qreal QSwipeGesture::swipeAngle() const
+{
+ Q_D(const QSwipeGesture);
+ return d->swipeAngle;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const
+{
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 90 || d->swipeAngle > 270)
+ return QSwipeGesture::Right;
+ else
+ return QSwipeGesture::Left;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const
+{
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle <= 0 || d->swipeAngle == 180)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 180)
+ return QSwipeGesture::Up;
+ else
+ return QSwipeGesture::Down;
+}
+
+bool QSwipeGesture::eventFilter(QObject *receiver, QEvent *event)
+{
+ Q_D(QSwipeGesture);
+ if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ switch (ev->gestureType) {
+ case QNativeGestureEvent::Swipe:
+ d->swipeAngle = ev->angle;
+ updateState(Qt::GestureStarted);
+ updateState(Qt::GestureUpdated);
+ updateState(Qt::GestureFinished);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+ return QGesture::eventFilter(receiver, event);
+}
+
+/*! \internal */
+bool QSwipeGesture::filterEvent(QEvent *)
+{
+ return false;
+}
+
+/*! \internal */
+void QSwipeGesture::reset()
+{
+ Q_D(QSwipeGesture);
+ d->swipeAngle = -1;
+ QGesture::reset();
+}
+
QT_END_NAMESPACE
#include "moc_qstandardgestures.cpp"