summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-05-18 13:32:39 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-05-18 13:32:39 (GMT)
commit6cc1e0106845a0dfe9433c4413b3c064c73ccfe2 (patch)
treea0372fb3e03000dc1e1f93a4154adecd70fd5119 /src
parent86edc526684d80e405bcd1c63b5a314b70408679 (diff)
parent537243d70de1474cf234880b215c75e83e80abcd (diff)
downloadQt-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.cpp44
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h6
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp16
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp120
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h5
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.cpp9
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.h1
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp1
-rw-r--r--src/gui/kernel/qapplication.cpp9
-rw-r--r--src/gui/kernel/qapplication_p.h3
-rw-r--r--src/gui/kernel/qgesture.h6
-rw-r--r--src/gui/kernel/qgesture_p.h4
-rw-r--r--src/gui/kernel/qgesturemanager.cpp142
-rw-r--r--src/gui/kernel/qgesturemanager_p.h11
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp3
-rw-r--r--src/gui/kernel/qgesturerecognizer.h2
-rw-r--r--src/gui/kernel/qwidget.cpp22
-rw-r--r--src/gui/kernel/qwidget_p.h1
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