1
/****************************************************************************
2
**
3
** Copyright (C) 2011 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
                    Q_ASSERT(false);
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
                    Q_ASSERT(false);
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) { }
1522
1523
        bool event(QEvent *event)
1524
        {
1525
            if (event->type() == QEvent::Gesture) {
1526
                QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1527
                Q_ASSERT(ge->gestures().count() == 1); // can't use QCOMPARE here...
1528
                ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1529
            }
1530
            return GestureWidget::event(event);
1531
        }
1532
    };
1533
1534
    const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1535
1536
    MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext
1537
    parent.resize(300, 100);
1538
    parent.setWindowFlags(Qt::X11BypassWindowManagerHint);
1539
    GestureWidget *child = new GestureWidget("child", &parent);
1540
    child->setGeometry(10, 10, 100, 80);
1541
1542
    parent.grabGesture(CustomGesture::GestureType);
1543
    child->grabGesture(secondGesture);
1544
    parent.show();
1545
    QTest::qWaitForWindowShown(&parent);
1546
1547
    /*
1548
      An event is send to both the child and the parent, when the child gets it a gesture is triggered
1549
      and send to the child.
1550
      When the parent gets the event a new gesture is triggered and delivered to the parent. When the
1551
      parent gets it he accepts it and that causes the cancel policy to activate.
1552
      The cause of that is the gesture for the child is cancelled and send to the child as such.
1553
    */
1554
    CustomEvent event;
1555
    event.serial = CustomGesture::SerialStartedThreshold;
1556
    QApplication::sendEvent(child, &event);
1557
    QCOMPARE(child->events.all.count(), 2);
1558
    QCOMPARE(child->events.started.count(), 1);
1559
    QCOMPARE(child->events.canceled.count(), 1);
1560
    QCOMPARE(parent.events.all.count(), 1);
1561
1562
    // clean up, make the parent gesture finish
1563
    event.serial = CustomGesture::SerialFinishedThreshold;
1564
    QApplication::sendEvent(child, &event);
1565
    QCOMPARE(parent.events.all.count(), 2);
1566
}
1567
1568
void tst_Gestures::autoCancelGestures2()
1569
{
1570
    class MockItem : public GestureItem {
1571
      public:
1572
        MockItem(const char *name) : GestureItem(name) { }
1573
1574
        bool event(QEvent *event) {
1575
            if (event->type() == QEvent::Gesture) {
1576
                QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1577
                Q_ASSERT(ge->gestures().count() == 1); // can't use QCOMPARE here...
1578
                ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1579
            }
1580
            return GestureItem::event(event);
1581
        }
1582
    };
1583
1584
    const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer);
1585
1586
    QGraphicsScene scene;
1587
    QGraphicsView view(&scene);
1588
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1589
1590
    MockItem *parent = new MockItem("parent");
1591
    GestureItem *child = new GestureItem("child");
1592
    child->setParentItem(parent);
1593
    parent->setPos(0, 0);
1594
    child->setPos(10, 10);
1595
    scene.addItem(parent);
1596
    parent->grabGesture(CustomGesture::GestureType);
1597
    child->grabGesture(secondGesture);
1598
1599
    view.show();
1600
    QTest::qWaitForWindowShown(&view);
1601
    view.ensureVisible(scene.sceneRect());
1602
1603
    CustomEvent event;
1604
    event.serial = CustomGesture::SerialStartedThreshold;
1605
    event.hasHotSpot = true;
1606
    event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view);
1607
    scene.sendEvent(child, &event);
1608
    QCOMPARE(parent->events.all.count(), 1);
1609
    QCOMPARE(child->events.started.count(), 1);
1610
    QCOMPARE(child->events.canceled.count(), 1);
1611
    QCOMPARE(child->events.all.count(), 2);
1612
1613
    // clean up, make the parent gesture finish
1614
    event.serial = CustomGesture::SerialFinishedThreshold;
1615
    scene.sendEvent(child, &event);
1616
    QCOMPARE(parent->events.all.count(), 2);
