1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
43
#include <QtTest/QtTest>
44
#include <QtTest/qtesttouch.h>
45
#include "../../shared/util.h"
46
47
#include <qevent.h>
48
#include <qwidget.h>
49
#include <qlayout.h>
50
#include <qgesture.h>
51
#include <qgesturerecognizer.h>
52
#include <qgraphicsitem.h>
53
#include <qgraphicswidget.h>
54
#include <qgraphicsview.h>
55
#include <qmainwindow.h>
56
57
#include <qdebug.h>
58
59
//TESTED_CLASS=
60
//TESTED_FILES=
61
62
static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view)
63
{
64
    return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt)));
65
}
66
67
class CustomGesture : public QGesture
68
{
69
    Q_OBJECT
70
public:
71
    static Qt::GestureType GestureType;
72
73
    CustomGesture(QObject *parent = 0)
74
        : QGesture(parent), serial(0)
75
    {
76
    }
77
78
    int serial;
79
80
    static const int SerialMaybeThreshold;
81
    static const int SerialStartedThreshold;
82
    static const int SerialFinishedThreshold;
83
};
84
Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture;
85
const int CustomGesture::SerialMaybeThreshold = 1;
86
const int CustomGesture::SerialStartedThreshold = 3;
87
const int CustomGesture::SerialFinishedThreshold = 6;
88
89
class CustomEvent : public QEvent
90
{
91
public:
92
    static int EventType;
93
94
    CustomEvent(int serial_ = 0)
95
        : QEvent(QEvent::Type(CustomEvent::EventType)),
96
          serial(serial_), hasHotSpot(false)
97
    {
98
    }
99
100
    int serial;
101
    QPointF hotSpot;
102
    bool hasHotSpot;
103
};
104
int CustomEvent::EventType = 0;
105
106
class CustomGestureRecognizer : public QGestureRecognizer
107
{
108
public:
109
    static bool ConsumeEvents;
110
111
    CustomGestureRecognizer()
112
    {
113
        if (!CustomEvent::EventType)
114
            CustomEvent::EventType = QEvent::registerEventType();
115
    }
116
117
    QGesture* create(QObject *)
118
    {
119
        return new CustomGesture;
120
    }
121
122
    QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
123
    {
124
        if (event->type() == CustomEvent::EventType) {
125
            QGestureRecognizer::Result result = 0;
126
            if (CustomGestureRecognizer::ConsumeEvents)
127
                result |= QGestureRecognizer::ConsumeEventHint;
128
            CustomGesture *g = static_cast<CustomGesture*>(state);
129
            CustomEvent *e = static_cast<CustomEvent*>(event);
130
            g->serial = e->serial;
131
            if (e->hasHotSpot)
132
                g->setHotSpot(e->hotSpot);
133
            if (g->serial >= CustomGesture::SerialFinishedThreshold)
134
                result |= QGestureRecognizer::FinishGesture;
135
            else if (g->serial >= CustomGesture::SerialStartedThreshold)
136
                result |= QGestureRecognizer::TriggerGesture;
137
            else if (g->serial >= CustomGesture::SerialMaybeThreshold)
138
                result |= QGestureRecognizer::MayBeGesture;
139
            else
140
                result = QGestureRecognizer::CancelGesture;
141
            return result;
142
        }
143
        return QGestureRecognizer::Ignore;
144
    }
145
146
    void reset(QGesture *state)
147
    {
148
        CustomGesture *g = static_cast<CustomGesture *>(state);
149
        g->serial = 0;
150
        QGestureRecognizer::reset(state);
151
    }
152
};
153
bool CustomGestureRecognizer::ConsumeEvents = false;
154
155
// same as CustomGestureRecognizer but triggers early without the maybe state
156
class CustomContinuousGestureRecognizer : public QGestureRecognizer
157
{
158
public:
159
    CustomContinuousGestureRecognizer()
160
    {
161
        if (!CustomEvent::EventType)
162
            CustomEvent::EventType = QEvent::registerEventType();
163
    }
164
165
    QGesture* create(QObject *)
166
    {
167
        return new CustomGesture;
168
    }
169
170
    QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
171
    {
172
        if (event->type() == CustomEvent::EventType) {
173
            QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint;
174
            CustomGesture *g = static_cast<CustomGesture *>(state);
175
            CustomEvent *e = static_cast<CustomEvent *>(event);
176
            g->serial = e->serial;
177
            if (e->hasHotSpot)
178
                g->setHotSpot(e->hotSpot);
179
            if (g->serial >= CustomGesture::SerialFinishedThreshold)
180
                result |= QGestureRecognizer::FinishGesture;
181
            else if (g->serial >= CustomGesture::SerialMaybeThreshold)
182
                result |= QGestureRecognizer::TriggerGesture;
183
            else
184
                result = QGestureRecognizer::CancelGesture;
185
            return result;
186
        }
187
        return QGestureRecognizer::Ignore;
188
    }
189
190
    void reset(QGesture *state)
191
    {
192
        CustomGesture *g = static_cast<CustomGesture *>(state);
193
        g->serial = 0;
194
        QGestureRecognizer::reset(state);
195
    }
196
};
197
198
class GestureWidget : public QWidget
199
{
200
    Q_OBJECT
201
public:
202
    GestureWidget(const char *name = 0, QWidget *parent = 0)
203
        : QWidget(parent)
204
    {
205
        if (name)
206
            setObjectName(QLatin1String(name));
207
        reset();
208
        acceptGestureOverride = false;
209
    }
210
    void reset()
211
    {
212
        customEventsReceived = 0;
213
        gestureEventsReceived = 0;
214
        gestureOverrideEventsReceived = 0;
215
        events.clear();
216
        overrideEvents.clear();
217
        ignoredGestures.clear();
218
    }
219
220
    int customEventsReceived;
221
    int gestureEventsReceived;
222
    int gestureOverrideEventsReceived;
223
    struct Events
224
    {
225
        QList<Qt::GestureType> all;
226
        QList<Qt::GestureType> started;
227
        QList<Qt::GestureType> updated;
228
        QList<Qt::GestureType> finished;
229
        QList<Qt::GestureType> canceled;
230
231
        void clear()
232
        {
233
            all.clear();
234
            started.clear();
235
            updated.clear();
236
            finished.clear();
237
            canceled.clear();
238
        }
239
    } events, overrideEvents;
240
241
    bool acceptGestureOverride;
242
    QSet<Qt::GestureType> ignoredGestures;
243
244
protected:
245
    bool event(QEvent *event)
246
    {
247
        Events *eventsPtr = 0;
248
        if (event->type() == QEvent::Gesture) {
249
            QGestureEvent *e = static_cast<QGestureEvent*>(event);
250
            ++gestureEventsReceived;
251
            eventsPtr = &events;
252
            foreach(Qt::GestureType type, ignoredGestures)
253
                e->ignore(e->gesture(type));
254
        } else if (event->type() == QEvent::GestureOverride) {
255
            ++gestureOverrideEventsReceived;
256
            eventsPtr = &overrideEvents;
257
            if (acceptGestureOverride)
258
                event->accept();
259
        }
260
        if (eventsPtr) {
261
            QGestureEvent *e = static_cast<QGestureEvent*>(event);
262
            QList<QGesture*> gestures = e->gestures();
263
            foreach(QGesture *g, gestures) {
264
                eventsPtr->all << g->gestureType();
265
                switch(g->state()) {
266
                case Qt::GestureStarted:
267
                    emit gestureStarted(e->type(), g);
268
                    eventsPtr->started << g->gestureType();
269
                    break;
270
                case Qt::GestureUpdated:
271
                    emit gestureUpdated(e->type(), g);
272
                    eventsPtr->updated << g->gestureType();
273
                    break;
274
                case Qt::GestureFinished:
275
                    emit gestureFinished(e->type(), g);
276
                    eventsPtr->finished << g->gestureType();
277
                    break;
278
                case Qt::GestureCanceled:
279
                    emit gestureCanceled(e->type(), g);
280
                    eventsPtr->canceled << g->gestureType();
281
                    break;
282
                default:
283
                    qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
284
                }
285
            }
286
        } else if (event->type() == CustomEvent::EventType) {
287
            ++customEventsReceived;
288
        } else {
289
            return QWidget::event(event);
290
        }
291
        return true;
292
    }
293
294
Q_SIGNALS:
295
    void gestureStarted(QEvent::Type, QGesture *);
296
    void gestureUpdated(QEvent::Type, QGesture *);
297
    void gestureFinished(QEvent::Type, QGesture *);
298
    void gestureCanceled(QEvent::Type, QGesture *);
299
300
public Q_SLOTS:
301
    void deleteThis() { delete this; }
302
};
303
304
// TODO rename to sendGestureSequence
305
static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0)
306
{
307
    QWeakPointer<QObject> receiver(object);
308
    for (int i = CustomGesture::SerialMaybeThreshold;
309
         i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) {
310
        event->serial = i;
311
        if (scene)
312
            scene->sendEvent(qobject_cast<QGraphicsObject *>(object), event);
313
        else
314
            QApplication::sendEvent(object, event);
315
    }
316
}
317
318
class tst_Gestures : public QObject
319
{
320
Q_OBJECT
321
322
public:
323
    tst_Gestures();
324
    virtual ~tst_Gestures();
325
326
public slots:
327
    void initTestCase();
328
    void cleanupTestCase();
329
    void init();
330
    void cleanup();
331
332
private slots:
333
    void customGesture();
334
    void autoCancelingGestures();
335
    void gestureOverChild();
336
    void multipleWidgetOnlyGestureInTree();
337
    void conflictingGestures();
338
    void conflictingGesturesInGraphicsView();
339
    void finishedWithoutStarted();
340
    void unknownGesture();
341
    void graphicsItemGesture();
342
    void graphicsView();
343
    void graphicsItemTreeGesture();
344
    void explicitGraphicsObjectTarget();
345
    void gestureOverChildGraphicsItem();
346
    void twoGesturesOnDifferentLevel();
347
    void multipleGesturesInTree();
348
    void multipleGesturesInComplexTree();
349
    void testMapToScene();
350
    void ungrabGesture();
351
    void consumeEventHint();
352
    void unregisterRecognizer();
353
    void autoCancelGestures();
354
    void autoCancelGestures2();
355
    void graphicsViewParentPropagation();
356
    void panelPropagation();
357
    void panelStacksBehindParent();
358
    void deleteGestureTargetWidget();
359
    void deleteGestureTargetItem_data();
360
    void deleteGestureTargetItem();
361
    void viewportCoordinates();
362
    void partialGesturePropagation();
363
    void testQGestureRecognizerCleanup();
364
    void testReuseCanceledGestures();
365
    void bug_13501_gesture_not_accepted();
366
};
367
368
tst_Gestures::tst_Gestures()
369
{
370
}
371
372
tst_Gestures::~tst_Gestures()
373
{
374
}
375
376
void tst_Gestures::initTestCase()
377
{
378
    CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
379
    QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
380
    QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
381
}
382
383
void tst_Gestures::cleanupTestCase()
384
{
385
    QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType);
