1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the test suite of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
43
#include <QtTest/QtTest>
44
#include <QtTest/qtesttouch.h>
50
#include <qgesturerecognizer.h>
51
#include <qgraphicsitem.h>
52
#include <qgraphicswidget.h>
53
#include <qgraphicsview.h>
54
#include <qmainwindow.h>
55
#include <qpa/qwindowsysteminterface.h>
59
static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view)
61
return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt)));
64
class CustomGesture : public QGesture
68
static Qt::GestureType GestureType;
70
CustomGesture(QObject *parent = 0)
71
: QGesture(parent), serial(0)
77
static const int SerialMaybeThreshold;
78
static const int SerialStartedThreshold;
79
static const int SerialFinishedThreshold;
81
Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture;
82
const int CustomGesture::SerialMaybeThreshold = 1;
83
const int CustomGesture::SerialStartedThreshold = 3;
84
const int CustomGesture::SerialFinishedThreshold = 6;
86
class CustomEvent : public QEvent
91
explicit CustomEvent(int serial_ = 0)
92
: QEvent(QEvent::Type(CustomEvent::EventType)),
93
serial(serial_), hasHotSpot(false)
101
int CustomEvent::EventType = 0;
103
class CustomGestureRecognizer : public QGestureRecognizer
106
static bool ConsumeEvents;
108
CustomGestureRecognizer()
110
if (!CustomEvent::EventType)
111
CustomEvent::EventType = QEvent::registerEventType();
114
QGesture* create(QObject *)
116
return new CustomGesture;
119
QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
121
if (event->type() == CustomEvent::EventType) {
122
QGestureRecognizer::Result result = 0;
123
if (CustomGestureRecognizer::ConsumeEvents)
124
result |= QGestureRecognizer::ConsumeEventHint;
125
CustomGesture *g = static_cast<CustomGesture*>(state);
126
CustomEvent *e = static_cast<CustomEvent*>(event);
127
g->serial = e->serial;
129
g->setHotSpot(e->hotSpot);
130
if (g->serial >= CustomGesture::SerialFinishedThreshold)
131
result |= QGestureRecognizer::FinishGesture;
132
else if (g->serial >= CustomGesture::SerialStartedThreshold)
133
result |= QGestureRecognizer::TriggerGesture;
134
else if (g->serial >= CustomGesture::SerialMaybeThreshold)
135
result |= QGestureRecognizer::MayBeGesture;
137
result = QGestureRecognizer::CancelGesture;
140
return QGestureRecognizer::Ignore;
143
void reset(QGesture *state)
145
CustomGesture *g = static_cast<CustomGesture *>(state);
147
QGestureRecognizer::reset(state);
150
bool CustomGestureRecognizer::ConsumeEvents = false;
152
// same as CustomGestureRecognizer but triggers early without the maybe state
153
class CustomContinuousGestureRecognizer : public QGestureRecognizer
156
CustomContinuousGestureRecognizer()
158
if (!CustomEvent::EventType)
159
CustomEvent::EventType = QEvent::registerEventType();
162
QGesture* create(QObject *)
164
return new CustomGesture;
167
QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
169
if (event->type() == CustomEvent::EventType) {
170
QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint;
171
CustomGesture *g = static_cast<CustomGesture *>(state);
172
CustomEvent *e = static_cast<CustomEvent *>(event);
173
g->serial = e->serial;
175
g->setHotSpot(e->hotSpot);
176
if (g->serial >= CustomGesture::SerialFinishedThreshold)
177
result |= QGestureRecognizer::FinishGesture;
178
else if (g->serial >= CustomGesture::SerialMaybeThreshold)
179
result |= QGestureRecognizer::TriggerGesture;
181
result = QGestureRecognizer::CancelGesture;
184
return QGestureRecognizer::Ignore;
187
void reset(QGesture *state)
189
CustomGesture *g = static_cast<CustomGesture *>(state);
191
QGestureRecognizer::reset(state);
195
class GestureWidget : public QWidget
199
GestureWidget(const char *name = 0, QWidget *parent = 0)
203
setObjectName(QLatin1String(name));
205
acceptGestureOverride = false;
209
customEventsReceived = 0;
210
gestureEventsReceived = 0;
211
gestureOverrideEventsReceived = 0;
213
overrideEvents.clear();
214
ignoredGestures.clear();
217
int customEventsReceived;
218
int gestureEventsReceived;
219
int gestureOverrideEventsReceived;
222
QList<Qt::GestureType> all;
223
QList<Qt::GestureType> started;
224
QList<Qt::GestureType> updated;
225
QList<Qt::GestureType> finished;
226
QList<Qt::GestureType> canceled;
236
} events, overrideEvents;
238
bool acceptGestureOverride;
239
QSet<Qt::GestureType> ignoredGestures;
242
bool event(QEvent *event)
244
Events *eventsPtr = 0;
245
if (event->type() == QEvent::Gesture) {
246
QGestureEvent *e = static_cast<QGestureEvent*>(event);
247
++gestureEventsReceived;
249
foreach(Qt::GestureType type, ignoredGestures)
250
e->ignore(e->gesture(type));
251
} else if (event->type() == QEvent::GestureOverride) {
252
++gestureOverrideEventsReceived;
253
eventsPtr = &overrideEvents;
254
if (acceptGestureOverride)
258
QGestureEvent *e = static_cast<QGestureEvent*>(event);
259
QList<QGesture*> gestures = e->gestures();
260
foreach(QGesture *g, gestures) {
261
eventsPtr->all << g->gestureType();
263
case Qt::GestureStarted:
264
emit gestureStarted(e->type(), g);
265
eventsPtr->started << g->gestureType();
267
case Qt::GestureUpdated:
268
emit gestureUpdated(e->type(), g);
269
eventsPtr->updated << g->gestureType();
271
case Qt::GestureFinished:
272
emit gestureFinished(e->type(), g);
273
eventsPtr->finished << g->gestureType();
275
case Qt::GestureCanceled:
276
emit gestureCanceled(e->type(), g);
277
eventsPtr->canceled << g->gestureType();
280
qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
283
} else if (event->type() == CustomEvent::EventType) {
284
++customEventsReceived;
286
return QWidget::event(event);
292
void gestureStarted(QEvent::Type, QGesture *);
293
void gestureUpdated(QEvent::Type, QGesture *);
294
void gestureFinished(QEvent::Type, QGesture *);
295
void gestureCanceled(QEvent::Type, QGesture *);
298
void deleteThis() { delete this; }
301
// TODO rename to sendGestureSequence
302
static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0)
304
QPointer<QObject> receiver(object);
305
for (int i = CustomGesture::SerialMaybeThreshold;
306
i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) {
309
scene->sendEvent(qobject_cast<QGraphicsObject *>(object), event);
311
QApplication::sendEvent(object, event);
315
class tst_Gestures : public QObject
321
virtual ~tst_Gestures();
325
void cleanupTestCase();
330
void customGesture();
331
void autoCancelingGestures();
332
void gestureOverChild();
333
void multipleWidgetOnlyGestureInTree();
334
void conflictingGestures();
335
void conflictingGesturesInGraphicsView();
336
void finishedWithoutStarted();
337
void unknownGesture();
338
void graphicsItemGesture();
340
void graphicsItemTreeGesture();
341
void explicitGraphicsObjectTarget();
342
void gestureOverChildGraphicsItem();
343
void twoGesturesOnDifferentLevel();
344
void multipleGesturesInTree();
345
void multipleGesturesInComplexTree();
346
void testMapToScene();
347
void ungrabGesture();
348
void consumeEventHint();
349
void unregisterRecognizer();
350
void autoCancelGestures();
351
void autoCancelGestures2();
352
void graphicsViewParentPropagation();
353
void panelPropagation();
354
void panelStacksBehindParent();
355
void deleteGestureTargetWidget();
356
void deleteGestureTargetItem_data();
357
void deleteGestureTargetItem();
358
void viewportCoordinates();
359
void partialGesturePropagation();
360
void testQGestureRecognizerCleanup();
361
void testReuseCanceledGestures();
362
void bug_13501_gesture_not_accepted();
365
tst_Gestures::tst_Gestures()
369
tst_Gestures::~tst_Gestures()
373
void tst_Gestures::initTestCase()
375
CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
376
QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
377
QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
380
void tst_Gestures::cleanupTestCase()
382
QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType);
385
void tst_Gestures::init()
389
void tst_Gestures::cleanup()
393
void tst_Gestures::customGesture()
395
GestureWidget widget;
396
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
398
QVERIFY(QTest::qWaitForWindowExposed(&widget));
401
event.hotSpot = widget.mapToGlobal(QPoint(5,5));
402
event.hasHotSpot = true;
403
sendCustomGesture(&event, &widget);
405
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
406
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
407
QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount);
408
QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
409
QCOMPARE(widget.gestureOverrideEventsReceived, 0);
410
QCOMPARE(widget.events.all.size(), TotalGestureEventsCount);
411
for(int i = 0; i < widget.events.all.size(); ++i)
412
QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
413
QCOMPARE(widget.events.started.size(), 1);
414
QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
415
QCOMPARE(widget.events.finished.size(), 1);
416
QCOMPARE(widget.events.canceled.size(), 0);
419
void tst_Gestures::consumeEventHint()
421
GestureWidget widget;
422
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
424
CustomGestureRecognizer::ConsumeEvents = true;
426
sendCustomGesture(&event, &widget);
427
CustomGestureRecognizer::ConsumeEvents = false;
429
QCOMPARE(widget.customEventsReceived, 0);
432
void tst_Gestures::autoCancelingGestures()
434
GestureWidget widget;
435
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
436
// send partial gesture. The gesture will be in the "maybe" state, but will
437
// never get enough events to fire, so Qt will have to kill it.
439
for (int i = CustomGesture::SerialMaybeThreshold;
440
i < CustomGesture::SerialStartedThreshold; ++i) {
442
QApplication::sendEvent(&widget, &ev);
444
// wait long enough so the gesture manager will cancel the gesture
446
QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold);
447
QCOMPARE(widget.gestureEventsReceived, 0);
448
QCOMPARE(widget.gestureOverrideEventsReceived, 0);
449
QCOMPARE(widget.events.all.size(), 0);
452
void tst_Gestures::gestureOverChild()
454
GestureWidget widget("widget");
455
QVBoxLayout *l = new QVBoxLayout(&widget);
456
GestureWidget *child = new GestureWidget("child");
459
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
462
sendCustomGesture(&event, child);
464
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
465
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
467
QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
468
QCOMPARE(widget.customEventsReceived, 0);
469
QCOMPARE(child->gestureEventsReceived, 0);
470
QCOMPARE(child->gestureOverrideEventsReceived, 0);
471
QCOMPARE(widget.gestureEventsReceived, 0);
472
QCOMPARE(widget.gestureOverrideEventsReceived, 0);
474
// enable gestures over the children
475
widget.grabGesture(CustomGesture::GestureType);
480
sendCustomGesture(&event, child);
482
QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
483
QCOMPARE(widget.customEventsReceived, 0);
485
QCOMPARE(child->gestureEventsReceived, 0);
486
QCOMPARE(child->gestureOverrideEventsReceived, 0);
487
QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
488
QCOMPARE(widget.gestureOverrideEventsReceived, 0);
489
for(int i = 0; i < widget.events.all.size(); ++i)
490
QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
491
QCOMPARE(widget.events.started.size(), 1);
492
QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
493
QCOMPARE(widget.events.finished.size(), 1);
494
QCOMPARE(widget.events.canceled.size(), 0);
497
void tst_Gestures::multipleWidgetOnlyGestureInTree()
499
GestureWidget parent("parent");
500
QVBoxLayout *l = new QVBoxLayout(&parent);
501
GestureWidget *child = new GestureWidget("child");
504
parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
505
child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
507
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
508
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
510
// sending events to the child and making sure there is no conflict
512
sendCustomGesture(&event, child);
514
QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
515
QCOMPARE(parent.customEventsReceived, 0);
516
QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
517
QCOMPARE(child->gestureOverrideEventsReceived, 0);
518
QCOMPARE(parent.gestureEventsReceived, 0);
519
QCOMPARE(parent.gestureOverrideEventsReceived, 0);
524
// same for the parent widget
525
sendCustomGesture(&event, &parent);
527
QCOMPARE(child->customEventsReceived, 0);
528
QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount);
529
QCOMPARE(child->gestureEventsReceived, 0);
530
QCOMPARE(child->gestureOverrideEventsReceived, 0);
531
QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
532
QCOMPARE(parent.gestureOverrideEventsReceived, 0);
535
void tst_Gestures::conflictingGestures()
537
GestureWidget parent("parent");
538
QVBoxLayout *l = new QVBoxLayout(&parent);
539
GestureWidget *child = new GestureWidget("child");
542
parent.grabGesture(CustomGesture::GestureType);
543
child->grabGesture(CustomGesture::GestureType);
545
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
547
// child accepts the override, parent will not receive anything
548
parent.acceptGestureOverride = false;
549
child->acceptGestureOverride = true;
551
// sending events to the child and making sure there is no conflict
553
sendCustomGesture(&event, child);
555
QCOMPARE(child->gestureOverrideEventsReceived, 1);
556
QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
557
QCOMPARE(parent.gestureOverrideEventsReceived, 0);
558
QCOMPARE(parent.gestureEventsReceived, 0);
563
// parent accepts the override
564
parent.acceptGestureOverride = true;
565
child->acceptGestureOverride = false;
567
// sending events to the child and making sure there is no conflict
568
sendCustomGesture(&event, child);
570
QCOMPARE(child->gestureOverrideEventsReceived, 1);
571
QCOMPARE(child->gestureEventsReceived, 0);
572
QCOMPARE(parent.gestureOverrideEventsReceived, 1);
573
QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
578
// nobody accepts the override, we will send normal events to the closest
579
// context (i.e. to the child widget) and it will be propagated and
580
// accepted by the parent widget
581
parent.acceptGestureOverride = false;
582
child->acceptGestureOverride = false;
583
child->ignoredGestures << CustomGesture::GestureType;
585
// sending events to the child and making sure there is no conflict
586
sendCustomGesture(&event, child);
588
QCOMPARE(child->gestureOverrideEventsReceived, 1);
589
QCOMPARE(child->gestureEventsReceived, 1);
590
QCOMPARE(parent.gestureOverrideEventsReceived, 1);
591
QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
596
// nobody accepts the override, and nobody accepts the gesture event
597
parent.acceptGestureOverride = false;
598
child->acceptGestureOverride = false;
599
parent.ignoredGestures << CustomGesture::GestureType;
600
child->ignoredGestures << CustomGesture::GestureType;
602
// sending events to the child and making sure there is no conflict
603
sendCustomGesture(&event, child);
605
QCOMPARE(child->gestureOverrideEventsReceived, 1);
606
QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
607
QCOMPARE(parent.gestureOverrideEventsReceived, 1);
608
QCOMPARE(parent.gestureEventsReceived, 1);
613
// we set an attribute to make sure all gesture events are propagated
614
parent.grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
615
parent.acceptGestureOverride = false;
616
child->acceptGestureOverride = false;
617
parent.ignoredGestures << CustomGesture::GestureType;
618
child->ignoredGestures << CustomGesture::GestureType;
620
// sending events to the child and making sure there is no conflict
621
sendCustomGesture(&event, child);
623
QCOMPARE(child->gestureOverrideEventsReceived, 1);
624
QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
625
QCOMPARE(parent.gestureOverrideEventsReceived, 1);
626
QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
631
Qt::GestureType ContinuousGesture = QGestureRecognizer::registerRecognizer(new CustomContinuousGestureRecognizer);
632
static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
633
child->grabGesture(ContinuousGesture);
634
// child accepts override. And it also receives another custom gesture.
635
parent.acceptGestureOverride = false;
636
child->acceptGestureOverride = true;
637
sendCustomGesture(&event, child);
639
QCOMPARE(child->gestureOverrideEventsReceived, 1);
640
QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount);
641
QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount);
642
QCOMPARE(parent.gestureOverrideEventsReceived, 0);
643
QCOMPARE(parent.gestureEventsReceived, 0);
645
QGestureRecognizer::unregisterRecognizer(ContinuousGesture);
648
void tst_Gestures::finishedWithoutStarted()
650
GestureWidget widget;
651
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
653
// the gesture will claim it finished, but it was never started.
655
ev.serial = CustomGesture::SerialFinishedThreshold;
656
QApplication::sendEvent(&widget, &ev);
658
QCOMPARE(widget.customEventsReceived, 1);
659
QCOMPARE(widget.gestureEventsReceived, 2);
660
QCOMPARE(widget.gestureOverrideEventsReceived, 0);
661
QCOMPARE(widget.events.all.size(), 2);
662
QCOMPARE(widget.events.started.size(), 1);
663
QCOMPARE(widget.events.updated.size(), 0);
664
QCOMPARE(widget.events.finished.size(), 1);
665
QCOMPARE(widget.events.canceled.size(), 0);
668
void tst_Gestures::unknownGesture()
670
GestureWidget widget;
671
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
672
widget.grabGesture(Qt::CustomGesture, Qt::DontStartGestureOnChildren);
673
widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::DontStartGestureOnChildren);
676
sendCustomGesture(&event, &widget);
678
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
680
QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
683
static const QColor InstanceColors[] = {
684
Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow
687
class GestureItem : public QGraphicsObject
690
static int InstanceCount;
692
GestureItem(const char *name = 0)
694
instanceNumber = InstanceCount++;
696
setObjectName(QLatin1String(name));
699
size = QRectF(0, 0, 100, 100);
700
customEventsReceived = 0;
701
gestureEventsReceived = 0;
702
gestureOverrideEventsReceived = 0;
704
overrideEvents.clear();
705
acceptGestureOverride = false;
714
int customEventsReceived;
715
int gestureEventsReceived;
716
int gestureOverrideEventsReceived;
719
QList<Qt::GestureType> all;
720
QList<Qt::GestureType> started;
721
QList<Qt::GestureType> updated;
722
QList<Qt::GestureType> finished;
723
QList<Qt::GestureType> canceled;
733
} events, overrideEvents;
735
bool acceptGestureOverride;
736
QSet<Qt::GestureType> ignoredGestures;
737
QSet<Qt::GestureType> ignoredStartedGestures;
738
QSet<Qt::GestureType> ignoredUpdatedGestures;
739
QSet<Qt::GestureType> ignoredFinishedGestures;
746
customEventsReceived = 0;
747
gestureEventsReceived = 0;
748
gestureOverrideEventsReceived = 0;
750
overrideEvents.clear();
751
ignoredGestures.clear();
752
ignoredStartedGestures.clear();
753
ignoredUpdatedGestures.clear();
754
ignoredFinishedGestures.clear();
757
QRectF boundingRect() const
761
void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
763
QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))];
764
p->fillRect(boundingRect(), color);
767
bool event(QEvent *event)
769
Events *eventsPtr = 0;
770
if (event->type() == QEvent::Gesture) {
771
++gestureEventsReceived;
773
QGestureEvent *e = static_cast<QGestureEvent *>(event);
774
foreach(Qt::GestureType type, ignoredGestures)
775
e->ignore(e->gesture(type));
776
foreach(QGesture *g, e->gestures()) {
777
switch (g->state()) {
778
case Qt::GestureStarted:
779
if (ignoredStartedGestures.contains(g->gestureType()))
782
case Qt::GestureUpdated:
783
if (ignoredUpdatedGestures.contains(g->gestureType()))
786
case Qt::GestureFinished:
787
if (ignoredFinishedGestures.contains(g->gestureType()))
794
} else if (event->type() == QEvent::GestureOverride) {
795
++gestureOverrideEventsReceived;
796
eventsPtr = &overrideEvents;
797
if (acceptGestureOverride)
801
QGestureEvent *e = static_cast<QGestureEvent*>(event);
802
QList<QGesture*> gestures = e->gestures();
803
foreach(QGesture *g, gestures) {
804
eventsPtr->all << g->gestureType();
806
case Qt::GestureStarted:
807
eventsPtr->started << g->gestureType();
808
emit gestureStarted(e->type(), g);
810
case Qt::GestureUpdated:
811
eventsPtr->updated << g->gestureType();
812
emit gestureUpdated(e->type(), g);
814
case Qt::GestureFinished:
815
eventsPtr->finished << g->gestureType();
816
emit gestureFinished(e->type(), g);
818
case Qt::GestureCanceled:
819
eventsPtr->canceled << g->gestureType();
820
emit gestureCanceled(e->type(), g);
823
qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
826
} else if (event->type() == CustomEvent::EventType) {
827
++customEventsReceived;
829
return QGraphicsObject::event(event);
835
void gestureStarted(QEvent::Type, QGesture *);
836
void gestureUpdated(QEvent::Type, QGesture *);
837
void gestureFinished(QEvent::Type, QGesture *);
838
void gestureCanceled(QEvent::Type, QGesture *);
841
// some arguments for the slots below:
842
QGraphicsScene *scene;
845
void deleteThis() { delete this; }
846
void addSelfToScene(QEvent::Type eventType, QGesture *)
848
if (eventType == QEvent::Gesture) {
849
disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*)));
850
scene->addItem(this);
854
int GestureItem::InstanceCount = 0;
856
void tst_Gestures::graphicsItemGesture()
858
QGraphicsScene scene;
859
QGraphicsView view(&scene);
860
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
862
GestureItem *item = new GestureItem("item");
864
item->setPos(100, 100);
867
QVERIFY(QTest::qWaitForWindowExposed(&view));
868
view.ensureVisible(scene.sceneRect());
870
item->grabGesture(CustomGesture::GestureType);
872
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
873
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
876
// gesture without hotspot should not be delivered to items in the view
877
QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
878
QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
879
QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
880
QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
881
sendCustomGesture(&event, item, &scene);
883
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
884
QCOMPARE(item->gestureEventsReceived, 0);
885
QCOMPARE(item->gestureOverrideEventsReceived, 0);
889
// make sure the event is properly delivered if only the hotspot is set.
890
event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
891
event.hasHotSpot = true;
892
sendCustomGesture(&event, item, &scene);
894
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
895
QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
896
QCOMPARE(item->gestureOverrideEventsReceived, 0);
897
QCOMPARE(item->events.all.size(), TotalGestureEventsCount);
898
for(int i = 0; i < item->events.all.size(); ++i)
899
QCOMPARE(item->events.all.at(i), CustomGesture::GestureType);
900
QCOMPARE(item->events.started.size(), 1);
901
QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2);
902
QCOMPARE(item->events.finished.size(), 1);
903
QCOMPARE(item->events.canceled.size(), 0);
907
// send gesture to the item which ignores it.
908
item->ignoredGestures << CustomGesture::GestureType;
910
event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
911
event.hasHotSpot = true;
912
sendCustomGesture(&event, item, &scene);
913
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
914
QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
915
QCOMPARE(item->gestureOverrideEventsReceived, 0);
918
void tst_Gestures::graphicsView()
920
QGraphicsScene scene;
921
QGraphicsView view(&scene);
922
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
924
GestureItem *item = new GestureItem("item");
926
item->setPos(100, 100);
929
QVERIFY(QTest::qWaitForWindowExposed(&view));
930
view.ensureVisible(scene.sceneRect());
932
item->grabGesture(CustomGesture::GestureType);
934
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
935
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
938
// make sure the event is properly delivered if only the hotspot is set.
939
event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
940
event.hasHotSpot = true;
941
sendCustomGesture(&event, item, &scene);
943
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
944
QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
945
QCOMPARE(item->gestureOverrideEventsReceived, 0);
947
// change the viewport and try again
948
QWidget *newViewport = new QWidget;
949
view.setViewport(newViewport);
952
sendCustomGesture(&event, item, &scene);
954
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
955
QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
956
QCOMPARE(item->gestureOverrideEventsReceived, 0);
958
// change the scene and try again
959
QGraphicsScene newScene;
960
item = new GestureItem("newItem");
961
newScene.addItem(item);
962
item->setPos(100, 100);
963
view.setScene(&newScene);
966
// first without a gesture
967
sendCustomGesture(&event, item, &newScene);
969
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
970
QCOMPARE(item->gestureEventsReceived, 0);
971
QCOMPARE(item->gestureOverrideEventsReceived, 0);
973
// then grab the gesture and try again
975
item->grabGesture(CustomGesture::GestureType);
976
sendCustomGesture(&event, item, &newScene);
978
QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
979
QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
980
QCOMPARE(item->gestureOverrideEventsReceived, 0);
983
void tst_Gestures::graphicsItemTreeGesture()
985
QGraphicsScene scene;
986
QGraphicsView view(&scene);
987
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
989
GestureItem *item1 = new GestureItem("item1");
990
item1->setPos(100, 100);
991
item1->size = QRectF(0, 0, 350, 200);
992
scene.addItem(item1);
994
GestureItem *item1_child1 = new GestureItem("item1_child1");
995
item1_child1->setPos(50, 50);
996
item1_child1->size = QRectF(0, 0, 100, 100);
997
item1_child1->setParentItem(item1);
999
GestureItem *item1_child2 = new GestureItem("item1_child2");
1000
item1_child2->size = QRectF(0, 0, 100, 100);
1001
item1_child2->setPos(200, 50);
1002
item1_child2->setParentItem(item1);
1005
QVERIFY(QTest::qWaitForWindowExposed(&view));
1006
view.ensureVisible(scene.sceneRect());
1008
item1->grabGesture(CustomGesture::GestureType);
1010
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1013
event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view);
1014
event.hasHotSpot = true;
1016
item1->ignoredGestures << CustomGesture::GestureType;
1017
sendCustomGesture(&event, item1_child1, &scene);
1018
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1019
QCOMPARE(item1_child1->gestureEventsReceived, 0);
1020
QCOMPARE(item1_child2->gestureEventsReceived, 0);
1021
QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1022
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1023
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1025
item1->reset(); item1_child1->reset(); item1_child2->reset();
1027
item1_child1->grabGesture(CustomGesture::GestureType);
1029
item1->ignoredGestures << CustomGesture::GestureType;
1030
item1_child1->ignoredGestures << CustomGesture::GestureType;
1031
sendCustomGesture(&event, item1_child1, &scene);
1032
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1033
QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1034
QCOMPARE(item1_child2->gestureEventsReceived, 0);
1035
QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1036
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1037
QCOMPARE(item1->gestureEventsReceived, 1);
1040
void tst_Gestures::explicitGraphicsObjectTarget()
1042
QGraphicsScene scene;
1043
QGraphicsView view(&scene);
1044
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1046
GestureItem *item1 = new GestureItem("item1");
1047
scene.addItem(item1);
1048
item1->setPos(100, 100);
1049
item1->setZValue(1);
1051
GestureItem *item2 = new GestureItem("item2");
1052
scene.addItem(item2);
1053
item2->setPos(100, 100);
1054
item2->setZValue(5);
1056
GestureItem *item2_child1 = new GestureItem("item2_child1");
1057
scene.addItem(item2_child1);
1058
item2_child1->setParentItem(item2);
1059
item2_child1->setPos(10, 10);
1062
QVERIFY(QTest::qWaitForWindowExposed(&view));
1063
view.ensureVisible(scene.sceneRect());
1065
item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1066
item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1067
item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1069
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1071
// sending events to item1, but the hotSpot is set to item2
1073
event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view);
1074
event.hasHotSpot = true;
1076
sendCustomGesture(&event, item1, &scene);
1078
QCOMPARE(item1->gestureEventsReceived, 0);
1079
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1080
QCOMPARE(item2_child1->gestureEventsReceived, TotalGestureEventsCount);
1081
QCOMPARE(item2_child1->gestureOverrideEventsReceived, 1);
1082
QCOMPARE(item2_child1->events.all.size(), TotalGestureEventsCount);
1083
for(int i = 0; i < item2_child1->events.all.size(); ++i)
1084
QCOMPARE(item2_child1->events.all.at(i), CustomGesture::GestureType);
1085
QCOMPARE(item2_child1->events.started.size(), 1);
1086
QCOMPARE(item2_child1->events.updated.size(), TotalGestureEventsCount - 2);
1087
QCOMPARE(item2_child1->events.finished.size(), 1);
1088
QCOMPARE(item2_child1->events.canceled.size(), 0);
1089
QCOMPARE(item2->gestureEventsReceived, 0);
1090
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1093
void tst_Gestures::gestureOverChildGraphicsItem()
1095
QGraphicsScene scene;
1096
QGraphicsView view(&scene);
1097
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1099
GestureItem *item0 = new GestureItem("item0");
1100
scene.addItem(item0);
1101
item0->setPos(0, 0);
1102
item0->grabGesture(CustomGesture::GestureType);
1103
item0->setZValue(1);
1105
GestureItem *item1 = new GestureItem("item1");
1106
scene.addItem(item1);
1107
item1->setPos(100, 100);
1108
item1->setZValue(5);
1110
GestureItem *item2 = new GestureItem("item2");
1111
scene.addItem(item2);
1112
item2->setPos(100, 100);
1113
item2->setZValue(10);
1115
GestureItem *item2_child1 = new GestureItem("item2_child1");
1116
scene.addItem(item2_child1);
1117
item2_child1->setParentItem(item2);
1118
item2_child1->setPos(0, 0);
1121
QVERIFY(QTest::qWaitForWindowExposed(&view));
1122
view.ensureVisible(scene.sceneRect());
1124
item1->grabGesture(CustomGesture::GestureType);
1126
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1127
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1130
event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1131
event.hasHotSpot = true;
1132
sendCustomGesture(&event, item0, &scene);
1134
QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1135
QCOMPARE(item2_child1->gestureEventsReceived, 0);
1136
QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1137
QCOMPARE(item2->gestureEventsReceived, 0);
1138
QCOMPARE(item2->gestureOverrideEventsReceived, 0);
1139
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1140
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1142
item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1143
item2->grabGesture(CustomGesture::GestureType);
1144
item2->ignoredGestures << CustomGesture::GestureType;
1146
event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1147
event.hasHotSpot = true;
1148
sendCustomGesture(&event, item0, &scene);
1150
QCOMPARE(item2_child1->gestureEventsReceived, 0);
1151
QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1152
QCOMPARE(item2->gestureEventsReceived, 1);
1153
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1154
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1155
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1157
item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1158
item2->grabGesture(CustomGesture::GestureType);
1159
item2->ignoredGestures << CustomGesture::GestureType;
1160
item1->ignoredGestures << CustomGesture::GestureType;
1162
event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1163
event.hasHotSpot = true;
1164
sendCustomGesture(&event, item0, &scene);
1166
QCOMPARE(item2_child1->gestureEventsReceived, 0);
1167
QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1168
QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1169
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1170
QCOMPARE(item1->gestureEventsReceived, 1);
1171
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1173
item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1174
item2->grabGesture(CustomGesture::GestureType);
1175
item2->ignoredGestures << CustomGesture::GestureType;
1176
item1->ignoredGestures << CustomGesture::GestureType;
1177
item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1179
event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1180
event.hasHotSpot = true;
1181
sendCustomGesture(&event, item0, &scene);
1183
QCOMPARE(item2_child1->gestureEventsReceived, 0);
1184
QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1185
QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1186
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1187
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1188
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1191
void tst_Gestures::twoGesturesOnDifferentLevel()
1193
GestureWidget parent("parent");
1194
QVBoxLayout *l = new QVBoxLayout(&parent);
1195
GestureWidget *child = new GestureWidget("child");
1196
l->addWidget(child);
1198
Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1200
parent.grabGesture(CustomGesture::GestureType);
1201
child->grabGesture(SecondGesture);
1204
// sending events that form a gesture to one widget, but they will be
1205
// filtered by two different gesture recognizers and will generate two
1206
// QGesture objects. Check that those gesture objects are delivered to
1207
// different widgets properly.
1208
sendCustomGesture(&event, child);
1210
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1211
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1213
QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
1214
QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
1215
QCOMPARE(child->gestureOverrideEventsReceived, 0);
1216
QCOMPARE(child->events.all.size(), TotalGestureEventsCount);
1217
for(int i = 0; i < child->events.all.size(); ++i)
1218
QCOMPARE(child->events.all.at(i), SecondGesture);
1220
QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
1221
QCOMPARE(parent.gestureOverrideEventsReceived, 0);
1222
QCOMPARE(parent.events.all.size(), TotalGestureEventsCount);
1223
for(int i = 0; i < child->events.all.size(); ++i)
1224
QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType);
1226
QGestureRecognizer::unregisterRecognizer(SecondGesture);
1229
void tst_Gestures::multipleGesturesInTree()
1231
GestureWidget a("A");
1232
GestureWidget *A = &a;
1233
GestureWidget *B = new GestureWidget("B", A);
1234
GestureWidget *C = new GestureWidget("C", B);
1235
GestureWidget *D = new GestureWidget("D", C);
1237
Qt::GestureType FirstGesture = CustomGesture::GestureType;
1238
Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1239
Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1241
Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1242
A->grabGesture(FirstGesture, flags); // A [1 3]
1243
A->grabGesture(ThirdGesture, flags); // |
1244
B->grabGesture(SecondGesture, flags); // B [ 2 3]
1245
B->grabGesture(ThirdGesture, flags); // |
1246
C->grabGesture(FirstGesture, flags); // C [1 2 3]
1247
C->grabGesture(SecondGesture, flags); // |
1248
C->grabGesture(ThirdGesture, flags); // D [1 3]
1249
D->grabGesture(FirstGesture, flags);
1250
D->grabGesture(ThirdGesture, flags);
1252
// make sure all widgets ignore events, so they get propagated.
1253
A->ignoredGestures << FirstGesture << ThirdGesture;
1254
B->ignoredGestures << SecondGesture << ThirdGesture;
1255
C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture;
1256
D->ignoredGestures << FirstGesture << ThirdGesture;
1259
sendCustomGesture(&event, D);
1261
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1263
// gesture override events
1264
QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1265
QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1266
QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1268
QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1269
QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1270
QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1272
QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1273
QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1274
QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1276
QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1277
QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1278
QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1280
// normal gesture events
1281
QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1282
QCOMPARE(D->events.all.count(SecondGesture), 0);
1283
QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1285
QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1286
QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1287
QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1289
QCOMPARE(B->events.all.count(FirstGesture), 0);
1290
QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1291
QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1293
QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1294
QCOMPARE(A->events.all.count(SecondGesture), 0);
1295
QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1297
QGestureRecognizer::unregisterRecognizer(SecondGesture);
1298
QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1301
void tst_Gestures::multipleGesturesInComplexTree()
1303
GestureWidget a("A");
1304
GestureWidget *A = &a;
1305
GestureWidget *B = new GestureWidget("B", A);
1306
GestureWidget *C = new GestureWidget("C", B);
1307
GestureWidget *D = new GestureWidget("D", C);
1309
Qt::GestureType FirstGesture = CustomGesture::GestureType;
1310
Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1311
Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1312
Qt::GestureType FourthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1313
Qt::GestureType FifthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1314
Qt::GestureType SixthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1315
Qt::GestureType SeventhGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1317
Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1318
A->grabGesture(FirstGesture, flags); // A [1,3,4]
1319
A->grabGesture(ThirdGesture, flags); // |
1320
A->grabGesture(FourthGesture, flags); // B [2,3,5]
1321
B->grabGesture(SecondGesture, flags); // |
1322
B->grabGesture(ThirdGesture, flags); // C [1,2,3,6]
1323
B->grabGesture(FifthGesture, flags); // |
1324
C->grabGesture(FirstGesture, flags); // D [1,3,7]
1325
C->grabGesture(SecondGesture, flags);
1326
C->grabGesture(ThirdGesture, flags);
1327
C->grabGesture(SixthGesture, flags);
1328
D->grabGesture(FirstGesture, flags);
1329
D->grabGesture(ThirdGesture, flags);
1330
D->grabGesture(SeventhGesture, flags);
1332
// make sure all widgets ignore events, so they get propagated.
1333
QSet<Qt::GestureType> allGestureTypes;
1334
allGestureTypes << FirstGesture << SecondGesture << ThirdGesture
1335
<< FourthGesture << FifthGesture << SixthGesture << SeventhGesture;
1336
A->ignoredGestures = B->ignoredGestures = allGestureTypes;
1337
C->ignoredGestures = D->ignoredGestures = allGestureTypes;
1340
sendCustomGesture(&event, D);
1342
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1344
// gesture override events
1345
QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1346
QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1347
QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1349
QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1350
QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1351
QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1353
QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1354
QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1355
QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1357
QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1358
QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1359
QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1361
// normal gesture events
1362
QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1363
QCOMPARE(D->events.all.count(SecondGesture), 0);
1364
QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1365
QCOMPARE(D->events.all.count(FourthGesture), 0);
1366
QCOMPARE(D->events.all.count(FifthGesture), 0);
1367
QCOMPARE(D->events.all.count(SixthGesture), 0);
1368
QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount);
1370
QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1371
QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1372
QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1373
QCOMPARE(C->events.all.count(FourthGesture), 0);
1374
QCOMPARE(C->events.all.count(FifthGesture), 0);
1375
QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount);
1376
QCOMPARE(C->events.all.count(SeventhGesture), 0);
1378
QCOMPARE(B->events.all.count(FirstGesture), 0);
1379
QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1380
QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1381
QCOMPARE(B->events.all.count(FourthGesture), 0);
1382
QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount);
1383
QCOMPARE(B->events.all.count(SixthGesture), 0);
1384
QCOMPARE(B->events.all.count(SeventhGesture), 0);
1386
QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1387
QCOMPARE(A->events.all.count(SecondGesture), 0);
1388
QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1389
QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount);
1390
QCOMPARE(A->events.all.count(FifthGesture), 0);
1391
QCOMPARE(A->events.all.count(SixthGesture), 0);
1392
QCOMPARE(A->events.all.count(SeventhGesture), 0);
1394
QGestureRecognizer::unregisterRecognizer(SecondGesture);
1395
QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1396
QGestureRecognizer::unregisterRecognizer(FourthGesture);
1397
QGestureRecognizer::unregisterRecognizer(FifthGesture);
1398
QGestureRecognizer::unregisterRecognizer(SixthGesture);
1399
QGestureRecognizer::unregisterRecognizer(SeventhGesture);
1402
void tst_Gestures::testMapToScene()
1405
QList<QGesture*> list;
1407
QGestureEvent event(list);
1408
QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much
1410
QGraphicsScene scene;
1411
QGraphicsView view(&scene);
1412
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1414
GestureItem *item0 = new GestureItem;
1415
scene.addItem(item0);
1416
item0->setPos(14, 16);
1418
view.show(); // need to show to give it a global coordinate
1419
QVERIFY(QTest::qWaitForWindowExposed(&view));
1420
view.ensureVisible(scene.sceneRect());
1422
QPoint origin = view.mapToGlobal(QPoint());
1423
event.setWidget(view.viewport());
1425
QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200)));
1428
void tst_Gestures::ungrabGesture() // a method on QWidget
1430
class MockGestureWidget : public GestureWidget {
1432
MockGestureWidget(const char *name = 0, QWidget *parent = 0)
1433
: GestureWidget(name, parent) { }
1436
QSet<QGesture*> gestures;
1438
bool event(QEvent *event)
1440
if (event->type() == QEvent::Gesture) {
1441
QGestureEvent *gestureEvent = static_cast<QGestureEvent*>(event);
1443
foreach (QGesture *g, gestureEvent->gestures())
1446
return GestureWidget::event(event);
1450
MockGestureWidget parent("A");
1451
MockGestureWidget *a = &parent;
1452
MockGestureWidget *b = new MockGestureWidget("B", a);
1454
a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1455
b->grabGesture(CustomGesture::GestureType);
1456
b->ignoredGestures << CustomGesture::GestureType;
1459
// sending an event will cause the QGesture objects to be instantiated for the widgets
1460
sendCustomGesture(&event, b);
1462
QCOMPARE(a->gestures.count(), 1);
1463
QPointer<QGesture> customGestureA;
1464
customGestureA = *(a->gestures.begin());
1465
QVERIFY(!customGestureA.isNull());
1466
QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1468
QCOMPARE(b->gestures.count(), 1);
1469
QPointer<QGesture> customGestureB;
1470
customGestureB = *(b->gestures.begin());
1471
QVERIFY(!customGestureB.isNull());
1472
QVERIFY(customGestureA.data() == customGestureB.data());
1473
QCOMPARE(customGestureB->gestureType(), CustomGesture::GestureType);
1475
a->gestures.clear();
1476
// sending an event will cause the QGesture objects to be instantiated for the widget
1477
sendCustomGesture(&event, a);
1479
QCOMPARE(a->gestures.count(), 1);
1480
customGestureA = *(a->gestures.begin());
1481
QVERIFY(!customGestureA.isNull());
1482
QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1483
QVERIFY(customGestureA.data() != customGestureB.data());
1485
a->ungrabGesture(CustomGesture::GestureType);
1486
//We changed the deletion of Gestures to lazy during QT-4022, so we can't ensure the QGesture is deleted until now
1487
QVERIFY(!customGestureB.isNull());
1489
a->gestures.clear();
1491
// send again to 'b' and make sure a never gets it.
1492
sendCustomGesture(&event, b);
1493
//After all Gestures are processed in the QGestureManager, we can ensure the QGesture is now deleted
1494
QVERIFY(customGestureA.isNull());
1495
QCOMPARE(a->gestureEventsReceived, 0);
1496
QCOMPARE(a->gestureOverrideEventsReceived, 0);
1499
void tst_Gestures::unregisterRecognizer() // a method on QApplication
1502
The hardest usecase to get right is when we remove a recognizer while several
1503
of the gestures it created are in active state and we immediately add a new recognizer
1504
for the same type (thus replacing the old one).
1505
The expected result is that all old gestures continue till they are finished/cancelled
1506
and the new recognizer starts creating gestures immediately at registration.
1508
This implies that deleting of the recognizer happens only when there are no more gestures
1509
that it created. (since gestures might have a pointer to the recognizer)
1514
void tst_Gestures::autoCancelGestures()
1516
class MockWidget : public GestureWidget {
1518
MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { }
1520
bool event(QEvent *event)
1522
if (event->type() == QEvent::Gesture) {
1523
QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1524
if (ge->gestures().count() != 1)
1525
++badGestureEvents; // event should contain exactly one gesture
1526
ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1528
return GestureWidget::event(event);
1531
int badGestureEvents;
1534
const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1536
MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext
1537
parent.resize(300, 100);
1538
parent.setWindowFlags(Qt::X11BypassWindowManagerHint);
1539
GestureWidget *child = new GestureWidget("child", &parent);
1540
child->setGeometry(10, 10, 100, 80);
1542
parent.grabGesture(CustomGesture::GestureType);
1543
child->grabGesture(secondGesture);
1545
QVERIFY(QTest::qWaitForWindowExposed(&parent));
1548
An event is send to both the child and the parent, when the child gets it a gesture is triggered
1549
and send to the child.
1550
When the parent gets the event a new gesture is triggered and delivered to the parent. When the
1551
parent gets it he accepts it and that causes the cancel policy to activate.
1552
The cause of that is the gesture for the child is cancelled and send to the child as such.
1555
event.serial = CustomGesture::SerialStartedThreshold;
1556
QApplication::sendEvent(child, &event);
1557
QCOMPARE(child->events.all.count(), 2);
1558
QCOMPARE(child->events.started.count(), 1);
1559
QCOMPARE(child->events.canceled.count(), 1);
1560
QCOMPARE(parent.events.all.count(), 1);
1562
// clean up, make the parent gesture finish
1563
event.serial = CustomGesture::SerialFinishedThreshold;
1564
QApplication::sendEvent(child, &event);
1565
QCOMPARE(parent.events.all.count(), 2);
1566
QCOMPARE(parent.badGestureEvents, 0);
1569
void tst_Gestures::autoCancelGestures2()
1571
class MockItem : public GestureItem {
1573
MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { }
1575
bool event(QEvent *event) {
1576
if (event->type() == QEvent::Gesture) {
1577
QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1578
if (ge->gestures().count() != 1)
1579
++badGestureEvents; // event should contain exactly one gesture
1580
ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1582
return GestureItem::event(event);
1585
int badGestureEvents;
1588
const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer);
1590
QGraphicsScene scene;
1591
QGraphicsView view(&scene);
1592
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1594
MockItem *parent = new MockItem("parent");
1595
GestureItem *child = new GestureItem("child");
1596
child->setParentItem(parent);
1597
parent->setPos(0, 0);
1598
child->setPos(10, 10);
1599
scene.addItem(parent);
1600
parent->grabGesture(CustomGesture::GestureType);
1601
child->grabGesture(secondGesture);
1604
QVERIFY(QTest::qWaitForWindowExposed(&view));
1605
view.ensureVisible(scene.sceneRect());
1608
event.serial = CustomGesture::SerialStartedThreshold;
1609
event.hasHotSpot = true;
1610
event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view);
1611
scene.sendEvent(child, &event);
1612
QCOMPARE(parent->events.all.count(), 1);
1613
QCOMPARE(child->events.started.count(), 1);
1614
QCOMPARE(child->events.canceled.count(), 1);
1615
QCOMPARE(child->events.all.count(), 2);
1617
// clean up, make the parent gesture finish
1618
event.serial = CustomGesture::SerialFinishedThreshold;
1619
scene.sendEvent(child, &event);
1620
QCOMPARE(parent->events.all.count(), 2);
1621
QCOMPARE(parent->badGestureEvents, 0);
1624
void tst_Gestures::graphicsViewParentPropagation()
1626
QGraphicsScene scene;
1627
QGraphicsView view(&scene);
1628
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1630
GestureItem *item0 = new GestureItem("item0");
1631
scene.addItem(item0);
1632
item0->setPos(0, 0);
1633
item0->grabGesture(CustomGesture::GestureType);
1634
item0->setZValue(1);
1636
GestureItem *item1 = new GestureItem("item1");
1637
scene.addItem(item1);
1638
item1->setPos(0, 0);
1639
item1->setZValue(5);
1641
GestureItem *item1_c1 = new GestureItem("item1_child1");
1642
item1_c1->setParentItem(item1);
1643
item1_c1->setPos(0, 0);
1645
GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1");
1646
item1_c1_c1->setParentItem(item1_c1);
1647
item1_c1_c1->setPos(0, 0);
1650
QVERIFY(QTest::qWaitForWindowExposed(&view));
1651
view.ensureVisible(scene.sceneRect());
1653
item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1654
item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1655
item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent);
1656
item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1658
item0->ignoredUpdatedGestures << CustomGesture::GestureType;
1659
item0->ignoredFinishedGestures << CustomGesture::GestureType;
1660
item1->ignoredUpdatedGestures << CustomGesture::GestureType;
1661
item1->ignoredFinishedGestures << CustomGesture::GestureType;
1662
item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1663
item1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1664
item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1665
item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1667
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1670
event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view);
1671
event.hasHotSpot = true;
1672
sendCustomGesture(&event, item0, &scene);
1674
QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount);
1675
QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1);
1676
QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1);
1677
QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1);
1678
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1);
1679
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1680
QCOMPARE(item0->gestureEventsReceived, 0);
1681
QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1684
void tst_Gestures::panelPropagation()
1686
QGraphicsScene scene;
1687
QGraphicsView view(&scene);
1688
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1690
GestureItem *item0 = new GestureItem("item0");
1691
scene.addItem(item0);
1692
item0->setPos(0, 0);
1693
item0->size = QRectF(0, 0, 200, 200);
1694
item0->grabGesture(CustomGesture::GestureType);
1695
item0->setZValue(1);
1697
GestureItem *item1 = new GestureItem("item1");
1698
item1->grabGesture(CustomGesture::GestureType);
1699
scene.addItem(item1);
1700
item1->setPos(10, 10);
1701
item1->size = QRectF(0, 0, 180, 180);
1702
item1->setZValue(2);
1704
GestureItem *item1_child1 = new GestureItem("item1_child1[panel]");
1705
item1_child1->setFlags(QGraphicsItem::ItemIsPanel);
1706
item1_child1->setParentItem(item1);
1707
item1_child1->grabGesture(CustomGesture::GestureType);
1708
item1_child1->setPos(10, 10);
1709
item1_child1->size = QRectF(0, 0, 160, 160);
1710
item1_child1->setZValue(5);
1712
GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1");
1713
item1_child1_child1->setParentItem(item1_child1);
1714
item1_child1_child1->grabGesture(CustomGesture::GestureType);
1715
item1_child1_child1->setPos(10, 10);
1716
item1_child1_child1->size = QRectF(0, 0, 140, 140);
1717
item1_child1_child1->setZValue(10);
1720
QVERIFY(QTest::qWaitForWindowExposed(&view));
1721
view.ensureVisible(scene.sceneRect());
1723
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1724
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1727
event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view);
1728
event.hasHotSpot = true;
1729
sendCustomGesture(&event, item0, &scene);
1731
QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1732
QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount);
1733
QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1);
1734
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1735
QCOMPARE(item1->gestureEventsReceived, 0);
1736
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1737
QCOMPARE(item0->gestureEventsReceived, 0);
1738
QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1740
item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1742
event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1743
event.hasHotSpot = true;
1744
sendCustomGesture(&event, item1, &scene);
1746
QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1747
QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1748
QCOMPARE(item1_child1->gestureEventsReceived, 0);
1749
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1750
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1751
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1752
QCOMPARE(item0->gestureEventsReceived, 0);
1753
QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1755
item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1756
// try with a modal panel
1757
item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1759
event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1760
event.hasHotSpot = true;
1761
sendCustomGesture(&event, item1, &scene);
1763
QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1764
QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1765
QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1766
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1767
QCOMPARE(item1->gestureEventsReceived, 0);
1768
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1769
QCOMPARE(item0->gestureEventsReceived, 0);
1770
QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1772
item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1773
// try with a modal panel, however set the hotspot to be outside of the
1774
// panel and its parent
1775
item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1777
event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1778
event.hasHotSpot = true;
1779
sendCustomGesture(&event, item1, &scene);
1781
QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1782
QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1783
QCOMPARE(item1_child1->gestureEventsReceived, 0);
1784
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1785
QCOMPARE(item1->gestureEventsReceived, 0);
1786
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1787
QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount);
1788
QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1790
item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1791
// try with a scene modal panel
1792
item1_child1->setPanelModality(QGraphicsItem::SceneModal);
1794
event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1795
event.hasHotSpot = true;
1796
sendCustomGesture(&event, item0, &scene);
1798
QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1799
QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1800
QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1801
QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1802
QCOMPARE(item1->gestureEventsReceived, 0);
1803
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1804
QCOMPARE(item0->gestureEventsReceived, 0);
1805
QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1808
void tst_Gestures::panelStacksBehindParent()
1810
QGraphicsScene scene;
1811
QGraphicsView view(&scene);
1812
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1814
GestureItem *item1 = new GestureItem("item1");
1815
item1->grabGesture(CustomGesture::GestureType);
1816
scene.addItem(item1);
1817
item1->setPos(10, 10);
1818
item1->size = QRectF(0, 0, 180, 180);
1819
item1->setZValue(2);
1821
GestureItem *panel = new GestureItem("panel");
1822
panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent);
1823
panel->setPanelModality(QGraphicsItem::PanelModal);
1824
panel->setParentItem(item1);
1825
panel->grabGesture(CustomGesture::GestureType);
1826
panel->setPos(-10, -10);
1827
panel->size = QRectF(0, 0, 200, 200);
1828
panel->setZValue(5);
1831
QVERIFY(QTest::qWaitForWindowExposed(&view));
1832
view.ensureVisible(scene.sceneRect());
1834
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1837
event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1838
event.hasHotSpot = true;
1839
sendCustomGesture(&event, item1, &scene);
1841
QCOMPARE(item1->gestureEventsReceived, 0);
1842
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1843
QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount);
1844
QCOMPARE(panel->gestureOverrideEventsReceived, 0);
1847
void tst_Gestures::deleteGestureTargetWidget()
1851
void tst_Gestures::deleteGestureTargetItem_data()
1853
QTest::addColumn<bool>("propagateUpdateGesture");
1854
QTest::addColumn<QString>("emitter");
1855
QTest::addColumn<QString>("receiver");
1856
QTest::addColumn<QByteArray>("signalName");
1857
QTest::addColumn<QByteArray>("slotName");
1859
QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*));
1860
QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*));
1861
QByteArray deleteThis = SLOT(deleteThis());
1862
QByteArray deleteLater = SLOT(deleteLater());
1864
QTest::newRow("delete1")
1865
<< false << "item1" << "item1" << gestureUpdated << deleteThis;
1866
QTest::newRow("delete2")
1867
<< false << "item2" << "item2" << gestureUpdated << deleteThis;
1868
QTest::newRow("delete3")
1869
<< false << "item1" << "item2" << gestureUpdated << deleteThis;
1871
QTest::newRow("deleteLater1")
1872
<< false << "item1" << "item1" << gestureUpdated << deleteLater;
1873
QTest::newRow("deleteLater2")
1874
<< false << "item2" << "item2" << gestureUpdated << deleteLater;
1875
QTest::newRow("deleteLater3")
1876
<< false << "item1" << "item2" << gestureUpdated << deleteLater;
1877
QTest::newRow("deleteLater4")
1878
<< false << "item2" << "item1" << gestureUpdated << deleteLater;
1880
QTest::newRow("delete-self-and-propagate")
1881
<< true << "item2" << "item2" << gestureUpdated << deleteThis;
1882
QTest::newRow("deleteLater-self-and-propagate")
1883
<< true << "item2" << "item2" << gestureUpdated << deleteLater;
1884
QTest::newRow("propagate-to-deletedLater")
1885
<< true << "item2" << "item1" << gestureUpdated << deleteLater;
1888
void tst_Gestures::deleteGestureTargetItem()
1890
QFETCH(bool, propagateUpdateGesture);
1891
QFETCH(QString, emitter);
1892
QFETCH(QString, receiver);
1893
QFETCH(QByteArray, signalName);
1894
QFETCH(QByteArray, slotName);
1896
QGraphicsScene scene;
1897
QGraphicsView view(&scene);
1898
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1900
GestureItem *item1 = new GestureItem("item1");
1901
item1->grabGesture(CustomGesture::GestureType);
1902
item1->setZValue(2);
1903
scene.addItem(item1);
1905
GestureItem *item2 = new GestureItem("item2");
1906
item2->grabGesture(CustomGesture::GestureType);
1907
item2->setZValue(5);
1908
scene.addItem(item2);
1910
QMap<QString, GestureItem *> items;
1911
items.insert(item1->objectName(), item1);
1912
items.insert(item2->objectName(), item2);
1915
QVERIFY(QTest::qWaitForWindowExposed(&view));
1916
view.ensureVisible(scene.sceneRect());
1918
if (propagateUpdateGesture)
1919
item2->ignoredUpdatedGestures << CustomGesture::GestureType;
1920
connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName);
1922
// some debug output to see the current test data tag, so if we crash
1923
// we know which one caused the crash.
1924
qDebug() << "<-- testing";
1927
event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view);
1928
event.hasHotSpot = true;
1929
sendCustomGesture(&event, item1, &scene);
1932
class GraphicsView : public QGraphicsView
1935
GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
1936
: QGraphicsView(scene, parent)
1940
using QGraphicsView::setViewportMargins;
1943
// just making sure that even if the graphicsview has margins hotspot still
1944
// works properly. It should use viewport for converting global coordinates to
1945
// scene coordinates.
1946
void tst_Gestures::viewportCoordinates()
1948
QGraphicsScene scene;
1949
GraphicsView view(&scene);
1950
view.setViewportMargins(10,20,15,25);
1951
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1953
GestureItem *item1 = new GestureItem("item1");
1954
item1->grabGesture(CustomGesture::GestureType);
1955
item1->size = QRectF(0, 0, 3, 3);
1956
item1->setZValue(2);
1957
scene.addItem(item1);
1960
QVERIFY(QTest::qWaitForWindowExposed(&view));
1961
view.ensureVisible(scene.sceneRect());
1964
event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view);
1965
event.hasHotSpot = true;
1966
sendCustomGesture(&event, item1, &scene);
1967
QVERIFY(item1->gestureEventsReceived != 0);
1970
void tst_Gestures::partialGesturePropagation()
1972
QGraphicsScene scene;
1973
QGraphicsView view(&scene);
1974
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1976
GestureItem *item1 = new GestureItem("item1");
1977
item1->grabGesture(CustomGesture::GestureType);
1978
item1->setZValue(8);
1979
scene.addItem(item1);
1981
GestureItem *item2 = new GestureItem("item2[partial]");
1982
item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1983
item2->setZValue(6);
1984
scene.addItem(item2);
1986
GestureItem *item3 = new GestureItem("item3");
1987
item3->grabGesture(CustomGesture::GestureType);
1988
item3->setZValue(4);
1989
scene.addItem(item3);
1991
GestureItem *item4 = new GestureItem("item4[partial]");
1992
item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1993
item4->setZValue(2);
1994
scene.addItem(item4);
1997
QVERIFY(QTest::qWaitForWindowExposed(&view));
1998
view.ensureVisible(scene.sceneRect());
2000
item1->ignoredUpdatedGestures << CustomGesture::GestureType;
2003
event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
2004
event.hasHotSpot = true;
2005
sendCustomGesture(&event, item1, &scene);
2007
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2009
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2010
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2011
QCOMPARE(item3->gestureOverrideEventsReceived, 1);
2012
QCOMPARE(item4->gestureOverrideEventsReceived, 1);
2014
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2015
QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished
2016
QCOMPARE(item3->gestureEventsReceived, 0);
2017
QCOMPARE(item4->gestureEventsReceived, 0);
2020
class WinNativePan : public QPanGesture {
2025
class Pan : public QPanGesture {
2030
class CustomPan : public QPanGesture {
2035
// Recognizer for active gesture triggers on mouse press
2036
class PanRecognizer : public QGestureRecognizer {
2038
enum PanType { Platform, Default, Custom };
2040
PanRecognizer(int id) : m_id(id) {}
2041
QGesture *create(QObject *) {
2043
case Platform: return new WinNativePan();
2044
case Default: return new Pan();
2045
default: return new CustomPan();
2049
Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; }
2054
void tst_Gestures::testQGestureRecognizerCleanup()
2056
// Clean first the current recognizers in QGManager
2057
QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2059
// v-- Qt singleton QGManager initialization
2061
// Mimic QGestureManager: register both default and "platform" recognizers
2062
// (this is done in windows when QT_NO_NATIVE_GESTURES is not defined)
2063
PanRecognizer *def = new PanRecognizer(PanRecognizer::Default);
2064
QGestureRecognizer::registerRecognizer(def);
2065
PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform);
2066
QGestureRecognizer::registerRecognizer(plt);
2067
qDebug () << "register: default =" << def << "; platform =" << plt;
2069
// ^-- Qt singleton QGManager initialization
2071
// Here, application code would start
2073
// Create QGV (has a QAScrollArea, which uses Qt::PanGesture)
2074
QMainWindow *w = new QMainWindow;
2075
QGraphicsView *v = new QGraphicsView();
2076
w->setCentralWidget(v);
2078
// Unregister Qt recognizers
2079
QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2081
// Register a custom Pan recognizer
2082
//QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom));
2085
QVERIFY(QTest::qWaitForWindowExposed(w));
2089
class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
2093
RmbAndCancelAllType,
2097
ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
2099
QGesture *create(QObject *) {
2100
QGesture *g = new QGesture;
2104
Result recognize(QGesture *gesture, QObject *, QEvent *event) {
2105
QMouseEvent *me = static_cast<QMouseEvent *>(event);
2106
Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton);
2108
switch(event->type()) {
2109
case QEvent::MouseButtonPress:
2110
if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) {
2111
gesture->setHotSpot(QPointF(me->globalPos()));
2112
if (m_type == RmbAndCancelAllType)
2113
gesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
2114
return QGestureRecognizer::TriggerGesture;
2117
case QEvent::MouseButtonRelease:
2118
if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
2119
return QGestureRecognizer::FinishGesture;
2123
return QGestureRecognizer::Ignore;
2129
class ReuseCanceledGesturesWidget : public QGraphicsWidget
2132
ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0)
2133
: QGraphicsWidget(parent),
2134
m_gestureType(gestureType),
2135
m_started(0), m_updated(0), m_canceled(0), m_finished(0)
2139
bool event(QEvent *event) {
2140
if (event->type() == QEvent::Gesture) {
2141
QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
2143
switch(gesture->state()) {
2144
case Qt::GestureStarted: m_started++; break;
2145
case Qt::GestureUpdated: m_updated++; break;
2146
case Qt::GestureFinished: m_finished++; break;
2147
case Qt::GestureCanceled: m_canceled++; break;
2153
if (event->type() == QEvent::GraphicsSceneMousePress) {
2156
return QGraphicsWidget::event(event);
2159
int started() { return m_started; }
2160
int updated() { return m_updated; }
2161
int finished() { return m_finished; }
2162
int canceled() { return m_canceled; }
2165
Qt::GestureType m_gestureType;
2172
void tst_Gestures::testReuseCanceledGestures()
2174
Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
2175
new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
2176
Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
2177
new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
2180
mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
2181
QGraphicsView *gv = new QGraphicsView(&mw);
2182
QGraphicsScene *scene = new QGraphicsScene;
2184
gv->setScene(scene);
2185
scene->setSceneRect(0,0,100,100);
2187
// Create container and add to the scene
2188
ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
2189
container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
2191
// Create widget and add to the scene
2192
ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
2193
target->grabGesture(tapGestureTypeId);
2195
container->setGeometry(scene->sceneRect());
2197
scene->addItem(container);
2199
mw.setCentralWidget(gv);
2201
// Viewport needs to grab all gestures that widgets in scene grab
2202
gv->viewport()->grabGesture(cancellingGestureTypeId);
2203
gv->viewport()->grabGesture(tapGestureTypeId);
2206
QVERIFY(QTest::qWaitForWindowExposed(&mw));
2208
QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
2209
targetPos = gv->viewport()->mapFromParent(targetPos);
2211
// "Tap" starts on child widget
2212
QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2213
QCOMPARE(target->started(), 1);
2214
QCOMPARE(target->updated(), 0);
2215
QCOMPARE(target->finished(), 0);
2216
QCOMPARE(target->canceled(), 0);
2218
// Canceling gesture starts on parent
2219
QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos);
2220
QCOMPARE(target->started(), 1);
2221
QCOMPARE(target->updated(), 0);
2222
QCOMPARE(target->finished(), 0);
2223
QCOMPARE(target->canceled(), 1); // <- child canceled
2225
// Canceling gesture ends
2226
QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos);
2227
QCOMPARE(target->started(), 1);
2228
QCOMPARE(target->updated(), 0);
2229
QCOMPARE(target->finished(), 0);
2230
QCOMPARE(target->canceled(), 1);
2232
// Tap would end if not canceled
2233
QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2234
QCOMPARE(target->started(), 1);
2235
QCOMPARE(target->updated(), 0);
2236
QCOMPARE(target->finished(), 0);
2237
QCOMPARE(target->canceled(), 1);
2240
QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2241
QCOMPARE(target->started(), 2);
2242
QCOMPARE(target->updated(), 0);
2243
QCOMPARE(target->finished(), 0);
2244
QCOMPARE(target->canceled(), 1);
2246
QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2247
QCOMPARE(target->started(), 2);
2248
QCOMPARE(target->updated(), 0);
2249
QCOMPARE(target->finished(), 1);
2250
QCOMPARE(target->canceled(), 1);
2253
void tst_Gestures::conflictingGesturesInGraphicsView()
2255
QGraphicsScene scene;
2256
GraphicsView view(&scene);
2257
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
2259
GestureItem *item1 = new GestureItem("item1");
2260
item1->grabGesture(CustomGesture::GestureType);
2261
item1->size = QRectF(0, 0, 100, 100);
2262
item1->setZValue(2);
2263
scene.addItem(item1);
2265
GestureItem *item2 = new GestureItem("item2");
2266
item2->grabGesture(CustomGesture::GestureType);
2267
item2->size = QRectF(0, 0, 100, 100);
2268
item2->setZValue(5);
2269
scene.addItem(item2);
2272
QVERIFY(QTest::qWaitForWindowExposed(&view));
2273
view.ensureVisible(scene.sceneRect());
2275
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2279
// nobody accepts override
2280
item1->acceptGestureOverride = false;
2281
item2->acceptGestureOverride = false;
2282
event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2283
event.hasHotSpot = true;
2284
sendCustomGesture(&event, item2, &scene);
2285
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2286
QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2287
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2288
QCOMPARE(item1->gestureEventsReceived, 0);
2290
item1->reset(); item2->reset();
2292
// the original target accepts override
2293
item1->acceptGestureOverride = false;
2294
item2->acceptGestureOverride = true;
2295
event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2296
event.hasHotSpot = true;
2297
sendCustomGesture(&event, item2, &scene);
2298
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2299
QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2300
QCOMPARE(item1->gestureOverrideEventsReceived, 0);
2301
QCOMPARE(item1->gestureEventsReceived, 0);
2303
item1->reset(); item2->reset();
2305
// the item behind accepts override
2306
item1->acceptGestureOverride = true;
2307
item2->acceptGestureOverride = false;
2308
event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2309
event.hasHotSpot = true;
2310
sendCustomGesture(&event, item2, &scene);
2312
QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2313
QCOMPARE(item2->gestureEventsReceived, 0);
2314
QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2315
QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2318
class NoConsumeWidgetBug13501 :public QWidget
2322
bool event(QEvent *e) {
2323
if(e->type() == QEvent::Gesture) {
2326
return QWidget::event(e);
2330
void tst_Gestures::bug_13501_gesture_not_accepted()
2332
// Create a gesture event that is not accepted by any widget
2333
// make sure this does not lead to an assert in QGestureManager
2334
NoConsumeWidgetBug13501 w;
2335
w.grabGesture(Qt::TapGesture);
2337
QVERIFY(QTest::qWaitForWindowExposed(&w));
2338
//QTest::mousePress(&ignoreEvent, Qt::LeftButton);
2339
QTouchDevice *device = new QTouchDevice;
2340
device->setType(QTouchDevice::TouchScreen);
2341
QWindowSystemInterface::registerTouchDevice(device);
2342
QTest::touchEvent(&w, device).press(0, QPoint(10, 10), &w);
2345
QTEST_MAIN(tst_Gestures)
2346
#include "tst_gestures.moc"