1617
}
1618
1619
void tst_Gestures::graphicsViewParentPropagation()
1620
{
1621
    QGraphicsScene scene;
1622
    QGraphicsView view(&scene);
1623
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1624
1625
    GestureItem *item0 = new GestureItem("item0");
1626
    scene.addItem(item0);
1627
    item0->setPos(0, 0);
1628
    item0->grabGesture(CustomGesture::GestureType);
1629
    item0->setZValue(1);
1630
1631
    GestureItem *item1 = new GestureItem("item1");
1632
    scene.addItem(item1);
1633
    item1->setPos(0, 0);
1634
    item1->setZValue(5);
1635
1636
    GestureItem *item1_c1 = new GestureItem("item1_child1");
1637
    item1_c1->setParentItem(item1);
1638
    item1_c1->setPos(0, 0);
1639
1640
    GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1");
1641
    item1_c1_c1->setParentItem(item1_c1);
1642
    item1_c1_c1->setPos(0, 0);
1643
1644
    view.show();
1645
    QTest::qWaitForWindowShown(&view);
1646
    view.ensureVisible(scene.sceneRect());
1647
1648
    item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1649
    item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1650
    item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent);
1651
    item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1652
1653
    item0->ignoredUpdatedGestures << CustomGesture::GestureType;
1654
    item0->ignoredFinishedGestures << CustomGesture::GestureType;
1655
    item1->ignoredUpdatedGestures << CustomGesture::GestureType;
1656
    item1->ignoredFinishedGestures << CustomGesture::GestureType;
1657
    item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1658
    item1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1659
    item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1660
    item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1661
1662
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1663
1664
    CustomEvent event;
1665
    event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view);
1666
    event.hasHotSpot = true;
1667
    sendCustomGesture(&event, item0, &scene);
1668
1669
    QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount);
1670
    QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1);
1671
    QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1);
1672
    QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1);
1673
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1);
1674
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1675
    QCOMPARE(item0->gestureEventsReceived, 0);
1676
    QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1677
}
1678
1679
void tst_Gestures::panelPropagation()
1680
{
1681
    QGraphicsScene scene;
1682
    QGraphicsView view(&scene);
1683
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1684
1685
    GestureItem *item0 = new GestureItem("item0");
1686
    scene.addItem(item0);
1687
    item0->setPos(0, 0);
1688
    item0->size = QRectF(0, 0, 200, 200);
1689
    item0->grabGesture(CustomGesture::GestureType);
1690
    item0->setZValue(1);
1691
1692
    GestureItem *item1 = new GestureItem("item1");
1693
    item1->grabGesture(CustomGesture::GestureType);
1694
    scene.addItem(item1);
1695
    item1->setPos(10, 10);
1696
    item1->size = QRectF(0, 0, 180, 180);
1697
    item1->setZValue(2);
1698
1699
    GestureItem *item1_child1 = new GestureItem("item1_child1[panel]");
1700
    item1_child1->setFlags(QGraphicsItem::ItemIsPanel);
1701
    item1_child1->setParentItem(item1);
1702
    item1_child1->grabGesture(CustomGesture::GestureType);
1703
    item1_child1->setPos(10, 10);
1704
    item1_child1->size = QRectF(0, 0, 160, 160);
1705
    item1_child1->setZValue(5);
1706
1707
    GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1");
1708
    item1_child1_child1->setParentItem(item1_child1);
1709
    item1_child1_child1->grabGesture(CustomGesture::GestureType);
1710
    item1_child1_child1->setPos(10, 10);
1711
    item1_child1_child1->size = QRectF(0, 0, 140, 140);
1712
    item1_child1_child1->setZValue(10);
1713
1714
    view.show();
1715
    QTest::qWaitForWindowShown(&view);
1716
    view.ensureVisible(scene.sceneRect());
1717
1718
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1719
    static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1720
1721
    CustomEvent event;
1722
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view);
1723
    event.hasHotSpot = true;
1724
    sendCustomGesture(&event, item0, &scene);
1725
1726
    QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1727
    QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount);
1728
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1);
1729
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1730
    QCOMPARE(item1->gestureEventsReceived, 0);
1731
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1732
    QCOMPARE(item0->gestureEventsReceived, 0);
1733
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1734
1735
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1736
1737
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1738
    event.hasHotSpot = true;
1739
    sendCustomGesture(&event, item1, &scene);
