From 74dfe3e87c6a126e090a86b918f383e4bba9cb5a Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 27 Aug 2009 15:59:36 +0200 Subject: Gestures: Implement swipe gesture Note: if this fails building on any platform, talk to Denis! --- examples/gestures/imageviewer/imagewidget.cpp | 15 +++- src/gui/kernel/qapplication_p.h | 5 +- src/gui/kernel/qcocoaview_mac.mm | 9 ++- src/gui/kernel/qevent_p.h | 2 +- src/gui/kernel/qstandardgestures.cpp | 108 ++++++++++++++++++++++++++ src/gui/kernel/qstandardgestures.h | 28 +++++++ src/gui/kernel/qstandardgestures_p.h | 14 ++++ src/gui/kernel/qwidget_mac.mm | 9 ++- 8 files changed, 183 insertions(+), 7 deletions(-) diff --git a/examples/gestures/imageviewer/imagewidget.cpp b/examples/gestures/imageviewer/imagewidget.cpp index 495b73a..6803d84 100644 --- a/examples/gestures/imageviewer/imagewidget.cpp +++ b/examples/gestures/imageviewer/imagewidget.cpp @@ -70,6 +70,9 @@ ImageWidget::ImageWidget(QWidget *parent) connect(pinchGesture, SIGNAL(finished()), this, SLOT(pinchTriggered())); connect(pinchGesture, SIGNAL(cancelled()), this, SLOT(pinchTriggered())); connect(pinchGesture, SIGNAL(triggered()), this, SLOT(pinchTriggered())); + + QGesture *swipeGesture = new QSwipeGesture(this); + connect(swipeGesture, SIGNAL(triggered()), this, SLOT(swipeTriggered())); } void ImageWidget::paintEvent(QPaintEvent*) @@ -127,9 +130,15 @@ void ImageWidget::pinchTriggered() void ImageWidget::swipeTriggered() { - qDebug() << "swipe!"; - goNextImage(); -// goPrevImage(); + QSwipeGesture *pg = qobject_cast(sender()); + qDebug() << (int) pg->horizontalDirection(); + qDebug() << pg->swipeAngle(); + + if (pg->horizontalDirection() == QSwipeGesture::Left + || pg->verticalDirection() == QSwipeGesture::Up) + goPrevImage(); + else + goNextImage(); update(); } diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index e839617..f7f8ce9 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -264,12 +264,15 @@ typedef struct tagGESTURECONFIG class QPanGesture; class QPinchGesture; +class QSwipeGesture; + struct QStandardGestures { QPanGesture *pan; QPinchGesture *pinch; + QSwipeGesture *swipe; - QStandardGestures() : pan(0), pinch(0) { } + QStandardGestures() : pan(0), pinch(0), swipe(0) { } }; diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index df50e55..0a45ce9 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -905,7 +905,14 @@ extern "C" { qNGEvent.gestureType = QNativeGestureEvent::Swipe; NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; qNGEvent.position = flipPoint(p).toPoint(); - qNGEvent.direction = QSize(-[event deltaX], -[event deltaY]); + if ([event deltaX] == 1) + qNGEvent.angle = 180.0f; + else if ([event deltaX] == -1) + qNGEvent.angle = 0.0f; + else if ([event deltaY] == 1) + qNGEvent.angle = 90.0f; + else if ([event deltaY] == -1) + qNGEvent.angle = 270.0f; qt_sendSpontaneousEvent(qwidget, &qNGEvent); } diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index a26f585..11d3138 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -143,7 +143,7 @@ public: Type gestureType; float percentage; QPoint position; - QSize direction; + float angle; #ifdef Q_WS_WIN ulong sequenceId; quint64 argument; diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 0c4cadf..de6e7c7 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -295,6 +295,7 @@ QSizeF QPanGesture::lastOffset() const return d->lastOffset; } +////////////////////////////////////////////////////////////////////////////// /*! \class QPinchGesture @@ -314,6 +315,7 @@ QSizeF QPanGesture::lastOffset() const QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent) : QGesture(*new QPinchGesturePrivate, gestureTarget, parent) { + setObjectName(QLatin1String("QPinchGesture")); } void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget) @@ -510,6 +512,112 @@ 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(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(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(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" diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h index 9f2f204..029e6dc 100644 --- a/src/gui/kernel/qstandardgestures.h +++ b/src/gui/kernel/qstandardgestures.h @@ -119,6 +119,34 @@ private: friend class QWidget; }; +class QSwipeGesturePrivate; +class Q_GUI_EXPORT QSwipeGesture : public QGesture +{ + Q_OBJECT + Q_ENUMS(SwipeDirection) + + Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection) + Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection) + Q_PROPERTY(qreal swipeAngle READ swipeAngle) + + Q_DECLARE_PRIVATE(QSwipeGesture) + +public: + enum SwipeDirection { NoDirection, Left, Right, Up, Down }; + QSwipeGesture(QWidget *gestureTarget, QObject *parent = 0); + + bool filterEvent(QEvent *event); + void reset(); + + SwipeDirection horizontalDirection() const; + SwipeDirection verticalDirection() const; + qreal swipeAngle() const; + +private: + bool eventFilter(QObject *receiver, QEvent *event); + + friend class QWidget; +}; QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index 0a4debe..9829cf0 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -110,6 +110,20 @@ public: #endif }; +class QSwipeGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QSwipeGesture) + +public: + QSwipeGesturePrivate() + : swipeAngle(-1) + { + } + + void setupGestureTarget(QObject *o); + qreal swipeAngle; +}; + QT_END_NAMESPACE #endif // QSTANDARDGESTURES_P_H diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 192ae6b..cdf0706 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -1074,7 +1074,14 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, break; } qNGEvent.gestureType = QNativeGestureEvent::Swipe; - qNGEvent.direction = QSize(-swipeDirection.x, -swipeDirection.y); + if (swipeDirection.x == 1) + qNGEvent.angle = 180.0f; + else if (swipeDirection.x == -1) + qNGEvent.angle = 0.0f; + else if (swipeDirection.y == 1) + qNGEvent.angle = 90.0f; + else if (swipeDirection.y == -1) + qNGEvent.angle = 270.0f; break; } case kEventGestureMagnify: { CGFloat amount; -- cgit v0.12