386
}
387
388
void tst_Gestures::init()
389
{
390
}
391
392
void tst_Gestures::cleanup()
393
{
394
}
395
396
void tst_Gestures::customGesture()
397
{
398
    GestureWidget widget;
399
    widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
400
    widget.show();
401
    QTest::qWaitForWindowShown(&widget);
402
403
    CustomEvent event;
404
    event.hotSpot = widget.mapToGlobal(QPoint(5,5));
405
    event.hasHotSpot = true;
406
    sendCustomGesture(&event, &widget);
407
408
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
409
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
410
    QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount);
411
    QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
412
    QCOMPARE(widget.gestureOverrideEventsReceived, 0);
413
    QCOMPARE(widget.events.all.size(), TotalGestureEventsCount);
414
    for(int i = 0; i < widget.events.all.size(); ++i)
415
        QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
416
    QCOMPARE(widget.events.started.size(), 1);
417
    QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
418
    QCOMPARE(widget.events.finished.size(), 1);
419
    QCOMPARE(widget.events.canceled.size(), 0);
420
}
421
422
void tst_Gestures::consumeEventHint()
423
{
424
    GestureWidget widget;
425
    widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
426
427
    CustomGestureRecognizer::ConsumeEvents = true;
428
    CustomEvent event;
429
    sendCustomGesture(&event, &widget);
430
    CustomGestureRecognizer::ConsumeEvents = false;
431
432
    QCOMPARE(widget.customEventsReceived, 0);
433
}
434
435
void tst_Gestures::autoCancelingGestures()
436
{
437
    GestureWidget widget;
438
    widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
439
    // send partial gesture. The gesture will be in the "maybe" state, but will
440
    // never get enough events to fire, so Qt will have to kill it.
441
    CustomEvent ev;
442
    for (int i = CustomGesture::SerialMaybeThreshold;
443
         i < CustomGesture::SerialStartedThreshold; ++i) {
444
        ev.serial = i;
445
        QApplication::sendEvent(&widget, &ev);
446
    }
447
    // wait long enough so the gesture manager will cancel the gesture
448
    QTest::qWait(5000);
449
    QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold);
450
    QCOMPARE(widget.gestureEventsReceived, 0);
451
    QCOMPARE(widget.gestureOverrideEventsReceived, 0);
452
    QCOMPARE(widget.events.all.size(), 0);
453
}
454
455
void tst_Gestures::gestureOverChild()
456
{
457
    GestureWidget widget("widget");
458
    QVBoxLayout *l = new QVBoxLayout(&widget);
459
    GestureWidget *child = new GestureWidget("child");
460
    l->addWidget(child);
461
462
    widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
463
464
    CustomEvent event;
465
    sendCustomGesture(&event, child);
466
467
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
468
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
469
470
    QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
471
    QCOMPARE(widget.customEventsReceived, 0);
472
    QCOMPARE(child->gestureEventsReceived, 0);
473
    QCOMPARE(child->gestureOverrideEventsReceived, 0);
474
    QCOMPARE(widget.gestureEventsReceived, 0);
475
    QCOMPARE(widget.gestureOverrideEventsReceived, 0);
476
477
    // enable gestures over the children
478
    widget.grabGesture(CustomGesture::GestureType);
479
480
    widget.reset();
481
    child->reset();
482
483
    sendCustomGesture(&event, child);
484
485
    QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
486
    QCOMPARE(widget.customEventsReceived, 0);
487
488
    QCOMPARE(child->gestureEventsReceived, 0);
489
    QCOMPARE(child->gestureOverrideEventsReceived, 0);
490
    QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
491
    QCOMPARE(widget.gestureOverrideEventsReceived, 0);
492
    for(int i = 0; i < widget.events.all.size(); ++i)
493
        QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
494
    QCOMPARE(widget.events.started.size(), 1);
495
    QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
496
    QCOMPARE(widget.events.finished.size(), 1);
497
    QCOMPARE(widget.events.canceled.size(), 0);
498
}
499
500
void tst_Gestures::multipleWidgetOnlyGestureInTree()
501
{
502
    GestureWidget parent("parent");
503
    QVBoxLayout *l = new QVBoxLayout(&parent);
504
    GestureWidget *child = new GestureWidget("child");
505
    l->addWidget(child);
506
507
    parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
508
    child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
509
510
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
511
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
512
513
    // sending events to the child and making sure there is no conflict
514
    CustomEvent event;
515
    sendCustomGesture(&event, child);
516
517
    QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
518
    QCOMPARE(parent.customEventsReceived, 0);
519
    QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
520
    QCOMPARE(child->gestureOverrideEventsReceived, 0);
521
    QCOMPARE(parent.gestureEventsReceived, 0);
522
    QCOMPARE(parent.gestureOverrideEventsReceived, 0);
523
524
    parent.reset();
525
    child->reset();
526
527
    // same for the parent widget
528
    sendCustomGesture(&event, &parent);
529
530
    QCOMPARE(child->customEventsReceived, 0);
531
    QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount);
532
    QCOMPARE(child->gestureEventsReceived, 0);
533
    QCOMPARE(child->gestureOverrideEventsReceived, 0);
534
    QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
535
    QCOMPARE(parent.gestureOverrideEventsReceived, 0);
536
}
537
538
void tst_Gestures::conflictingGestures()
539
{
540
    GestureWidget parent("parent");
541
    QVBoxLayout *l = new QVBoxLayout(&parent);
542
    GestureWidget *child = new GestureWidget("child");
543
    l->addWidget(child);
544
545
    parent.grabGesture(CustomGesture::GestureType);
546
    child->grabGesture(CustomGesture::GestureType);
547
548
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
549
550
    // child accepts the override, parent will not receive anything
551
    parent.acceptGestureOverride = false;
552
    child->acceptGestureOverride = true;
553
554
    // sending events to the child and making sure there is no conflict
555
    CustomEvent event;
556
    sendCustomGesture(&event, child);
557
558
    QCOMPARE(child->gestureOverrideEventsReceived, 1);
559
    QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
560
    QCOMPARE(parent.gestureOverrideEventsReceived, 0);
561
    QCOMPARE(parent.gestureEventsReceived, 0);
562
563
    parent.reset();
564
    child->reset();
565
566
    // parent accepts the override
567
    parent.acceptGestureOverride = true;
568
    child->acceptGestureOverride = false;
569
570
    // sending events to the child and making sure there is no conflict
571
    sendCustomGesture(&event, child);
572
573
    QCOMPARE(child->gestureOverrideEventsReceived, 1);
574
    QCOMPARE(child->gestureEventsReceived, 0);
575
    QCOMPARE(parent.gestureOverrideEventsReceived, 1);
576
    QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
577
578
    parent.reset();
579
    child->reset();
580
581
    // nobody accepts the override, we will send normal events to the closest
582
    // context (i.e. to the child widget) and it will be propagated and
583
    // accepted by the parent widget
584
    parent.acceptGestureOverride = false;
585
    child->acceptGestureOverride = false;
586
    child->ignoredGestures << CustomGesture::GestureType;
587
588
    // sending events to the child and making sure there is no conflict
589
    sendCustomGesture(&event, child);
590
591
    QCOMPARE(child->gestureOverrideEventsReceived, 1);
592
    QCOMPARE(child->gestureEventsReceived, 1);
593
    QCOMPARE(parent.gestureOverrideEventsReceived, 1);
594
    QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
595
596
    parent.reset();
597
    child->reset();
598
599
    // nobody accepts the override, and nobody accepts the gesture event
600
    parent.acceptGestureOverride = false;
601
    child->acceptGestureOverride = false;
602
    parent.ignoredGestures << CustomGesture::GestureType;
603
    child->ignoredGestures << CustomGesture::GestureType;
604
605
    // sending events to the child and making sure there is no conflict
606
    sendCustomGesture(&event, child);
607
608
    QCOMPARE(child->gestureOverrideEventsReceived, 1);
609
    QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
610
    QCOMPARE(parent.gestureOverrideEventsReceived, 1);
611
    QCOMPARE(parent.gestureEventsReceived, 1);
612
613
    parent.reset();
614
    child->reset();
615
616
    // we set an attribute to make sure all gesture events are propagated
617
    parent.grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
618
    parent.acceptGestureOverride = false;
619
    child->acceptGestureOverride = false;
620
    parent.ignoredGestures << CustomGesture::GestureType;
621
    child->ignoredGestures << CustomGesture::GestureType;
622
623
    // sending events to the child and making sure there is no conflict
624
    sendCustomGesture(&event, child);
625
626
    QCOMPARE(child->gestureOverrideEventsReceived, 1);
627
    QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
628
    QCOMPARE(parent.gestureOverrideEventsReceived, 1);
629
    QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
630
631
    parent.reset();
632
    child->reset();
633
634
    Qt::GestureType ContinuousGesture = QGestureRecognizer::registerRecognizer(new CustomContinuousGestureRecognizer);
635
    static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
636
    child->grabGesture(ContinuousGesture);
637
    // child accepts override. And it also receives another custom gesture.
638
    parent.acceptGestureOverride = false;
639
    child->acceptGestureOverride = true;
640
    sendCustomGesture(&event, child);
641
642
    QCOMPARE(child->gestureOverrideEventsReceived, 1);
643
    QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount);
