diff options
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 32 | ||||
-rw-r--r-- | src/gui/kernel/qevent.cpp | 48 | ||||
-rw-r--r-- | src/gui/kernel/qevent.h | 7 | ||||
-rw-r--r-- | src/gui/kernel/qevent_p.h | 14 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 28 | ||||
-rw-r--r-- | tests/auto/gestures/tst_gestures.cpp | 66 |
7 files changed, 156 insertions, 42 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index af1c1c8..7c38d4b 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4170,41 +4170,41 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (wd->gestureContext.contains(type)) { allGestures.removeAt(i); gestures.append(g); - gestureEvent->setAccepted(g, false); } else { ++i; } } - if (!gestures.isEmpty()) { + if (!gestures.isEmpty()) { // we have gestures for this w QGestureEvent ge(gestures); ge.t = gestureEvent->t; ge.spont = gestureEvent->spont; ge.m_accept = wasAccepted; + ge.d_func()->accepted = gestureEvent->d_func()->accepted; res = d->notify_helper(w, &ge); gestureEvent->spont = false; eventAccepted = ge.isAccepted(); - if (res && eventAccepted && allGestures.isEmpty()) - break; - if (!eventAccepted) { - // ### two ways to ignore the event/gesture - - // if the whole event wasn't accepted, put back those - // gestures that were not accepted. - for (int i = 0; i < gestures.size(); ++i) { - QGesture *g = gestures.at(i); - if (!ge.isAccepted(g)) - allGestures.append(g); + for (int i = 0; i < gestures.size(); ++i) { + QGesture *g = gestures.at(i); + if ((res && eventAccepted) || (!eventAccepted && ge.isAccepted(g))) { + // if the gesture was accepted, mark the target widget for it + gestureEvent->d_func()->targetWidgets[g->gestureType()] = w; + gestureEvent->setAccepted(g, true); + } else if (!eventAccepted && !ge.isAccepted(g)) { + // if the gesture was explicitly ignored by the application, + // put it back so a parent can get it + allGestures.append(g); } } } - if (allGestures.isEmpty()) + if (allGestures.isEmpty()) // everything delivered break; if (w->isWindow()) break; w = w->parentWidget(); } - gestureEvent->m_accept = eventAccepted; - gestureEvent->gestures_ = allGestures; + foreach (QGesture *g, allGestures) + gestureEvent->setAccepted(g, false); + gestureEvent->m_accept = false; // to make sure we check individual gestures } else { res = d->notify_helper(receiver, e); } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e49de02..1c6a820 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4223,8 +4223,17 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T Creates new QGestureEvent containing a list of \a gestures. */ QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures) - : QEvent(QEvent::Gesture), gestures_(gestures) + : QEvent(QEvent::Gesture) { + d = reinterpret_cast<QEventPrivate *>(new QGestureEventPrivate(gestures)); +} + +/*! + Destroys QGestureEvent. +*/ +QGestureEvent::~QGestureEvent() +{ + delete reinterpret_cast<QGestureEventPrivate *>(d); } /*! @@ -4232,7 +4241,7 @@ QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures) */ QList<QGesture *> QGestureEvent::allGestures() const { - return gestures_; + return d_func()->gestures; } /*! @@ -4240,9 +4249,10 @@ QList<QGesture *> QGestureEvent::allGestures() const */ QGesture *QGestureEvent::gesture(Qt::GestureType type) const { - for(int i = 0; i < gestures_.size(); ++i) - if (gestures_.at(i)->gestureType() == type) - return gestures_.at(i); + const QGestureEventPrivate *d = d_func(); + for(int i = 0; i < d->gestures.size(); ++i) + if (d->gestures.at(i)->gestureType() == type) + return d->gestures.at(i); return 0; } @@ -4251,7 +4261,7 @@ QGesture *QGestureEvent::gesture(Qt::GestureType type) const */ QList<QGesture *> QGestureEvent::activeGestures() const { - return gestures_; + return d_func()->gestures; } /*! @@ -4259,7 +4269,7 @@ QList<QGesture *> QGestureEvent::activeGestures() const */ QList<QGesture *> QGestureEvent::canceledGestures() const { - return gestures_; + return d_func()->gestures; } /*! @@ -4279,7 +4289,7 @@ void QGestureEvent::setAccepted(QGesture *gesture, bool value) { setAccepted(false); if (gesture) - gesture->d_func()->accept = value; + d_func()->accepted[gesture->gestureType()] = value; } /*! @@ -4315,7 +4325,7 @@ void QGestureEvent::ignore(QGesture *gesture) */ bool QGestureEvent::isAccepted(QGesture *gesture) const { - return gesture ? gesture->d_func()->accept : false; + return gesture ? d_func()->accepted.value(gesture->gestureType(), true) : false; } /*! @@ -4323,7 +4333,7 @@ bool QGestureEvent::isAccepted(QGesture *gesture) const */ void QGestureEvent::setWidget(QWidget *widget) { - widget_ = widget; + d_func()->widget = widget; } /*! @@ -4331,7 +4341,23 @@ void QGestureEvent::setWidget(QWidget *widget) */ QWidget *QGestureEvent::widget() const { - return widget_; + return d_func()->widget; +} + +/*! + \internal +*/ +QGestureEventPrivate *QGestureEvent::d_func() +{ + return reinterpret_cast<QGestureEventPrivate *>(d); +} + +/*! + \internal +*/ +const QGestureEventPrivate *QGestureEvent::d_func() const +{ + return reinterpret_cast<const QGestureEventPrivate *>(d); } #ifdef Q_NO_USING_KEYWORD diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 1ba2d41..5eefc2d 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -820,10 +820,12 @@ protected: }; class QGesture; +class QGestureEventPrivate; class Q_GUI_EXPORT QGestureEvent : public QEvent { public: QGestureEvent(const QList<QGesture *> &gestures); + ~QGestureEvent(); QList<QGesture *> allGestures() const; QGesture *gesture(Qt::GestureType type) const; @@ -854,10 +856,11 @@ public: QWidget *widget() const; private: - QList<QGesture *> gestures_; - QWidget *widget_; + QGestureEventPrivate *d_func(); + const QGestureEventPrivate *d_func() const; friend class QApplication; + friend class QGestureManager; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index c7a4975..6e6ab01 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -150,6 +150,20 @@ public: #endif }; +class QGestureEventPrivate +{ +public: + inline QGestureEventPrivate(const QList<QGesture *> &list) + : gestures(list), widget(0) + { + } + + QList<QGesture *> gestures; + QWidget *widget; + QMap<Qt::GestureType, bool> accepted; + QMap<Qt::GestureType, QWidget *> targetWidgets; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 7f69a4e..10887f6 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -68,7 +68,7 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() : gestureType(Qt::CustomGesture), state(Qt::NoGesture), isHotSpotSet(false), - targetObject(0), accept(true) + targetObject(0) { } @@ -77,7 +77,6 @@ public: QPointF hotSpot; bool isHotSpotSet; QObject *targetObject; - bool accept; }; class QPanGesturePrivate : public QGesturePrivate diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index f8e1e49..b4913f0 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -44,6 +44,7 @@ #include "private/qwidget_p.h" #include "private/qgesture_p.h" #include "private/qgraphicsitem_p.h" +#include "private/qevent_p.h" #include "qgesture.h" #include "qevent.h" #include "qgraphicsitem.h" @@ -478,17 +479,26 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, << "gestures:" << gestures; QGestureEvent event(gestures); event.t = QEvent::GestureOverride; + // mark event and individual gestures as ignored event.ignore(); + foreach(QGesture *g, gestures) + event.setAccepted(g, false); + QApplication::sendEvent(receiver, &event); - if (!event.isAccepted()) { - // nobody accepted the GestureOverride, put gestures that were not - // accepted back to deliver as usual - QList<QGesture *> &gestures = normalStartedGestures[receiver]; - foreach(QGesture *gesture, event.allGestures()) { - if (!event.isAccepted(gesture)) { - DEBUG() << "override event wasn't accepted. putting back:" << gesture; - gestures.append(gesture); - } + bool eventAccepted = event.isAccepted(); + foreach(QGesture *gesture, event.allGestures()) { + if (eventAccepted || event.isAccepted(gesture)) { + QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0); + Q_ASSERT(w); + DEBUG() << "override event: gesture was accepted:" << gesture << w; + QList<QGesture *> &gestures = normalStartedGestures[w]; + gestures.append(gesture); + // override the target + gestureTargets[gesture] = w; + } else { + DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture; + QList<QGesture *> &gestures = normalStartedGestures[receiver]; + gestures.append(gesture); } } } diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index 4d072bc..28dd40c 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -144,6 +144,49 @@ public: } }; +// same as CustomGestureRecognizer but triggers early without the maybe state +class CustomContinuousGestureRecognizer : public QGestureRecognizer +{ +public: + CustomContinuousGestureRecognizer() + { + if (!CustomEvent::EventType) + CustomEvent::EventType = QEvent::registerEventType(); + } + + QGesture* createGesture(QObject *) + { + return new CustomGesture; + } + + QGestureRecognizer::Result filterEvent(QGesture *state, QObject*, QEvent *event) + { + if (event->type() == CustomEvent::EventType) { + QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint; + CustomGesture *g = static_cast<CustomGesture*>(state); + CustomEvent *e = static_cast<CustomEvent*>(event); + g->serial = e->serial; + if (e->hasHotSpot) + g->setHotSpot(e->hotSpot); + if (g->serial >= CustomGesture::SerialFinishedThreshold) + result |= QGestureRecognizer::GestureFinished; + else if (g->serial >= CustomGesture::SerialMaybeThreshold) + result |= QGestureRecognizer::GestureTriggered; + else + result = QGestureRecognizer::NotGesture; + return result; + } + return QGestureRecognizer::Ignore; + } + + void reset(QGesture *state) + { + CustomGesture *g = static_cast<CustomGesture*>(state); + g->serial = 0; + QGestureRecognizer::reset(state); + } +}; + class GestureWidget : public QWidget { Q_OBJECT @@ -163,6 +206,7 @@ public: gestureOverrideEventsReceived = 0; events.clear(); overrideEvents.clear(); + ignoredGestures.clear(); } int customEventsReceived; @@ -450,7 +494,7 @@ void tst_Gestures::conflictingGestures() sendCustomGesture(&event, child); QCOMPARE(child->gestureOverrideEventsReceived, 1); - QCOMPARE(child->gestureEventsReceived, 0); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); QCOMPARE(parent.gestureOverrideEventsReceived, 0); QCOMPARE(parent.gestureEventsReceived, 0); @@ -467,7 +511,7 @@ void tst_Gestures::conflictingGestures() QCOMPARE(child->gestureOverrideEventsReceived, 1); QCOMPARE(child->gestureEventsReceived, 0); QCOMPARE(parent.gestureOverrideEventsReceived, 1); - QCOMPARE(parent.gestureEventsReceived, 0); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); parent.reset(); child->reset(); @@ -475,6 +519,7 @@ void tst_Gestures::conflictingGestures() // nobody accepts the override, we will send normal events to the closest context (to the child) parent.acceptGestureOverride = false; child->acceptGestureOverride = false; + child->ignoredGestures << CustomGesture::GestureType; // sending events to the child and making sure there is no conflict sendCustomGesture(&event, child); @@ -482,6 +527,23 @@ void tst_Gestures::conflictingGestures() QCOMPARE(child->gestureOverrideEventsReceived, 1); QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + + parent.reset(); + child->reset(); + + Qt::GestureType ContinuousGesture = qApp->registerGestureRecognizer(new CustomContinuousGestureRecognizer); + static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + child->grabGesture(ContinuousGesture); + // child accepts override. And it also receives another custom gesture. + parent.acceptGestureOverride = false; + child->acceptGestureOverride = true; + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount); + QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); QCOMPARE(parent.gestureEventsReceived, 0); } |