~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to tests/auto/other/gestures/tst_gestures.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

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