644
    QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount);
645
    QCOMPARE(parent.gestureOverrideEventsReceived, 0);
646
    QCOMPARE(parent.gestureEventsReceived, 0);
647
648
    QGestureRecognizer::unregisterRecognizer(ContinuousGesture);
649
}
650
651
void tst_Gestures::finishedWithoutStarted()
652
{
653
    GestureWidget widget;
654
    widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
655
656
    // the gesture will claim it finished, but it was never started.
657
    CustomEvent ev;
658
    ev.serial = CustomGesture::SerialFinishedThreshold;
659
    QApplication::sendEvent(&widget, &ev);
660
661
    QCOMPARE(widget.customEventsReceived, 1);
662
    QCOMPARE(widget.gestureEventsReceived, 2);
663
    QCOMPARE(widget.gestureOverrideEventsReceived, 0);
664
    QCOMPARE(widget.events.all.size(), 2);
665
    QCOMPARE(widget.events.started.size(), 1);
666
    QCOMPARE(widget.events.updated.size(), 0);
667
    QCOMPARE(widget.events.finished.size(), 1);
668
    QCOMPARE(widget.events.canceled.size(), 0);
669
}
670
671
void tst_Gestures::unknownGesture()
672
{
673
    GestureWidget widget;
674
    widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
675
    widget.grabGesture(Qt::CustomGesture, Qt::DontStartGestureOnChildren);
676
    widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::DontStartGestureOnChildren);
677
678
    CustomEvent event;
679
    sendCustomGesture(&event, &widget);
680
681
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
682
683
    QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
684
}
685
686
static const QColor InstanceColors[] = {
687
    Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow
688
};
689
690
class GestureItem : public QGraphicsObject
691
{
692
    Q_OBJECT
693
    static int InstanceCount;
694
public:
695
    GestureItem(const char *name = 0)
696
    {
697
        instanceNumber = InstanceCount++;
698
        if (name) {
699
            setObjectName(QLatin1String(name));
700
            setToolTip(name);
701
        }
702
        size = QRectF(0, 0, 100, 100);
703
        customEventsReceived = 0;
704
        gestureEventsReceived = 0;
705
        gestureOverrideEventsReceived = 0;
706
        events.clear();
707
        overrideEvents.clear();
708
        acceptGestureOverride = false;
709
710
        scene = 0;
711
    }
712
    ~GestureItem()
713
    {
714
        --InstanceCount;
715
    }
716
717
    int customEventsReceived;
718
    int gestureEventsReceived;
719
    int gestureOverrideEventsReceived;
720
    struct Events
721
    {
722
        QList<Qt::GestureType> all;
723
        QList<Qt::GestureType> started;
724
        QList<Qt::GestureType> updated;
725
        QList<Qt::GestureType> finished;
726
        QList<Qt::GestureType> canceled;
727
728
        void clear()
729
        {
730
            all.clear();
731
            started.clear();
732
            updated.clear();
733
            finished.clear();
734
            canceled.clear();
735
        }
736
    } events, overrideEvents;
737
738
    bool acceptGestureOverride;
739
    QSet<Qt::GestureType> ignoredGestures;
740
    QSet<Qt::GestureType> ignoredStartedGestures;
741
    QSet<Qt::GestureType> ignoredUpdatedGestures;
742
    QSet<Qt::GestureType> ignoredFinishedGestures;
743
744
    QRectF size;
745
    int instanceNumber;
746
747
    void reset()
748
    {
749
        customEventsReceived = 0;
750
        gestureEventsReceived = 0;
751
        gestureOverrideEventsReceived = 0;
752
        events.clear();
753
        overrideEvents.clear();
754
        ignoredGestures.clear();
755
        ignoredStartedGestures.clear();
756
        ignoredUpdatedGestures.clear();
757
        ignoredFinishedGestures.clear();
758
    }
759
760
    QRectF boundingRect() const
761
    {
762
        return size;
763
    }
764
    void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
765
    {
766
        QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))];
767
        p->fillRect(boundingRect(), color);
768
    }
769
770
    bool event(QEvent *event)
771
    {
772
        Events *eventsPtr = 0;
773
        if (event->type() == QEvent::Gesture) {
774
            ++gestureEventsReceived;
775
            eventsPtr = &events;
776
            QGestureEvent *e = static_cast<QGestureEvent *>(event);
777
            foreach(Qt::GestureType type, ignoredGestures)
778
                e->ignore(e->gesture(type));
779
            foreach(QGesture *g, e->gestures()) {
780
                switch (g->state()) {
781
                case Qt::GestureStarted:
782
                    if (ignoredStartedGestures.contains(g->gestureType()))
783
                        e->ignore(g);
784
                    break;
785
                case Qt::GestureUpdated:
786
                    if (ignoredUpdatedGestures.contains(g->gestureType()))
787
                        e->ignore(g);
788
                    break;
789
                case Qt::GestureFinished:
790
                    if (ignoredFinishedGestures.contains(g->gestureType()))
791
                        e->ignore(g);
792
                    break;
793
                default:
794
                    break;
795
                }
796
            }
797
        } else if (event->type() == QEvent::GestureOverride) {
798
            ++gestureOverrideEventsReceived;
799
            eventsPtr = &overrideEvents;
800
            if (acceptGestureOverride)
801
                event->accept();
802
        }
803
        if (eventsPtr) {
804
            QGestureEvent *e = static_cast<QGestureEvent*>(event);
805
            QList<QGesture*> gestures = e->gestures();
806
            foreach(QGesture *g, gestures) {
807
                eventsPtr->all << g->gestureType();
808
                switch(g->state()) {
809
                case Qt::GestureStarted:
810
                    eventsPtr->started << g->gestureType();
811
                    emit gestureStarted(e->type(), g);
812
                    break;
813
                case Qt::GestureUpdated:
814
                    eventsPtr->updated << g->gestureType();
815
                    emit gestureUpdated(e->type(), g);
816
                    break;
817
                case Qt::GestureFinished:
818
                    eventsPtr->finished << g->gestureType();
819
                    emit gestureFinished(e->type(), g);
820
                    break;
821
                case Qt::GestureCanceled:
822
                    eventsPtr->canceled << g->gestureType();
823
                    emit gestureCanceled(e->type(), g);
824
                    break;
825
                default:
826
                    qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
827
                }
828
            }
829
        } else if (event->type() == CustomEvent::EventType) {
830
            ++customEventsReceived;
831
        } else {
832
            return QGraphicsObject::event(event);
833
        }
834
        return true;
835
    }
836
837
Q_SIGNALS:
838
    void gestureStarted(QEvent::Type, QGesture *);
839
    void gestureUpdated(QEvent::Type, QGesture *);
840
    void gestureFinished(QEvent::Type, QGesture *);
841
    void gestureCanceled(QEvent::Type, QGesture *);
842
843
public:
844
    // some arguments for the slots below:
845
    QGraphicsScene *scene;
846
847
public Q_SLOTS:
848
    void deleteThis() { delete this; }
849
    void addSelfToScene(QEvent::Type eventType, QGesture *)
850
    {
851
        if (eventType == QEvent::Gesture) {
852
            disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*)));
853
            scene->addItem(this);
854
        }
855
    }
856
};
857
int GestureItem::InstanceCount = 0;
858
859
void tst_Gestures::graphicsItemGesture()
860
{
861
    QGraphicsScene scene;
862
    QGraphicsView view(&scene);
863
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
864
865
    GestureItem *item = new GestureItem("item");
866
    scene.addItem(item);
867
    item->setPos(100, 100);
868
869
    view.show();
870
    QTest::qWaitForWindowShown(&view);
871
    view.ensureVisible(scene.sceneRect());
872
873
    item->grabGesture(CustomGesture::GestureType);
874
875
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
876
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
877
878
    CustomEvent event;
879
    // gesture without hotspot should not be delivered to items in the view
880
    QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
881
    QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
882
    QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
883
    QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
884
    sendCustomGesture(&event, item, &scene);
885
886
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
887
    QCOMPARE(item->gestureEventsReceived, 0);
888
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
889
890
    item->reset();
891
892
    // make sure the event is properly delivered if only the hotspot is set.
893
    event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
894
    event.hasHotSpot = true;
895
    sendCustomGesture(&event, item, &scene);
896
897
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
898
    QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
899
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
900
    QCOMPARE(item->events.all.size(), TotalGestureEventsCount);
901
    for(int i = 0; i < item->events.all.size(); ++i)
902
        QCOMPARE(item->events.all.at(i), CustomGesture::GestureType);
903
    QCOMPARE(item->events.started.size(), 1);
904
    QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2);
905
    QCOMPARE(item->events.finished.size(), 1);
906
    QCOMPARE(item->events.canceled.size(), 0);
907
908
    item->reset();
909
910
    // send gesture to the item which ignores it.
911
    item->ignoredGestures << CustomGesture::GestureType;
912
913
    event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
914
    event.hasHotSpot = true;
915
    sendCustomGesture(&event, item, &scene);
916
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
917
    QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
