diff options
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 31 | ||||
-rw-r--r-- | src/gui/kernel/qevent.cpp | 51 | ||||
-rw-r--r-- | src/gui/kernel/qevent.h | 11 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.h | 8 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 120 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager_p.h | 3 |
8 files changed, 167 insertions, 62 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 9772e0f..ba105e0 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4019,37 +4019,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } break; #endif - - case QEvent::Gesture: { - QWidget *w = static_cast<QWidget*>(receiver); - QGestureEvent *ge = static_cast<QGestureEvent*>(e); - QSet<QString> eventGestures; - foreach(const QString &gesture, ge->gestureTypes()) - eventGestures << gesture; - bool eventAccepted = ge->isAccepted(); - - QPoint offset; - while (w) { - QSet<int> widgetGestures = w->d_func()->gestures; - foreach(int gestureId, widgetGestures) { - if (eventGestures.contains(QGestureManager::instance()->gestureNameFromId(gestureId))) { - foreach(QGesture *gesture, ge->gestures()) - gesture->translate(offset); - offset = QPoint(); - res = d->notify_helper(w, ge); - ge->spont = false; - eventAccepted = ge->isAccepted(); - if (res && eventAccepted) - break; - } - } - if (w->isWindow()) - break; - offset += w->pos(); - w = w->parentWidget(); - } - break; - } case QEvent::TouchBegin: // Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated { diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index f24f186..fa85bf2 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3532,10 +3532,11 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) are being executed and a list of gesture that were cancelled (\a cancelledGestures). */ -QGestureEvent::QGestureEvent(const QList<QGesture*> &gestures, +QGestureEvent::QGestureEvent(const QSet<QGesture*> &gestures, const QSet<QString> &cancelledGestures) : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) { + setAccepted(false); foreach(QGesture *r, gestures) m_gestures.insert(r->type(), r); } @@ -3606,6 +3607,54 @@ QSet<QString> QGestureEvent::cancelledGestures() const return m_cancelledGestures; } +/*! + Sets the accept flag of the all gestures inside the event object, + the equivalent of calling \l{QEvent::accept()}{accept()} or + \l{QEvent::setAccepted()}{setAccepted(true)}. + + Setting the accept parameter indicates that the event receiver + wants the gesture. Unwanted gestures might be propagated to the parent + widget. +*/ +void QGestureEvent::acceptAll() +{ + QHash<QString, QGesture*>::iterator it = m_gestures.begin(), + e = m_gestures.end(); + for(; it != e; ++it) + it.value()->accept(); + setAccepted(true); +} + +/*! + Sets the accept flag of the specified gesture inside the event + object, the equivalent of calling + \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()} + + Setting the accept parameter indicates that the event receiver + wants the gesture. Unwanted gestures might be propagated to the parent + widget. +*/ +void QGestureEvent::accept(Qt::GestureType type) +{ + if (QGesture *g = m_gestures.value(qt_getStandardGestureTypeName(type), 0)) + g->accept(); +} + +/*! + Sets the accept flag of the specified gesture inside the event + object, the equivalent of calling + \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()} + + Setting the accept parameter indicates that the event receiver + wants the gesture. Unwanted gestures might be propagated to the parent + widget. +*/ +void QGestureEvent::accept(const QString &type) +{ + if (QGesture *g = m_gestures.value(type, 0)) + g->accept(); +} + /*! \class QTouchEvent \brief The QTouchEvent class contains parameters that describe a touch event . diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 666cd3f..ea4f577 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -716,7 +716,7 @@ private: class Q_GUI_EXPORT QGestureEvent : public QEvent { public: - QGestureEvent(const QList<QGesture*> &gestures, + QGestureEvent(const QSet<QGesture*> &gestures, const QSet<QString> &cancelledGestures = QSet<QString>()); ~QGestureEvent(); @@ -731,6 +731,15 @@ public: QSet<QString> cancelledGestures() const; + void acceptAll(); +#ifndef Q_NO_USING_KEYWORD + using QEvent::accept; +#else + inline void accept() { QEvent::accept(); } +#endif + void accept(Qt::GestureType type); + void accept(const QString &type); + protected: QHash<QString, QGesture*> m_gestures; QSet<QString> m_cancelledGestures; diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 4d492f8..7437ed3 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -79,7 +79,7 @@ QString qt_getStandardGestureTypeName(Qt::GestureType type); QGestureRecognizer classes. */ QGesture::QGesture(QObject *parent, const QString &type, Qt::GestureState state) - : QObject(*new QGesturePrivate, parent) + : QObject(*new QGesturePrivate, parent), m_accept(0) { Q_D(QGesture); d->type = type; diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index da1bc90..d220232 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -82,6 +82,12 @@ public: uint duration, Qt::GestureState state); virtual ~QGesture(); + inline void setAccepted(bool accepted) { m_accept = accepted; } + inline bool isAccepted() const { return m_accept; } + + inline void accept() { m_accept = true; } + inline void ignore() { m_accept = false; } + QString type() const; Qt::GestureState state() const; @@ -100,6 +106,8 @@ protected: virtual void translate(const QPoint &offset); private: + ushort m_accept : 1; + friend class QGestureManager; friend class QApplication; friend class QGestureRecognizerPan; diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 22d6d7f..d2d77cc 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -66,7 +66,7 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() - : duration(0) { } + : state(Qt::NoGesture), singleshot(0), duration(0) { } void init(const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, @@ -86,6 +86,7 @@ public: Qt::GestureState state; QPointer<QWidget> widget; + uint singleshot:1; QRect rect; QPoint hotSpot; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index a93248a..c7341f2 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -166,14 +166,18 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) DEBUG() << "QGestureManager: sending gesture event for: " << activeGestures << " and " << finishedGestures; - QList<QGesture*> gestures; + QSet<QGesture*> gestures; foreach(QGestureRecognizer *r, finishedGestures) { - if (QGesture *gesture = r->getGesture()) + if (QGesture *gesture = r->getGesture()) { gestures << gesture; + gesture->d_func()->singleshot = true; + } } foreach(QGestureRecognizer *r, activeGestures) { - if (QGesture *gesture = r->getGesture()) + if (QGesture *gesture = r->getGesture()) { gestures << gesture; + gesture->d_func()->singleshot = false; + } } Q_ASSERT(!gestures.isEmpty()); ret = sendGestureEvent(receiver, gestures); @@ -243,7 +247,6 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) activeGestures -= newMaybeGestures; activeGestures -= cancelledGestures; - activeGestures -= finishedGestures; activeGestures += startedGestures; foreach(QGestureRecognizer *r, startedGestures+finishedGestures+notGestures) { QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.find(r); @@ -260,7 +263,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) maybeGestures.insert(r, timerId); } } - QList<QGesture*> gestures; + QSet<QGesture*> gestures; if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { // another gesture found! ret = true; @@ -268,12 +271,17 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) << activeGestures << " and " << finishedGestures; foreach(QGestureRecognizer *r, finishedGestures) { - if (QGesture *gesture = r->getGesture()) + if (QGesture *gesture = r->getGesture()) { gestures << gesture; + gesture->d_func()->singleshot = activeGestures.contains(r); + } } + activeGestures -= finishedGestures; foreach(QGestureRecognizer *r, activeGestures) { - if (QGesture *gesture = r->getGesture()) + if (QGesture *gesture = r->getGesture()) { gestures << gesture; + gesture->d_func()->singleshot = false; + } } } QSet<QString> cancelledGestureNames; @@ -439,7 +447,7 @@ void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) killTimer(maybeGestures.value(recognizer)); maybeGestures.remove(recognizer); } - QList<QGesture*> gestures; + QSet<QGesture*> gestures; if (QGesture *gesture = recognizer->getGesture()) gestures << gesture; if(!gestures.isEmpty()) { @@ -452,7 +460,7 @@ void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) case QGestureRecognizer::MaybeGesture: { DEBUG() << "QGestureManager: maybe gesture: " << recognizer; if (activeGestures.contains(recognizer)) { - //FIXME: sendGestureEvent(targetWidget, QList<QGesture*>(), QSet<QString>() << recognizer->gestureType()); + //FIXME: sendGestureEvent(targetWidget, QSet<QGesture*>(), QSet<QString>() << recognizer->gestureType()); } if (!maybeGestures.contains(recognizer)) { int timerId = startTimer(MaximumGestureRecognitionTimeout); @@ -480,43 +488,63 @@ void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) } } -bool QGestureManager::sendGestureEvent(QWidget *receiver, const QList<QGesture*> &gestures, +bool QGestureManager::widgetHasGesture(QWidget *widget, QGesture *gesture) const +{ + const QString gestureName = gesture->type(); + QSet<int>::iterator it = widget->d_func()->gestures.begin(), + e = widget->d_func()->gestures.end(); + for (; it != e; ++it) { + if (gestureNameFromId(*it) == gestureName) + return true; + } + return false; +} + +bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet<QGesture*> &gestures, const QSet<QString> &cancelled) { - typedef QMap<QWidget*, QList<QGesture*> > WidgetGesturesMap; + if (gestures.isEmpty()) + return false; + DEBUG() << "QGestureManager::sendGestureEvent: sending to" << receiver + << "gestures:" << gestures << "; cancelled:" << cancelled; + QSet<QGesture*> startedGestures; + // grouping gesture objects by receiver widgets. + typedef QMap<QWidget*, QSet<QGesture*> > WidgetGesturesMap; WidgetGesturesMap widgetGestures; - for(QList<QGesture*>::const_iterator it = gestures.begin(), e = gestures.end(); + for(QSet<QGesture*>::const_iterator it = gestures.begin(), e = gestures.end(); it != e; ++it) { QGesture *g = *it; QGesturePrivate *gd = g->d_func(); - if (g->state() == Qt::GestureStarted) { + if (!gd->widget && (g->state() == Qt::GestureStarted || g->state() == Qt::GestureFinished)) { + startedGestures.insert(g); // find the target widget QWidget *w = receiver; + QPoint offset; while (w) { - QSet<int>::iterator it = w->d_func()->gestures.begin(), - e = w->d_func()->gestures.end(); - for (; it != e; ++it) { - if (gestureNameFromId(*it) == g->type()) - break; - } - if (it != e) + if (widgetHasGesture(w, g)) break; + if (w->isWindow()) { + w = 0; + break; + } + offset += w->pos(); w = w->parentWidget(); } if (!w) // no widget in the tree that accepts this gesture. continue; gd->widget = w; + g->translate(offset); } if (!gd->widget) { DEBUG() << "QGestureManager: didn't find a widget to send gesture event (" << g->type() << ") for tree:" << receiver; + // TODO: maybe we should reset gesture recognizers when nobody interested in its gestures. continue; } - widgetGestures[gd->widget].append(g); + widgetGestures[gd->widget].insert(g); } - // we return true and stop original from being delivered if any of - // the gesture events were accepted by a receiver. + QSet<QGesture*> ignoredGestures; bool ret = false; for(WidgetGesturesMap::const_iterator it = widgetGestures.begin(), e = widgetGestures.end(); it != e; ++it) { @@ -524,10 +552,50 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QList<QGesture*> Q_ASSERT(receiver != 0 /*should be taken care above*/); // TODO: send cancelled gesture event to the widget that received the original gesture! QGestureEvent event(it.value(), cancelled); - if (qt_sendSpontaneousEvent(receiver, &event) && event.isAccepted()) - ret = true; + bool processed = qt_sendSpontaneousEvent(receiver, &event); + QSet<QGesture*> started = startedGestures.intersect(it.value()); + if (!started.isEmpty() && !(processed && event.isAccepted())) { + // there are started gestures event that weren't + // accepted, so propagating each gesture independently. + QSet<QGesture*>::const_iterator it = started.begin(), + e = started.end(); + for(; it != e; ++it) { + QGesture *g = *it; + if (processed && g->isAccepted()) { + ret = true; + continue; + } + // if it wasn't accepted, find the first parent widget + // that is subscribed to the gesture. + QGesturePrivate *gd = g->d_func(); + QWidget *w = gd->widget; + gd->widget = 0; + + if (!w->isWindow()) { + g->translate(w->pos()); + w = w->parentWidget(); + QPoint offset; + while (w) { + if (widgetHasGesture(w, g)) { + DEBUG() << "QGestureManager: sendGestureEvent:" << w << "didn't accept gesture" << g; + ignoredGestures.insert(g); + break; + } + if (w->isWindow()) { + w = 0; + break; + } + offset += w->pos(); + w = w->parentWidget(); + } + if (w) + g->translate(offset); + } + } + } } - return ret; + // try to send all gestures that were ignored to the next parent + return sendGestureEvent(0, ignoredGestures, cancelled) || ret; } int QGestureManager::eventDeliveryDelay() const diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index beed323..963edf9 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -93,7 +93,8 @@ private slots: void recognizerStateChanged(QGestureRecognizer::Result); private: - bool sendGestureEvent(QWidget *receiver, const QList<QGesture*> &gestures, + bool widgetHasGesture(QWidget *widget, QGesture *gesture) const; + bool sendGestureEvent(QWidget *receiver, const QSet<QGesture*> &gestures, const QSet<QString> &cancelled = QSet<QString>()); QSet<QGestureRecognizer*> activeGestures; |