diff options
Diffstat (limited to 'src/gui/kernel/qstandardgestures.cpp')
-rw-r--r-- | src/gui/kernel/qstandardgestures.cpp | 243 |
1 files changed, 140 insertions, 103 deletions
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index c8b11c5..4753416 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -45,9 +45,14 @@ #include <qabstractscrollarea.h> #include <qscrollbar.h> #include <private/qapplication_p.h> +#include <private/qevent_p.h> QT_BEGIN_NAMESPACE +#ifdef Q_WS_WIN +QApplicationPrivate* getQApplicationPrivateInternal(); +#endif + /*! \class QPanGesture \since 4.6 @@ -68,7 +73,6 @@ QPanGesture::QPanGesture(QWidget *parent) { #ifdef Q_WS_WIN if (parent) { - QApplicationPrivate* getQApplicationPrivateInternal(); QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); qAppPriv->widgetGestures[parent].pan = this; } @@ -93,9 +97,81 @@ bool QPanGesture::event(QEvent *event) break; } #endif + +#if defined(Q_OS_MAC) && !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); + setState(Qt::GestureFinished); + emit triggered(); + setState(Qt::NoGesture); + } + } +#endif + return QObject::event(event); } +bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) +{ +#ifdef Q_WS_WIN + if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); + QApplicationPrivate::WidgetStandardGesturesMap::iterator it; + it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver)); + if (it == qAppPriv->widgetGestures.end()) + return false; + QPanGesture *gesture = it.value().pan; + if (!gesture) + return false; + Qt::GestureState nextState = state(); + switch(ev->gestureType) { + case QNativeGestureEvent::GestureBegin: + // next we might receive the first gesture update event, so we + // prepare for it. + setState(Qt::GestureStarted); + return false; + case QNativeGestureEvent::Pan: + nextState = Qt::GestureUpdated; + break; + case QNativeGestureEvent::GestureEnd: + if (state() != QNativeGestureEvent::Pan) + return false; // some other gesture has ended + setState(Qt::GestureFinished); + nextState = Qt::GestureFinished; + break; + default: + return false; + } + QPanGesturePrivate *d = gesture->d_func(); + if (state() == Qt::GestureStarted) { + d->lastPosition = ev->position; + d->lastOffset = d->totalOffset = QSize(); + } else { + d->lastOffset = QSize(ev->position.x() - d->lastPosition.x(), + ev->position.y() - d->lastPosition.y()); + d->totalOffset += d->lastOffset; + } + d->lastPosition = ev->position; + + if (state() == Qt::GestureStarted) + emit gesture->started(); + emit gesture->triggered(); + if (state() == Qt::GestureFinished) + emit gesture->finished(); + event->accept(); + gesture->setState(nextState); + return true; + } +#endif + return QGesture::eventFilter(receiver, event); +} + /*! \internal */ bool QPanGesture::filterEvent(QEvent *event) { @@ -104,28 +180,34 @@ bool QPanGesture::filterEvent(QEvent *event) return false; const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); if (event->type() == QEvent::TouchBegin) { - d->touchPoints = ev->touchPoints(); - const QPoint p = ev->touchPoints().at(0).pos().toPoint(); - setStartPos(p); - setLastPos(p); - setPos(p); - return false; + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + d->lastPosition = p.pos().toPoint(); + d->lastOffset = d->totalOffset = QSize(); } else if (event->type() == QEvent::TouchEnd) { if (state() != Qt::NoGesture) { setState(Qt::GestureFinished); - setLastPos(pos()); - setPos(ev->touchPoints().at(0).pos().toPoint()); + if (!ev->touchPoints().isEmpty()) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + const QPoint pos = p.pos().toPoint(); + const QPoint lastPos = p.lastPos().toPoint(); + const QPoint startPos = p.startPos().toPoint(); + d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); + d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); + } emit triggered(); emit finished(); } setState(Qt::NoGesture); reset(); } else if (event->type() == QEvent::TouchUpdate) { - d->touchPoints = ev->touchPoints(); - QPointF pt = d->touchPoints.at(0).pos() - d->touchPoints.at(0).startPos(); - setLastPos(pos()); - setPos(ev->touchPoints().at(0).pos().toPoint()); - if (pt.x() > 10 || pt.y() > 10 || pt.x() < -10 || pt.y() < -10) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + const QPoint pos = p.pos().toPoint(); + const QPoint lastPos = p.lastPos().toPoint(); + const QPoint startPos = p.startPos().toPoint(); + d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); + d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); + if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || + d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { if (state() == Qt::NoGesture) setState(Qt::GestureStarted); else @@ -133,6 +215,36 @@ bool QPanGesture::filterEvent(QEvent *event) emit triggered(); } } +#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); + + if (state() == Qt::NoGesture) { + setState(Qt::GestureStarted); + d->totalOffset = d->lastOffset; + } else { + setState(Qt::GestureUpdated); + d->totalOffset += d->lastOffset; + } + + killTimer(d->panFinishedTimer); + d->panFinishedTimer = startTimer(200); + emit triggered(); +#endif + return true; + } +#endif return false; } @@ -140,7 +252,14 @@ bool QPanGesture::filterEvent(QEvent *event) void QPanGesture::reset() { Q_D(QPanGesture); - d->touchPoints.clear(); + 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; + } +#endif } /*! @@ -150,8 +269,8 @@ void QPanGesture::reset() */ QSize QPanGesture::totalOffset() const { - QPoint pt = pos() - startPos(); - return QSize(pt.x(), pt.y()); + Q_D(const QPanGesture); + return d->totalOffset; } /*! @@ -162,93 +281,11 @@ QSize QPanGesture::totalOffset() const */ QSize QPanGesture::lastOffset() const { - QPoint pt = pos() - lastPos(); - return QSize(pt.x(), pt.y()); -} - -/*! - \class QTapAndHoldGesture - \since 4.6 - - \brief The QTapAndHoldGesture class represents a Tap-and-Hold gesture, - providing additional information. -*/ - -const int QTapAndHoldGesturePrivate::iterationCount = 40; -const int QTapAndHoldGesturePrivate::iterationTimeout = 50; - -/*! - Creates a new Tap and Hold gesture handler object and marks it as a child - of \a parent. - - On some platforms like Windows there is a system-wide tap and hold gesture - that cannot be overriden, hence the gesture might never trigger and default - context menu will be shown instead. -*/ -QTapAndHoldGesture::QTapAndHoldGesture(QWidget *parent) - : QGesture(*new QTapAndHoldGesturePrivate, parent) -{ -} - -/*! \internal */ -bool QTapAndHoldGesture::filterEvent(QEvent *event) -{ - Q_D(QTapAndHoldGesture); - if (!event->spontaneous()) - return false; - const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); - switch (event->type()) { - case QEvent::TouchBegin: { - if (d->timer.isActive()) - d->timer.stop(); - d->timer.start(QTapAndHoldGesturePrivate::iterationTimeout, this); - const QPoint p = ev->touchPoints().at(0).pos().toPoint(); - setStartPos(p); - setLastPos(p); - setPos(p); - break; - } - case QEvent::TouchUpdate: - if (ev->touchPoints().size() != 1) - reset(); - else if ((startPos() - ev->touchPoints().at(0).pos().toPoint()).manhattanLength() > 15) - reset(); - break; - case QEvent::TouchEnd: - reset(); - break; - default: - break; - } - return false; + Q_D(const QPanGesture); + return d->lastOffset; } -/*! \internal */ -void QTapAndHoldGesture::timerEvent(QTimerEvent *event) -{ - Q_D(QTapAndHoldGesture); - if (event->timerId() != d->timer.timerId()) - return; - if (d->iteration == QTapAndHoldGesturePrivate::iterationCount) { - d->timer.stop(); - setState(Qt::GestureFinished); - emit triggered(); - } else { - setState(Qt::GestureStarted); - emit triggered(); - } - ++d->iteration; -} +QT_END_NAMESPACE -/*! \internal */ -void QTapAndHoldGesture::reset() -{ - Q_D(QTapAndHoldGesture); - if (state() != Qt::NoGesture) - emit cancelled(); - setState(Qt::NoGesture); - d->timer.stop(); - d->iteration = 0; -} +#include "moc_qstandardgestures.cpp" -QT_END_NAMESPACE |