1740
1741
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1742
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1743
    QCOMPARE(item1_child1->gestureEventsReceived, 0);
1744
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1745
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1746
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1747
    QCOMPARE(item0->gestureEventsReceived, 0);
1748
    QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1749
1750
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1751
    // try with a modal panel
1752
    item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1753
1754
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1755
    event.hasHotSpot = true;
1756
    sendCustomGesture(&event, item1, &scene);
1757
1758
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1759
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1760
    QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1761
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1762
    QCOMPARE(item1->gestureEventsReceived, 0);
1763
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1764
    QCOMPARE(item0->gestureEventsReceived, 0);
1765
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1766
1767
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1768
    // try with a modal panel, however set the hotspot to be outside of the
1769
    // panel and its parent
1770
    item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1771
1772
    event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1773
    event.hasHotSpot = true;
1774
    sendCustomGesture(&event, item1, &scene);
1775
1776
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1777
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1778
    QCOMPARE(item1_child1->gestureEventsReceived, 0);
1779
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1780
    QCOMPARE(item1->gestureEventsReceived, 0);
1781
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1782
    QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount);
1783
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1784
1785
    item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1786
    // try with a scene modal panel
1787
    item1_child1->setPanelModality(QGraphicsItem::SceneModal);
1788
1789
    event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1790
    event.hasHotSpot = true;
1791
    sendCustomGesture(&event, item0, &scene);
1792
1793
    QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1794
    QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1795
    QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1796
    QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1797
    QCOMPARE(item1->gestureEventsReceived, 0);
1798
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1799
    QCOMPARE(item0->gestureEventsReceived, 0);
1800
    QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1801
}
1802
1803
void tst_Gestures::panelStacksBehindParent()
1804
{
1805
    QGraphicsScene scene;
1806
    QGraphicsView view(&scene);
1807
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1808
1809
    GestureItem *item1 = new GestureItem("item1");
1810
    item1->grabGesture(CustomGesture::GestureType);
1811
    scene.addItem(item1);
1812
    item1->setPos(10, 10);
1813
    item1->size = QRectF(0, 0, 180, 180);
1814
    item1->setZValue(2);
1815
1816
    GestureItem *panel = new GestureItem("panel");
1817
    panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent);
1818
    panel->setPanelModality(QGraphicsItem::PanelModal);
1819
    panel->setParentItem(item1);
1820
    panel->grabGesture(CustomGesture::GestureType);
1821
    panel->setPos(-10, -10);
1822
    panel->size = QRectF(0, 0, 200, 200);
1823
    panel->setZValue(5);
1824
1825
    view.show();
1826
    QTest::qWaitForWindowShown(&view);
1827
    view.ensureVisible(scene.sceneRect());
1828
1829
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1830
1831
    CustomEvent event;
1832
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1833
    event.hasHotSpot = true;
1834
    sendCustomGesture(&event, item1, &scene);
1835
1836
    QCOMPARE(item1->gestureEventsReceived, 0);
1837
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1838
    QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount);
1839
    QCOMPARE(panel->gestureOverrideEventsReceived, 0);
1840
}
1841
1842
void tst_Gestures::deleteGestureTargetWidget()
1843
{
1844
}
1845
1846
void tst_Gestures::deleteGestureTargetItem_data()
1847
{
1848
    QTest::addColumn<bool>("propagateUpdateGesture");
1849
    QTest::addColumn<QString>("emitter");
1850
    QTest::addColumn<QString>("receiver");
1851
    QTest::addColumn<QByteArray>("signalName");
1852
    QTest::addColumn<QByteArray>("slotName");
1853
1854
    QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*));
1855
    QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*));
1856
    QByteArray deleteThis = SLOT(deleteThis());
1857
    QByteArray deleteLater = SLOT(deleteLater());
1858
1859
    QTest::newRow("delete1")
1860
            << false << "item1" << "item1" << gestureUpdated << deleteThis;
1861
    QTest::newRow("delete2")
1862
            << false << "item2" << "item2" << gestureUpdated << deleteThis;
1863
    QTest::newRow("delete3")
1864
            << false << "item1" << "item2" << gestureUpdated << deleteThis;
1865
1866
    QTest::newRow("deleteLater1")
