src/gui/kernel/qstandardgestures.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    42 #include "qstandardgestures_p.h"
    42 #include "qstandardgestures_p.h"
    43 #include "qgesture.h"
    43 #include "qgesture.h"
    44 #include "qgesture_p.h"
    44 #include "qgesture_p.h"
    45 #include "qevent.h"
    45 #include "qevent.h"
    46 #include "qwidget.h"
    46 #include "qwidget.h"
       
    47 #include "qabstractscrollarea.h"
       
    48 #include "qdebug.h"
    47 
    49 
    48 QT_BEGIN_NAMESPACE
    50 QT_BEGIN_NAMESPACE
    49 
    51 
    50 QPanGestureRecognizer::QPanGestureRecognizer()
    52 QPanGestureRecognizer::QPanGestureRecognizer()
    51 {
    53 {
    52 }
    54 }
    53 
    55 
    54 QGesture *QPanGestureRecognizer::createGesture(QObject *target)
    56 QGesture *QPanGestureRecognizer::create(QObject *target)
    55 {
    57 {
    56     if (target && target->isWidgetType()) {
    58     if (target && target->isWidgetType()) {
       
    59 #if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
       
    60         // for scroll areas on Windows we want to use native gestures instead
       
    61         if (!qobject_cast<QAbstractScrollArea *>(target->parent()))
       
    62             static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
       
    63 #else
    57         static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
    64         static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
       
    65 #endif
    58     }
    66     }
    59     return new QPanGesture;
    67     return new QPanGesture;
    60 }
    68 }
    61 
    69 
    62 QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, QObject *, QEvent *event)
    70 QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
    63 {
    71                                                             QObject *,
    64     QPanGesture *q = static_cast<QPanGesture*>(state);
    72                                                             QEvent *event)
       
    73 {
       
    74     QPanGesture *q = static_cast<QPanGesture *>(state);
    65     QPanGesturePrivate *d = q->d_func();
    75     QPanGesturePrivate *d = q->d_func();
    66 
    76 
    67     const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
    77     const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
    68 
    78 
    69     QGestureRecognizer::Result result;
    79     QGestureRecognizer::Result result;
    70 
       
    71     switch (event->type()) {
    80     switch (event->type()) {
    72     case QEvent::TouchBegin: {
    81     case QEvent::TouchBegin: {
    73         result = QGestureRecognizer::MaybeGesture;
    82         result = QGestureRecognizer::MayBeGesture;
    74         QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
    83         QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
    75         d->lastPosition = p.pos().toPoint();
    84         d->lastOffset = d->offset = QPointF();
    76         d->lastOffset = d->totalOffset = d->offset = QPointF();
       
    77         break;
    85         break;
    78     }
    86     }
    79     case QEvent::TouchEnd: {
    87     case QEvent::TouchEnd: {
    80         if (q->state() != Qt::NoGesture) {
    88         if (q->state() != Qt::NoGesture) {
    81             if (ev->touchPoints().size() == 2) {
    89             if (ev->touchPoints().size() == 2) {
    82                 QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
    90                 QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
    83                 QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
    91                 QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
    84                 d->lastOffset = d->offset;
    92                 d->lastOffset = d->offset;
    85                 d->offset =
    93                 d->offset =
    86                         QPointF(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
    94                         QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
    87                               p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
    95                               p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
    88                 d->totalOffset += d->offset;
    96             }
    89             }
    97             result = QGestureRecognizer::FinishGesture;
    90             result = QGestureRecognizer::GestureFinished;
       
    91         } else {
    98         } else {
    92             result = QGestureRecognizer::NotGesture;
    99             result = QGestureRecognizer::CancelGesture;
    93         }
   100         }
    94         break;
   101         break;
    95     }
   102     }
    96     case QEvent::TouchUpdate: {
   103     case QEvent::TouchUpdate: {
    97         if (ev->touchPoints().size() >= 2) {
   104         if (ev->touchPoints().size() >= 2) {
    98             QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
   105             QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
    99             QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
   106             QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
   100             d->lastOffset = d->offset;
   107             d->lastOffset = d->offset;
   101             d->offset =
   108             d->offset =
   102                     QPointF(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
   109                     QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
   103                           p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
   110                           p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
   104             d->totalOffset += d->offset;
   111             if (d->offset.x() > 10  || d->offset.y() > 10 ||
   105             if (d->totalOffset.x() > 10  || d->totalOffset.y() > 10 ||
   112                 d->offset.x() < -10 || d->offset.y() < -10) {
   106                 d->totalOffset.x() < -10 || d->totalOffset.y() < -10) {
   113                 result = QGestureRecognizer::TriggerGesture;
   107                 result = QGestureRecognizer::GestureTriggered;
       
   108             } else {
   114             } else {
   109                 result = QGestureRecognizer::MaybeGesture;
   115                 result = QGestureRecognizer::MayBeGesture;
   110             }
   116             }
   111         }
   117         }
   112         break;
   118         break;
   113     }
   119     }
   114     case QEvent::MouseButtonPress:
   120     case QEvent::MouseButtonPress:
   126 void QPanGestureRecognizer::reset(QGesture *state)
   132 void QPanGestureRecognizer::reset(QGesture *state)
   127 {
   133 {
   128     QPanGesture *pan = static_cast<QPanGesture*>(state);
   134     QPanGesture *pan = static_cast<QPanGesture*>(state);
   129     QPanGesturePrivate *d = pan->d_func();
   135     QPanGesturePrivate *d = pan->d_func();
   130 
   136 
   131     d->totalOffset = d->lastOffset = d->offset = QPointF();
   137     d->lastOffset = d->offset = QPointF();
   132     d->lastPosition = QPoint();
       
   133     d->acceleration = 0;
   138     d->acceleration = 0;
   134 
   139 
   135 //#if defined(QT_MAC_USE_COCOA)
       
   136 //    d->singleTouchPanTimer.stop();
       
   137 //    d->prevMousePos = QPointF(0, 0);
       
   138 //#endif
       
   139 
       
   140     QGestureRecognizer::reset(state);
   140     QGestureRecognizer::reset(state);
   141 }
   141 }
   142 
   142 
   143 /*! \internal */
   143 
   144 /*
   144 //
   145 bool QPanGestureRecognizer::event(QEvent *event)
   145 // QPinchGestureRecognizer
   146 {
   146 //
   147 #if defined(QT_MAC_USE_COCOA)
   147 
   148     Q_D(QPanGesture);
   148 QPinchGestureRecognizer::QPinchGestureRecognizer()
   149     if (event->type() == QEvent::Timer) {
   149 {
   150         const QTimerEvent *te = static_cast<QTimerEvent *>(event);
   150 }
   151         if (te->timerId() == d->singleTouchPanTimer.timerId()) {
   151 
   152             d->singleTouchPanTimer.stop();
   152 QGesture *QPinchGestureRecognizer::create(QObject *target)
   153             updateState(Qt::GestureStarted);
   153 {
   154         }
   154     if (target && target->isWidgetType()) {
   155     }
   155         static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
   156 #endif
   156     }
   157 
   157     return new QPinchGesture;
   158     bool consume = false;
   158 }
   159 
   159 
   160 #if defined(Q_WS_WIN)
   160 QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
   161 #elif defined(QT_MAC_USE_COCOA)
   161                                                               QObject *,
   162     // The following implements single touch
   162                                                               QEvent *event)
   163     // panning on Mac:
   163 {
   164     const int panBeginDelay = 300;
   164     QPinchGesture *q = static_cast<QPinchGesture *>(state);
   165     const int panBeginRadius = 3;
   165     QPinchGesturePrivate *d = q->d_func();
   166     const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
   166 
       
   167     const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
       
   168 
       
   169     QGestureRecognizer::Result result;
   167 
   170 
   168     switch (event->type()) {
   171     switch (event->type()) {
   169     case QEvent::TouchBegin: {
   172     case QEvent::TouchBegin: {
   170         if (ev->touchPoints().size() == 1) {
   173         result = QGestureRecognizer::MayBeGesture;
   171             d->delayManager->setEnabled(true);
   174         break;
   172             consume = d->delayManager->append(d->gestureTarget, *event);
   175     }
   173             d->lastPosition = QCursor::pos();
       
   174             d->singleTouchPanTimer.start(panBeginDelay, this);
       
   175         }
       
   176         break;}
       
   177     case QEvent::TouchEnd: {
   176     case QEvent::TouchEnd: {
   178         d->delayManager->setEnabled(false);
   177         if (q->state() != Qt::NoGesture) {
   179         if (state() != Qt::NoGesture) {
   178             result = QGestureRecognizer::FinishGesture;
   180             updateState(Qt::GestureFinished);
       
   181             consume = true;
       
   182             d->delayManager->clear();
       
   183         } else {
   179         } else {
   184             d->delayManager->replay();
   180             result = QGestureRecognizer::CancelGesture;
   185         }
   181         }
   186         reset();
   182         break;
   187         break;}
   183     }
   188     case QEvent::TouchUpdate: {
   184     case QEvent::TouchUpdate: {
   189         consume = d->delayManager->append(d->gestureTarget, *event);
   185         d->changeFlags = 0;
   190         if (ev->touchPoints().size() == 1) {
   186         if (ev->touchPoints().size() == 2) {
   191             if (state() == Qt::NoGesture) {
   187             QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
   192                 // INVARIANT: The singleTouchTimer has still not fired.
   188             QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
   193                 // Lets check if the user moved his finger so much from
   189 
   194                 // the starting point that it makes sense to cancel:
   190             d->hotSpot = p1.screenPos();
   195                 const QPointF startPos = ev->touchPoints().at(0).startPos().toPoint();
   191             d->isHotSpotSet = true;
   196                 const QPointF p = ev->touchPoints().at(0).pos().toPoint();
   192 
   197                 if ((startPos - p).manhattanLength() > panBeginRadius) {
   193             if (d->isNewSequence) {
   198                     d->delayManager->replay();
   194                 d->startPosition[0] = p1.screenPos();
   199                     consume = false;
   195                 d->startPosition[1] = p2.screenPos();
   200                     reset();
   196             }
   201                 } else {
   197             QLineF line(p1.screenPos(), p2.screenPos());
   202                     d->lastPosition = QCursor::pos();
   198             QLineF tmp(line);
   203                 }
   199             tmp.setLength(line.length() / 2.);
       
   200             QPointF centerPoint = tmp.p2();
       
   201 
       
   202             d->lastCenterPoint = d->centerPoint;
       
   203             d->centerPoint = centerPoint;
       
   204             d->changeFlags |= QPinchGesture::CenterPointChanged;
       
   205 
       
   206             const qreal scaleFactor =
       
   207                     QLineF(p1.screenPos(), p2.screenPos()).length()
       
   208                     / QLineF(d->startPosition[0],  d->startPosition[1]).length();
       
   209             if (d->isNewSequence) {
       
   210                 d->lastScaleFactor = scaleFactor;
   204             } else {
   211             } else {
   205                 d->delayManager->clear();
   212                 d->lastScaleFactor = d->scaleFactor;
   206                 QPointF mousePos = QCursor::pos();
   213             }
   207                 QPointF dist = mousePos - d->lastPosition;
   214             d->scaleFactor = scaleFactor;
   208                 d->lastPosition = mousePos;
   215             d->totalScaleFactor += d->scaleFactor - d->lastScaleFactor;
   209                 d->lastOffset = d->offset;
   216             d->changeFlags |= QPinchGesture::ScaleFactorChanged;
   210                 d->offset = QSizeF(dist.x(), dist.y());
   217 
   211                 d->totalOffset += d->offset;
   218             qreal angle = QLineF(p1.screenPos(), p2.screenPos()).angle();
   212                 updateState(Qt::GestureUpdated);
   219             if (angle > 180)
   213             }
   220                 angle -= 360;
   214         } else if (state() == Qt::NoGesture) {
   221             qreal startAngle = QLineF(p1.startScreenPos(), p2.startScreenPos()).angle();
   215             d->delayManager->replay();
   222             if (startAngle > 180)
   216             consume = false;
   223                 startAngle -= 360;
   217             reset();
   224             const qreal rotationAngle = startAngle - angle;
   218         }
   225             if (d->isNewSequence)
   219         break;}
   226                 d->lastRotationAngle = rotationAngle;
       
   227             else
       
   228                 d->lastRotationAngle = d->rotationAngle;
       
   229             d->rotationAngle = rotationAngle;
       
   230             d->totalRotationAngle += d->rotationAngle - d->lastRotationAngle;
       
   231             d->changeFlags |= QPinchGesture::RotationAngleChanged;
       
   232 
       
   233             d->totalChangeFlags |= d->changeFlags;
       
   234             d->isNewSequence = false;
       
   235             result = QGestureRecognizer::TriggerGesture;
       
   236         } else {
       
   237             d->isNewSequence = true;
       
   238             if (q->state() == Qt::NoGesture)
       
   239                 result = QGestureRecognizer::Ignore;
       
   240             else
       
   241                 result = QGestureRecognizer::FinishGesture;
       
   242         }
       
   243         break;
       
   244     }
   220     case QEvent::MouseButtonPress:
   245     case QEvent::MouseButtonPress:
   221     case QEvent::MouseMove:
   246     case QEvent::MouseMove:
   222     case QEvent::MouseButtonRelease:
   247     case QEvent::MouseButtonRelease:
   223         if (d->delayManager->isEnabled())
   248         result = QGestureRecognizer::Ignore;
   224             consume = d->delayManager->append(d->gestureTarget, *event);
       
   225         break;
   249         break;
   226     default:
   250     default:
   227         return false;
   251         result = QGestureRecognizer::Ignore;
   228     }
   252         break;
   229 #else
   253     }
   230     Q_UNUSED(event);
   254     return result;
   231 #endif
   255 }
   232     return QGestureRecognizer::Ignore;
   256 
   233 }
   257 void QPinchGestureRecognizer::reset(QGesture *state)
   234     */
   258 {
       
   259     QPinchGesture *pinch = static_cast<QPinchGesture *>(state);
       
   260     QPinchGesturePrivate *d = pinch->d_func();
       
   261 
       
   262     d->totalChangeFlags = d->changeFlags = 0;
       
   263 
       
   264     d->startCenterPoint = d->lastCenterPoint = d->centerPoint = QPointF();
       
   265     d->totalScaleFactor = d->lastScaleFactor = d->scaleFactor = 0;
       
   266     d->totalRotationAngle = d->lastRotationAngle = d->rotationAngle = 0;
       
   267 
       
   268     d->isNewSequence = true;
       
   269     d->startPosition[0] = d->startPosition[1] = QPointF();
       
   270 
       
   271     QGestureRecognizer::reset(state);
       
   272 }
       
   273 
       
   274 //
       
   275 // QSwipeGestureRecognizer
       
   276 //
       
   277 
       
   278 QSwipeGestureRecognizer::QSwipeGestureRecognizer()
       
   279 {
       
   280 }
       
   281 
       
   282 QGesture *QSwipeGestureRecognizer::create(QObject *target)
       
   283 {
       
   284     if (target && target->isWidgetType()) {
       
   285         static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
       
   286     }
       
   287     return new QSwipeGesture;
       
   288 }
       
   289 
       
   290 QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
       
   291                                                               QObject *,
       
   292                                                               QEvent *event)
       
   293 {
       
   294     QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
       
   295     QSwipeGesturePrivate *d = q->d_func();
       
   296 
       
   297     const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
       
   298 
       
   299     QGestureRecognizer::Result result;
       
   300 
       
   301     switch (event->type()) {
       
   302     case QEvent::TouchBegin: {
       
   303         d->speed = 1;
       
   304         d->time = QTime::currentTime();
       
   305         d->started = true;
       
   306         result = QGestureRecognizer::MayBeGesture;
       
   307         break;
       
   308     }
       
   309     case QEvent::TouchEnd: {
       
   310         if (q->state() != Qt::NoGesture) {
       
   311             result = QGestureRecognizer::FinishGesture;
       
   312         } else {
       
   313             result = QGestureRecognizer::CancelGesture;
       
   314         }
       
   315         break;
       
   316     }
       
   317     case QEvent::TouchUpdate: {
       
   318         if (!d->started)
       
   319             result = QGestureRecognizer::CancelGesture;
       
   320         else if (ev->touchPoints().size() == 3) {
       
   321             QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
       
   322             QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
       
   323             QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2);
       
   324 
       
   325             if (d->lastPositions[0].isNull()) {
       
   326                 d->lastPositions[0] = p1.startScreenPos().toPoint();
       
   327                 d->lastPositions[1] = p2.startScreenPos().toPoint();
       
   328                 d->lastPositions[2] = p3.startScreenPos().toPoint();
       
   329             }
       
   330             d->hotSpot = p1.screenPos();
       
   331             d->isHotSpotSet = true;
       
   332 
       
   333             int xDistance = (p1.screenPos().x() - d->lastPositions[0].x() +
       
   334                              p2.screenPos().x() - d->lastPositions[1].x() +
       
   335                              p3.screenPos().x() - d->lastPositions[2].x()) / 3;
       
   336             int yDistance = (p1.screenPos().y() - d->lastPositions[0].y() +
       
   337                              p2.screenPos().y() - d->lastPositions[1].y() +
       
   338                              p3.screenPos().y() - d->lastPositions[2].y()) / 3;
       
   339 
       
   340             const int distance = xDistance >= yDistance ? xDistance : yDistance;
       
   341             int elapsedTime = d->time.msecsTo(QTime::currentTime());
       
   342             if (!elapsedTime)
       
   343                 elapsedTime = 1;
       
   344             d->speed = 0.9 * d->speed + distance / elapsedTime;
       
   345             d->time = QTime::currentTime();
       
   346             d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
       
   347 
       
   348             static const int MoveThreshold = 50;
       
   349             if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
       
   350                 // measure the distance to check if the direction changed
       
   351                 d->lastPositions[0] = p1.screenPos().toPoint();
       
   352                 d->lastPositions[1] = p2.screenPos().toPoint();
       
   353                 d->lastPositions[2] = p3.screenPos().toPoint();
       
   354                 QSwipeGesture::SwipeDirection horizontal =
       
   355                         xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left;
       
   356                 QSwipeGesture::SwipeDirection vertical =
       
   357                         yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up;
       
   358                 if (d->verticalDirection == QSwipeGesture::NoDirection)
       
   359                     d->verticalDirection = vertical;
       
   360                 if (d->horizontalDirection == QSwipeGesture::NoDirection)
       
   361                     d->horizontalDirection = horizontal;
       
   362                 if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) {
       
   363                     // the user has changed the direction!
       
   364                     result = QGestureRecognizer::CancelGesture;
       
   365                 }
       
   366                 result = QGestureRecognizer::TriggerGesture;
       
   367             } else {
       
   368                 if (q->state() != Qt::NoGesture)
       
   369                     result = QGestureRecognizer::TriggerGesture;
       
   370                 else
       
   371                     result = QGestureRecognizer::MayBeGesture;
       
   372             }
       
   373         } else if (ev->touchPoints().size() > 3) {
       
   374             result = QGestureRecognizer::CancelGesture;
       
   375         } else { // less than 3 touch points
       
   376             if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed))
       
   377                 result = QGestureRecognizer::CancelGesture;
       
   378             else if (d->started)
       
   379                 result = QGestureRecognizer::Ignore;
       
   380             else
       
   381                 result = QGestureRecognizer::MayBeGesture;
       
   382         }
       
   383         break;
       
   384     }
       
   385     case QEvent::MouseButtonPress:
       
   386     case QEvent::MouseMove:
       
   387     case QEvent::MouseButtonRelease:
       
   388         result = QGestureRecognizer::Ignore;
       
   389         break;
       
   390     default:
       
   391         result = QGestureRecognizer::Ignore;
       
   392         break;
       
   393     }
       
   394     return result;
       
   395 }
       
   396 
       
   397 void QSwipeGestureRecognizer::reset(QGesture *state)
       
   398 {
       
   399     QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
       
   400     QSwipeGesturePrivate *d = q->d_func();
       
   401 
       
   402     d->verticalDirection = d->horizontalDirection = QSwipeGesture::NoDirection;
       
   403     d->swipeAngle = 0;
       
   404 
       
   405     d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint();
       
   406     d->started = false;
       
   407     d->speed = 0;
       
   408     d->time = QTime();
       
   409 
       
   410     QGestureRecognizer::reset(state);
       
   411 }
       
   412 
       
   413 //
       
   414 // QTapGestureRecognizer
       
   415 //
       
   416 
       
   417 QTapGestureRecognizer::QTapGestureRecognizer()
       
   418 {
       
   419 }
       
   420 
       
   421 QGesture *QTapGestureRecognizer::create(QObject *target)
       
   422 {
       
   423     if (target && target->isWidgetType()) {
       
   424         static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
       
   425     }
       
   426     return new QTapGesture;
       
   427 }
       
   428 
       
   429 QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state,
       
   430                                                             QObject *,
       
   431                                                             QEvent *event)
       
   432 {
       
   433     QTapGesture *q = static_cast<QTapGesture *>(state);
       
   434     QTapGesturePrivate *d = q->d_func();
       
   435 
       
   436     const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
       
   437 
       
   438     QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture;
       
   439 
       
   440     switch (event->type()) {
       
   441     case QEvent::TouchBegin: {
       
   442         d->position = ev->touchPoints().at(0).pos();
       
   443         result = QGestureRecognizer::TriggerGesture;
       
   444         break;
       
   445     }
       
   446     case QEvent::TouchUpdate:
       
   447     case QEvent::TouchEnd: {
       
   448         if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) {
       
   449             QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
       
   450             QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
       
   451             enum { TapRadius = 40 };
       
   452             if (delta.manhattanLength() <= TapRadius) {
       
   453                 if (event->type() == QEvent::TouchEnd)
       
   454                     result = QGestureRecognizer::FinishGesture;
       
   455                 else
       
   456                     result = QGestureRecognizer::TriggerGesture;
       
   457             }
       
   458         }
       
   459         break;
       
   460     }
       
   461     case QEvent::MouseButtonPress:
       
   462     case QEvent::MouseMove:
       
   463     case QEvent::MouseButtonRelease:
       
   464         result = QGestureRecognizer::Ignore;
       
   465         break;
       
   466     default:
       
   467         result = QGestureRecognizer::Ignore;
       
   468         break;
       
   469     }
       
   470     return result;
       
   471 }
       
   472 
       
   473 void QTapGestureRecognizer::reset(QGesture *state)
       
   474 {
       
   475     QTapGesture *q = static_cast<QTapGesture *>(state);
       
   476     QTapGesturePrivate *d = q->d_func();
       
   477 
       
   478     d->position = QPointF();
       
   479 
       
   480     QGestureRecognizer::reset(state);
       
   481 }
       
   482 
       
   483 //
       
   484 // QTapAndHoldGestureRecognizer
       
   485 //
       
   486 
       
   487 QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer()
       
   488 {
       
   489 }
       
   490 
       
   491 QGesture *QTapAndHoldGestureRecognizer::create(QObject *target)
       
   492 {
       
   493     if (target && target->isWidgetType()) {
       
   494         static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
       
   495     }
       
   496     return new QTapAndHoldGesture;
       
   497 }
       
   498 
       
   499 QGestureRecognizer::Result
       
   500 QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object,
       
   501                                         QEvent *event)
       
   502 {
       
   503     QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state);
       
   504     QTapAndHoldGesturePrivate *d = q->d_func();
       
   505 
       
   506     if (object == state && event->type() == QEvent::Timer) {
       
   507         q->killTimer(d->timerId);
       
   508         d->timerId = 0;
       
   509         return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint;
       
   510     }
       
   511 
       
   512     const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
       
   513 
       
   514     QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture;
       
   515 
       
   516     enum { TimerInterval = 2000 };
       
   517     enum { TapRadius = 40 };
       
   518 
       
   519     switch (event->type()) {
       
   520     case QEvent::TouchBegin:
       
   521         d->position = ev->touchPoints().at(0).pos();
       
   522         if (d->timerId)
       
   523             q->killTimer(d->timerId);
       
   524         d->timerId = q->startTimer(TimerInterval);
       
   525         result = QGestureRecognizer::TriggerGesture;
       
   526         break;
       
   527     case QEvent::TouchEnd:
       
   528         if (d->timerId)
       
   529             result = QGestureRecognizer::CancelGesture;
       
   530         else
       
   531             result = QGestureRecognizer::FinishGesture;
       
   532         break;
       
   533     case QEvent::TouchUpdate:
       
   534         if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) {
       
   535             QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
       
   536             QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
       
   537             if (delta.manhattanLength() <= TapRadius)
       
   538                 result = QGestureRecognizer::TriggerGesture;
       
   539         }
       
   540         break;
       
   541     case QEvent::MouseButtonPress:
       
   542     case QEvent::MouseMove:
       
   543     case QEvent::MouseButtonRelease:
       
   544         result = QGestureRecognizer::Ignore;
       
   545         break;
       
   546     default:
       
   547         result = QGestureRecognizer::Ignore;
       
   548         break;
       
   549     }
       
   550     return result;
       
   551 }
       
   552 
       
   553 void QTapAndHoldGestureRecognizer::reset(QGesture *state)
       
   554 {
       
   555     QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state);
       
   556     QTapAndHoldGesturePrivate *d = q->d_func();
       
   557 
       
   558     d->position = QPointF();
       
   559     if (d->timerId)
       
   560         q->killTimer(d->timerId);
       
   561     d->timerId = 0;
       
   562 
       
   563     QGestureRecognizer::reset(state);
       
   564 }
   235 
   565 
   236 QT_END_NAMESPACE
   566 QT_END_NAMESPACE