diff options
author | Morten Johan Sørvig <morten.sorvig@nokia.com> | 2009-11-05 12:11:45 (GMT) |
---|---|---|
committer | Morten Johan Sørvig <morten.sorvig@nokia.com> | 2009-11-05 12:11:45 (GMT) |
commit | 9418962051579959981515bb74bf6463436aa75e (patch) | |
tree | 4f23a58b639e55b7c4785a1bc159dd960fbc9d03 | |
parent | 8927e54d9ab5dda2c1f8e0e17988ad37ab0e4b1e (diff) | |
parent | 75da4b5855c63b41060886c7b8ed7856888e4e35 (diff) | |
download | Qt-9418962051579959981515bb74bf6463436aa75e.zip Qt-9418962051579959981515bb74bf6463436aa75e.tar.gz Qt-9418962051579959981515bb74bf6463436aa75e.tar.bz2 |
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt-platform-team into 4.6
-rw-r--r-- | examples/gestures/imagegestures/imagewidget.cpp | 31 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 66 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.h | 34 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 34 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 6 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures.cpp | 320 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures_p.h | 29 |
7 files changed, 497 insertions, 23 deletions
diff --git a/examples/gestures/imagegestures/imagewidget.cpp b/examples/gestures/imagegestures/imagewidget.cpp index df8f56d..afa0185 100644 --- a/examples/gestures/imagegestures/imagewidget.cpp +++ b/examples/gestures/imagegestures/imagewidget.cpp @@ -76,7 +76,6 @@ bool ImageWidget::event(QEvent *event) void ImageWidget::paintEvent(QPaintEvent*) { QPainter p(this); - p.fillRect(rect(), Qt::white); float iw = currentImage.width(); float ih = currentImage.height(); @@ -95,6 +94,7 @@ void ImageWidget::mouseDoubleClickEvent(QMouseEvent *) { rotationAngle = 0; scaleFactor = 1; + currentStepScaleFactor = 1; verticalOffset = 0; horizontalOffset = 0; update(); @@ -103,12 +103,12 @@ void ImageWidget::mouseDoubleClickEvent(QMouseEvent *) //! [gesture event handler] bool ImageWidget::gestureEvent(QGestureEvent *event) { - if (QGesture *pan = event->gesture(Qt::PanGesture)) + if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) + swipeTriggered(static_cast<QSwipeGesture *>(swipe)); + else if (QGesture *pan = event->gesture(Qt::PanGesture)) panTriggered(static_cast<QPanGesture *>(pan)); if (QGesture *pinch = event->gesture(Qt::PinchGesture)) pinchTriggered(static_cast<QPinchGesture *>(pinch)); - if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) - swipeTriggered(static_cast<QSwipeGesture *>(swipe)); return true; } //! [gesture event handler] @@ -141,12 +141,11 @@ void ImageWidget::pinchTriggered(QPinchGesture *gesture) } if (changeFlags & QPinchGesture::ScaleFactorChanged) { qreal value = gesture->property("scaleFactor").toReal(); - if (gesture->state() == Qt::GestureFinished) { - scaleFactor *= currentStepScaleFactor; - currentStepScaleFactor = 1; - } else { - currentStepScaleFactor = value; - } + currentStepScaleFactor = value; + } + if (gesture->state() == Qt::GestureFinished) { + scaleFactor *= currentStepScaleFactor; + currentStepScaleFactor = 1; } update(); } @@ -154,12 +153,14 @@ void ImageWidget::pinchTriggered(QPinchGesture *gesture) //! [swipe function] void ImageWidget::swipeTriggered(QSwipeGesture *gesture) { - if (gesture->horizontalDirection() == QSwipeGesture::Left + if (gesture->state() == Qt::GestureFinished) { + if (gesture->horizontalDirection() == QSwipeGesture::Left || gesture->verticalDirection() == QSwipeGesture::Up) - goPrevImage(); - else - goNextImage(); - update(); + goPrevImage(); + else + goNextImage(); + update(); + } } //! [swipe function] diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 4edf8a9..88c04e2 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -667,4 +667,70 @@ void QSwipeGesture::setSwipeAngle(qreal value) d_func()->swipeAngle = value; } +/*! + \class QTapGesture + \since 4.6 + \brief The QTapGesture class describes a tap gesture made by the user. + \ingroup gestures + + \sa {Gestures Programming}, QPanGesture, QPinchGesture +*/ + +/*! + \property QTapGesture::position + \brief the position of the tap +*/ + +/*! + \internal +*/ +QTapGesture::QTapGesture(QObject *parent) + : QGesture(*new QTapGesturePrivate, parent) +{ + d_func()->gestureType = Qt::TapGesture; +} + +QPointF QTapGesture::position() const +{ + return d_func()->position; +} + +void QTapGesture::setPosition(const QPointF &value) +{ + d_func()->position = value; +} +/*! + \class QTapAndHoldGesture + \since 4.6 + \brief The QTapAndHoldGesture class describes a tap-and-hold (aka LongTap) + gesture made by the user. + \ingroup gestures + + \sa {Gestures Programming}, QPanGesture, QPinchGesture +*/ + +/*! + \property QTapAndHoldGesture::position + \brief the position of the tap +*/ + +/*! + \internal +*/ +QTapAndHoldGesture::QTapAndHoldGesture(QObject *parent) + : QGesture(*new QTapAndHoldGesturePrivate, parent) +{ + d_func()->gestureType = Qt::TapAndHoldGesture; +} + +QPointF QTapAndHoldGesture::position() const +{ + return d_func()->position; +} + +void QTapAndHoldGesture::setPosition(const QPointF &value) +{ + d_func()->position = value; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index dd322ad..f995d7b 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -219,6 +219,40 @@ public: friend class QSwipeGestureRecognizer; }; +class QTapGesturePrivate; +class Q_GUI_EXPORT QTapGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTapGesture) + + Q_PROPERTY(QPointF position READ position WRITE setPosition) + +public: + QTapGesture(QObject *parent = 0); + + QPointF position() const; + void setPosition(const QPointF &pos); + + friend class QTapGestureRecognizer; +}; + +class QTapAndHoldGesturePrivate; +class Q_GUI_EXPORT QTapAndHoldGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTapAndHoldGesture) + + Q_PROPERTY(QPointF position READ position WRITE setPosition) + +public: + QTapAndHoldGesture(QObject *parent = 0); + + QPointF position() const; + void setPosition(const QPointF &pos); + + friend class QTapAndHoldGestureRecognizer; +}; + QT_END_NAMESPACE Q_DECLARE_METATYPE(QGesture::GestureCancelPolicy) diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index ae2e287..2537f47 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -136,13 +136,45 @@ public: QSwipeGesturePrivate() : horizontalDirection(QSwipeGesture::NoDirection), verticalDirection(QSwipeGesture::NoDirection), - swipeAngle(0) + swipeAngle(0), + started(false), speed(0) { } QSwipeGesture::SwipeDirection horizontalDirection; QSwipeGesture::SwipeDirection verticalDirection; qreal swipeAngle; + + QPoint lastPositions[3]; + bool started; + qreal speed; + QTime time; +}; + +class QTapGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QTapGesture) + +public: + QTapGesturePrivate() + { + } + + QPointF position; +}; + +class QTapAndHoldGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QTapAndHoldGesture) + +public: + QTapAndHoldGesturePrivate() + : timerId(0) + { + } + + QPointF position; + int timerId; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 628892d..375116f 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -90,9 +90,13 @@ QGestureManager::QGestureManager(QObject *parent) #else registerGestureRecognizer(new QPanGestureRecognizer); registerGestureRecognizer(new QPinchGestureRecognizer); + registerGestureRecognizer(new QSwipeGestureRecognizer); + registerGestureRecognizer(new QTapGestureRecognizer); +#endif #if defined(Q_OS_WIN) registerGestureRecognizer(new QWinNativePanGestureRecognizer); -#endif +#else + registerGestureRecognizer(new QTapAndHoldGestureRecognizer); #endif } diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index dfd49eb..0ea4764 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -45,6 +45,7 @@ #include "qevent.h" #include "qwidget.h" #include "qabstractscrollarea.h" +#include "qdebug.h" QT_BEGIN_NAMESPACE @@ -66,7 +67,9 @@ QGesture *QPanGestureRecognizer::create(QObject *target) return new QPanGesture; } -QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) +QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) { QPanGesture *q = static_cast<QPanGesture *>(state); QPanGesturePrivate *d = q->d_func(); @@ -155,7 +158,9 @@ QGesture *QPinchGestureRecognizer::create(QObject *target) return new QPinchGesture; } -QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) +QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) { QPinchGesture *q = static_cast<QPinchGesture *>(state); QPinchGesturePrivate *d = q->d_func(); @@ -199,8 +204,9 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q d->centerPoint = centerPoint; d->changeFlags |= QPinchGesture::CenterPointChanged; - const qreal scaleFactor = QLineF(p1.pos(), p2.pos()).length() - / QLineF(d->startPosition[0], d->startPosition[1]).length(); + const qreal scaleFactor = + QLineF(p1.screenPos(), p2.screenPos()).length() + / QLineF(d->startPosition[0], d->startPosition[1]).length(); if (d->isNewSequence) { d->lastScaleFactor = scaleFactor; } else { @@ -210,7 +216,13 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q d->totalScaleFactor += d->scaleFactor - d->lastScaleFactor; d->changeFlags |= QPinchGesture::ScaleFactorChanged; - const qreal rotationAngle = -line.angle(); + qreal angle = QLineF(p1.screenPos(), p2.screenPos()).angle(); + if (angle > 180) + angle -= 360; + qreal startAngle = QLineF(p1.startScreenPos(), p2.startScreenPos()).angle(); + if (startAngle > 180) + startAngle -= 360; + const qreal rotationAngle = startAngle - angle; if (d->isNewSequence) d->lastRotationAngle = rotationAngle; else @@ -224,7 +236,10 @@ QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state, Q result = QGestureRecognizer::TriggerGesture; } else { d->isNewSequence = true; - result = QGestureRecognizer::MayBeGesture; + if (q->state() == Qt::NoGesture) + result = QGestureRecognizer::Ignore; + else + result = QGestureRecognizer::FinishGesture; } break; } @@ -252,6 +267,299 @@ void QPinchGestureRecognizer::reset(QGesture *state) d->totalRotationAngle = d->lastRotationAngle = d->rotationAngle = 0; d->isNewSequence = true; + d->startPosition[0] = d->startPosition[1] = QPointF(); + + QGestureRecognizer::reset(state); +} + +// +// QSwipeGestureRecognizer +// + +QSwipeGestureRecognizer::QSwipeGestureRecognizer() +{ +} + +QGesture *QSwipeGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + } + return new QSwipeGesture; +} + +QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) +{ + QSwipeGesture *q = static_cast<QSwipeGesture *>(state); + QSwipeGesturePrivate *d = q->d_func(); + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + + QGestureRecognizer::Result result; + + switch (event->type()) { + case QEvent::TouchBegin: { + d->speed = 1; + d->time = QTime::currentTime(); + d->started = true; + result = QGestureRecognizer::MayBeGesture; + break; + } + case QEvent::TouchEnd: { + if (q->state() != Qt::NoGesture) { + result = QGestureRecognizer::FinishGesture; + } else { + result = QGestureRecognizer::CancelGesture; + } + break; + } + case QEvent::TouchUpdate: { + if (!d->started) + result = QGestureRecognizer::CancelGesture; + else if (ev->touchPoints().size() == 3) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2); + + if (d->lastPositions[0].isNull()) { + d->lastPositions[0] = p1.startScreenPos().toPoint(); + d->lastPositions[1] = p2.startScreenPos().toPoint(); + d->lastPositions[2] = p3.startScreenPos().toPoint(); + } + d->hotSpot = p1.screenPos(); + d->isHotSpotSet = true; + + int xDistance = (p1.screenPos().x() - d->lastPositions[0].x() + + p2.screenPos().x() - d->lastPositions[1].x() + + p3.screenPos().x() - d->lastPositions[2].x()) / 3; + int yDistance = (p1.screenPos().y() - d->lastPositions[0].y() + + p2.screenPos().y() - d->lastPositions[1].y() + + p3.screenPos().y() - d->lastPositions[2].y()) / 3; + + const int distance = xDistance >= yDistance ? xDistance : yDistance; + int elapsedTime = d->time.msecsTo(QTime::currentTime()); + if (!elapsedTime) + elapsedTime = 1; + d->speed = 0.9 * d->speed + distance / elapsedTime; + d->time = QTime::currentTime(); + d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle(); + + static const int MoveThreshold = 50; + if (xDistance > MoveThreshold || yDistance > MoveThreshold) { + // measure the distance to check if the direction changed + d->lastPositions[0] = p1.screenPos().toPoint(); + d->lastPositions[1] = p2.screenPos().toPoint(); + d->lastPositions[2] = p3.screenPos().toPoint(); + QSwipeGesture::SwipeDirection horizontal = + xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left; + QSwipeGesture::SwipeDirection vertical = + yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up; + if (d->verticalDirection == QSwipeGesture::NoDirection) + d->verticalDirection = vertical; + if (d->horizontalDirection == QSwipeGesture::NoDirection) + d->horizontalDirection = horizontal; + if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) { + // the user has changed the direction! + result = QGestureRecognizer::CancelGesture; + } + result = QGestureRecognizer::TriggerGesture; + } else { + if (q->state() != Qt::NoGesture) + result = QGestureRecognizer::TriggerGesture; + else + result = QGestureRecognizer::MayBeGesture; + } + } else if (ev->touchPoints().size() > 3) { + result = QGestureRecognizer::CancelGesture; + } else { // less than 3 touch points + if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed)) + result = QGestureRecognizer::CancelGesture; + else if (d->started) + result = QGestureRecognizer::Ignore; + else + result = QGestureRecognizer::MayBeGesture; + } + break; + } + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + result = QGestureRecognizer::Ignore; + break; + default: + result = QGestureRecognizer::Ignore; + break; + } + return result; +} + +void QSwipeGestureRecognizer::reset(QGesture *state) +{ + QSwipeGesture *q = static_cast<QSwipeGesture *>(state); + QSwipeGesturePrivate *d = q->d_func(); + + d->verticalDirection = d->horizontalDirection = QSwipeGesture::NoDirection; + d->swipeAngle = 0; + + d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint(); + d->started = false; + d->speed = 0; + d->time = QTime(); + + QGestureRecognizer::reset(state); +} + +// +// QTapGestureRecognizer +// + +QTapGestureRecognizer::QTapGestureRecognizer() +{ +} + +QGesture *QTapGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + } + return new QTapGesture; +} + +QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state, + QObject *, + QEvent *event) +{ + QTapGesture *q = static_cast<QTapGesture *>(state); + QTapGesturePrivate *d = q->d_func(); + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + + QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; + + switch (event->type()) { + case QEvent::TouchBegin: { + d->position = ev->touchPoints().at(0).pos(); + result = QGestureRecognizer::TriggerGesture; + break; + } + case QEvent::TouchUpdate: + case QEvent::TouchEnd: { + if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); + enum { TapRadius = 40 }; + if (delta.manhattanLength() <= TapRadius) { + if (event->type() == QEvent::TouchEnd) + result = QGestureRecognizer::FinishGesture; + else + result = QGestureRecognizer::TriggerGesture; + } + } + break; + } + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + result = QGestureRecognizer::Ignore; + break; + default: + result = QGestureRecognizer::Ignore; + break; + } + return result; +} + +void QTapGestureRecognizer::reset(QGesture *state) +{ + QTapGesture *q = static_cast<QTapGesture *>(state); + QTapGesturePrivate *d = q->d_func(); + + d->position = QPointF(); + + QGestureRecognizer::reset(state); +} + +// +// QTapAndHoldGestureRecognizer +// + +QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer() +{ +} + +QGesture *QTapAndHoldGestureRecognizer::create(QObject *target) +{ + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + } + return new QTapAndHoldGesture; +} + +QGestureRecognizer::Result +QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, + QEvent *event) +{ + QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); + QTapAndHoldGesturePrivate *d = q->d_func(); + + if (object == state && event->type() == QEvent::Timer) { + q->killTimer(d->timerId); + d->timerId = 0; + return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; + } + + const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); + + QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; + + enum { TimerInterval = 2000 }; + enum { TapRadius = 40 }; + + switch (event->type()) { + case QEvent::TouchBegin: + d->position = ev->touchPoints().at(0).pos(); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = q->startTimer(TimerInterval); + result = QGestureRecognizer::TriggerGesture; + break; + case QEvent::TouchEnd: + if (d->timerId) + result = QGestureRecognizer::CancelGesture; + else + result = QGestureRecognizer::FinishGesture; + break; + case QEvent::TouchUpdate: + if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); + if (delta.manhattanLength() <= TapRadius) + result = QGestureRecognizer::TriggerGesture; + } + break; + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + result = QGestureRecognizer::Ignore; + break; + default: + result = QGestureRecognizer::Ignore; + break; + } + return result; +} + +void QTapAndHoldGestureRecognizer::reset(QGesture *state) +{ + QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); + QTapAndHoldGesturePrivate *d = q->d_func(); + + d->position = QPointF(); + if (d->timerId) + q->killTimer(d->timerId); + d->timerId = 0; QGestureRecognizer::reset(state); } diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index e6f346c..8fea2bc 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -74,7 +74,36 @@ public: QPinchGestureRecognizer(); QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QSwipeGestureRecognizer : public QGestureRecognizer +{ +public: + QSwipeGestureRecognizer(); + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QTapGestureRecognizer : public QGestureRecognizer +{ +public: + QTapGestureRecognizer(); + + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); + void reset(QGesture *state); +}; + +class QTapAndHoldGestureRecognizer : public QGestureRecognizer +{ +public: + QTapAndHoldGestureRecognizer(); + + QGesture *create(QObject *target); QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); void reset(QGesture *state); }; |