1867
            << false << "item1" << "item1" << gestureUpdated << deleteLater;
1868
    QTest::newRow("deleteLater2")
1869
            << false << "item2" << "item2" << gestureUpdated << deleteLater;
1870
    QTest::newRow("deleteLater3")
1871
            << false << "item1" << "item2" << gestureUpdated << deleteLater;
1872
    QTest::newRow("deleteLater4")
1873
            << false << "item2" << "item1" << gestureUpdated << deleteLater;
1874
1875
    QTest::newRow("delete-self-and-propagate")
1876
            << true << "item2" << "item2" << gestureUpdated << deleteThis;
1877
    QTest::newRow("deleteLater-self-and-propagate")
1878
            << true << "item2" << "item2" << gestureUpdated << deleteLater;
1879
    QTest::newRow("propagate-to-deletedLater")
1880
            << true << "item2" << "item1" << gestureUpdated << deleteLater;
1881
}
1882
1883
void tst_Gestures::deleteGestureTargetItem()
1884
{
1885
    QFETCH(bool, propagateUpdateGesture);
1886
    QFETCH(QString, emitter);
1887
    QFETCH(QString, receiver);
1888
    QFETCH(QByteArray, signalName);
1889
    QFETCH(QByteArray, slotName);
1890
1891
    QGraphicsScene scene;
1892
    QGraphicsView view(&scene);
1893
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1894
1895
    GestureItem *item1 = new GestureItem("item1");
1896
    item1->grabGesture(CustomGesture::GestureType);
1897
    item1->setZValue(2);
1898
    scene.addItem(item1);
1899
1900
    GestureItem *item2 = new GestureItem("item2");
1901
    item2->grabGesture(CustomGesture::GestureType);
1902
    item2->setZValue(5);
1903
    scene.addItem(item2);
1904
1905
    QMap<QString, GestureItem *> items;
1906
    items.insert(item1->objectName(), item1);
1907
    items.insert(item2->objectName(), item2);
1908
1909
    view.show();
1910
    QTest::qWaitForWindowShown(&view);
1911
    view.ensureVisible(scene.sceneRect());
1912
1913
    if (propagateUpdateGesture)
1914
        item2->ignoredUpdatedGestures << CustomGesture::GestureType;
1915
    connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName);
1916
1917
    // some debug output to see the current test data tag, so if we crash
1918
    // we know which one caused the crash.
1919
    qDebug() << "<-- testing";
1920
1921
    CustomEvent event;
1922
    event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view);
1923
    event.hasHotSpot = true;
1924
    sendCustomGesture(&event, item1, &scene);
1925
}
1926
1927
class GraphicsView : public QGraphicsView
1928
{
1929
public:
1930
    GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
1931
        : QGraphicsView(scene, parent)
1932
    {
1933
    }
1934
1935
    using QGraphicsView::setViewportMargins;
1936
};
1937
1938
// just making sure that even if the graphicsview has margins hotspot still
1939
// works properly. It should use viewport for converting global coordinates to
1940
// scene coordinates.
1941
void tst_Gestures::viewportCoordinates()
1942
{
1943
    QGraphicsScene scene;
1944
    GraphicsView view(&scene);
1945
    view.setViewportMargins(10,20,15,25);
1946
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1947
1948
    GestureItem *item1 = new GestureItem("item1");
1949
    item1->grabGesture(CustomGesture::GestureType);
1950
    item1->size = QRectF(0, 0, 3, 3);
1951
    item1->setZValue(2);
1952
    scene.addItem(item1);
1953
1954
    view.show();
1955
    QTest::qWaitForWindowShown(&view);
1956
    view.ensureVisible(scene.sceneRect());
1957
1958
    CustomEvent event;
1959
    event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view);
1960
    event.hasHotSpot = true;
1961
    sendCustomGesture(&event, item1, &scene);
1962
    QVERIFY(item1->gestureEventsReceived != 0);