918
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
919
}
920
921
void tst_Gestures::graphicsView()
922
{
923
    QGraphicsScene scene;
924
    QGraphicsView view(&scene);
925
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
926
927
    GestureItem *item = new GestureItem("item");
928
    scene.addItem(item);
929
    item->setPos(100, 100);
930
931
    view.show();
932
    QTest::qWaitForWindowShown(&view);
933
    view.ensureVisible(scene.sceneRect());
934
935
    item->grabGesture(CustomGesture::GestureType);
936
937
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
938
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
939
940
    CustomEvent event;
941
    // make sure the event is properly delivered if only the hotspot is set.
942
    event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
943
    event.hasHotSpot = true;
944
    sendCustomGesture(&event, item, &scene);
945
946
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
947
    QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
948
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
949
950
    // change the viewport and try again
951
    QWidget *newViewport = new QWidget;
952
    view.setViewport(newViewport);
953
954
    item->reset();
955
    sendCustomGesture(&event, item, &scene);
956
957
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
958
    QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
959
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
960
961
    // change the scene and try again
962
    QGraphicsScene newScene;
963
    item = new GestureItem("newItem");
964
    newScene.addItem(item);
965
    item->setPos(100, 100);
966
    view.setScene(&newScene);
967
968
    item->reset();
969
    // first without a gesture
970
    sendCustomGesture(&event, item, &newScene);
971
972
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
973
    QCOMPARE(item->gestureEventsReceived, 0);
974
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
975
976
    // then grab the gesture and try again
977
    item->reset();
978
    item->grabGesture(CustomGesture::GestureType);
979
    sendCustomGesture(&event, item, &newScene);
980
981
    QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
982
    QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
983
    QCOMPARE(item->gestureOverrideEventsReceived, 0);
984
}
985
986
void tst_Gestures::graphicsItemTreeGesture()
987
{
988
    QGraphicsScene scene;
989
    QGraphicsView view(&scene);
990
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
991
992
    GestureItem *item1 = new GestureItem("item1");
993
    item1->setPos(100, 100);
994
    item1->size = QRectF(0, 0, 350, 200);
995
    scene.addItem(item1);
996
997
    GestureItem *item1_child1 = new GestureItem("item1_child1");
998
    item1_child1->setPos(50, 50);
999
    item1_child1->size = QRectF(0, 0, 100, 100);
1000
    item1_child1->setParentItem(item1);
1001
1002
    GestureItem *item1_child2 = new GestureItem("item1_child2");
1003
    item1_child2->size = QRectF(0, 0, 100, 100);
1004
    item1_child2->setPos(200, 50);
1005
    item1_child2->setParentItem(item1);
1006
1007
    view.show();
1008
    QTest::qWaitForWindowShown(&view);
1009
    view.ensureVisible(scene.sceneRect());
1010
1011
    item1->grabGesture(CustomGesture::GestureType);
1012
1013
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1014
1015
    CustomEvent event;
1016
    event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view);
1017
    event.hasHotSpot = true;
1018
1019
    item1->ignoredGestures << CustomGesture::GestureType;
1020
    sendCustomGesture(&event, item1_child1, &scene);
1021
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1022
    QCOMPARE(item1_child1->gestureEventsReceived, 0);
1023
    QCOMPARE(item1_child2->gestureEventsReceived, 0);
1024
    QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1025
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1026
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1027
1028
    item1->reset(); item1_child1->reset(); item1_child2->reset();
1029
1030
    item1_child1->grabGesture(CustomGesture::GestureType);
1031
1032
    item1->ignoredGestures << CustomGesture::GestureType;
1033
    item1_child1->ignoredGestures << CustomGesture::GestureType;
1034
    sendCustomGesture(&event, item1_child1, &scene);
1035
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1036
    QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1037
    QCOMPARE(item1_child2->gestureEventsReceived, 0);
1038
    QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1039
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1040
    QCOMPARE(item1->gestureEventsReceived, 1);
1041
}
1042
1043
void tst_Gestures::explicitGraphicsObjectTarget()
1044
{
1045
    QGraphicsScene scene;
1046
    QGraphicsView view(&scene);
1047
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1048
1049
    GestureItem *item1 = new GestureItem("item1");
1050
    scene.addItem(item1);
1051
    item1->setPos(100, 100);
1052
    item1->setZValue(1);
1053
1054
    GestureItem *item2 = new GestureItem("item2");
1055
    scene.addItem(item2);
1056
    item2->setPos(100, 100);
1057
    item2->setZValue(5);
1058
1059
    GestureItem *item2_child1 = new GestureItem("item2_child1");
1060
    scene.addItem(item2_child1);
1061
    item2_child1->setParentItem(item2);
1062
    item2_child1->setPos(10, 10);
1063
1064
    view.show();
1065
    QTest::qWaitForWindowShown(&view);
1066
    view.ensureVisible(scene.sceneRect());
1067
1068
    item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1069
    item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1070
    item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1071
1072
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1073
1074
    // sending events to item1, but the hotSpot is set to item2
1075
    CustomEvent event;
1076
    event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view);
1077
    event.hasHotSpot = true;
1078
1079
    sendCustomGesture(&event, item1, &scene);
1080
1081
    QCOMPARE(item1->gestureEventsReceived, 0);
1082
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1083
    QCOMPARE(item2_child1->gestureEventsReceived, TotalGestureEventsCount);
1084
    QCOMPARE(item2_child1->gestureOverrideEventsReceived, 1);
1085
    QCOMPARE(item2_child1->events.all.size(), TotalGestureEventsCount);
1086
    for(int i = 0; i < item2_child1->events.all.size(); ++i)
1087
        QCOMPARE(item2_child1->events.all.at(i), CustomGesture::GestureType);
1088
    QCOMPARE(item2_child1->events.started.size(), 1);
1089
    QCOMPARE(item2_child1->events.updated.size(), TotalGestureEventsCount - 2);
1090
    QCOMPARE(item2_child1->events.finished.size(), 1);
1091
    QCOMPARE(item2_child1->events.canceled.size(), 0);
1092
    QCOMPARE(item2->gestureEventsReceived, 0);
1093
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1094
}
1095
1096
void tst_Gestures::gestureOverChildGraphicsItem()
1097
{
1098
    QGraphicsScene scene;
1099
    QGraphicsView view(&scene);
1100
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1101
1102
    GestureItem *item0 = new GestureItem("item0");
1103
    scene.addItem(item0);
1104
    item0->setPos(0, 0);
1105
    item0->grabGesture(CustomGesture::GestureType);
1106
    item0->setZValue(1);
1107
1108
    GestureItem *item1 = new GestureItem("item1");
1109
    scene.addItem(item1);
1110
    item1->setPos(100, 100);
1111
    item1->setZValue(5);
1112
1113
    GestureItem *item2 = new GestureItem("item2");
1114
    scene.addItem(item2);
1115
    item2->setPos(100, 100);
1116
    item2->setZValue(10);
1117
1118
    GestureItem *item2_child1 = new GestureItem("item2_child1");
1119
    scene.addItem(item2_child1);
1120
    item2_child1->setParentItem(item2);
1121
    item2_child1->setPos(0, 0);
1122
1123
    view.show();
1124
    QTest::qWaitForWindowShown(&view);
1125
    view.ensureVisible(scene.sceneRect());
1126
1127
    item1->grabGesture(CustomGesture::GestureType);
1128
1129
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1130
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1131
1132
    CustomEvent event;
1133
    event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1134
    event.hasHotSpot = true;
1135
    sendCustomGesture(&event, item0, &scene);
1136
1137
    QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1138
    QCOMPARE(item2_child1->gestureEventsReceived, 0);
1139
    QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1140
    QCOMPARE(item2->gestureEventsReceived, 0);
1141
    QCOMPARE(item2->gestureOverrideEventsReceived, 0);
1142
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1143
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1144
1145
    item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1146
    item2->grabGesture(CustomGesture::GestureType);
1147
    item2->ignoredGestures << CustomGesture::GestureType;
1148
1149
    event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1150
    event.hasHotSpot = true;
1151
    sendCustomGesture(&event, item0, &scene);
1152
1153
    QCOMPARE(item2_child1->gestureEventsReceived, 0);
1154
    QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1155
    QCOMPARE(item2->gestureEventsReceived, 1);
1156
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1157
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1158
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1159
1160
    item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1161
    item2->grabGesture(CustomGesture::GestureType);
1162
    item2->ignoredGestures << CustomGesture::GestureType;
1163
    item1->ignoredGestures << CustomGesture::GestureType;
1164
1165
    event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1166
    event.hasHotSpot = true;
1167
    sendCustomGesture(&event, item0, &scene);
1168
1169
    QCOMPARE(item2_child1->gestureEventsReceived, 0);
1170
    QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1171
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1172
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1173
    QCOMPARE(item1->gestureEventsReceived, 1);
1174
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1175
1176
    item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1177
    item2->grabGesture(CustomGesture::GestureType);
1178
    item2->ignoredGestures << CustomGesture::GestureType;
1179
    item1->ignoredGestures << CustomGesture::GestureType;
1180
    item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1181
1182
    event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1183
    event.hasHotSpot = true;
1184
    sendCustomGesture(&event, item0, &scene);
1185
1186
    QCOMPARE(item2_child1->gestureEventsReceived, 0);
1187
    QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1188
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1189
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1190
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1191
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1192
}
1193
1194
void tst_Gestures::twoGesturesOnDifferentLevel()
1195
{
1196
    GestureWidget parent("parent");
1197
    QVBoxLayout *l = new QVBoxLayout(&parent);
1198
    GestureWidget *child = new GestureWidget("child");
1199
    l->addWidget(child);
1200
1201
    Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1202
1203
    parent.grabGesture(CustomGesture::GestureType);
1204
    child->grabGesture(SecondGesture);
1205
1206
    CustomEvent event;
1207
    // sending events that form a gesture to one widget, but they will be
1208
    // filtered by two different gesture recognizers and will generate two
1209
    // QGesture objects. Check that those gesture objects are delivered to
1210
    // different widgets properly.
1211
    sendCustomGesture(&event, child);
1212
1213
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1214
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1215
1216
    QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
1217
    QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
1218
    QCOMPARE(child->gestureOverrideEventsReceived, 0);
1219
    QCOMPARE(child->events.all.size(), TotalGestureEventsCount);
1220
    for(int i = 0; i < child->events.all.size(); ++i)
1221
        QCOMPARE(child->events.all.at(i), SecondGesture);
1222
1223
    QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
1224
    QCOMPARE(parent.gestureOverrideEventsReceived, 0);
1225
    QCOMPARE(parent.events.all.size(), TotalGestureEventsCount);
1226
    for(int i = 0; i < child->events.all.size(); ++i)
1227
        QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType);
1228
1229
    QGestureRecognizer::unregisterRecognizer(SecondGesture);
