summaryrefslogtreecommitdiffstats
path: root/tests/auto/gestures/tst_gestures.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/gestures/tst_gestures.cpp')
-rw-r--r--tests/auto/gestures/tst_gestures.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp
index 4a9f1d1..a968520 100644
--- a/tests/auto/gestures/tst_gestures.cpp
+++ b/tests/auto/gestures/tst_gestures.cpp
@@ -49,6 +49,7 @@
#include <qgesture.h>
#include <qgesturerecognizer.h>
#include <qgraphicsitem.h>
+#include <qgraphicswidget.h>
#include <qgraphicsview.h>
#include <qmainwindow.h>
@@ -333,6 +334,7 @@ private slots:
void gestureOverChild();
void multipleWidgetOnlyGestureInTree();
void conflictingGestures();
+ void conflictingGesturesInGraphicsView();
void finishedWithoutStarted();
void unknownGesture();
void graphicsItemGesture();
@@ -358,6 +360,7 @@ private slots:
void viewportCoordinates();
void partialGesturePropagation();
void testQGestureRecognizerCleanup();
+ void testReuseCanceledGestures();
};
tst_Gestures::tst_Gestures()
@@ -2069,5 +2072,234 @@ void tst_Gestures::testQGestureRecognizerCleanup()
delete w;
}
+class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
+{
+public:
+ enum Type {
+ RmbAndCancelAllType,
+ LmbType
+ };
+
+ ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
+
+ QGesture *create(QObject *) {
+ QGesture *g = new QGesture;
+ return g;
+ }
+
+ Result recognize(QGesture *gesture, QObject *, QEvent *event) {
+ QMouseEvent *me = static_cast<QMouseEvent *>(event);
+ Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton);
+
+ switch(event->type()) {
+ case QEvent::MouseButtonPress:
+ if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) {
+ gesture->setHotSpot(QPointF(me->globalPos()));
+ if (m_type == RmbAndCancelAllType)
+ gesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
+ return QGestureRecognizer::TriggerGesture;
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
+ return QGestureRecognizer::FinishGesture;
+ default:
+ break;
+ }
+ return QGestureRecognizer::Ignore;
+ }
+private:
+ Type m_type;
+};
+
+class ReuseCanceledGesturesWidget : public QGraphicsWidget
+{
+ public:
+ ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0)
+ : QGraphicsWidget(parent),
+ m_gestureType(gestureType),
+ m_started(0), m_updated(0), m_canceled(0), m_finished(0)
+ {
+ }
+
+ bool event(QEvent *event) {
+ if (event->type() == QEvent::Gesture) {
+ QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
+ if (gesture) {
+ switch(gesture->state()) {
+ case Qt::GestureStarted: m_started++; break;
+ case Qt::GestureUpdated: m_updated++; break;
+ case Qt::GestureFinished: m_finished++; break;
+ case Qt::GestureCanceled: m_canceled++; break;
+ default: break;
+ }
+ }
+ return true;
+ }
+ if (event->type() == QEvent::GraphicsSceneMousePress) {
+ return true;
+ }
+ return QGraphicsWidget::event(event);
+ }
+
+ int started() { return m_started; }
+ int updated() { return m_updated; }
+ int finished() { return m_finished; }
+ int canceled() { return m_canceled; }
+
+ private:
+ Qt::GestureType m_gestureType;
+ int m_started;
+ int m_updated;
+ int m_canceled;
+ int m_finished;
+};
+
+void tst_Gestures::testReuseCanceledGestures()
+{
+ Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
+ new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
+ Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
+ new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
+
+ QMainWindow mw;
+ mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QGraphicsView *gv = new QGraphicsView(&mw);
+ QGraphicsScene *scene = new QGraphicsScene;
+
+ gv->setScene(scene);
+ scene->setSceneRect(0,0,100,100);
+
+ // Create container and add to the scene
+ ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
+ container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
+
+ // Create widget and add to the scene
+ ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
+ target->grabGesture(tapGestureTypeId);
+
+ container->setGeometry(scene->sceneRect());
+
+ scene->addItem(container);
+
+ mw.setCentralWidget(gv);
+
+ // Viewport needs to grab all gestures that widgets in scene grab
+ gv->viewport()->grabGesture(cancellingGestureTypeId);
+ gv->viewport()->grabGesture(tapGestureTypeId);
+
+ mw.show();
+ QTest::qWaitForWindowShown(&mw);
+
+ QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
+ targetPos = gv->viewport()->mapFromParent(targetPos);
+
+ // "Tap" starts on child widget
+ QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
+ QCOMPARE(target->started(), 1);
+ QCOMPARE(target->updated(), 0);
+ QCOMPARE(target->finished(), 0);
+ QCOMPARE(target->canceled(), 0);
+
+ // Canceling gesture starts on parent
+ QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos);
+ QCOMPARE(target->started(), 1);
+ QCOMPARE(target->updated(), 0);
+ QCOMPARE(target->finished(), 0);
+ QCOMPARE(target->canceled(), 1); // <- child canceled
+
+ // Canceling gesture ends
+ QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos);
+ QCOMPARE(target->started(), 1);
+ QCOMPARE(target->updated(), 0);
+ QCOMPARE(target->finished(), 0);
+ QCOMPARE(target->canceled(), 1);
+
+ // Tap would end if not canceled
+ QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
+ QCOMPARE(target->started(), 1);
+ QCOMPARE(target->updated(), 0);
+ QCOMPARE(target->finished(), 0);
+ QCOMPARE(target->canceled(), 1);
+
+ // New "Tap" starts
+ QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
+ QCOMPARE(target->started(), 2);
+ QCOMPARE(target->updated(), 0);
+ QCOMPARE(target->finished(), 0);
+ QCOMPARE(target->canceled(), 1);
+
+ QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
+ QCOMPARE(target->started(), 2);
+ QCOMPARE(target->updated(), 0);
+ QCOMPARE(target->finished(), 1);
+ QCOMPARE(target->canceled(), 1);
+}
+
+void tst_Gestures::conflictingGesturesInGraphicsView()
+{
+ QGraphicsScene scene;
+ GraphicsView view(&scene);
+ view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ GestureItem *item1 = new GestureItem("item1");
+ item1->grabGesture(CustomGesture::GestureType);
+ item1->size = QRectF(0, 0, 100, 100);
+ item1->setZValue(2);
+ scene.addItem(item1);
+
+ GestureItem *item2 = new GestureItem("item2");
+ item2->grabGesture(CustomGesture::GestureType);
+ item2->size = QRectF(0, 0, 100, 100);
+ item2->setZValue(5);
+ scene.addItem(item2);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.ensureVisible(scene.sceneRect());
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+
+ CustomEvent event;
+
+ // nobody accepts override
+ item1->acceptGestureOverride = false;
+ item2->acceptGestureOverride = false;
+ event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
+ event.hasHotSpot = true;
+ sendCustomGesture(&event, item2, &scene);
+ QCOMPARE(item2->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(item1->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item1->gestureEventsReceived, 0);
+
+ item1->reset(); item2->reset();
+
+ // the original target accepts override
+ item1->acceptGestureOverride = false;
+ item2->acceptGestureOverride = true;
+ event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
+ event.hasHotSpot = true;
+ sendCustomGesture(&event, item2, &scene);
+ QCOMPARE(item2->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(item1->gestureOverrideEventsReceived, 0);
+ QCOMPARE(item1->gestureEventsReceived, 0);
+
+ item1->reset(); item2->reset();
+
+ // the item behind accepts override
+ item1->acceptGestureOverride = true;
+ item2->acceptGestureOverride = false;
+ event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
+ event.hasHotSpot = true;
+ sendCustomGesture(&event, item2, &scene);
+
+ QCOMPARE(item2->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item2->gestureEventsReceived, 0);
+ QCOMPARE(item1->gestureOverrideEventsReceived, 1);
+ QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
+}
+
QTEST_MAIN(tst_Gestures)
#include "tst_gestures.moc"