1963
}
1964
1965
void tst_Gestures::partialGesturePropagation()
1966
{
1967
    QGraphicsScene scene;
1968
    QGraphicsView view(&scene);
1969
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1970
1971
    GestureItem *item1 = new GestureItem("item1");
1972
    item1->grabGesture(CustomGesture::GestureType);
1973
    item1->setZValue(8);
1974
    scene.addItem(item1);
1975
1976
    GestureItem *item2 = new GestureItem("item2[partial]");
1977
    item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1978
    item2->setZValue(6);
1979
    scene.addItem(item2);
1980
1981
    GestureItem *item3 = new GestureItem("item3");
1982
    item3->grabGesture(CustomGesture::GestureType);
1983
    item3->setZValue(4);
1984
    scene.addItem(item3);
1985
1986
    GestureItem *item4 = new GestureItem("item4[partial]");
1987
    item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1988
    item4->setZValue(2);
1989
    scene.addItem(item4);
1990
1991
    view.show();
1992
    QTest::qWaitForWindowShown(&view);
1993
    view.ensureVisible(scene.sceneRect());
1994
1995
    item1->ignoredUpdatedGestures << CustomGesture::GestureType;
1996
1997
    CustomEvent event;
1998
    event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1999
    event.hasHotSpot = true;
2000
    sendCustomGesture(&event, item1, &scene);
2001
2002
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2003
2004
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2005
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2006
    QCOMPARE(item3->gestureOverrideEventsReceived, 1);
2007
    QCOMPARE(item4->gestureOverrideEventsReceived, 1);
2008
2009
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2010
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished
2011
    QCOMPARE(item3->gestureEventsReceived, 0);
2012
    QCOMPARE(item4->gestureEventsReceived, 0);
2013
}
2014
2015
class WinNativePan : public QPanGesture {
2016
public:
2017
    WinNativePan() {}
2018
};
2019
2020
class Pan : public QPanGesture {
2021
public:
2022
    Pan() {}
2023
};
2024
2025
class CustomPan : public QPanGesture {
2026
public:
2027
    CustomPan() {}
2028
};
2029
2030
// Recognizer for active gesture triggers on mouse press
2031
class PanRecognizer : public QGestureRecognizer {
2032
public:
2033
    enum PanType { Platform, Default, Custom };
2034
2035
    PanRecognizer(int id) : m_id(id) {}
2036
    QGesture *create(QObject *) {
2037
        switch(m_id) {
2038
        case Platform: return new WinNativePan();
2039
        case Default:  return new Pan();
2040
        default:       return new CustomPan();
2041
        }
2042
    }
2043
2044
    Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; }
2045
2046
    const int m_id;
2047
};
2048
2049
void tst_Gestures::testQGestureRecognizerCleanup()
2050
{
2051
    // Clean first the current recognizers in QGManager
2052
    QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2053
2054
    // v-- Qt singleton QGManager initialization
2055
2056
    // Mimic QGestureManager: register both default and "platform" recognizers
2057
    // (this is done in windows when QT_NO_NATIVE_GESTURES is not defined)
2058
    PanRecognizer *def = new PanRecognizer(PanRecognizer::Default);
2059
    QGestureRecognizer::registerRecognizer(def);
2060
    PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform);
2061
    QGestureRecognizer::registerRecognizer(plt);
2062
    qDebug () << "register: default =" << def << "; platform =" << plt;
2063
2064
    // ^-- Qt singleton QGManager initialization
2065
2066
    // Here, application code would start
2067
2068
    // Create QGV (has a QAScrollArea, which uses Qt::PanGesture)
2069
    QMainWindow    *w = new QMainWindow;
2070
    QGraphicsView  *v = new QGraphicsView();
2071
    w->setCentralWidget(v);
2072
2073
    // Unregister Qt recognizers
2074
    QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2075
2076
    // Register a custom Pan recognizer
2077
    //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom));
2078
2079
    w->show();
2080
    QTest::qWaitForWindowShown(w);
2081
    delete w;
2082
}
2083
2084
class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
2085
{
2086
public:
2087
    enum Type {
2088
        RmbAndCancelAllType,
2089
        LmbType
2090
    };
2091
2092
    ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
2093
2094
    QGesture *create(QObject *) {
2095
        QGesture *g = new QGesture;
2096
        return g;
2097
    }
2098
2099
    Result recognize(QGesture *gesture, QObject *, QEvent *event) {
2100
        QMouseEvent *me = static_cast<QMouseEvent *>(event);
2101
        Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton);
2102
2103
        switch(event->type()) {
2104
        case QEvent::MouseButtonPress:
2105
            if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) {
2106
                gesture->setHotSpot(QPointF(me->globalPos()));
2107
                if (m_type == RmbAndCancelAllType)
2108
                    gesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
2109
                return QGestureRecognizer::TriggerGesture;
2110
            }
2111
            break;
2112
        case QEvent::MouseButtonRelease:
2113
            if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
2114
                return QGestureRecognizer::FinishGesture;
2115
        default:
2116
            break;
2117
        }