1230
}
1231
1232
void tst_Gestures::multipleGesturesInTree()
1233
{
1234
    GestureWidget a("A");
1235
    GestureWidget *A = &a;
1236
    GestureWidget *B = new GestureWidget("B", A);
1237
    GestureWidget *C = new GestureWidget("C", B);
1238
    GestureWidget *D = new GestureWidget("D", C);
1239
1240
    Qt::GestureType FirstGesture  = CustomGesture::GestureType;
1241
    Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1242
    Qt::GestureType ThirdGesture  = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1243
1244
    Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1245
    A->grabGesture(FirstGesture,  flags);   // A [1   3]
1246
    A->grabGesture(ThirdGesture,  flags);   // |
1247
    B->grabGesture(SecondGesture, flags);   // B [  2 3]
1248
    B->grabGesture(ThirdGesture,  flags);   // |
1249
    C->grabGesture(FirstGesture,  flags);   // C [1 2 3]
1250
    C->grabGesture(SecondGesture, flags);   // |
1251
    C->grabGesture(ThirdGesture,  flags);   // D [1   3]
1252
    D->grabGesture(FirstGesture,  flags);
1253
    D->grabGesture(ThirdGesture,  flags);
1254
1255
    // make sure all widgets ignore events, so they get propagated.
1256
    A->ignoredGestures << FirstGesture << ThirdGesture;
1257
    B->ignoredGestures << SecondGesture << ThirdGesture;
1258
    C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture;
1259
    D->ignoredGestures << FirstGesture << ThirdGesture;
1260
1261
    CustomEvent event;
1262
    sendCustomGesture(&event, D);
1263
1264
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1265
1266
    // gesture override events
1267
    QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1268
    QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1269
    QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1270
1271
    QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1272
    QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1273
    QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1274
1275
    QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1276
    QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1277
    QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1278
1279
    QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1280
    QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1281
    QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1282
1283
    // normal gesture events
1284
    QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1285
    QCOMPARE(D->events.all.count(SecondGesture), 0);
1286
    QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1287
1288
    QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1289
    QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1290
    QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1291
1292
    QCOMPARE(B->events.all.count(FirstGesture), 0);
1293
    QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1294
    QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1295
1296
    QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1297
    QCOMPARE(A->events.all.count(SecondGesture), 0);
1298
    QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1299
1300
    QGestureRecognizer::unregisterRecognizer(SecondGesture);
1301
    QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1302
}
1303
1304
void tst_Gestures::multipleGesturesInComplexTree()
1305
{
1306
    GestureWidget a("A");
1307
    GestureWidget *A = &a;
1308
    GestureWidget *B = new GestureWidget("B", A);
1309
    GestureWidget *C = new GestureWidget("C", B);
1310
    GestureWidget *D = new GestureWidget("D", C);
1311
1312
    Qt::GestureType FirstGesture   = CustomGesture::GestureType;
1313
    Qt::GestureType SecondGesture  = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1314
    Qt::GestureType ThirdGesture   = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1315
    Qt::GestureType FourthGesture  = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1316
    Qt::GestureType FifthGesture   = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1317
    Qt::GestureType SixthGesture   = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1318
    Qt::GestureType SeventhGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1319
1320
    Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1321
    A->grabGesture(FirstGesture,   flags); // A [1,3,4]
1322
    A->grabGesture(ThirdGesture,   flags); // |
1323
    A->grabGesture(FourthGesture,  flags); // B [2,3,5]
1324
    B->grabGesture(SecondGesture,  flags); // |
1325
    B->grabGesture(ThirdGesture,   flags); // C [1,2,3,6]
1326
    B->grabGesture(FifthGesture,   flags); // |
1327
    C->grabGesture(FirstGesture,   flags); // D [1,3,7]
1328
    C->grabGesture(SecondGesture,  flags);
1329
    C->grabGesture(ThirdGesture,   flags);
1330
    C->grabGesture(SixthGesture,   flags);
1331
    D->grabGesture(FirstGesture,   flags);
1332
    D->grabGesture(ThirdGesture,   flags);
1333
    D->grabGesture(SeventhGesture, flags);
1334
1335
    // make sure all widgets ignore events, so they get propagated.
1336
    QSet<Qt::GestureType> allGestureTypes;
1337
    allGestureTypes << FirstGesture << SecondGesture << ThirdGesture
1338
            << FourthGesture << FifthGesture << SixthGesture << SeventhGesture;
1339
    A->ignoredGestures = B->ignoredGestures = allGestureTypes;
1340
    C->ignoredGestures = D->ignoredGestures = allGestureTypes;
1341
1342
    CustomEvent event;
1343
    sendCustomGesture(&event, D);
1344
1345
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1346
1347
    // gesture override events
1348
    QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1349
    QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1350
    QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1351
1352
    QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1353
    QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1354
    QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1355
1356
    QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1357
    QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1358
    QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1359
1360
    QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1361
    QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1362
    QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1363
1364
    // normal gesture events
1365
    QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1366
    QCOMPARE(D->events.all.count(SecondGesture), 0);
1367
    QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1368
    QCOMPARE(D->events.all.count(FourthGesture), 0);
1369
    QCOMPARE(D->events.all.count(FifthGesture), 0);
1370
    QCOMPARE(D->events.all.count(SixthGesture), 0);
1371
    QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount);
1372
1373
    QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1374
    QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1375
    QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1376
    QCOMPARE(C->events.all.count(FourthGesture), 0);
1377
    QCOMPARE(C->events.all.count(FifthGesture), 0);
1378
    QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount);
1379
    QCOMPARE(C->events.all.count(SeventhGesture), 0);
1380
1381
    QCOMPARE(B->events.all.count(FirstGesture), 0);
1382
    QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1383
    QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1384
    QCOMPARE(B->events.all.count(FourthGesture), 0);
1385
    QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount);
1386
    QCOMPARE(B->events.all.count(SixthGesture), 0);
1387
    QCOMPARE(B->events.all.count(SeventhGesture), 0);
1388
1389
    QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1390
    QCOMPARE(A->events.all.count(SecondGesture), 0);
1391
    QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1392
    QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount);
1393
    QCOMPARE(A->events.all.count(FifthGesture), 0);
1394
    QCOMPARE(A->events.all.count(SixthGesture), 0);
1395
    QCOMPARE(A->events.all.count(SeventhGesture), 0);
1396
1397
    QGestureRecognizer::unregisterRecognizer(SecondGesture);
1398
    QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1399
    QGestureRecognizer::unregisterRecognizer(FourthGesture);
1400
    QGestureRecognizer::unregisterRecognizer(FifthGesture);
1401
    QGestureRecognizer::unregisterRecognizer(SixthGesture);
1402
    QGestureRecognizer::unregisterRecognizer(SeventhGesture);
1403
}
1404
1405
void tst_Gestures::testMapToScene()
1406
{
1407
    QGesture gesture;
1408
    QList<QGesture*> list;
1409
    list << &gesture;
1410
    QGestureEvent event(list);
1411
    QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much
1412
1413
    QGraphicsScene scene;
1414
    QGraphicsView view(&scene);
1415
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1416
1417
    GestureItem *item0 = new GestureItem;
1418
    scene.addItem(item0);
1419
    item0->setPos(14, 16);
1420
1421
    view.show(); // need to show to give it a global coordinate
1422
    QTest::qWaitForWindowShown(&view);
1423
    view.ensureVisible(scene.sceneRect());
1424
1425
    QPoint origin = view.mapToGlobal(QPoint());
1426
    event.setWidget(view.viewport());
1427
1428
    QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200)));
