summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/global/qnamespace.h12
-rw-r--r--src/corelib/global/qnamespace.qdoc18
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp13
-rw-r--r--src/gui/kernel/qapplication.cpp7
-rw-r--r--src/gui/kernel/qgesturemanager.cpp16
-rw-r--r--tests/auto/gestures/tst_gestures.cpp121
6 files changed, 150 insertions, 37 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index aeaca54f71..561ffc1c51 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1715,14 +1715,19 @@ public:
LastGestureType = ~0u
};
- enum GestureContext
+ enum GestureContextFlag
{
WidgetGesture = 0,
WidgetWithChildrenGesture = 3,
- ItemGesture = WidgetGesture,
- ItemWithChildrenGesture = WidgetWithChildrenGesture
+ ItemGesture = WidgetGesture,
+ ItemWithChildrenGesture = WidgetWithChildrenGesture,
+
+ GestureContext_Mask = 0x00ff,
+ AcceptPartialGesturesHint = 0x0100,
+ GestureContextHint_Mask = 0xff00
};
+ Q_DECLARE_FLAGS(GestureContext, GestureContextFlag)
enum NavigationMode
{
@@ -1757,6 +1762,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints)
Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TouchPointStates)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::GestureContext)
typedef bool (*qInternalCallback)(void **);
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 3fcbe57928..f2a8882855 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -2917,11 +2917,11 @@
QApplication::registerGestureRecognizer() function which generates a custom gesture ID
in the range of values from CustomGesture to LastGestureType.
- \sa QGesture, QWidget::grabGesture()
+ \sa QGesture, QWidget::grabGesture(), QGraphicsObject::grabGesture()
*/
/*!
- \enum Qt::GestureContext
+ \enum Qt::GestureContextFlag
\since 4.6
This enum type describes the context of a gesture.
@@ -2937,7 +2937,19 @@
\value ItemWithChildrenGesture Gestures can start on the item or over
any of its children.
- \sa QWidget::grabGesture()
+ \value AcceptPartialGesturesHint Allows any ignored gesture events to be
+ propagated to parent widgets which have specified this hint. By default
+ only gestures that are in the Qt::GestureStarted state are propagated and
+ the widget only gets the full gesture sequence starting with a gesture in
+ the Qt::GestureStarted state and ending with a gesture in the
+ Qt::GestureFinished or Qt::GestureCanceled states.
+
+ \value GestureContext_Mask A mask for extracting the context type of the
+ context flags.
+ \value GestureContextHint_Mask A mask for extracting additional hints for
+ the context.
+
+ \sa QWidget::grabGesture(), QGraphicsObject::grabGesture()
*/
/*!
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 9279fe36cc..f5bb408a7a 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5900,7 +5900,12 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
foreach(QGesture *g, alreadyIgnoredGestures) {
- if (gid->gestureContext.contains(g->gestureType()))
+ QMap<Qt::GestureType, Qt::GestureContext>::iterator contextit =
+ gid->gestureContext.find(g->gestureType());
+ bool deliver = contextit != gid->gestureContext.end() &&
+ (g->state() == Qt::GestureStarted ||
+ (contextit.value() & Qt::GestureContextHint_Mask) & Qt::AcceptPartialGesturesHint);
+ if (deliver)
gestures += g;
}
if (gestures.isEmpty())
@@ -5913,8 +5918,12 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
sendEvent(item, &ev);
QSet<QGesture *> ignoredGestures;
foreach (QGesture *g, gestures) {
- if (!ev.isAccepted() && !ev.isAccepted(g))
+ if (!ev.isAccepted() && !ev.isAccepted(g)) {
ignoredGestures.insert(g);
+ } else {
+ if (g->state() == Qt::GestureStarted)
+ gestureTargets[g] = item;
+ }
}
if (!ignoredGestures.isEmpty()) {
// get a list of items under the (current) hotspot of each ignored
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 06787eb2bc..b9e7d527e7 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -4161,7 +4161,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
for (int i = 0; i < allGestures.size();) {
QGesture *g = allGestures.at(i);
Qt::GestureType type = g->gestureType();
- if (wd->gestureContext.contains(type)) {
+ QMap<Qt::GestureType, Qt::GestureContext>::iterator contextit =
+ wd->gestureContext.find(type);
+ bool deliver = contextit != wd->gestureContext.end() &&
+ (g->state() == Qt::GestureStarted || w == receiver ||
+ (contextit.value() & Qt::GestureContextHint_Mask) & Qt::AcceptPartialGesturesHint);
+ if (deliver) {
allGestures.removeAt(i);
gestures.append(g);
} else {
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 318d4b5638..e4a1eb4630 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -448,7 +448,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
{
for (ContextIterator it = w->d_func()->gestureContext.begin(),
e = w->d_func()->gestureContext.end(); it != e; ++it) {
- if (it.value() == Qt::WidgetWithChildrenGesture) {
+ if ((it.value() & Qt::GestureContext_Mask) == Qt::WidgetWithChildrenGesture) {
if (!types.contains(it.key())) {
types.insert(it.key());
contexts.insertMulti(w, it.key());
@@ -482,7 +482,7 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
- if (it.value() == Qt::ItemWithChildrenGesture) {
+ if ((it.value() & Qt::GestureContext_Mask) == Qt::ItemWithChildrenGesture) {
if (!types.contains(it.key())) {
types.insert(it.key());
contexts.insertMulti(item, it.key());
@@ -525,7 +525,7 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
= w->d_func()->gestureContext.find(type);
if (it != w->d_func()->gestureContext.end()) {
// i.e. 'w' listens to gesture 'type'
- Qt::GestureContext context = it.value();
+ Qt::GestureContext context = it.value() & Qt::GestureContext_Mask;
if (context == Qt::WidgetWithChildrenGesture && w != widget) {
// conflicting gesture!
(*conflicts)[widget].append(gestures[widget]);
@@ -645,6 +645,16 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
<< "gestures:" << it.value();
QGestureEvent event(it.value());
QApplication::sendEvent(it.key(), &event);
+ bool eventAccepted = event.isAccepted();
+ foreach (QGesture *gesture, event.allGestures()) {
+ if (gesture->state() == Qt::GestureStarted &&
+ (eventAccepted || event.isAccepted(gesture))) {
+ QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0);
+ Q_ASSERT(w);
+ DEBUG() << "started gesture was delivered and accepted by" << w;
+ m_gestureTargets[gesture] = w;
+ }
+ }
}
}
}
diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp
index 79de8239d3..9b2bc577fe 100644
--- a/tests/auto/gestures/tst_gestures.cpp
+++ b/tests/auto/gestures/tst_gestures.cpp
@@ -543,7 +543,9 @@ void tst_Gestures::conflictingGestures()
parent.reset();
child->reset();
- // nobody accepts the override, we will send normal events to the closest context (to the child)
+ // nobody accepts the override, we will send normal events to the closest
+ // context (i.e. to the child widget) and it will be propagated and
+ // accepted by the parent widget
parent.acceptGestureOverride = false;
child->acceptGestureOverride = false;
child->ignoredGestures << CustomGesture::GestureType;
@@ -552,6 +554,41 @@ void tst_Gestures::conflictingGestures()
sendCustomGesture(&event, child);
QCOMPARE(child->gestureOverrideEventsReceived, 1);
+ QCOMPARE(child->gestureEventsReceived, 1);
+ QCOMPARE(parent.gestureOverrideEventsReceived, 1);
+ QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
+
+ parent.reset();
+ child->reset();
+
+ // nobody accepts the override, and nobody accepts the gesture event
+ parent.acceptGestureOverride = false;
+ child->acceptGestureOverride = false;
+ parent.ignoredGestures << CustomGesture::GestureType;
+ child->ignoredGestures << CustomGesture::GestureType;
+
+ // sending events to the child and making sure there is no conflict
+ sendCustomGesture(&event, child);
+
+ QCOMPARE(child->gestureOverrideEventsReceived, 1);
+ QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(parent.gestureOverrideEventsReceived, 1);
+ QCOMPARE(parent.gestureEventsReceived, 1);
+
+ parent.reset();
+ child->reset();
+
+ // we set an attribute to make sure all gesture events are propagated
+ parent.grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint);
+ parent.acceptGestureOverride = false;
+ child->acceptGestureOverride = false;
+ parent.ignoredGestures << CustomGesture::GestureType;
+ child->ignoredGestures << CustomGesture::GestureType;
+
+ // sending events to the child and making sure there is no conflict
+ sendCustomGesture(&event, child);
+
+ QCOMPARE(child->gestureOverrideEventsReceived, 1);
QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
QCOMPARE(parent.gestureOverrideEventsReceived, 1);
QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
@@ -851,7 +888,7 @@ void tst_Gestures::graphicsItemTreeGesture()
QCOMPARE(item1_child2->gestureEventsReceived, 0);
QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
- QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(item1->gestureEventsReceived, 1);
}
void tst_Gestures::explicitGraphicsObjectTarget()
@@ -966,7 +1003,39 @@ void tst_Gestures::gestureOverChildGraphicsItem()
event.hasHotSpot = true;
sendCustomGesture(&event, item0, &scene);
- QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(item2_child1->gestureEventsReceived, 0);
+ QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
+ QCOMPARE(item2->gestureEventsReceived, 1);
+ QCOMPARE(item2->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(item1->gestureOverrideEventsReceived, 1);
+
+ item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
+ item2->grabGesture(CustomGesture::GestureType);
+ item2->ignoredGestures << CustomGesture::GestureType;
+ item1->ignoredGestures << CustomGesture::GestureType;
+
+ event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
+ event.hasHotSpot = true;
+ sendCustomGesture(&event, item0, &scene);
+
+ QCOMPARE(item2_child1->gestureEventsReceived, 0);
+ QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
+ QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(item2->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item1->gestureEventsReceived, 1);
+ QCOMPARE(item1->gestureOverrideEventsReceived, 1);
+
+ item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
+ item2->grabGesture(CustomGesture::GestureType);
+ item2->ignoredGestures << CustomGesture::GestureType;
+ item1->ignoredGestures << CustomGesture::GestureType;
+ item1->grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint);
+
+ event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
+ event.hasHotSpot = true;
+ sendCustomGesture(&event, item0, &scene);
+
QCOMPARE(item2_child1->gestureEventsReceived, 0);
QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
@@ -1025,15 +1094,16 @@ void tst_Gestures::multipleGesturesInTree()
Qt::GestureType SecondGesture = QApplication::registerGestureRecognizer(new CustomGestureRecognizer);
Qt::GestureType ThirdGesture = QApplication::registerGestureRecognizer(new CustomGestureRecognizer);
- A->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // A [1 3]
- A->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // |
- B->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); // B [ 2 3]
- B->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // |
- C->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // C [1 2 3]
- C->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); // |
- C->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // D [1 3]
- D->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture);
- D->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture);
+ Qt::GestureContext context = Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint;
+ A->grabGesture(FirstGesture, context); // A [1 3]
+ A->grabGesture(ThirdGesture, context); // |
+ B->grabGesture(SecondGesture, context); // B [ 2 3]
+ B->grabGesture(ThirdGesture, context); // |
+ C->grabGesture(FirstGesture, context); // C [1 2 3]
+ C->grabGesture(SecondGesture, context); // |
+ C->grabGesture(ThirdGesture, context); // D [1 3]
+ D->grabGesture(FirstGesture, context);
+ D->grabGesture(ThirdGesture, context);
// make sure all widgets ignore events, so they get propagated.
A->ignoredGestures << FirstGesture << ThirdGesture;
@@ -1100,19 +1170,20 @@ void tst_Gestures::multipleGesturesInComplexTree()
Qt::GestureType SixthGesture = QApplication::registerGestureRecognizer(new CustomGestureRecognizer);
Qt::GestureType SeventhGesture = QApplication::registerGestureRecognizer(new CustomGestureRecognizer);
- A->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // A [1,3,4]
- A->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // |
- A->grabGesture(FourthGesture, Qt::WidgetWithChildrenGesture); // B [2,3,5]
- B->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); // |
- B->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // C [1,2,3,6]
- B->grabGesture(FifthGesture, Qt::WidgetWithChildrenGesture); // |
- C->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // D [1,3,7]
- C->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture);
- C->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture);
- C->grabGesture(SixthGesture, Qt::WidgetWithChildrenGesture);
- D->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture);
- D->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture);
- D->grabGesture(SeventhGesture, Qt::WidgetWithChildrenGesture);
+ Qt::GestureContext context = Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint;
+ A->grabGesture(FirstGesture, context); // A [1,3,4]
+ A->grabGesture(ThirdGesture, context); // |
+ A->grabGesture(FourthGesture, context); // B [2,3,5]
+ B->grabGesture(SecondGesture, context); // |
+ B->grabGesture(ThirdGesture, context); // C [1,2,3,6]
+ B->grabGesture(FifthGesture, context); // |
+ C->grabGesture(FirstGesture, context); // D [1,3,7]
+ C->grabGesture(SecondGesture, context);
+ C->grabGesture(ThirdGesture, context);
+ C->grabGesture(SixthGesture, context);
+ D->grabGesture(FirstGesture, context);
+ D->grabGesture(ThirdGesture, context);
+ D->grabGesture(SeventhGesture, context);
// make sure all widgets ignore events, so they get propagated.
QSet<Qt::GestureType> allGestureTypes;