2118
        return QGestureRecognizer::Ignore;
2119
    }
2120
private:
2121
    Type m_type;
2122
};
2123
2124
class ReuseCanceledGesturesWidget : public QGraphicsWidget
2125
{
2126
  public:
2127
    ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0)
2128
        : QGraphicsWidget(parent),
2129
        m_gestureType(gestureType),
2130
        m_started(0), m_updated(0), m_canceled(0), m_finished(0)
2131
    {
2132
    }
2133
2134
    bool event(QEvent *event) {
2135
        if (event->type() == QEvent::Gesture) {
2136
            QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
2137
            if (gesture) {
2138
                switch(gesture->state()) {
2139
                case Qt::GestureStarted: m_started++; break;
2140
                case Qt::GestureUpdated: m_updated++; break;
2141
                case Qt::GestureFinished: m_finished++; break;
2142
                case Qt::GestureCanceled: m_canceled++; break;
2143
                default: break;
2144
                }
2145
            }
2146
            return true;
2147
        }
2148
        if (event->type() == QEvent::GraphicsSceneMousePress) {
2149
            return true;
2150
        }
2151
        return QGraphicsWidget::event(event);
2152
    }
2153
2154
    int started() { return m_started; }
2155
    int updated() { return m_updated; }
2156
    int finished() { return m_finished; }
2157
    int canceled() { return m_canceled; }
2158
2159
  private:
2160
    Qt::GestureType m_gestureType;
2161
    int m_started;
2162
    int m_updated;
2163
    int m_canceled;
2164
    int m_finished;
2165
};
2166
2167
void tst_Gestures::testReuseCanceledGestures()
2168
{
2169
    Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
2170
            new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
2171
    Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
2172
            new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
2173
2174
    QMainWindow mw;
2175
    mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
2176
    QGraphicsView *gv = new QGraphicsView(&mw);
2177
    QGraphicsScene *scene = new QGraphicsScene;
2178
2179
    gv->setScene(scene);
2180
    scene->setSceneRect(0,0,100,100);
2181
2182
    // Create container and add to the scene
2183
    ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
2184
    container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
2185
2186
    // Create widget and add to the scene
2187
    ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
2188
    target->grabGesture(tapGestureTypeId);
2189
2190
    container->setGeometry(scene->sceneRect());
2191
2192
    scene->addItem(container);
2193
2194
    mw.setCentralWidget(gv);
2195
2196
    // Viewport needs to grab all gestures that widgets in scene grab
2197
    gv->viewport()->grabGesture(cancellingGestureTypeId);
2198
    gv->viewport()->grabGesture(tapGestureTypeId);
2199
2200
    mw.show();
2201
    QTest::qWaitForWindowShown(&mw);
2202
2203
    QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
2204
    targetPos = gv->viewport()->mapFromParent(targetPos);
2205
2206
    // "Tap" starts on child widget
2207
    QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2208
    QCOMPARE(target->started(),  1);
2209
    QCOMPARE(target->updated(),  0);
2210
    QCOMPARE(target->finished(), 0);
2211
    QCOMPARE(target->canceled(), 0);
2212
2213
    // Canceling gesture starts on parent
2214
    QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos);
2215
    QCOMPARE(target->started(),  1);
2216
    QCOMPARE(target->updated(),  0);
2217
    QCOMPARE(target->finished(), 0);
2218
    QCOMPARE(target->canceled(), 1); // <- child canceled
2219
2220
    // Canceling gesture ends
2221
    QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos);
2222
    QCOMPARE(target->started(),  1);
2223
    QCOMPARE(target->updated(),  0);
2224
    QCOMPARE(target->finished(), 0);
2225
    QCOMPARE(target->canceled(), 1);
