diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-05-18 13:32:39 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-05-18 13:32:39 (GMT) |
commit | 6cc1e0106845a0dfe9433c4413b3c064c73ccfe2 (patch) | |
tree | a0372fb3e03000dc1e1f93a4154adecd70fd5119 /src | |
parent | 86edc526684d80e405bcd1c63b5a314b70408679 (diff) | |
parent | 537243d70de1474cf234880b215c75e83e80abcd (diff) | |
download | Qt-6cc1e0106845a0dfe9433c4413b3c064c73ccfe2.zip Qt-6cc1e0106845a0dfe9433c4413b3c064c73ccfe2.tar.gz Qt-6cc1e0106845a0dfe9433c4413b3c064c73ccfe2.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt-multitouch
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 44 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 6 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsproxywidget.cpp | 16 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 120 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene_p.h | 5 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicssceneevent.cpp | 9 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicssceneevent.h | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.cpp | 1 | ||||
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 9 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.h | 6 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 142 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager_p.h | 11 | ||||
-rw-r--r-- | src/gui/kernel/qgesturerecognizer.cpp | 3 | ||||
-rw-r--r-- | src/gui/kernel/qgesturerecognizer.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 22 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 1 |
18 files changed, 293 insertions, 112 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 747d510..ae33674 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5857,6 +5857,7 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const */ int QGraphicsItem::grabGesture(Qt::GestureType gesture) { + /// TODO: if we are QGraphicsProxyWidget we should subscribe the widget to gesture as well. return grabGesture(qt_getStandardGestureTypeName(gesture)); } @@ -5872,12 +5873,30 @@ int QGraphicsItem::grabGesture(Qt::GestureType gesture) int QGraphicsItem::grabGesture(const QString &gesture) { int id = QGestureManager::instance()->makeGestureId(gesture); - d_ptr->gestures << id; - if (d_ptr->scene) - d_ptr->scene->d_func()->grabGesture(this, id); + d_ptr->grabGesture(id); return id; } +void QGraphicsItemPrivate::grabGesture(int id) +{ + Q_Q(QGraphicsItem); + gestures << id; + if (scene) + scene->d_func()->grabGesture(q, id); +} + +bool QGraphicsItemPrivate::releaseGesture(int id) +{ + Q_Q(QGraphicsItem); + if (gestures.contains(id)) { + if (scene) + scene->d_func()->releaseGesture(q, id); + gestures.remove(id); + return true; + } + return false; +} + /*! \since 4.6 @@ -5888,10 +5907,9 @@ int QGraphicsItem::grabGesture(const QString &gesture) */ void QGraphicsItem::releaseGesture(int gestureId) { - if (d_ptr->scene) - d_ptr->scene->d_func()->releaseGesture(this, gestureId); - QGestureManager::instance()->releaseGestureId(gestureId); - d_ptr->gestures.remove(gestureId); + /// TODO: if we are QGraphicsProxyWidget we should unsubscribe the widget from gesture as well. + if (d_ptr->releaseGesture(gestureId)) + QGestureManager::instance()->releaseGestureId(gestureId); } /*! @@ -5909,6 +5927,18 @@ void QGraphicsItem::setGestureEnabled(int gestureId, bool enable) //### } +bool QGraphicsItemPrivate::hasGesture(const QString &name) const +{ + QGestureManager *gm = QGestureManager::instance(); + QSet<int>::const_iterator it = gestures.begin(), + e = gestures.end(); + for (; it != e; ++it) { + if (gm->gestureNameFromId(*it) == name) + return true; + } + return false; +} + /*! This virtual function is called by QGraphicsItem to notify custom items that some part of the item's state changes. By reimplementing this diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index b6daa85..091a461 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -305,7 +305,11 @@ public: int depth; QSet<int> gestures; - // Packed 32 bits + bool hasGesture(const QString &gesture) const; + void grabGesture(int id); + bool releaseGesture(int id); + + // Packed 32 bytes quint32 acceptedMouseButtons : 5; quint32 visible : 1; quint32 explicitlyHidden : 1; diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 01b7593..5641068 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -48,6 +48,7 @@ #include "private/qgraphicsproxywidget_p.h" #include "private/qwidget_p.h" #include "private/qapplication_p.h" +#include "private/qgesturemanager_p.h" #include <QtCore/qdebug.h> #include <QtGui/qevent.h> @@ -275,7 +276,7 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber; QApplicationPrivate::sendMouseEvent(receiver, mouseEvent, alienWidget, widget, - &embeddedMouseGrabberPtr, lastWidgetUnderMouse); + &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous()); embeddedMouseGrabber = embeddedMouseGrabberPtr; // Handle enter/leave events when last button is released from mouse @@ -648,6 +649,9 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto q->setAttribute(Qt::WA_OpaquePaintEvent); widget = newWidget; + foreach(int gestureId, widget->d_func()->gestures) { + grabGesture(gestureId); + } // Changes only go from the widget to the proxy. enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; @@ -871,6 +875,16 @@ bool QGraphicsProxyWidget::event(QEvent *event) } break; } + case QEvent::GraphicsSceneGesture: { + qDebug() << "QGraphicsProxyWidget: graphicsscenegesture"; + if (d->widget && d->widget->isVisible()) { + QGraphicsSceneGestureEvent *ge = static_cast<QGraphicsSceneGestureEvent*>(event); + //### TODO: widget->childAt(): decompose gesture event and find widget under hotspots. + //QGestureManager::instance()->sendGestureEvent(d->widget, ge->gestures().toSet(), ge->cancelledGestures()); + return true; + } + break; + } default: break; } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4d0d991..8e5ebdb 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -248,6 +248,7 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include <private/qt_x11_p.h> #endif #include <private/qgesturemanager_p.h> +#include <private/qgesture_p.h> QT_BEGIN_NAMESPACE @@ -3919,40 +3920,44 @@ bool QGraphicsScene::event(QEvent *event) update(); break; case QEvent::GraphicsSceneGesture: { + qDebug() << "GraphicsSceneGesture"; QGraphicsSceneGestureEvent *ev = static_cast<QGraphicsSceneGestureEvent*>(event); - QList<QString> gestureTypes = ev->gestureTypes(); QGraphicsView *view = qobject_cast<QGraphicsView*>(ev->widget()); if (!view) { qWarning("QGraphicsScene::event: gesture event was received without a view"); break; } - // find graphics items that intersects with gestures hot spots. - QPolygonF poly; - QMap<QString, QPointF> sceneHotSpots; - foreach(const QString &type, gestureTypes) { - QPointF pt = ev->mapToScene(ev->gesture(type)->hotSpot()); - sceneHotSpots.insert(type, pt); - poly << pt; + // get a list of gestures that just started. + QSet<QGesture*> startedGestures; + QList<QGesture*> gestures = ev->gestures(); + for(QList<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 || gd->singleshot) { + startedGestures.insert(g); + } } - QList<QGraphicsItem*> itemsInGestureArea = items(poly, Qt::IntersectsItemBoundingRect); - - foreach(QGraphicsItem *item, itemsInGestureArea) { - QMap<QString, QPointF>::const_iterator it = sceneHotSpots.begin(), - e = sceneHotSpots.end(); - for(; it != e; ++it) { - if (item->contains(item->mapFromScene(it.value()))) { - const QString gestureName = it.key(); - foreach(int gestureId, item->d_ptr->gestures) { - if (QGestureManager::instance()->gestureNameFromId(gestureId) == gestureName) { - d->sendEvent(item, ev); - if (ev->isAccepted()) - break; - } + if (!startedGestures.isEmpty()) { + // find a target for each started gesture. + for(QSet<QGesture*>::const_iterator it = startedGestures.begin(), e = startedGestures.end(); + it != e; ++it) { + QGesture *g = *it; + QGesturePrivate *gd = g->d_func(); + QList<QGraphicsItem*> itemsInGestureArea = items(g->hotSpot()); + const QString gestureName = g->type(); + foreach(QGraphicsItem *item, itemsInGestureArea) { + if (item->d_func()->hasGesture(gestureName)) { + Q_ASSERT(gd->graphicsItem == 0); + gd->graphicsItem = item; + d->itemsWithGestures[item].insert(g); + break; } } } } + d->sendGestureEvent(ev->gestures().toSet(), ev->cancelledGestures()); } break; case QEvent::GraphicsSceneTouchBegin: @@ -3976,6 +3981,74 @@ bool QGraphicsScene::event(QEvent *event) return true; } +void QGraphicsScenePrivate::sendGestureEvent(const QSet<QGesture*> &gestures, const QSet<QString> &cancelled) +{ + qDebug() << "QGraphicsScenePrivate::sendGestureEvent:" << gestures; + Q_Q(QGraphicsScene); + typedef QMap<QGraphicsItem*, QSet<QGesture*> > ItemGesturesMap; + ItemGesturesMap itemGestures; + QSet<QGesture*> startedGestures; + for(QSet<QGesture*>::const_iterator it = gestures.begin(), e = gestures.end(); + it != e; ++it) { + QGesture *g = *it; + Q_ASSERT(g != 0); + QGesturePrivate *gd = g->d_func(); + if (gd->graphicsItem != 0) { + itemGestures[gd->graphicsItem].insert(g); + if (g->state() == Qt::GestureStarted || gd->singleshot) + startedGestures.insert(g); + } + } + + qDebug() << "QGraphicsScenePrivate::sendGestureEvent: started: " << startedGestures; + QSet<QGesture*> ignoredGestures; + for(ItemGesturesMap::const_iterator it = itemGestures.begin(), e = itemGestures.end(); + it != e; ++it) { + QGraphicsItem *receiver = it.key(); + Q_ASSERT(receiver != 0); + QGraphicsSceneGestureEvent event; + event.setGestures(it.value()); + event.setCancelledGestures(cancelled); + qDebug() << "QGraphicsScenePrivate::sendGestureEvent: sending to " << receiver << it.value(); + bool processed = sendEvent(receiver, &event); + QSet<QGesture*> started = startedGestures.intersect(it.value()); + if (event.isAccepted()) + foreach(QGesture *g, started) + g->accept(); + 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; + qDebug() << "result: " << g << ":" << processed << g->isAccepted(); + if (processed && g->isAccepted()) { + continue; + } + QGesturePrivate *gd = g->d_func(); + QGraphicsItem *item = gd->graphicsItem; + gd->graphicsItem = 0; + + //### THIS IS BS, DONT FORGET TO REWRITE THIS CODE + // need to make sure we try to deliver event just once to each widget + const QString gestureType = g->type(); + QList<QGraphicsItem*> itemsUnderGesture = q->items(g->hotSpot()); + for (int i = 0; i < itemsUnderGesture.size(); ++i) { + QGraphicsItem *item = itemsUnderGesture.at(i); + if (item != receiver && item->d_func()->hasGesture(gestureType)) { + ignoredGestures.insert(g); + gd->graphicsItem = item; + break; + } + } + } + } + } + if (!ignoredGestures.isEmpty()) + sendGestureEvent(ignoredGestures, cancelled); +} + /*! \reimp @@ -5606,12 +5679,13 @@ void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, int gestureId) foreach(QGraphicsView *view, views) view->d_func()->grabGesture(gestureId); } - itemsWithGestures << item; + (void)itemsWithGestures[item]; grabbedGestures << gestureId; } void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, int gestureId) { + itemsWithGestures.remove(item); //### } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 7928a45..160ba49 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -74,6 +74,7 @@ QT_BEGIN_NAMESPACE class QGraphicsView; class QGraphicsWidget; +class QGesture; class QGraphicsScenePrivate : public QObjectPrivate { @@ -267,10 +268,12 @@ public: void resolvePalette(); void updatePalette(const QPalette &palette); - QSet<QGraphicsItem*> itemsWithGestures; + // items with gestures -> list of started gestures. + QMap<QGraphicsItem*, QSet<QGesture*> > itemsWithGestures; QSet<int> grabbedGestures; void grabGesture(QGraphicsItem *item, int gestureId); void releaseGesture(QGraphicsItem *item, int gestureId); + void sendGestureEvent(const QSet<QGesture*> &gestures, const QSet<QString> &cancelled); mutable QVector<QTransform> sceneTransformCache; mutable QBitArray validTransforms; diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index d5d0fb9..2c5c946 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1895,6 +1895,15 @@ void QGraphicsSceneGestureEvent::setGestures(const QList<QGesture*> &gestures) } /*! + Set a list of gesture objects containing extended information about \a gestures. +*/ +void QGraphicsSceneGestureEvent::setGestures(const QSet<QGesture*> &gestures) +{ + foreach(QGesture *g, gestures) + m_gestures.insert(g->type(), g); +} + +/*! 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)}. diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index 01cdab9..8b24d33 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -325,6 +325,7 @@ public: const QGesture* gesture(const QString &type) const; QList<QGesture*> gestures() const; void setGestures(const QList<QGesture*> &gestures); + void setGestures(const QSet<QGesture*> &gestures); QSet<QString> cancelledGestures() const; void setCancelledGestures(const QSet<QString> &cancelledGestures); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index b75619c..2babce9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2875,6 +2875,7 @@ bool QGraphicsView::viewportEvent(QEvent *event) gestureEvent.setGestures(ev->gestures()); gestureEvent.setCancelledGestures(ev->cancelledGestures()); QApplication::sendEvent(d->scene, &gestureEvent); + event->setAccepted(gestureEvent.isAccepted()); if (gestureEvent.isAccepted()) return true; } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 204cff6..b142f2e 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -2874,7 +2874,8 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint */ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *nativeWidget, - QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver) + QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, + bool spontaneous) { Q_ASSERT(receiver); Q_ASSERT(event); @@ -2927,7 +2928,11 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, // We need this quard in case someone opens a modal dialog / popup. If that's the case // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver. const bool wasLeaveAfterRelease = leaveAfterRelease != 0; - bool result = QApplication::sendSpontaneousEvent(receiver, event); + bool result; + if (spontaneous) + result = QApplication::sendSpontaneousEvent(receiver, event); + else + result = QApplication::sendEvent(receiver, event); if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) { diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 096c349..08020fb 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -424,7 +424,8 @@ public: QEvent::Type type, Qt::MouseButtons buttons, QWidget *buttonDown, QWidget *alienWidget); static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, - QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver); + QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, + bool spontaneous = true); #if defined(Q_WS_WIN) || defined(Q_WS_X11) void sendSyntheticEnterLeave(QWidget *widget); #endif diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index d220232..64a1424 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -73,8 +73,8 @@ class Q_GUI_EXPORT QGesture : public QObject Q_PROPERTY(QPoint pos READ pos) public: - explicit QGesture(QObject *parent, const QString &type, - Qt::GestureState state = Qt::GestureStarted); + QGesture(QObject *parent, const QString &type, + Qt::GestureState state = Qt::GestureStarted); QGesture(QObject *parent, const QString &type, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, @@ -110,6 +110,8 @@ private: friend class QGestureManager; friend class QApplication; + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; friend class QGestureRecognizerPan; friend class QDoubleTapGestureRecognizer; friend class QTapAndHoldGestureRecognizer; diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index d2d77cc..0f2e791 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -60,13 +60,14 @@ QT_BEGIN_NAMESPACE +class QGraphicsItem; class QGesturePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGesture) public: QGesturePrivate() - : state(Qt::NoGesture), singleshot(0), duration(0) { } + : state(Qt::NoGesture), graphicsItem(0), singleshot(0), duration(0) { } void init(const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, @@ -86,6 +87,7 @@ public: Qt::GestureState state; QPointer<QWidget> widget; + QGraphicsItem *graphicsItem; uint singleshot:1; QRect rect; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index c7341f2..9e8a5bb 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -139,7 +139,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) notGestures << r; } } - activeGestures -= newMaybeGestures; + Q_ASSERT(activeGestures.isEmpty()); activeGestures += startedGestures; for(QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.begin(); it != maybeGestures.end();) { @@ -160,27 +160,24 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) maybeGestures.insert(r, timerId); } } - if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { + if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) { // gesture found! ret = true; - DEBUG() << "QGestureManager: sending gesture event for: " - << activeGestures << " and " << finishedGestures; - - QSet<QGesture*> gestures; + QSet<QGesture*> started; foreach(QGestureRecognizer *r, finishedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; + started << gesture; gesture->d_func()->singleshot = true; } } - foreach(QGestureRecognizer *r, activeGestures) { + foreach(QGestureRecognizer *r, startedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; + started << gesture; gesture->d_func()->singleshot = false; } } - Q_ASSERT(!gestures.isEmpty()); - ret = sendGestureEvent(receiver, gestures); + Q_ASSERT(!started.isEmpty()); + ret = sendGestureEvent(receiver, started, QSet<QGesture*>()); if (!activeGestures.isEmpty()) { DEBUG() << "QGestureManager: new state = Gesture"; @@ -243,16 +240,16 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) } } } - // TODO: make sure that if gesture recognizer ignored the event we dont swallow it. - activeGestures -= newMaybeGestures; - activeGestures -= cancelledGestures; - activeGestures += startedGestures; - foreach(QGestureRecognizer *r, startedGestures+finishedGestures+notGestures) { - QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.find(r); - if (it != maybeGestures.end()) { + for(QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.begin(); + it != maybeGestures.end();) { + QGestureRecognizer *r = it.key(); + if (startedGestures.contains(r) || finishedGestures.contains(r) || + notGestures.contains(r)) { killTimer(it.value()); - maybeGestures.erase(it); + it = maybeGestures.erase(it); + } else { + ++it; } } foreach(QGestureRecognizer *r, newMaybeGestures) { @@ -263,33 +260,37 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) maybeGestures.insert(r, timerId); } } - QSet<QGesture*> gestures; - if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { + QSet<QGesture*> started, updated; + if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) { // another gesture found! ret = true; - DEBUG() << "QGestureManager: sending gesture event for: " - << activeGestures << " and " << finishedGestures; - foreach(QGestureRecognizer *r, finishedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; - gesture->d_func()->singleshot = activeGestures.contains(r); + gesture->d_func()->singleshot = !activeGestures.contains(r); + if (gesture->d_func()->singleshot) + started << gesture; + else + updated << gesture; } } - activeGestures -= finishedGestures; - foreach(QGestureRecognizer *r, activeGestures) { + foreach(QGestureRecognizer *r, startedGestures) { if (QGesture *gesture = r->getGesture()) { - gestures << gesture; - gesture->d_func()->singleshot = false; + gesture->d_func()->singleshot = !activeGestures.contains(r); + if (gesture->d_func()->singleshot) + started << gesture; + else + updated << gesture; } } } + activeGestures -= newMaybeGestures; + activeGestures -= cancelledGestures; + activeGestures += startedGestures; + activeGestures -= finishedGestures; QSet<QString> cancelledGestureNames; foreach(QGestureRecognizer *r, cancelledGestures) cancelledGestureNames << r->gestureType(); - if(!gestures.isEmpty()) { - ret = sendGestureEvent(receiver, gestures, cancelledGestureNames); - } + ret = sendGestureEvent(receiver, started, updated, cancelledGestureNames); foreach(QGestureRecognizer *r, finishedGestures) r->reset(); @@ -488,40 +489,29 @@ void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) } } -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, +bool QGestureManager::sendGestureEvent(QWidget *receiver, + const QSet<QGesture*> &startedGestures, + const QSet<QGesture*> &updatedGestures, const QSet<QString> &cancelled) { - if (gestures.isEmpty()) - return false; DEBUG() << "QGestureManager::sendGestureEvent: sending to" << receiver - << "gestures:" << gestures << "; cancelled:" << cancelled; - QSet<QGesture*> startedGestures; + << "gestures:" << startedGestures << "," << updatedGestures + << "cancelled:" << cancelled; // grouping gesture objects by receiver widgets. typedef QMap<QWidget*, QSet<QGesture*> > WidgetGesturesMap; WidgetGesturesMap widgetGestures; - for(QSet<QGesture*>::const_iterator it = gestures.begin(), e = gestures.end(); + for(QSet<QGesture*>::const_iterator it = startedGestures.begin(), e = startedGestures.end(); it != e; ++it) { QGesture *g = *it; QGesturePrivate *gd = g->d_func(); - if (!gd->widget && (g->state() == Qt::GestureStarted || g->state() == Qt::GestureFinished)) { - startedGestures.insert(g); + if (receiver) { // find the target widget + gd->widget = 0; QWidget *w = receiver; QPoint offset; + const QString gestureType = g->type(); while (w) { - if (widgetHasGesture(w, g)) + if (w->d_func()->hasGesture(gestureType)) break; if (w->isWindow()) { w = 0; @@ -530,10 +520,11 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet<QGesture*> offset += w->pos(); w = w->parentWidget(); } - if (!w) // no widget in the tree that accepts this gesture. - continue; + if (w && w != gd->widget) { + DEBUG() << "QGestureManager::sendGestureEvent:" << g << "propagating to widget" << w << "offset" << offset; + g->translate(offset); + } gd->widget = w; - g->translate(offset); } if (!gd->widget) { DEBUG() << "QGestureManager: didn't find a widget to send gesture event (" @@ -550,13 +541,25 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet<QGesture*> it != e; ++it) { QWidget *receiver = it.key(); Q_ASSERT(receiver != 0 /*should be taken care above*/); + QSet<QGesture*> gestures = it.value(); + // mark all gestures as ignored by default + for(QSet<QGesture*>::iterator it = gestures.begin(), e = gestures.end(); it != e; ++it) + (*it)->ignore(); // TODO: send cancelled gesture event to the widget that received the original gesture! - QGestureEvent event(it.value(), cancelled); + QGestureEvent event(gestures, cancelled); + DEBUG() << "QGestureManager::sendGestureEvent: sending now to" << receiver + << "gestures" << gestures; bool processed = qt_sendSpontaneousEvent(receiver, &event); - QSet<QGesture*> started = startedGestures.intersect(it.value()); + QSet<QGesture*> started = startedGestures & gestures; + DEBUG() << "QGestureManager::sendGestureEvent:" << + (event.isAccepted() ? "" : "not") << "all gestures were accepted"; if (!started.isEmpty() && !(processed && event.isAccepted())) { - // there are started gestures event that weren't + // there are started gestures events that weren't // accepted, so propagating each gesture independently. + if (event.isAccepted()) { + foreach(QGesture *g, started) + g->accept(); + } QSet<QGesture*>::const_iterator it = started.begin(), e = started.end(); for(; it != e; ++it) { @@ -571,14 +574,17 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet<QGesture*> QWidget *w = gd->widget; gd->widget = 0; - if (!w->isWindow()) { + if (w && !w->isWindow()) { g->translate(w->pos()); w = w->parentWidget(); QPoint offset; + const QString gestureType = g->type(); while (w) { - if (widgetHasGesture(w, g)) { - DEBUG() << "QGestureManager: sendGestureEvent:" << w << "didn't accept gesture" << g; + if (w->d_func()->hasGesture(gestureType)) { + DEBUG() << "QGestureManager::sendGestureEvent:" << receiver + << "didn't accept gesture" << g << "propagating to" << w; ignoredGestures.insert(g); + gd->widget = w; break; } if (w->isWindow()) { @@ -588,14 +594,20 @@ bool QGestureManager::sendGestureEvent(QWidget *receiver, const QSet<QGesture*> offset += w->pos(); w = w->parentWidget(); } - if (w) + if (w) { g->translate(offset); + } else { + DEBUG() << "QGestureManager::sendGestureEvent:" << receiver + << "didn't accept gesture" << g << "and nobody wants it"; + } } } } } + if (ignoredGestures.isEmpty()) + return ret; // try to send all gestures that were ignored to the next parent - return sendGestureEvent(0, ignoredGestures, cancelled) || ret; + return sendGestureEvent(0, ignoredGestures, QSet<QGesture*>(), cancelled) || ret; } int QGestureManager::eventDeliveryDelay() const diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 963edf9..745feb3 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE class QWidget; -class Q_GUI_EXPORT QGestureManager : public QObject +class Q_AUTOTEST_EXPORT QGestureManager : public QObject { Q_OBJECT public: @@ -86,6 +86,11 @@ public: // declared in qapplication.cpp static QGestureManager* instance(); + bool sendGestureEvent(QWidget *receiver, + const QSet<QGesture*> &startedGestures, + const QSet<QGesture*> &updatedGestures, + const QSet<QString> &cancelled = QSet<QString>()); + protected: void timerEvent(QTimerEvent *event); @@ -93,10 +98,6 @@ private slots: void recognizerStateChanged(QGestureRecognizer::Result); private: - bool widgetHasGesture(QWidget *widget, QGesture *gesture) const; - bool sendGestureEvent(QWidget *receiver, const QSet<QGesture*> &gestures, - const QSet<QString> &cancelled = QSet<QString>()); - QSet<QGestureRecognizer*> activeGestures; QMap<QGestureRecognizer*, int> maybeGestures; QSet<QGestureRecognizer*> recognizers; diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index 41160cd..879f557 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -108,6 +108,9 @@ QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); to QGestureRecognizer::GestureStarted or QGestureRecognizer::GestureFinished. + The returned QGesture object must point to the same object in a + single gesture sequence. + The gesture object is owned by the recognizer itself. */ diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index 8bc8b97..67d7949 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -60,7 +60,7 @@ public: { Ignore, NotGesture, - GestureStarted, + GestureStarted, //TODO: rename to just Gesture? GestureFinished, MaybeGesture }; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 3a146e5..7920139 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -10970,7 +10970,10 @@ QWindowSurface *QWidget::windowSurface() const int QWidget::grabGesture(const QString &gesture) { Q_D(QWidget); - return d->grabGesture(QGestureManager::instance()->makeGestureId(gesture)); + int id = d->grabGesture(QGestureManager::instance()->makeGestureId(gesture)); + if (d->extra && d->extra->proxyWidget) + d->extra->proxyWidget->QGraphicsItem::d_ptr->grabGesture(id); + return id; } int QWidgetPrivate::grabGesture(int gestureId) @@ -10993,6 +10996,18 @@ bool QWidgetPrivate::releaseGesture(int gestureId) return false; } +bool QWidgetPrivate::hasGesture(const QString &name) const +{ + QGestureManager *gm = QGestureManager::instance(); + QSet<int>::const_iterator it = gestures.begin(), + e = gestures.end(); + for (; it != e; ++it) { + if (gm->gestureNameFromId(*it) == name) + return true; + } + return false; +} + /*! \since 4.6 @@ -11018,8 +11033,11 @@ int QWidget::grabGesture(Qt::GestureType gesture) void QWidget::releaseGesture(int gestureId) { Q_D(QWidget); - if (d->releaseGesture(gestureId)) + if (d->releaseGesture(gestureId)) { + if (d->extra && d->extra->proxyWidget) + d->extra->proxyWidget->QGraphicsItem::d_ptr->releaseGesture(gestureId); QGestureManager::instance()->releaseGestureId(gestureId); + } } /*! diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index a603b44..b2ae75e 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -521,6 +521,7 @@ public: QSet<int> gestures; int grabGesture(int gestureId); bool releaseGesture(int gestureId); + bool hasGesture(const QString &type) const; // Bit fields. uint high_attributes[3]; // the low ones are in QWidget::widget_attributes |