1429
}
1430
1431
void tst_Gestures::ungrabGesture() // a method on QWidget
1432
{
1433
    class MockGestureWidget : public GestureWidget {
1434
    public:
1435
        MockGestureWidget(const char *name = 0, QWidget *parent = 0)
1436
            : GestureWidget(name, parent) { }
1437
1438
1439
        QSet<QGesture*> gestures;
1440
    protected:
1441
        bool event(QEvent *event)
1442
        {
1443
            if (event->type() == QEvent::Gesture) {
1444
                QGestureEvent *gestureEvent = static_cast<QGestureEvent*>(event);
1445
                if (gestureEvent)
1446
                    foreach (QGesture *g, gestureEvent->gestures())
1447
                        gestures.insert(g);
1448
            }
1449
            return GestureWidget::event(event);
1450
        }
1451
    };
1452
1453
    MockGestureWidget parent("A");
1454
    MockGestureWidget *a = &parent;
1455
    MockGestureWidget *b = new MockGestureWidget("B", a);
1456
1457
    a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1458
    b->grabGesture(CustomGesture::GestureType);
1459
    b->ignoredGestures << CustomGesture::GestureType;
1460
1461
    CustomEvent event;
1462
    // sending an event will cause the QGesture objects to be instantiated for the widgets
1463
    sendCustomGesture(&event, b);
1464
1465
    QCOMPARE(a->gestures.count(), 1);
1466
    QPointer<QGesture> customGestureA;
1467
    customGestureA = *(a->gestures.begin());
1468
    QVERIFY(!customGestureA.isNull());
1469
    QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1470
1471
    QCOMPARE(b->gestures.count(), 1);
1472
    QPointer<QGesture> customGestureB;
1473
    customGestureB = *(b->gestures.begin());
1474
    QVERIFY(!customGestureB.isNull());
1475
    QVERIFY(customGestureA.data() == customGestureB.data());
1476
    QCOMPARE(customGestureB->gestureType(), CustomGesture::GestureType);
1477
1478
    a->gestures.clear();
1479
    // sending an event will cause the QGesture objects to be instantiated for the widget
1480
    sendCustomGesture(&event, a);
1481
1482
    QCOMPARE(a->gestures.count(), 1);
1483
    customGestureA = *(a->gestures.begin());
1484
    QVERIFY(!customGestureA.isNull());
1485
    QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1486
    QVERIFY(customGestureA.data() != customGestureB.data());
1487
1488
    a->ungrabGesture(CustomGesture::GestureType);
1489
    //We changed the deletion of Gestures to lazy during QT-4022, so we can't ensure the QGesture is deleted until now
1490
    QVERIFY(!customGestureB.isNull());
1491
1492
    a->gestures.clear();
1493
    a->reset();
1494
    // send again to 'b' and make sure a never gets it.
1495
    sendCustomGesture(&event, b);
1496
    //After all Gestures are processed in the QGestureManager, we can ensure the QGesture is now deleted
1497
    QVERIFY(customGestureA.isNull());
1498
    QCOMPARE(a->gestureEventsReceived, 0);
1499
    QCOMPARE(a->gestureOverrideEventsReceived, 0);
1500
}
1501
1502
void tst_Gestures::unregisterRecognizer() // a method on QApplication
1503
{
1504
    /*
1505
     The hardest usecase to get right is when we remove a recognizer while several
1506
     of the gestures it created are in active state and we immediately add a new recognizer
1507
     for the same type (thus replacing the old one).
1508
     The expected result is that all old gestures continue till they are finished/cancelled
1509
     and the new recognizer starts creating gestures immediately at registration.
1510
1511
     This implies that deleting of the recognizer happens only when there are no more gestures
1512
     that it created. (since gestures might have a pointer to the recognizer)
1513
     */
1514
1515
}
1516
1517
void tst_Gestures::autoCancelGestures()
1518
{
1519
    class MockWidget : public GestureWidget {
1520
      public:
1521
        MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { }
1522
1523
        bool event(QEvent *event)
1524
        {
1525
            if (event->type() == QEvent::Gesture) {
1526
                QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1527
                if (ge->gestures().count() != 1)
1528
                    ++badGestureEvents;   // event should contain exactly one gesture
1529
                ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1530
            }
1531
            return GestureWidget::event(event);
1532
        }
1533
1534
        int badGestureEvents;
1535
    };
1536
1537
    const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1538
1539
    MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext
1540
    parent.resize(300, 100);
1541
    parent.setWindowFlags(Qt::X11BypassWindowManagerHint);
1542
    GestureWidget *child = new GestureWidget("child", &parent);
1543
    child->setGeometry(10, 10, 100, 80);
1544
1545
    parent.grabGesture(CustomGesture::GestureType);
1546
    child->grabGesture(secondGesture);
1547
    parent.show();
1548
    QTest::qWaitForWindowShown(&parent);
1549
1550
    /*
1551
      An event is send to both the child and the parent, when the child gets it a gesture is triggered
1552
      and send to the child.
1553
      When the parent gets the event a new gesture is triggered and delivered to the parent. When the
1554
      parent gets it he accepts it and that causes the cancel policy to activate.
1555
      The cause of that is the gesture for the child is cancelled and send to the child as such.
1556
    */
1557
    CustomEvent event;
1558
    event.serial = CustomGesture::SerialStartedThreshold;
1559
    QApplication::sendEvent(child, &event);
1560
    QCOMPARE(child->events.all.count(), 2);
1561
    QCOMPARE(child->events.started.count(), 1);
1562
    QCOMPARE(child->events.canceled.count(), 1);
1563
    QCOMPARE(parent.events.all.count(), 1);
1564
1565
    // clean up, make the parent gesture finish
1566
    event.serial = CustomGesture::SerialFinishedThreshold;
1567
    QApplication::sendEvent(child, &event);
1568
    QCOMPARE(parent.events.all.count(), 2);
1569
    QCOMPARE(parent.badGestureEvents, 0);
1570
}
1571
1572
void tst_Gestures::autoCancelGestures2()
1573
{
1574
    class MockItem : public GestureItem {
1575
      public:
1576
        MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { }
1577
1578
        bool event(QEvent *event) {
1579
            if (event->type() == QEvent::Gesture) {
1580
                QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1581
                if (ge->gestures().count() != 1)
1582
                    ++badGestureEvents;   // event should contain exactly one gesture
1583
                ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1584
            }
1585
            return GestureItem::event(event);
1586
        }
1587
1588
        int badGestureEvents;
1589
    };
1590
1591
    const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer);
1592
1593
    QGraphicsScene scene;
1594
    QGraphicsView view(&scene);
1595
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1596
1597
    MockItem *parent = new MockItem("parent");
1598
    GestureItem *child = new GestureItem("child");
1599
    child->setParentItem(parent);
1600
    parent->setPos(0, 0);
1601
    child->setPos(10, 10);
1602
    scene.addItem(parent);
1603
    parent->grabGesture(CustomGesture::GestureType);
1604
    child->grabGesture(secondGesture);
1605
1606
    view.show();
1607
    QTest::qWaitForWindowShown(&view);
1608
    view.ensureVisible(scene.sceneRect());
1609
1610
    CustomEvent event;
1611
    event.serial = CustomGesture::SerialStartedThreshold;
1612
    event.hasHotSpot = true;
1613
    event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view);
1614
    scene.sendEvent(child, &event);
1615
    QCOMPARE(parent->events.all.count(), 1);
1616
    QCOMPARE(child->events.started.count(), 1);
1617
    QCOMPARE(child->events.canceled.count(), 1);
1618
    QCOMPARE(child->events.all.count(), 2);
1619
1620
    // clean up, make the parent gesture finish
1621
    event.serial = CustomGesture::SerialFinishedThreshold;
1622
    scene.sendEvent(child, &event);
1623
    QCOMPARE(parent->events.all.count(), 2);
1624
    QCOMPARE(parent->badGestureEvents, 0);
1625
}
1626
1627
void tst_Gestures::graphicsViewParentPropagation()
1628
{
1629
    QGraphicsScene scene;
1630
    QGraphicsView view(&scene);
1631
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1632
1633
    GestureItem *item0 = new GestureItem("item0");
1634
    scene.addItem(item0);
1635
    item0->setPos(0, 0);
1636
    item0->grabGesture(CustomGesture::GestureType);
1637
    item0->setZValue(1);
1638
1639
    GestureItem *item1 = new GestureItem("item1");
1640
    scene.addItem(item1);
1641
    item1->setPos(0, 0);
1642
    item1->setZValue(5);
1643
1644
    GestureItem *item1_c1 = new GestureItem("item1_child1");
1645
    item1_c1->setParentItem(item1);
1646
    item1_c1->setPos(0, 0);
1647
1648
    GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1");
1649
    item1_c1_c1->setParentItem(item1_c1);
1650
    item1_c1_c1->setPos(0, 0);
1651
1652
    view.show();
1653
    QTest::qWaitForWindowShown(&view);
1654
    view.ensureVisible(scene.sceneRect());
1655
1656
    item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1657
    item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1658
    item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent);
1659
    item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1660
1661
    item0->ignoredUpdatedGestures << CustomGesture::GestureType;
1662
    item0->ignoredFinishedGestures << CustomGesture::GestureType;
1663
    item1->ignoredUpdatedGestures << CustomGesture::GestureType;
1664
    item1->ignoredFinishedGestures << CustomGesture::GestureType;
1665
    item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1666
    item1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1667
    item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1668
    item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1669
1670
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1671
1672
    CustomEvent event;
1673
    event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view);
1674
    event.hasHotSpot = true;
1675
    sendCustomGesture(&event, item0, &scene);
1676
1677
    QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount);
1678
    QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1);
1679
    QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1);
1680
    QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1);
1681
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1);
1682
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1683
    QCOMPARE(item0->gestureEventsReceived, 0);
1684
    QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1685
}
1686
1687
void tst_Gestures::panelPropagation()
1688
{
1689
    QGraphicsScene scene;
1690
    QGraphicsView view(&scene);
1691
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1692
1693
    GestureItem *item0 = new GestureItem("item0");
1694
    scene.addItem(item0);
1695
    item0->setPos(0, 0);
1696
    item0->size = QRectF(0, 0, 200, 200);
1697
    item0->grabGesture(CustomGesture::GestureType);
1698
    item0->setZValue(1);
1699
1700
    GestureItem *item1 = new GestureItem("item1");
1701
    item1->grabGesture(CustomGesture::GestureType);
1702
    scene.addItem(item1);
1703
    item1->setPos(10, 10);
1704
    item1->size = QRectF(0, 0, 180, 180);
1705
    item1->setZValue(2);
1706
1707
    GestureItem *item1_child1 = new GestureItem("item1_child1[panel]");
1708
    item1_child1->setFlags(QGraphicsItem::ItemIsPanel);
1709
    item1_child1->setParentItem(item1);
1710
    item1_child1->grabGesture(CustomGesture::GestureType);
1711
    item1_child1->setPos(10, 10);
1712
    item1_child1->size = QRectF(0, 0, 160, 160);
1713
    item1_child1->setZValue(5);
1714
1715
    GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1");
1716
    item1_child1_child1->setParentItem(item1_child1);
1717
    item1_child1_child1->grabGesture(CustomGesture::GestureType);
1718
    item1_child1_child1->setPos(10, 10);
1719
    item1_child1_child1->size = QRectF(0, 0, 140, 140);
1720
    item1_child1_child1->setZValue(10);
1721
1722
    view.show();
1723
    QTest::qWaitForWindowShown(&view);
1724
    view.ensureVisible(scene.sceneRect());
1725
1726
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1727
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1728
1729
    CustomEvent event;
1730
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view);
1731
    event.hasHotSpot = true;
1732
    sendCustomGesture(&event, item0, &scene);
1733
1734
    QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1735
    QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount);
1736
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1);
1737
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1738
    QCOMPARE(item1->gestureEventsReceived, 0);
1739
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1740
    QCOMPARE(item0->gestureEventsReceived, 0);
1741
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1742
1743
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1744
1745
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1746
    event.hasHotSpot = true;
1747
    sendCustomGesture(&event, item1, &scene);
1748
1749
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1750
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1751
    QCOMPARE(item1_child1->gestureEventsReceived, 0);
1752
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1753
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1754
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1755
    QCOMPARE(item0->gestureEventsReceived, 0);
1756
    QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1757
1758
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1759
    // try with a modal panel
1760
    item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1761
1762
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1763
    event.hasHotSpot = true;