2226
2227
    // Tap would end if not canceled
2228
    QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2229
    QCOMPARE(target->started(),  1);
2230
    QCOMPARE(target->updated(),  0);
2231
    QCOMPARE(target->finished(), 0);
2232
    QCOMPARE(target->canceled(), 1);
2233
2234
    // New "Tap" starts
2235
    QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2236
    QCOMPARE(target->started(),  2);
2237
    QCOMPARE(target->updated(),  0);
2238
    QCOMPARE(target->finished(), 0);
2239
    QCOMPARE(target->canceled(), 1);
2240
2241
    QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2242
    QCOMPARE(target->started(),  2);
2243
    QCOMPARE(target->updated(),  0);
2244
    QCOMPARE(target->finished(), 1);
2245
    QCOMPARE(target->canceled(), 1);
2246
}
2247
2248
void tst_Gestures::conflictingGesturesInGraphicsView()
2249
{
2250
    QGraphicsScene scene;
2251
    GraphicsView view(&scene);
2252
    view.setWindowFlags(Qt::X11BypassWindowManagerHint);
2253
2254
    GestureItem *item1 = new GestureItem("item1");
2255
    item1->grabGesture(CustomGesture::GestureType);
2256
    item1->size = QRectF(0, 0, 100, 100);
2257
    item1->setZValue(2);
2258
    scene.addItem(item1);
2259
2260
    GestureItem *item2 = new GestureItem("item2");
2261
    item2->grabGesture(CustomGesture::GestureType);
2262
    item2->size = QRectF(0, 0, 100, 100);
2263
    item2->setZValue(5);
2264
    scene.addItem(item2);
2265
2266
    view.show();
2267
    QTest::qWaitForWindowShown(&view);
2268
    view.ensureVisible(scene.sceneRect());
2269
2270
    static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2271
2272
    CustomEvent event;
2273
2274
    // nobody accepts override
2275
    item1->acceptGestureOverride = false;
2276
    item2->acceptGestureOverride = false;
2277
    event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2278
    event.hasHotSpot = true;
2279
    sendCustomGesture(&event, item2, &scene);
2280
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2281
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2282
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2283
    QCOMPARE(item1->gestureEventsReceived, 0);
2284
2285
    item1->reset(); item2->reset();
2286
2287
    // the original target accepts override
2288
    item1->acceptGestureOverride = false;
2289
    item2->acceptGestureOverride = true;
2290
    event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2291
    event.hasHotSpot = true;
2292
    sendCustomGesture(&event, item2, &scene);
2293
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2294
    QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2295
    QCOMPARE(item1->gestureOverrideEventsReceived, 0);
2296
    QCOMPARE(item1->gestureEventsReceived, 0);
2297
2298
    item1->reset(); item2->reset();
2299
2300
    // the item behind accepts override
2301
    item1->acceptGestureOverride = true;
2302
    item2->acceptGestureOverride = false;
2303
    event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2304
    event.hasHotSpot = true;
2305
    sendCustomGesture(&event, item2, &scene);
2306
2307
    QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2308
    QCOMPARE(item2->gestureEventsReceived, 0);
2309
    QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2310
    QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2311
}
2312
2313
class NoConsumeWidgetBug13501 :public QWidget
2314
{
2315
    Q_OBJECT
2316
protected:
2317
    bool event(QEvent *e) {
2318
        if(e->type() == QEvent::Gesture) {
2319
            return false;
2320
        }
2321
        return QWidget::event(e);
2322
    }
2323
};
2324
2325
void tst_Gestures::bug_13501_gesture_not_accepted()
2326
{
2327
    // Create a gesture event that is not accepted by any widget
2328
    // make sure this does not lead to an assert in QGestureManager
2329
    NoConsumeWidgetBug13501 w;
2330
    w.grabGesture(Qt::TapGesture);
2331
    w.show();
2332
    QTest::qWaitForWindowShown(&w);
2333
    //QTest::mousePress(&ignoreEvent, Qt::LeftButton);
2334
    QTest::touchEvent(&w).press(0, QPoint(10, 10), &w);
2335
}
2336
2337
QTEST_MAIN(tst_Gestures)
2338
#include "tst_gestures.moc"