1764
    sendCustomGesture(&event, item1, &scene);
1765
1766
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1767
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1768
    QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1769
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1770
    QCOMPARE(item1->gestureEventsReceived, 0);
1771
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1772
    QCOMPARE(item0->gestureEventsReceived, 0);
1773
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1774
1775
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1776
    // try with a modal panel, however set the hotspot to be outside of the
1777
    // panel and its parent
1778
    item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1779
1780
    event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1781
    event.hasHotSpot = true;
1782
    sendCustomGesture(&event, item1, &scene);
1783
1784
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1785
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1786
    QCOMPARE(item1_child1->gestureEventsReceived, 0);
1787
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1788
    QCOMPARE(item1->gestureEventsReceived, 0);
1789
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1790
    QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount);
1791
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1792
1793
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1794
    // try with a scene modal panel
1795
    item1_child1->setPanelModality(QGraphicsItem::SceneModal);
1796
1797
    event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1798
    event.hasHotSpot = true;
1799
    sendCustomGesture(&event, item0, &scene);
1800
1801
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1802
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1803
    QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1804
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1805
    QCOMPARE(item1->gestureEventsReceived, 0);
1806
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1807
    QCOMPARE(item0->gestureEventsReceived, 0);
1808
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1809
}
1810
1811
void tst_Gestures::panelStacksBehindParent()
1812
{
1813
    QGraphicsScene scene;
1814
    QGraphicsView view(&scene);
1815
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1816
1817
    GestureItem *item1 = new GestureItem("item1");
1818
    item1->grabGesture(CustomGesture::GestureType);
1819
    scene.addItem(item1);
1820
    item1->setPos(10, 10);
1821
    item1->size = QRectF(0, 0, 180, 180);
1822
    item1->setZValue(2);
1823
1824
    GestureItem *panel = new GestureItem("panel");
1825
    panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent);
1826
    panel->setPanelModality(QGraphicsItem::PanelModal);
1827
    panel->setParentItem(item1);
1828
    panel->grabGesture(CustomGesture::GestureType);
1829
    panel->setPos(-10, -10);
1830
    panel->size = QRectF(0, 0, 200, 200);
1831
    panel->setZValue(5);
1832
1833
    view.show();
1834
    QTest::qWaitForWindowShown(&view);
1835
    view.ensureVisible(scene.sceneRect());
1836
1837
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1838
1839
    CustomEvent event;
1840
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1841
    event.hasHotSpot = true;
1842
    sendCustomGesture(&event, item1, &scene);
1843
1844
    QCOMPARE(item1->gestureEventsReceived, 0);
1845
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1846
    QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount);
1847
    QCOMPARE(panel->gestureOverrideEventsReceived, 0);
1848
}
1849
1850
void tst_Gestures::deleteGestureTargetWidget()
1851
{
1852
}
1853
1854
void tst_Gestures::deleteGestureTargetItem_data()
1855
{
1856
    QTest::addColumn<bool>("propagateUpdateGesture");
1857
    QTest::addColumn<QString>("emitter");
1858
    QTest::addColumn<QString>("receiver");
1859
    QTest::addColumn<QByteArray>("signalName");
1860
    QTest::addColumn<QByteArray>("slotName");
1861
1862
    QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*));
1863
    QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*));
1864
    QByteArray deleteThis = SLOT(deleteThis());
1865
    QByteArray deleteLater = SLOT(deleteLater());
1866
1867
    QTest::newRow("delete1")
1868
            << false << "item1" << "item1" << gestureUpdated << deleteThis;
1869
    QTest::newRow("delete2")
1870
            << false << "item2" << "item2" << gestureUpdated << deleteThis;
1871
    QTest::newRow("delete3")
1872
            << false << "item1" << "item2" << gestureUpdated << deleteThis;
1873
1874
    QTest::newRow("deleteLater1")
1875
            << false << "item1" << "item1" << gestureUpdated << deleteLater;
1876
    QTest::newRow("deleteLater2")
1877
            << false << "item2" << "item2" << gestureUpdated << deleteLater;
1878
    QTest::newRow("deleteLater3")
1879
            << false << "item1" << "item2" << gestureUpdated << deleteLater;
1880
    QTest::newRow("deleteLater4")
1881
            << false << "item2" << "item1" << gestureUpdated << deleteLater;
1882
1883
    QTest::newRow("delete-self-and-propagate")
1884
            << true << "item2" << "item2" << gestureUpdated << deleteThis;
1885
    QTest::newRow("deleteLater-self-and-propagate")
1886
            << true << "item2" << "item2" << gestureUpdated << deleteLater;
1887
    QTest::newRow("propagate-to-deletedLater")
1888
            << true << "item2" << "item1" << gestureUpdated << deleteLater;
1889
}
1890
1891
void tst_Gestures::deleteGestureTargetItem()
1892
{
1893
    QFETCH(bool, propagateUpdateGesture);
1894
    QFETCH(QString, emitter);
1895
    QFETCH(QString, receiver);
1896
    QFETCH(QByteArray, signalName);
1897
    QFETCH(QByteArray, slotName);
1898
1899
    QGraphicsScene scene;
1900
    QGraphicsView view(&scene);
1901
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1902
1903
    GestureItem *item1 = new GestureItem("item1");
1904
    item1->grabGesture(CustomGesture::GestureType);
1905
    item1->setZValue(2);
1906
    scene.addItem(item1);
1907
1908
    GestureItem *item2 = new GestureItem("item2");
1909
    item2->grabGesture(CustomGesture::GestureType);
1910
    item2->setZValue(5);
1911
    scene.addItem(item2);
1912
1913
    QMap<QString, GestureItem *> items;
1914
    items.insert(item1->objectName(), item1);
1915
    items.insert(item2->objectName(), item2);
1916
1917
    view.show();
1918
    QTest::qWaitForWindowShown(&view);
1919
    view.ensureVisible(scene.sceneRect());
1920
1921
    if (propagateUpdateGesture)
1922
        item2->ignoredUpdatedGestures << CustomGesture::GestureType;
1923
    connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName);
1924
1925
    // some debug output to see the current test data tag, so if we crash
1926
    // we know which one caused the crash.
1927
    qDebug() << "<-- testing";
1928
1929
    CustomEvent event;
1930
    event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view);
1931
    event.hasHotSpot = true;
1932
    sendCustomGesture(&event, item1, &scene);
1933
}
1934
1935
class GraphicsView : public QGraphicsView
1936
{
1937
public:
1938
    GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
1939
        : QGraphicsView(scene, parent)
1940
    {
1941
    }
1942
1943
    using QGraphicsView::setViewportMargins;
1944
};
1945
1946
// just making sure that even if the graphicsview has margins hotspot still
1947
// works properly. It should use viewport for converting global coordinates to
1948
// scene coordinates.
1949
void tst_Gestures::viewportCoordinates()
1950
{
1951
    QGraphicsScene scene;
1952
    GraphicsView view(&scene);
1953
    view.setViewportMargins(10,20,15,25);
1954
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1955
1956
    GestureItem *item1 = new GestureItem("item1");
1957
    item1->grabGesture(CustomGesture::GestureType);
1958
    item1->size = QRectF(0, 0, 3, 3);
1959
    item1->setZValue(2);
1960
    scene.addItem(item1);
1961
1962
    view.show();
1963
    QTest::qWaitForWindowShown(&view);
1964
    view.ensureVisible(scene.sceneRect());
1965
1966
    CustomEvent event;
1967
    event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view);
1968
    event.hasHotSpot = true;
1969
    sendCustomGesture(&event, item1, &scene);
1970
    QVERIFY(item1->gestureEventsReceived != 0);
1971
}
1972
1973
void tst_Gestures::partialGesturePropagation()
1974
{
1975
    QGraphicsScene scene;
1976
    QGraphicsView view(&scene);
1977
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1978
1979
    GestureItem *item1 = new GestureItem("item1");
1980
    item1->grabGesture(CustomGesture::GestureType);
1981
    item1->setZValue(8);
1982
    scene.addItem(item1);
1983
1984
    GestureItem *item2 = new GestureItem("item2[partial]");
1985
    item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1986
    item2->setZValue(6);
1987
    scene.addItem(item2);
1988
1989
    GestureItem *item3 = new GestureItem("item3");
1990
    item3->grabGesture(CustomGesture::GestureType);
1991
    item3->setZValue(4);
1992
    scene.addItem(item3);
1993
1994
    GestureItem *item4 = new GestureItem("item4[partial]");
1995
    item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1996
    item4->setZValue(2);
1997
    scene.addItem(item4);
1998
1999
    view.show();
2000
    QTest::qWaitForWindowShown(&view);
2001
    view.ensureVisible(scene.sceneRect());
2002
2003
    item1->ignoredUpdatedGestures << CustomGesture::GestureType;
2004
2005
    CustomEvent event;
2006
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
2007
    event.hasHotSpot = true;
2008
    sendCustomGesture(&event, item1, &scene);
2009
2010
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2011
2012
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2013
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2014
    QCOMPARE(item3->gestureOverrideEventsReceived, 1);
2015
    QCOMPARE(item4->gestureOverrideEventsReceived, 1);
2016
2017
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2018
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished
2019
    QCOMPARE(item3->gestureEventsReceived, 0);
2020
    QCOMPARE(item4->gestureEventsReceived, 0);
2021
}
2022
2023
class WinNativePan : public QPanGesture {
2024
public:
2025
    WinNativePan() {}
2026
};
2027
2028
class Pan : public QPanGesture {
2029
public:
2030
    Pan() {}
2031
};
2032
2033
class CustomPan : public QPanGesture {
2034
public:
2035
    CustomPan() {}
2036
};
2037
2038
// Recognizer for active gesture triggers on mouse press
2039
class PanRecognizer : public QGestureRecognizer {
2040
public:
2041
    enum PanType { Platform, Default, Custom };
2042
2043
    PanRecognizer(int id) : m_id(id) {}
2044
    QGesture *create(QObject *) {
2045
        switch(m_id) {
2046
        case Platform: return new WinNativePan();
2047
        case Default:  return new Pan();
2048
        default:       return new CustomPan();
2049
        }
2050
    }
2051
2052
    Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; }
2053
2054
    const int m_id;
2055
};
2056
2057
void tst_Gestures::testQGestureRecognizerCleanup()
2058
{
2059
    // Clean first the current recognizers in QGManager
2060
    QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2061
2062
    // v-- Qt singleton QGManager initialization
2063
2064
    // Mimic QGestureManager: register both default and "platform" recognizers
2065
    // (this is done in windows when QT_NO_NATIVE_GESTURES is not defined)
2066
    PanRecognizer *def = new PanRecognizer(PanRecognizer::Default);
2067
    QGestureRecognizer::registerRecognizer(def);
2068
    PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform);
2069
    QGestureRecognizer::registerRecognizer(plt);
2070
    qDebug () << "register: default =" << def << "; platform =" << plt;
2071
2072
    // ^-- Qt singleton QGManager initialization
2073
2074
    // Here, application code would start
2075
2076
    // Create QGV (has a QAScrollArea, which uses Qt::PanGesture)
2077
    QMainWindow    *w = new QMainWindow;
2078
    QGraphicsView  *v = new QGraphicsView();
2079
    w->setCentralWidget(v);
2080
2081
    // Unregister Qt recognizers
2082
    QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2083
2084
    // Register a custom Pan recognizer
2085
    //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom));
2086
2087
    w->show();
2088
    QTest::qWaitForWindowShown(w);
2089
    delete w;
2090
}
2091
2092
class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
2093
{
2094
public:
2095
    enum Type {
2096
        RmbAndCancelAllType,
2097
        LmbType
2098
    };
2099
2100
    ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
2101
2102
    QGesture *create(QObject *) {
2103
        QGesture *g = new QGesture;
2104
        return g;
2105
    }
2106
2107
    Result recognize(QGesture *gesture, QObject *, QEvent *event) {
2108
        QMouseEvent *me = static_cast<QMouseEvent *>(event);
2109
        Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton);
2110
2111
        switch(event->type()) {
2112
        case QEvent::MouseButtonPress:
2113
            if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) {
2114
                gesture->setHotSpot(QPointF(me->globalPos()));
2115
                if (m_type == RmbAndCancelAllType)
2116
                    gesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
2117
                return QGestureRecognizer::TriggerGesture;
2118
            }
2119
            break;
2120
        case QEvent::MouseButtonRelease:
2121
            if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
2122
                return QGestureRecognizer::FinishGesture;
2123
        default:
2124
            break;
2125
        }
2126
        return QGestureRecognizer::Ignore;
2127
    }
2128
private:
2129
    Type m_type;
2130
};
2131
2132
class ReuseCanceledGesturesWidget : public QGraphicsWidget
2133
{
2134
  public:
2135
    ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0)
2136
        : QGraphicsWidget(parent),
2137
        m_gestureType(gestureType),
2138
        m_started(0), m_updated(0), m_canceled(0), m_finished(0)
2139
    {
2140
    }
2141
2142
    bool event(QEvent *event) {
2143
        if (event->type() == QEvent::Gesture) {
2144
            QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
2145
            if (gesture) {
2146
                switch(gesture->state()) {
2147
                case Qt::GestureStarted: m_started++; break;
2148
                case Qt::GestureUpdated: m_updated++; break;
2149
                case Qt::GestureFinished: m_finished++; break;
2150
                case Qt::GestureCanceled: m_canceled++; break;
2151
                default: break;
2152
                }
2153
            }
2154
            return true;
2155
        }
2156
        if (event->type() == QEvent::GraphicsSceneMousePress) {
2157
            return true;
2158
        }
2159
        return QGraphicsWidget::event(event);
2160
    }
2161
2162
    int started() { return m_started; }
2163
    int updated() { return m_updated; }
2164
    int finished() { return m_finished; }
2165
    int canceled() { return m_canceled; }
2166
2167
  private:
2168
    Qt::GestureType m_gestureType;
2169
    int m_started;
2170
    int m_updated;
2171
    int m_canceled;
2172
    int m_finished;
2173
};
2174
2175
void tst_Gestures::testReuseCanceledGestures()
2176
{
2177
    Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
2178
            new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
2179
    Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
2180
            new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
2181
2182
    QMainWindow mw;
2183
    mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
2184
    QGraphicsView *gv = new QGraphicsView(&mw);
2185
    QGraphicsScene *scene = new QGraphicsScene;
2186
2187
    gv->setScene(scene);
2188
    scene->setSceneRect(0,0,100,100);
2189
2190
    // Create container and add to the scene
2191
    ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
2192
    container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
2193
2194
    // Create widget and add to the scene
2195
    ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
2196
    target->grabGesture(tapGestureTypeId);
2197
2198
    container->setGeometry(scene->sceneRect());
2199
2200
    scene->addItem(container);
2201
2202
    mw.setCentralWidget(gv);
2203
2204
    // Viewport needs to grab all gestures that widgets in scene grab
2205
    gv->viewport()->grabGesture(cancellingGestureTypeId);
2206
    gv->viewport()->grabGesture(tapGestureTypeId);
2207
2208
    mw.show();
2209
    QTest::qWaitForWindowShown(&mw);
2210
2211
    QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
2212
    targetPos = gv->viewport()->mapFromParent(targetPos);
2213
2214
    // "Tap" starts on child widget
2215
    QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2216
    QCOMPARE(target->started(),  1);
2217
    QCOMPARE(target->updated(),  0);
2218
    QCOMPARE(target->finished(), 0);
2219
    QCOMPARE(target->canceled(), 0);
2220
2221
    // Canceling gesture starts on parent
2222
    QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos);
2223
    QCOMPARE(target->started(),  1);
2224
    QCOMPARE(target->updated(),  0);
2225
    QCOMPARE(target->finished(), 0);
2226
    QCOMPARE(target->canceled(), 1); // <- child canceled
2227
2228
    // Canceling gesture ends
2229
    QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos);
2230
    QCOMPARE(target->started(),  1);
2231
    QCOMPARE(target->updated(),  0);
2232
    QCOMPARE(target->finished(), 0);
2233
    QCOMPARE(target->canceled(), 1);
2234
2235
    // Tap would end if not canceled
2236
    QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2237
    QCOMPARE(target->started(),  1);
2238
    QCOMPARE(target->updated(),  0);
2239
    QCOMPARE(target->finished(), 0);
2240
    QCOMPARE(target->canceled(), 1);
2241
2242
    // New "Tap" starts
2243
    QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2244
    QCOMPARE(target->started(),  2);
2245
    QCOMPARE(target->updated(),  0);
2246
    QCOMPARE(target->finished(), 0);
2247
    QCOMPARE(target->canceled(), 1);
2248
2249
    QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2250
    QCOMPARE(target->started(),  2);
2251
    QCOMPARE(target->updated(),  0);
2252
    QCOMPARE(target->finished(), 1);
2253
    QCOMPARE(target->canceled(), 1);
2254
}
2255
2256
void tst_Gestures::conflictingGesturesInGraphicsView()
2257
{
2258
    QGraphicsScene scene;
2259
    GraphicsView view(&scene);
2260
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
2261
2262
    GestureItem *item1 = new GestureItem("item1");
2263
    item1->grabGesture(CustomGesture::GestureType);
2264
    item1->size = QRectF(0, 0, 100, 100);
2265
    item1->setZValue(2);
2266
    scene.addItem(item1);
2267
2268
    GestureItem *item2 = new GestureItem("item2");
2269
    item2->grabGesture(CustomGesture::GestureType);
2270
    item2->size = QRectF(0, 0, 100, 100);
2271
    item2->setZValue(5);
2272
    scene.addItem(item2);
2273
2274
    view.show();
2275
    QTest::qWaitForWindowShown(&view);
2276
    view.ensureVisible(scene.sceneRect());
2277
2278
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2279
2280
    CustomEvent event;
2281
2282
    // nobody accepts override
2283
    item1->acceptGestureOverride = false;
2284
    item2->acceptGestureOverride = false;
2285
    event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2286
    event.hasHotSpot = true;
2287
    sendCustomGesture(&event, item2, &scene);
2288
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2289
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2290
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2291
    QCOMPARE(item1->gestureEventsReceived, 0);
2292
2293
    item1->reset(); item2->reset();
2294
2295
    // the original target accepts override
2296
    item1->acceptGestureOverride = false;
2297
    item2->acceptGestureOverride = true;
2298
    event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2299
    event.hasHotSpot = true;
2300
    sendCustomGesture(&event, item2, &scene);
2301
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2302
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2303
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
2304
    QCOMPARE(item1->gestureEventsReceived, 0);
2305
2306
    item1->reset(); item2->reset();
2307
2308
    // the item behind accepts override
2309
    item1->acceptGestureOverride = true;
2310
    item2->acceptGestureOverride = false;
2311
    event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2312
    event.hasHotSpot = true;
2313
    sendCustomGesture(&event, item2, &scene);
2314
2315
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2316
    QCOMPARE(item2->gestureEventsReceived, 0);
2317
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2318
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2319
}
2320
2321
class NoConsumeWidgetBug13501 :public QWidget
2322
{
2323
    Q_OBJECT
2324
protected:
2325
    bool event(QEvent *e) {
2326
        if(e->type() == QEvent::Gesture) {
2327
            return false;
2328
        }
2329
        return QWidget::event(e);
2330
    }
2331
};
2332
2333
void tst_Gestures::bug_13501_gesture_not_accepted()
2334
{
2335
    // Create a gesture event that is not accepted by any widget
2336
    // make sure this does not lead to an assert in QGestureManager
2337
    NoConsumeWidgetBug13501 w;
2338
    w.grabGesture(Qt::TapGesture);
2339
    w.show();
2340
    QTest::qWaitForWindowShown(&w);
2341
    //QTest::mousePress(&ignoreEvent, Qt::LeftButton);
2342
    QTest::touchEvent(&w).press(0, QPoint(10, 10), &w);
2343
}
2344
2345
QTEST_MAIN(tst_Gestures)
2346
#include "tst_gestures.moc"