997e15ed5542b5b3ff4a4588d5bc3bceb286dc13
[profile/ivi/qtbase.git] / tests / auto / gui / kernel / qtouchevent / tst_qtouchevent.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the $MODULE$ of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtGui>
43 #include <QtWidgets>
44 #include <QtTest>
45
46 class tst_QTouchEventWidget : public QWidget
47 {
48 public:
49     QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints;
50     bool seenTouchBegin, seenTouchUpdate, seenTouchEnd;
51     bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd;
52     bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
53     ulong timestamp;
54     QTouchDevice *deviceFromEvent;
55
56     tst_QTouchEventWidget()
57         : QWidget()
58     {
59         reset();
60     }
61
62     void reset()
63     {
64         touchBeginPoints.clear();
65         touchUpdatePoints.clear();
66         touchEndPoints.clear();
67         seenTouchBegin = seenTouchUpdate = seenTouchEnd = false;
68         acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true;
69         deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
70     }
71
72     bool event(QEvent *event)
73     {
74         switch (event->type()) {
75         case QEvent::TouchBegin:
76             if (seenTouchBegin) qWarning("TouchBegin: already seen a TouchBegin");
77             if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin");
78             if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin");
79             seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd;
80             touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints();
81             timestamp = static_cast<QTouchEvent *>(event)->timestamp();
82             deviceFromEvent = static_cast<QTouchEvent *>(event)->device();
83             event->setAccepted(acceptTouchBegin);
84             if (deleteInTouchBegin)
85                 delete this;
86             break;
87         case QEvent::TouchUpdate:
88             if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin");
89             if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate");
90             seenTouchUpdate = seenTouchBegin && !seenTouchEnd;
91             touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints();
92             timestamp = static_cast<QTouchEvent *>(event)->timestamp();
93             deviceFromEvent = static_cast<QTouchEvent *>(event)->device();
94             event->setAccepted(acceptTouchUpdate);
95             if (deleteInTouchUpdate)
96                 delete this;
97             break;
98         case QEvent::TouchEnd:
99             if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin");
100             if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd");
101             seenTouchEnd = seenTouchBegin && !seenTouchEnd;
102             touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints();
103             timestamp = static_cast<QTouchEvent *>(event)->timestamp();
104             deviceFromEvent = static_cast<QTouchEvent *>(event)->device();
105             event->setAccepted(acceptTouchEnd);
106             if (deleteInTouchEnd)
107                 delete this;
108             break;
109         default:
110             return QWidget::event(event);
111         }
112         return true;
113     }
114 };
115
116 class tst_QTouchEventGraphicsItem : public QGraphicsItem
117 {
118 public:
119     QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints;
120     bool seenTouchBegin, seenTouchUpdate, seenTouchEnd;
121     int touchBeginCounter, touchUpdateCounter, touchEndCounter;
122     bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd;
123     bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
124     tst_QTouchEventGraphicsItem **weakpointer;
125
126     tst_QTouchEventGraphicsItem()
127         : QGraphicsItem(), weakpointer(0)
128     {
129         reset();
130     }
131
132     ~tst_QTouchEventGraphicsItem()
133     {
134         if (weakpointer)
135             *weakpointer = 0;
136     }
137
138     void reset()
139     {
140         touchBeginPoints.clear();
141         touchUpdatePoints.clear();
142         touchEndPoints.clear();
143         seenTouchBegin = seenTouchUpdate = seenTouchEnd = false;
144         touchBeginCounter = touchUpdateCounter = touchEndCounter = 0;
145         acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true;
146         deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
147     }
148
149     QRectF boundingRect() const { return QRectF(0, 0, 10, 10); }
150     void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) { }
151
152     bool sceneEvent(QEvent *event)
153     {
154         switch (event->type()) {
155         case QEvent::TouchBegin:
156             if (seenTouchBegin) qWarning("TouchBegin: already seen a TouchBegin");
157             if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin");
158             if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin");
159             seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd;
160             ++touchBeginCounter;
161             touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints();
162             event->setAccepted(acceptTouchBegin);
163             if (deleteInTouchBegin)
164                 delete this;
165             break;
166         case QEvent::TouchUpdate:
167             if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin");
168             if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate");
169             seenTouchUpdate = seenTouchBegin && !seenTouchEnd;
170             ++touchUpdateCounter;
171             touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints();
172             event->setAccepted(acceptTouchUpdate);
173             if (deleteInTouchUpdate)
174                 delete this;
175             break;
176         case QEvent::TouchEnd:
177             if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin");
178             if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd");
179             seenTouchEnd = seenTouchBegin && !seenTouchEnd;
180             ++touchEndCounter;
181             touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints();
182             event->setAccepted(acceptTouchEnd);
183             if (deleteInTouchEnd)
184                 delete this;
185             break;
186         default:
187             return QGraphicsItem::sceneEvent(event);
188         }
189         return true;
190     }
191 };
192
193 class tst_QTouchEvent : public QObject
194 {
195     Q_OBJECT
196 public:
197     tst_QTouchEvent();
198     ~tst_QTouchEvent() { }
199
200 private slots:
201     void touchDisabledByDefault();
202     void touchEventAcceptedByDefault();
203     void touchBeginPropagatesWhenIgnored();
204     void touchUpdateAndEndNeverPropagate();
205     void basicRawEventTranslation();
206     void multiPointRawEventTranslationOnTouchScreen();
207     void multiPointRawEventTranslationOnTouchPad();
208     void deleteInEventHandler();
209     void deleteInRawEventTranslation();
210     void crashInQGraphicsSceneAfterNotHandlingTouchBegin();
211     void touchBeginWithGraphicsWidget();
212     void testQGuiAppDelivery();
213     void testMultiDevice();
214
215 private:
216     QTouchDevice *touchScreenDevice;
217     QTouchDevice *touchPadDevice;
218 };
219
220 tst_QTouchEvent::tst_QTouchEvent()
221 {
222     touchScreenDevice = new QTouchDevice;
223     touchPadDevice = new QTouchDevice;
224     touchPadDevice->setType(QTouchDevice::TouchPad);
225     QWindowSystemInterface::registerTouchDevice(touchScreenDevice);
226     QWindowSystemInterface::registerTouchDevice(touchPadDevice);
227 }
228
229 void tst_QTouchEvent::touchDisabledByDefault()
230 {
231     // QWidget
232     {
233         // the widget attribute is not enabled by default
234         QWidget widget;
235         QVERIFY(!widget.testAttribute(Qt::WA_AcceptTouchEvents));
236
237         // events should not be accepted since they are not enabled
238         QList<QTouchEvent::TouchPoint> touchPoints;
239         touchPoints.append(QTouchEvent::TouchPoint(0));
240         QTouchEvent touchEvent(QEvent::TouchBegin,
241                                touchScreenDevice,
242                                Qt::NoModifier,
243                                Qt::TouchPointPressed,
244                                touchPoints);
245         bool res = QApplication::sendEvent(&widget, &touchEvent);
246         QVERIFY(!res);
247         QVERIFY(!touchEvent.isAccepted());
248     }
249
250     // QGraphicsView
251     {
252         QGraphicsScene scene;
253         tst_QTouchEventGraphicsItem item;
254         QGraphicsView view(&scene);
255         scene.addItem(&item);
256         item.setPos(100, 100);
257         view.resize(200, 200);
258         view.fitInView(scene.sceneRect());
259
260         // touch events are not accepted by default
261         QVERIFY(!item.acceptTouchEvents());
262
263         // compose an event to the scene that is over the item
264         QTouchEvent::TouchPoint touchPoint(0);
265         touchPoint.setState(Qt::TouchPointPressed);
266         touchPoint.setPos(view.mapFromScene(item.mapToScene(item.boundingRect().center())));
267         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
268         touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
269         QTouchEvent touchEvent(QEvent::TouchBegin,
270                                touchScreenDevice,
271                                Qt::NoModifier,
272                                Qt::TouchPointPressed,
273                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
274         bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
275         QVERIFY(!res);
276         QVERIFY(!touchEvent.isAccepted());
277         QVERIFY(!item.seenTouchBegin);
278     }
279 }
280
281 void tst_QTouchEvent::touchEventAcceptedByDefault()
282 {
283     // QWidget
284     {
285         // enabling touch events should automatically accept touch events
286         QWidget widget;
287         widget.setAttribute(Qt::WA_AcceptTouchEvents);
288
289         // QWidget handles touch event by converting them into a mouse event, so the event is both
290         // accepted and handled (res == true)
291         QList<QTouchEvent::TouchPoint> touchPoints;
292         touchPoints.append(QTouchEvent::TouchPoint(0));
293         QTouchEvent touchEvent(QEvent::TouchBegin,
294                                touchScreenDevice,
295                                Qt::NoModifier,
296                                Qt::TouchPointPressed,
297                                touchPoints);
298         bool res = QApplication::sendEvent(&widget, &touchEvent);
299         QVERIFY(res);
300         QVERIFY(touchEvent.isAccepted());
301
302         // tst_QTouchEventWidget does handle, sending succeeds
303         tst_QTouchEventWidget touchWidget;
304         touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
305         touchEvent.ignore();
306         res = QApplication::sendEvent(&touchWidget, &touchEvent);
307         QVERIFY(res);
308         QVERIFY(touchEvent.isAccepted());
309     }
310
311     // QGraphicsView
312     {
313         QGraphicsScene scene;
314         tst_QTouchEventGraphicsItem item;
315         QGraphicsView view(&scene);
316         scene.addItem(&item);
317         item.setPos(100, 100);
318         view.resize(200, 200);
319         view.fitInView(scene.sceneRect());
320
321         // enabling touch events on the item also enables events on the viewport
322         item.setAcceptTouchEvents(true);
323         QVERIFY(view.viewport()->testAttribute(Qt::WA_AcceptTouchEvents));
324
325         // compose an event to the scene that is over the item
326         QTouchEvent::TouchPoint touchPoint(0);
327         touchPoint.setState(Qt::TouchPointPressed);
328         touchPoint.setPos(view.mapFromScene(item.mapToScene(item.boundingRect().center())));
329         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
330         touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
331         QTouchEvent touchEvent(QEvent::TouchBegin,
332                                touchScreenDevice,
333                                Qt::NoModifier,
334                                Qt::TouchPointPressed,
335                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
336         bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
337         QVERIFY(res);
338         QVERIFY(touchEvent.isAccepted());
339         QVERIFY(item.seenTouchBegin);
340     }
341 }
342
343 void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
344 {
345     // QWidget
346     {
347         tst_QTouchEventWidget window, child, grandchild;
348         child.setParent(&window);
349         grandchild.setParent(&child);
350
351         // all widgets accept touch events, grandchild ignores, so child sees the event, but not window
352         window.setAttribute(Qt::WA_AcceptTouchEvents);
353         child.setAttribute(Qt::WA_AcceptTouchEvents);
354         grandchild.setAttribute(Qt::WA_AcceptTouchEvents);
355         grandchild.acceptTouchBegin = false;
356
357         QList<QTouchEvent::TouchPoint> touchPoints;
358         touchPoints.append(QTouchEvent::TouchPoint(0));
359         QTouchEvent touchEvent(QEvent::TouchBegin,
360                                touchScreenDevice,
361                                Qt::NoModifier,
362                                Qt::TouchPointPressed,
363                                touchPoints);
364         bool res = QApplication::sendEvent(&grandchild, &touchEvent);
365         QVERIFY(res);
366         QVERIFY(touchEvent.isAccepted());
367         QVERIFY(grandchild.seenTouchBegin);
368         QVERIFY(child.seenTouchBegin);
369         QVERIFY(!window.seenTouchBegin);
370
371         // disable touch on grandchild. even though it doesn't accept it, child should still get the
372         // TouchBegin
373         grandchild.reset();
374         child.reset();
375         window.reset();
376         grandchild.setAttribute(Qt::WA_AcceptTouchEvents, false);
377
378         touchEvent.ignore();
379         res = QApplication::sendEvent(&grandchild, &touchEvent);
380         QVERIFY(res);
381         QVERIFY(touchEvent.isAccepted());
382         QVERIFY(!grandchild.seenTouchBegin);
383         QVERIFY(child.seenTouchBegin);
384         QVERIFY(!window.seenTouchBegin);
385     }
386
387     // QGraphicsView
388     {
389         QGraphicsScene scene;
390         tst_QTouchEventGraphicsItem root, child, grandchild;        
391         QGraphicsView view(&scene);
392         scene.addItem(&root);
393         root.setPos(100, 100);
394         child.setParentItem(&root);
395         grandchild.setParentItem(&child);
396         view.resize(200, 200);
397         view.fitInView(scene.sceneRect());
398
399         // all items accept touch events, grandchild ignores, so child sees the event, but not root
400         root.setAcceptTouchEvents(true);
401         child.setAcceptTouchEvents(true);
402         grandchild.setAcceptTouchEvents(true);
403         grandchild.acceptTouchBegin = false;
404
405         // compose an event to the scene that is over the grandchild
406         QTouchEvent::TouchPoint touchPoint(0);
407         touchPoint.setState(Qt::TouchPointPressed);
408         touchPoint.setPos(view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())));
409         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
410         touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
411         QTouchEvent touchEvent(QEvent::TouchBegin,
412                                touchScreenDevice,
413                                Qt::NoModifier,
414                                Qt::TouchPointPressed,
415                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
416         bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
417         QVERIFY(res);
418         QVERIFY(touchEvent.isAccepted());
419         QVERIFY(grandchild.seenTouchBegin);
420         QVERIFY(child.seenTouchBegin);
421         QVERIFY(!root.seenTouchBegin);
422     }
423
424     // QGraphicsView
425     {
426         QGraphicsScene scene;
427         tst_QTouchEventGraphicsItem root, child, grandchild;
428         QGraphicsView view(&scene);
429         scene.addItem(&root);
430         root.setPos(100, 100);
431         child.setParentItem(&root);
432         grandchild.setParentItem(&child);
433         view.resize(200, 200);
434         view.fitInView(scene.sceneRect());
435
436         // leave touch disabled on grandchild. even though it doesn't accept it, child should
437         // still get the TouchBegin
438         root.setAcceptTouchEvents(true);
439         child.setAcceptTouchEvents(true);
440
441         // compose an event to the scene that is over the grandchild
442         QTouchEvent::TouchPoint touchPoint(0);
443         touchPoint.setState(Qt::TouchPointPressed);
444         touchPoint.setPos(view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())));
445         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
446         touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
447         QTouchEvent touchEvent(QEvent::TouchBegin,
448                                touchScreenDevice,
449                                Qt::NoModifier,
450                                Qt::TouchPointPressed,
451                                (QList<QTouchEvent::TouchPoint>() << touchPoint));
452         bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
453         QVERIFY(res);
454         QVERIFY(touchEvent.isAccepted());
455         QVERIFY(!grandchild.seenTouchBegin);
456         QVERIFY(child.seenTouchBegin);
457         QVERIFY(!root.seenTouchBegin);
458     }
459 }
460
461 void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
462 {
463     // QWidget
464     {
465         tst_QTouchEventWidget window, child;
466         child.setParent(&window);
467
468         window.setAttribute(Qt::WA_AcceptTouchEvents);
469         child.setAttribute(Qt::WA_AcceptTouchEvents);
470         child.acceptTouchUpdate = false;
471         child.acceptTouchEnd = false;
472
473         QList<QTouchEvent::TouchPoint> touchPoints;
474         touchPoints.append(QTouchEvent::TouchPoint(0));
475         QTouchEvent touchBeginEvent(QEvent::TouchBegin,
476                                     touchScreenDevice,
477                                     Qt::NoModifier,
478                                     Qt::TouchPointPressed,
479                                     touchPoints);
480         bool res = QApplication::sendEvent(&child, &touchBeginEvent);
481         QVERIFY(res);
482         QVERIFY(touchBeginEvent.isAccepted());
483         QVERIFY(child.seenTouchBegin);
484         QVERIFY(!window.seenTouchBegin);
485
486         // send the touch update to the child, but ignore it, it doesn't propagate
487         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
488                                      touchScreenDevice,
489                                      Qt::NoModifier,
490                                      Qt::TouchPointMoved,
491                                      touchPoints);
492         res = QApplication::sendEvent(&child, &touchUpdateEvent);
493         QVERIFY(res);
494         QVERIFY(!touchUpdateEvent.isAccepted());
495         QVERIFY(child.seenTouchUpdate);
496         QVERIFY(!window.seenTouchUpdate);
497
498         // send the touch end, same thing should happen as with touch update
499         QTouchEvent touchEndEvent(QEvent::TouchEnd,
500                                   touchScreenDevice,
501                                   Qt::NoModifier,
502                                   Qt::TouchPointReleased,
503                                   touchPoints);
504         res = QApplication::sendEvent(&child, &touchEndEvent);
505         QVERIFY(res);
506         QVERIFY(!touchEndEvent.isAccepted());
507         QVERIFY(child.seenTouchEnd);
508         QVERIFY(!window.seenTouchEnd);
509     }
510
511     // QGraphicsView
512     {
513         QGraphicsScene scene;
514         tst_QTouchEventGraphicsItem root, child, grandchild;
515         QGraphicsView view(&scene);
516         scene.addItem(&root);
517         root.setPos(100, 100);
518         child.setParentItem(&root);
519         grandchild.setParentItem(&child);
520         view.resize(200, 200);
521         view.fitInView(scene.sceneRect());
522
523         root.setAcceptTouchEvents(true);
524         child.setAcceptTouchEvents(true);
525         child.acceptTouchUpdate = false;
526         child.acceptTouchEnd = false;
527
528         // compose an event to the scene that is over the child
529         QTouchEvent::TouchPoint touchPoint(0);
530         touchPoint.setState(Qt::TouchPointPressed);
531         touchPoint.setPos(view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())));
532         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
533         touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
534         QTouchEvent touchBeginEvent(QEvent::TouchBegin,
535                                     touchScreenDevice,
536                                     Qt::NoModifier,
537                                     Qt::TouchPointPressed,
538                                     (QList<QTouchEvent::TouchPoint>() << touchPoint));
539         bool res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
540         QVERIFY(res);
541         QVERIFY(touchBeginEvent.isAccepted());
542         QVERIFY(child.seenTouchBegin);
543         QVERIFY(!root.seenTouchBegin);
544
545         // send the touch update to the child, but ignore it, it doesn't propagate
546         touchPoint.setState(Qt::TouchPointMoved);
547         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
548                                      touchScreenDevice,
549                                      Qt::NoModifier,
550                                      Qt::TouchPointMoved,
551                                      (QList<QTouchEvent::TouchPoint>() << touchPoint));
552         res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
553         QVERIFY(res);
554         // the scene accepts the event, since it found an item to send the event to
555         QVERIFY(!touchUpdateEvent.isAccepted());
556         QVERIFY(child.seenTouchUpdate);
557         QVERIFY(!root.seenTouchUpdate);
558
559         // send the touch end, same thing should happen as with touch update
560         touchPoint.setState(Qt::TouchPointReleased);
561         QTouchEvent touchEndEvent(QEvent::TouchEnd,
562                                   touchScreenDevice,
563                                   Qt::NoModifier,
564                                   Qt::TouchPointReleased,
565                                   (QList<QTouchEvent::TouchPoint>() << touchPoint));
566         res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
567         QVERIFY(res);
568         // the scene accepts the event, since it found an item to send the event to
569         QVERIFY(!touchEndEvent.isAccepted());
570         QVERIFY(child.seenTouchEnd);
571         QVERIFY(!root.seenTouchEnd);
572     }
573 }
574
575 QPointF normalized(const QPointF &pos, const QRectF &rect)
576 {
577     return QPointF(pos.x() / rect.width(), pos.y() / rect.height());
578 }
579
580 void tst_QTouchEvent::basicRawEventTranslation()
581 {
582     tst_QTouchEventWidget touchWidget;
583     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
584     touchWidget.setGeometry(100, 100, 400, 300);
585
586     QPointF pos = touchWidget.rect().center();
587     QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
588     QPointF delta(10, 10);
589     QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
590
591     QTouchEvent::TouchPoint rawTouchPoint;
592     rawTouchPoint.setId(0);
593
594     // this should be translated to a TouchBegin
595     rawTouchPoint.setState(Qt::TouchPointPressed);
596     rawTouchPoint.setScreenPos(screenPos);
597     rawTouchPoint.setNormalizedPos(normalized(rawTouchPoint.pos(), screenGeometry));
598     QVector<QPointF> rawPosList;
599     rawPosList << QPointF(12, 34) << QPointF(56, 78);
600     rawTouchPoint.setRawScreenPositions(rawPosList);
601     const ulong timestamp = 1234;
602     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
603                                              timestamp,
604                                              touchScreenDevice,
605                                              QTest::QTouchEventSequence::touchPointList(
606                                                  QList<QTouchEvent::TouchPoint>() << rawTouchPoint));
607     QCoreApplication::processEvents();
608     QVERIFY(touchWidget.seenTouchBegin);
609     QVERIFY(!touchWidget.seenTouchUpdate);
610     QVERIFY(!touchWidget.seenTouchEnd);
611     QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
612     QCOMPARE(touchWidget.timestamp, timestamp);
613     QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.first();
614     QCOMPARE(touchBeginPoint.id(), rawTouchPoint.id());
615     QCOMPARE(touchBeginPoint.state(), rawTouchPoint.state());
616     QCOMPARE(touchBeginPoint.pos(), pos);
617     QCOMPARE(touchBeginPoint.startPos(), pos);
618     QCOMPARE(touchBeginPoint.lastPos(), pos);
619     QCOMPARE(touchBeginPoint.scenePos(), rawTouchPoint.screenPos());
620     QCOMPARE(touchBeginPoint.startScenePos(), rawTouchPoint.screenPos());
621     QCOMPARE(touchBeginPoint.lastScenePos(), rawTouchPoint.screenPos());
622     QCOMPARE(touchBeginPoint.screenPos(), rawTouchPoint.screenPos());
623     QCOMPARE(touchBeginPoint.startScreenPos(), rawTouchPoint.screenPos());
624     QCOMPARE(touchBeginPoint.lastScreenPos(), rawTouchPoint.screenPos());
625     QCOMPARE(touchBeginPoint.normalizedPos(), rawTouchPoint.normalizedPos());
626     QCOMPARE(touchBeginPoint.startNormalizedPos(), touchBeginPoint.normalizedPos());
627     QCOMPARE(touchBeginPoint.lastNormalizedPos(), touchBeginPoint.normalizedPos());
628     QCOMPARE(touchBeginPoint.rect(), QRectF(pos, QSizeF(0, 0)));
629     QCOMPARE(touchBeginPoint.screenRect(), QRectF(rawTouchPoint.screenPos(), QSizeF(0, 0)));
630     QCOMPARE(touchBeginPoint.sceneRect(), touchBeginPoint.screenRect());
631     QCOMPARE(touchBeginPoint.pressure(), qreal(1.));
632     QCOMPARE(touchBeginPoint.velocity(), QVector2D());
633     QCOMPARE(touchBeginPoint.rawScreenPositions(), rawPosList);
634
635     // moving the point should translate to TouchUpdate
636     rawTouchPoint.setState(Qt::TouchPointMoved);
637     rawTouchPoint.setScreenPos(screenPos + delta);
638     rawTouchPoint.setNormalizedPos(normalized(rawTouchPoint.pos(), screenGeometry));
639     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
640                                              0,
641                                              touchScreenDevice,
642                                              QTest::QTouchEventSequence::touchPointList(QList<QTouchEvent::TouchPoint>() << rawTouchPoint));
643     QCoreApplication::processEvents();
644     QVERIFY(touchWidget.seenTouchBegin);
645     QVERIFY(touchWidget.seenTouchUpdate);
646     QVERIFY(!touchWidget.seenTouchEnd);
647     QCOMPARE(touchWidget.touchUpdatePoints.count(), 1);
648     QTouchEvent::TouchPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first();
649     QCOMPARE(touchUpdatePoint.id(), rawTouchPoint.id());
650     QCOMPARE(touchUpdatePoint.state(), rawTouchPoint.state());
651     QCOMPARE(touchUpdatePoint.pos(), pos + delta);
652     QCOMPARE(touchUpdatePoint.startPos(), pos);
653     QCOMPARE(touchUpdatePoint.lastPos(), pos);
654     QCOMPARE(touchUpdatePoint.scenePos(), rawTouchPoint.screenPos());
655     QCOMPARE(touchUpdatePoint.startScenePos(), screenPos);
656     QCOMPARE(touchUpdatePoint.lastScenePos(), screenPos);
657     QCOMPARE(touchUpdatePoint.screenPos(), rawTouchPoint.screenPos());
658     QCOMPARE(touchUpdatePoint.startScreenPos(), screenPos);
659     QCOMPARE(touchUpdatePoint.lastScreenPos(), screenPos);
660     QCOMPARE(touchUpdatePoint.normalizedPos(), rawTouchPoint.normalizedPos());
661     QCOMPARE(touchUpdatePoint.startNormalizedPos(), touchBeginPoint.normalizedPos());
662     QCOMPARE(touchUpdatePoint.lastNormalizedPos(), touchBeginPoint.normalizedPos());
663     QCOMPARE(touchUpdatePoint.rect(), QRectF(pos + delta, QSizeF(0, 0)));
664     QCOMPARE(touchUpdatePoint.screenRect(), QRectF(rawTouchPoint.screenPos(), QSizeF(0, 0)));
665     QCOMPARE(touchUpdatePoint.sceneRect(), touchUpdatePoint.screenRect());
666     QCOMPARE(touchUpdatePoint.pressure(), qreal(1.));
667
668     // releasing the point translates to TouchEnd
669     rawTouchPoint.setState(Qt::TouchPointReleased);
670     rawTouchPoint.setScreenPos(screenPos + delta + delta);
671     rawTouchPoint.setNormalizedPos(normalized(rawTouchPoint.pos(), screenGeometry));
672     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
673                                              0,
674                                              touchScreenDevice,
675                                              QTest::QTouchEventSequence::touchPointList(QList<QTouchEvent::TouchPoint>() << rawTouchPoint));
676     QCoreApplication::processEvents();
677     QVERIFY(touchWidget.seenTouchBegin);
678     QVERIFY(touchWidget.seenTouchUpdate);
679     QVERIFY(touchWidget.seenTouchEnd);
680     QCOMPARE(touchWidget.touchEndPoints.count(), 1);
681     QTouchEvent::TouchPoint touchEndPoint = touchWidget.touchEndPoints.first();
682     QCOMPARE(touchEndPoint.id(), rawTouchPoint.id());
683     QCOMPARE(touchEndPoint.state(), rawTouchPoint.state());
684     QCOMPARE(touchEndPoint.pos(), pos + delta + delta);
685     QCOMPARE(touchEndPoint.startPos(), pos);
686     QCOMPARE(touchEndPoint.lastPos(), pos + delta);
687     QCOMPARE(touchEndPoint.scenePos(), rawTouchPoint.screenPos());
688     QCOMPARE(touchEndPoint.startScenePos(), screenPos);
689     QCOMPARE(touchEndPoint.lastScenePos(), screenPos + delta);
690     QCOMPARE(touchEndPoint.screenPos(), rawTouchPoint.screenPos());
691     QCOMPARE(touchEndPoint.startScreenPos(), screenPos);
692     QCOMPARE(touchEndPoint.lastScreenPos(), screenPos + delta);
693     QCOMPARE(touchEndPoint.normalizedPos(), rawTouchPoint.normalizedPos());
694     QCOMPARE(touchEndPoint.startNormalizedPos(), touchBeginPoint.normalizedPos());
695     QCOMPARE(touchEndPoint.lastNormalizedPos(), touchUpdatePoint.normalizedPos());
696     QCOMPARE(touchEndPoint.rect(), QRectF(pos + delta + delta, QSizeF(0, 0)));
697     QCOMPARE(touchEndPoint.screenRect(), QRectF(rawTouchPoint.screenPos(), QSizeF(0, 0)));
698     QCOMPARE(touchEndPoint.sceneRect(), touchEndPoint.screenRect());
699     QCOMPARE(touchEndPoint.pressure(), qreal(0.));
700 }
701
702 void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
703 {
704     tst_QTouchEventWidget touchWidget;
705     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
706     touchWidget.setGeometry(100, 100, 400, 300);
707
708     tst_QTouchEventWidget leftWidget;
709     leftWidget.setParent(&touchWidget);
710     leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
711     leftWidget.setGeometry(0, 100, 100, 100);
712     leftWidget.show();
713
714     tst_QTouchEventWidget rightWidget;
715     rightWidget.setParent(&touchWidget);
716     rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
717     rightWidget.setGeometry(300, 100, 100, 100);
718     rightWidget.show();
719
720     QPointF leftPos = leftWidget.rect().center();
721     QPointF rightPos = rightWidget.rect().center();
722     QPointF centerPos = touchWidget.rect().center();
723     QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
724     QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
725     QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
726     QPointF delta(10, 10);
727     QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
728
729     QList<QTouchEvent::TouchPoint> rawTouchPoints;
730     rawTouchPoints.append(QTouchEvent::TouchPoint(0));
731     rawTouchPoints.append(QTouchEvent::TouchPoint(1));
732
733     // generate TouchBegins on both leftWidget and rightWidget
734     rawTouchPoints[0].setState(Qt::TouchPointPressed);
735     rawTouchPoints[0].setScreenPos(leftScreenPos);
736     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
737     rawTouchPoints[1].setState(Qt::TouchPointPressed);
738     rawTouchPoints[1].setScreenPos(rightScreenPos);
739     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
740     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
741                                              0,
742                                              touchScreenDevice,
743                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
744     QCoreApplication::processEvents();
745     QVERIFY(!touchWidget.seenTouchBegin);
746     QVERIFY(!touchWidget.seenTouchUpdate);
747     QVERIFY(!touchWidget.seenTouchEnd);
748     QVERIFY(leftWidget.seenTouchBegin);
749     QVERIFY(!leftWidget.seenTouchUpdate);
750     QVERIFY(!leftWidget.seenTouchEnd);
751     QVERIFY(rightWidget.seenTouchBegin);
752     QVERIFY(!rightWidget.seenTouchUpdate);
753     QVERIFY(!rightWidget.seenTouchEnd);
754     QCOMPARE(leftWidget.touchBeginPoints.count(), 1);    
755     QCOMPARE(rightWidget.touchBeginPoints.count(), 1);
756     {
757         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchBeginPoints.first();
758         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
759         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
760         QCOMPARE(leftTouchPoint.pos(), leftPos);
761         QCOMPARE(leftTouchPoint.startPos(), leftPos);
762         QCOMPARE(leftTouchPoint.lastPos(), leftPos);
763         QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos);
764         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
765         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
766         QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos);
767         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
768         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
769         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
770         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
771         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
772         QCOMPARE(leftTouchPoint.rect(), QRectF(leftPos, QSizeF(0, 0)));
773         QCOMPARE(leftTouchPoint.sceneRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
774         QCOMPARE(leftTouchPoint.screenRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
775         QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
776
777         QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchBeginPoints.first();
778         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
779         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
780         QCOMPARE(rightTouchPoint.pos(), rightPos);
781         QCOMPARE(rightTouchPoint.startPos(), rightPos);
782         QCOMPARE(rightTouchPoint.lastPos(), rightPos);
783         QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos);
784         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
785         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
786         QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos);
787         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
788         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
789         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
790         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
791         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
792         QCOMPARE(rightTouchPoint.rect(), QRectF(rightPos, QSizeF(0, 0)));
793         QCOMPARE(rightTouchPoint.sceneRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
794         QCOMPARE(rightTouchPoint.screenRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
795         QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
796     }
797
798     // generate TouchUpdates on both leftWidget and rightWidget
799     rawTouchPoints[0].setState(Qt::TouchPointMoved);
800     rawTouchPoints[0].setScreenPos(centerScreenPos);
801     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
802     rawTouchPoints[1].setState(Qt::TouchPointMoved);
803     rawTouchPoints[1].setScreenPos(centerScreenPos);
804     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
805     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
806                                              0,
807                                              touchScreenDevice,
808                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
809     QCoreApplication::processEvents();
810     QVERIFY(!touchWidget.seenTouchBegin);
811     QVERIFY(!touchWidget.seenTouchUpdate);
812     QVERIFY(!touchWidget.seenTouchEnd);
813     QVERIFY(leftWidget.seenTouchBegin);
814     QVERIFY(leftWidget.seenTouchUpdate);
815     QVERIFY(!leftWidget.seenTouchEnd);
816     QVERIFY(rightWidget.seenTouchBegin);
817     QVERIFY(rightWidget.seenTouchUpdate);
818     QVERIFY(!rightWidget.seenTouchEnd);
819     QCOMPARE(leftWidget.touchUpdatePoints.count(), 1);
820     QCOMPARE(rightWidget.touchUpdatePoints.count(), 1);
821     {
822         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchUpdatePoints.first();
823         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
824         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
825         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
826         QCOMPARE(leftTouchPoint.startPos(), leftPos);
827         QCOMPARE(leftTouchPoint.lastPos(), leftPos);
828         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
829         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
830         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
831         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
832         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
833         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
834         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
835         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
836         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
837         QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
838         QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
839         QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
840         QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
841
842         QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchUpdatePoints.first();
843         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
844         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
845         QCOMPARE(rightTouchPoint.pos(), QPointF(rightWidget.mapFromParent(centerPos.toPoint())));
846         QCOMPARE(rightTouchPoint.startPos(), rightPos);
847         QCOMPARE(rightTouchPoint.lastPos(), rightPos);
848         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
849         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
850         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
851         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
852         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
853         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
854         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
855         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
856         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
857         QCOMPARE(rightTouchPoint.rect(), QRectF(rightWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
858         QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
859         QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
860         QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
861     }
862
863     // generate TouchEnds on both leftWidget and rightWidget
864     rawTouchPoints[0].setState(Qt::TouchPointReleased);
865     rawTouchPoints[0].setScreenPos(centerScreenPos);
866     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
867     rawTouchPoints[1].setState(Qt::TouchPointReleased);
868     rawTouchPoints[1].setScreenPos(centerScreenPos);
869     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
870     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
871                                              0,
872                                              touchScreenDevice,
873                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
874     QCoreApplication::processEvents();
875     QVERIFY(!touchWidget.seenTouchBegin);
876     QVERIFY(!touchWidget.seenTouchUpdate);
877     QVERIFY(!touchWidget.seenTouchEnd);
878     QVERIFY(leftWidget.seenTouchBegin);
879     QVERIFY(leftWidget.seenTouchUpdate);
880     QVERIFY(leftWidget.seenTouchEnd);
881     QVERIFY(rightWidget.seenTouchBegin);
882     QVERIFY(rightWidget.seenTouchUpdate);
883     QVERIFY(rightWidget.seenTouchEnd);
884     QCOMPARE(leftWidget.touchEndPoints.count(), 1);
885     QCOMPARE(rightWidget.touchEndPoints.count(), 1);
886     {
887         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchEndPoints.first();
888         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
889         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
890         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
891         QCOMPARE(leftTouchPoint.startPos(), leftPos);
892         QCOMPARE(leftTouchPoint.lastPos(), leftTouchPoint.pos());
893         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
894         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
895         QCOMPARE(leftTouchPoint.lastScenePos(), leftTouchPoint.scenePos());
896         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
897         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
898         QCOMPARE(leftTouchPoint.lastScreenPos(), leftTouchPoint.screenPos());
899         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
900         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
901         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
902         QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
903         QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
904         QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
905         QCOMPARE(leftTouchPoint.pressure(), qreal(0.));
906
907         QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchEndPoints.first();
908         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
909         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
910         QCOMPARE(rightTouchPoint.pos(), QPointF(rightWidget.mapFromParent(centerPos.toPoint())));
911         QCOMPARE(rightTouchPoint.startPos(), rightPos);
912         QCOMPARE(rightTouchPoint.lastPos(), rightTouchPoint.pos());
913         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
914         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
915         QCOMPARE(rightTouchPoint.lastScenePos(), rightTouchPoint.scenePos());
916         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
917         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
918         QCOMPARE(rightTouchPoint.lastScreenPos(), rightTouchPoint.screenPos());
919         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
920         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
921         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
922         QCOMPARE(rightTouchPoint.rect(), QRectF(rightWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
923         QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
924         QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
925         QCOMPARE(rightTouchPoint.pressure(), qreal(0.));
926     }
927 }
928
929 void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
930 {
931     tst_QTouchEventWidget touchWidget;
932     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
933     touchWidget.setGeometry(100, 100, 400, 300);
934
935     tst_QTouchEventWidget leftWidget;
936     leftWidget.setParent(&touchWidget);
937     leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
938     leftWidget.setGeometry(0, 100, 100, 100);
939     leftWidget.show();
940
941     tst_QTouchEventWidget rightWidget;
942     rightWidget.setParent(&touchWidget);
943     rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
944     rightWidget.setGeometry(300, 100, 100, 100);
945     rightWidget.show();
946
947     QPointF leftPos = leftWidget.rect().center();
948     QPointF rightPos = rightWidget.rect().center();
949     QPointF centerPos = touchWidget.rect().center();
950     QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
951     QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
952     QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
953     QPointF delta(10, 10);
954     QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
955
956     QList<QTouchEvent::TouchPoint> rawTouchPoints;
957     rawTouchPoints.append(QTouchEvent::TouchPoint(0));
958     rawTouchPoints.append(QTouchEvent::TouchPoint(1));
959
960     // generate TouchBegin on leftWidget only
961     rawTouchPoints[0].setState(Qt::TouchPointPressed);
962     rawTouchPoints[0].setScreenPos(leftScreenPos);
963     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
964     rawTouchPoints[1].setState(Qt::TouchPointPressed);
965     rawTouchPoints[1].setScreenPos(rightScreenPos);
966     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
967     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
968                                              0,
969                                              touchPadDevice,
970                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
971     QCoreApplication::processEvents();
972     QVERIFY(!touchWidget.seenTouchBegin);
973     QVERIFY(!touchWidget.seenTouchUpdate);
974     QVERIFY(!touchWidget.seenTouchEnd);
975     QVERIFY(leftWidget.seenTouchBegin);
976     QVERIFY(!leftWidget.seenTouchUpdate);
977     QVERIFY(!leftWidget.seenTouchEnd);
978     QVERIFY(!rightWidget.seenTouchBegin);
979     QVERIFY(!rightWidget.seenTouchUpdate);
980     QVERIFY(!rightWidget.seenTouchEnd);
981     QCOMPARE(leftWidget.touchBeginPoints.count(), 2);
982     QCOMPARE(rightWidget.touchBeginPoints.count(), 0);
983     {
984         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchBeginPoints.at(0);
985         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
986         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
987         QCOMPARE(leftTouchPoint.pos(), leftPos);
988         QCOMPARE(leftTouchPoint.startPos(), leftPos);
989         QCOMPARE(leftTouchPoint.lastPos(), leftPos);
990         QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos);
991         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
992         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
993         QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos);
994         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
995         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
996         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
997         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
998         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
999         QCOMPARE(leftTouchPoint.rect(), QRectF(leftPos, QSizeF(0, 0)));
1000         QCOMPARE(leftTouchPoint.sceneRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
1001         QCOMPARE(leftTouchPoint.screenRect(), QRectF(leftScreenPos, QSizeF(0, 0)));
1002         QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
1003
1004         QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchBeginPoints.at(1);
1005         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
1006         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
1007         QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
1008         QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
1009         QCOMPARE(rightTouchPoint.lastPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
1010         QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos);
1011         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
1012         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
1013         QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos);
1014         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
1015         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
1016         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
1017         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
1018         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
1019         QCOMPARE(rightTouchPoint.rect(), QRectF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()), QSizeF(0, 0)));
1020         QCOMPARE(rightTouchPoint.sceneRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
1021         QCOMPARE(rightTouchPoint.screenRect(), QRectF(rightScreenPos, QSizeF(0, 0)));
1022         QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
1023     }
1024
1025     // generate TouchUpdate on leftWidget
1026     rawTouchPoints[0].setState(Qt::TouchPointMoved);
1027     rawTouchPoints[0].setScreenPos(centerScreenPos);
1028     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
1029     rawTouchPoints[1].setState(Qt::TouchPointMoved);
1030     rawTouchPoints[1].setScreenPos(centerScreenPos);
1031     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
1032     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
1033                                              0,
1034                                              touchPadDevice,
1035                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
1036     QCoreApplication::processEvents();
1037     QVERIFY(!touchWidget.seenTouchBegin);
1038     QVERIFY(!touchWidget.seenTouchUpdate);
1039     QVERIFY(!touchWidget.seenTouchEnd);
1040     QVERIFY(leftWidget.seenTouchBegin);
1041     QVERIFY(leftWidget.seenTouchUpdate);
1042     QVERIFY(!leftWidget.seenTouchEnd);
1043     QVERIFY(!rightWidget.seenTouchBegin);
1044     QVERIFY(!rightWidget.seenTouchUpdate);
1045     QVERIFY(!rightWidget.seenTouchEnd);
1046     QCOMPARE(leftWidget.touchUpdatePoints.count(), 2);
1047     QCOMPARE(rightWidget.touchUpdatePoints.count(), 0);
1048     {
1049         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchUpdatePoints.at(0);
1050         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
1051         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
1052         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
1053         QCOMPARE(leftTouchPoint.startPos(), leftPos);
1054         QCOMPARE(leftTouchPoint.lastPos(), leftPos);
1055         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
1056         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
1057         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos);
1058         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
1059         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
1060         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos);
1061         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
1062         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
1063         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
1064         QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
1065         QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1066         QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1067         QCOMPARE(leftTouchPoint.pressure(), qreal(1.));
1068
1069         QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchUpdatePoints.at(1);
1070         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
1071         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
1072         QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
1073         QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
1074         QCOMPARE(rightTouchPoint.lastPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
1075         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
1076         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
1077         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos);
1078         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
1079         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
1080         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos);
1081         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
1082         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
1083         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
1084         QCOMPARE(rightTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
1085         QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1086         QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1087         QCOMPARE(rightTouchPoint.pressure(), qreal(1.));
1088     }
1089
1090     // generate TouchEnd on leftWidget
1091     rawTouchPoints[0].setState(Qt::TouchPointReleased);
1092     rawTouchPoints[0].setScreenPos(centerScreenPos);
1093     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
1094     rawTouchPoints[1].setState(Qt::TouchPointReleased);
1095     rawTouchPoints[1].setScreenPos(centerScreenPos);
1096     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
1097     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
1098                                              0,
1099                                              touchPadDevice,
1100                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
1101     QCoreApplication::processEvents();
1102     QVERIFY(!touchWidget.seenTouchBegin);
1103     QVERIFY(!touchWidget.seenTouchUpdate);
1104     QVERIFY(!touchWidget.seenTouchEnd);
1105     QVERIFY(leftWidget.seenTouchBegin);
1106     QVERIFY(leftWidget.seenTouchUpdate);
1107     QVERIFY(leftWidget.seenTouchEnd);
1108     QVERIFY(!rightWidget.seenTouchBegin);
1109     QVERIFY(!rightWidget.seenTouchUpdate);
1110     QVERIFY(!rightWidget.seenTouchEnd);
1111     QCOMPARE(leftWidget.touchEndPoints.count(), 2);
1112     QCOMPARE(rightWidget.touchEndPoints.count(), 0);
1113     {
1114         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchEndPoints.at(0);
1115         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id());
1116         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state());
1117         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
1118         QCOMPARE(leftTouchPoint.startPos(), leftPos);
1119         QCOMPARE(leftTouchPoint.lastPos(), leftTouchPoint.pos());
1120         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos);
1121         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos);
1122         QCOMPARE(leftTouchPoint.lastScenePos(), leftTouchPoint.scenePos());
1123         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos);
1124         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos);
1125         QCOMPARE(leftTouchPoint.lastScreenPos(), leftTouchPoint.screenPos());
1126         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos());
1127         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos());
1128         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos());
1129         QCOMPARE(leftTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
1130         QCOMPARE(leftTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1131         QCOMPARE(leftTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1132         QCOMPARE(leftTouchPoint.pressure(), qreal(0.));
1133
1134         QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchEndPoints.at(1);
1135         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id());
1136         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state());
1137         QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint())));
1138         QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint())));
1139         QCOMPARE(rightTouchPoint.lastPos(), rightTouchPoint.pos());
1140         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos);
1141         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos);
1142         QCOMPARE(rightTouchPoint.lastScenePos(), rightTouchPoint.scenePos());
1143         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos);
1144         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos);
1145         QCOMPARE(rightTouchPoint.lastScreenPos(), rightTouchPoint.screenPos());
1146         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos());
1147         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos());
1148         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos());
1149         QCOMPARE(rightTouchPoint.rect(), QRectF(leftWidget.mapFromParent(centerPos.toPoint()), QSizeF(0, 0)));
1150         QCOMPARE(rightTouchPoint.sceneRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1151         QCOMPARE(rightTouchPoint.screenRect(), QRectF(centerScreenPos, QSizeF(0, 0)));
1152         QCOMPARE(rightTouchPoint.pressure(), qreal(0.));
1153     }
1154 }
1155
1156 void tst_QTouchEvent::deleteInEventHandler()
1157 {
1158     // QWidget
1159     {
1160         QWidget window;
1161         tst_QTouchEventWidget *child1, *child2, *child3;
1162         child1 = new tst_QTouchEventWidget;
1163         child2 = new tst_QTouchEventWidget;
1164         child3 = new tst_QTouchEventWidget;
1165         child1->setParent(&window);
1166         child2->setParent(&window);
1167         child3->setParent(&window);
1168         child1->setAttribute(Qt::WA_AcceptTouchEvents);
1169         child2->setAttribute(Qt::WA_AcceptTouchEvents);
1170         child3->setAttribute(Qt::WA_AcceptTouchEvents);
1171         child1->deleteInTouchBegin = true;
1172         child2->deleteInTouchUpdate = true;
1173         child3->deleteInTouchEnd = true;
1174
1175         QList<QTouchEvent::TouchPoint> touchPoints;
1176         touchPoints.append(QTouchEvent::TouchPoint(0));
1177         QTouchEvent touchBeginEvent(QEvent::TouchBegin,
1178                                     touchScreenDevice,
1179                                     Qt::NoModifier,
1180                                     Qt::TouchPointPressed,
1181                                     touchPoints);
1182         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
1183                                touchScreenDevice,
1184                                Qt::NoModifier,
1185                                Qt::TouchPointStationary,
1186                                touchPoints);
1187         QTouchEvent touchEndEvent(QEvent::TouchEnd,
1188                                touchScreenDevice,
1189                                Qt::NoModifier,
1190                                Qt::TouchPointReleased,
1191                                touchPoints);
1192         QWeakPointer<QWidget> p;
1193         bool res;
1194
1195         touchBeginEvent.ignore();
1196         p = child1;
1197         res = QApplication::sendEvent(child1, &touchBeginEvent);
1198         // event is handled, but widget should be deleted
1199         QVERIFY(res && touchBeginEvent.isAccepted() && p.isNull());
1200
1201         touchBeginEvent.ignore();
1202         p = child2;
1203         res = QApplication::sendEvent(child2, &touchBeginEvent);
1204         QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
1205         touchUpdateEvent.ignore();
1206         res = QApplication::sendEvent(child2, &touchUpdateEvent);
1207         QVERIFY(res && touchUpdateEvent.isAccepted() && p.isNull());
1208
1209         touchBeginEvent.ignore();
1210         p = child3;
1211         res = QApplication::sendEvent(child3, &touchBeginEvent);
1212         QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
1213         touchUpdateEvent.ignore();
1214         res = QApplication::sendEvent(child3, &touchUpdateEvent);
1215         QVERIFY(res && touchUpdateEvent.isAccepted() && !p.isNull());
1216         touchEndEvent.ignore();
1217         res = QApplication::sendEvent(child3, &touchEndEvent);
1218         QVERIFY(res && touchEndEvent.isAccepted() && p.isNull());
1219     }
1220
1221     // QGraphicsView
1222     {
1223         QGraphicsScene scene;
1224         QGraphicsView view(&scene);
1225         tst_QTouchEventGraphicsItem *root, *child1, *child2, *child3;
1226         root = new tst_QTouchEventGraphicsItem;
1227         child1 = new tst_QTouchEventGraphicsItem;
1228         child2 = new tst_QTouchEventGraphicsItem;
1229         child3 = new tst_QTouchEventGraphicsItem;
1230         child1->setParentItem(root);
1231         child2->setParentItem(root);
1232         child3->setParentItem(root);
1233         child1->setZValue(1.);
1234         child2->setZValue(0.);
1235         child3->setZValue(-1.);
1236         child1->setAcceptTouchEvents(true);
1237         child2->setAcceptTouchEvents(true);
1238         child3->setAcceptTouchEvents(true);
1239         child1->deleteInTouchBegin = true;
1240         child2->deleteInTouchUpdate = true;
1241         child3->deleteInTouchEnd = true;
1242
1243         scene.addItem(root);
1244         view.resize(200, 200);
1245         view.fitInView(scene.sceneRect());
1246
1247         QTouchEvent::TouchPoint touchPoint(0);
1248         touchPoint.setState(Qt::TouchPointPressed);
1249         touchPoint.setPos(view.mapFromScene(child1->mapToScene(child1->boundingRect().center())));
1250         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint()));
1251         touchPoint.setScenePos(view.mapToScene(touchPoint.pos().toPoint()));
1252         QList<QTouchEvent::TouchPoint> touchPoints;
1253         touchPoints.append(touchPoint);
1254         QTouchEvent touchBeginEvent(QEvent::TouchBegin,
1255                                     touchScreenDevice,
1256                                     Qt::NoModifier,
1257                                     Qt::TouchPointPressed,
1258                                     touchPoints);
1259         touchPoints[0].setState(Qt::TouchPointMoved);
1260         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate,
1261                                touchScreenDevice,
1262                                Qt::NoModifier,
1263                                Qt::TouchPointMoved,
1264                                touchPoints);
1265         touchPoints[0].setState(Qt::TouchPointReleased);
1266         QTouchEvent touchEndEvent(QEvent::TouchEnd,
1267                                touchScreenDevice,
1268                                Qt::NoModifier,
1269                                Qt::TouchPointReleased,
1270                                touchPoints);
1271         bool res;
1272
1273         child1->weakpointer = &child1;
1274         touchBeginEvent.ignore();
1275         res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
1276         QVERIFY(res && touchBeginEvent.isAccepted() && !child1);
1277         touchUpdateEvent.ignore();
1278         res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
1279         QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
1280         touchEndEvent.ignore();
1281         res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
1282         QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
1283
1284         child2->weakpointer = &child2;
1285         touchBeginEvent.ignore();
1286         res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
1287         QVERIFY(res && touchBeginEvent.isAccepted() && child2);
1288         touchUpdateEvent.ignore();
1289         res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
1290         QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
1291         touchEndEvent.ignore();
1292         res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
1293         QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
1294
1295         child3->weakpointer = &child3;
1296         res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
1297         QVERIFY(res && touchBeginEvent.isAccepted() && child3);
1298         res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
1299         QVERIFY(res && !touchUpdateEvent.isAccepted() && child3);
1300         res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
1301         QVERIFY(res && !touchEndEvent.isAccepted() && !child3);
1302
1303         delete root;
1304     }
1305 }
1306
1307 void tst_QTouchEvent::deleteInRawEventTranslation()
1308 {
1309     tst_QTouchEventWidget touchWidget;
1310     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
1311     touchWidget.setGeometry(100, 100, 300, 300);
1312
1313     tst_QTouchEventWidget *leftWidget = new tst_QTouchEventWidget;
1314     leftWidget->setParent(&touchWidget);
1315     leftWidget->setAttribute(Qt::WA_AcceptTouchEvents);
1316     leftWidget->setGeometry(0, 100, 100, 100);
1317     leftWidget->deleteInTouchBegin = true;
1318     leftWidget->show();
1319
1320     tst_QTouchEventWidget *centerWidget = new tst_QTouchEventWidget;
1321     centerWidget->setParent(&touchWidget);
1322     centerWidget->setAttribute(Qt::WA_AcceptTouchEvents);
1323     centerWidget->setGeometry(100, 100, 100, 100);
1324     centerWidget->deleteInTouchUpdate = true;
1325     centerWidget->show();
1326
1327     tst_QTouchEventWidget *rightWidget = new tst_QTouchEventWidget;
1328     rightWidget->setParent(&touchWidget);
1329     rightWidget->setAttribute(Qt::WA_AcceptTouchEvents);
1330     rightWidget->setGeometry(200, 100, 100, 100);
1331     rightWidget->deleteInTouchEnd = true;
1332     rightWidget->show();
1333
1334     QPointF leftPos = leftWidget->rect().center();
1335     QPointF centerPos = centerWidget->rect().center();
1336     QPointF rightPos = rightWidget->rect().center();
1337     QPointF leftScreenPos = leftWidget->mapToGlobal(leftPos.toPoint());
1338     QPointF centerScreenPos = centerWidget->mapToGlobal(centerPos.toPoint());
1339     QPointF rightScreenPos = rightWidget->mapToGlobal(rightPos.toPoint());
1340     QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
1341
1342     QWeakPointer<QWidget> pl = leftWidget, pc = centerWidget, pr = rightWidget;
1343
1344     QList<QTouchEvent::TouchPoint> rawTouchPoints;
1345     rawTouchPoints.append(QTouchEvent::TouchPoint(0));
1346     rawTouchPoints.append(QTouchEvent::TouchPoint(1));
1347     rawTouchPoints.append(QTouchEvent::TouchPoint(2));
1348     rawTouchPoints[0].setState(Qt::TouchPointPressed);
1349     rawTouchPoints[0].setScreenPos(leftScreenPos);
1350     rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
1351     rawTouchPoints[1].setState(Qt::TouchPointPressed);
1352     rawTouchPoints[1].setScreenPos(centerScreenPos);
1353     rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
1354     rawTouchPoints[2].setState(Qt::TouchPointPressed);
1355     rawTouchPoints[2].setScreenPos(rightScreenPos);
1356     rawTouchPoints[2].setNormalizedPos(normalized(rawTouchPoints[2].pos(), screenGeometry));
1357
1358     // generate begin events on all widgets, the left widget should die
1359     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
1360                                              0,
1361                                              touchScreenDevice,
1362                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
1363     QCoreApplication::processEvents();
1364     QVERIFY(pl.isNull() && !pc.isNull() && !pr.isNull());
1365
1366     // generate update events on all widget, the center widget should die
1367     rawTouchPoints[0].setState(Qt::TouchPointMoved);
1368     rawTouchPoints[1].setState(Qt::TouchPointMoved);
1369     rawTouchPoints[2].setState(Qt::TouchPointMoved);
1370     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
1371                                              0,
1372                                              touchScreenDevice,
1373                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
1374     QCoreApplication::processEvents();
1375
1376     // generate end events on all widget, the right widget should die
1377     rawTouchPoints[0].setState(Qt::TouchPointReleased);
1378     rawTouchPoints[1].setState(Qt::TouchPointReleased);
1379     rawTouchPoints[2].setState(Qt::TouchPointReleased);
1380     QWindowSystemInterface::handleTouchEvent(touchWidget.windowHandle(),
1381                                              0,
1382                                              touchScreenDevice,
1383                                              QTest::QTouchEventSequence::touchPointList(rawTouchPoints));
1384     QCoreApplication::processEvents();
1385 }
1386
1387 void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin()
1388 {
1389     QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
1390     rect->setAcceptTouchEvents(true);
1391
1392     QGraphicsRectItem *mainRect = new QGraphicsRectItem(0, 0, 100, 100, rect);
1393     mainRect->setBrush(Qt::lightGray);
1394
1395     QGraphicsRectItem *button = new QGraphicsRectItem(-20, -20, 40, 40, mainRect);
1396     button->setPos(50, 50);
1397     button->setBrush(Qt::darkGreen);
1398
1399     QGraphicsView view;
1400     QGraphicsScene scene;
1401     scene.addItem(rect);
1402     scene.setSceneRect(0,0,100,100);
1403     view.setScene(&scene);
1404
1405     view.show();
1406     QTest::qWaitForWindowShown(&view);
1407
1408     QPoint centerPos = view.mapFromScene(rect->boundingRect().center());
1409     // Touch the button
1410     QTest::touchEvent(view.viewport(), touchScreenDevice).press(0, centerPos, static_cast<QWindow *>(0));
1411     QTest::touchEvent(view.viewport(), touchScreenDevice).release(0, centerPos, static_cast<QWindow *>(0));
1412     // Touch outside of the button
1413     QTest::touchEvent(view.viewport(), touchScreenDevice).press(0, view.mapFromScene(QPoint(10, 10)), static_cast<QWindow *>(0));
1414     QTest::touchEvent(view.viewport(), touchScreenDevice).release(0, view.mapFromScene(QPoint(10, 10)), static_cast<QWindow *>(0));
1415 }
1416
1417 void tst_QTouchEvent::touchBeginWithGraphicsWidget()
1418 {
1419     QGraphicsScene scene;
1420     QGraphicsView view(&scene);
1421     tst_QTouchEventGraphicsItem *root;
1422     root = new tst_QTouchEventGraphicsItem;
1423     root->setAcceptTouchEvents(true);
1424     scene.addItem(root);
1425
1426     QGraphicsWidget *glassWidget = new QGraphicsWidget;
1427     glassWidget->setMinimumSize(100, 100);
1428     scene.addItem(glassWidget);
1429
1430     view.resize(200, 200);
1431     view.show();
1432     QTest::qWaitForWindowShown(&view);
1433     view.fitInView(scene.sceneRect());
1434
1435     QTest::touchEvent(&view, touchScreenDevice)
1436             .press(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport());
1437     QTest::touchEvent(&view, touchScreenDevice)
1438             .stationary(0)
1439             .press(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
1440     QTest::touchEvent(&view, touchScreenDevice)
1441             .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
1442             .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
1443
1444     QCOMPARE(root->touchBeginCounter, 1);
1445     QCOMPARE(root->touchUpdateCounter, 1);
1446     QCOMPARE(root->touchEndCounter, 1);
1447     QCOMPARE(root->touchUpdatePoints.size(), 2);
1448
1449     root->reset();
1450     glassWidget->setWindowFlags(Qt::Window); // make the glassWidget a panel
1451
1452     QTest::touchEvent(&view, touchScreenDevice)
1453             .press(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport());
1454     QTest::touchEvent(&view, touchScreenDevice)
1455             .stationary(0)
1456             .press(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
1457     QTest::touchEvent(&view, touchScreenDevice)
1458             .release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
1459             .release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
1460
1461     QCOMPARE(root->touchBeginCounter, 0);
1462     QCOMPARE(root->touchUpdateCounter, 0);
1463     QCOMPARE(root->touchEndCounter, 0);
1464
1465
1466     delete root;
1467     delete glassWidget;
1468 }
1469
1470 class WindowTouchEventFilter : public QObject
1471 {
1472     Q_OBJECT
1473 public:
1474     bool eventFilter(QObject *obj, QEvent *event);
1475     struct TouchInfo {
1476         QList<QTouchEvent::TouchPoint> points;
1477         QEvent::Type lastSeenType;
1478     };
1479     QMap<QTouchDevice *, TouchInfo> d;
1480 };
1481
1482 bool WindowTouchEventFilter::eventFilter(QObject *, QEvent *event)
1483 {
1484     if (event->type() == QEvent::TouchBegin
1485             || event->type() == QEvent::TouchUpdate
1486             || event->type() == QEvent::TouchEnd) {
1487         QTouchEvent *te = static_cast<QTouchEvent *>(event);
1488         TouchInfo &td = d[te->device()];
1489         if (event->type() == QEvent::TouchBegin)
1490             td.points.clear();
1491         td.points.append(te->touchPoints());
1492         td.lastSeenType = event->type();
1493     }
1494     return false;
1495 }
1496
1497 void tst_QTouchEvent::testQGuiAppDelivery()
1498 {
1499     QTouchDevice *device = new QTouchDevice;
1500     device->setType(QTouchDevice::TouchScreen);
1501     QWindowSystemInterface::registerTouchDevice(device);
1502
1503     QWindow *w = new QWindow;
1504     w->setGeometry(100, 100, 100, 100);
1505     w->show();
1506     QTest::qWaitForWindowShown(w);
1507
1508     WindowTouchEventFilter filter;
1509     w->installEventFilter(&filter);
1510
1511     QList<QWindowSystemInterface::TouchPoint> points;
1512
1513     // Pass empty list, should be ignored.
1514     QWindowSystemInterface::handleTouchEvent(w, 0, points);
1515     QCoreApplication::processEvents();
1516     QCOMPARE(filter.d.isEmpty(), true);
1517
1518     QWindowSystemInterface::TouchPoint tp;
1519     tp.id = 0;
1520     tp.state = Qt::TouchPointPressed;
1521     tp.area = QRectF(120, 120, 20, 20);
1522     points.append(tp);
1523
1524     // Pass 0 as device, should be ignored.
1525     QWindowSystemInterface::handleTouchEvent(w, 0, points);
1526     QCoreApplication::processEvents();
1527     QCOMPARE(filter.d.isEmpty(), true);
1528
1529     // Now the real thing.
1530     QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchBegin
1531     QCoreApplication::processEvents();
1532     QCOMPARE(filter.d.count(), 1);
1533     QCOMPARE(filter.d.contains(device), true);
1534     QCOMPARE(filter.d.value(device).points.count(), 1);
1535     QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchBegin);
1536
1537     points[0].state = Qt::TouchPointMoved;
1538     QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchUpdate
1539     QCoreApplication::processEvents();
1540     QCOMPARE(filter.d.count(), 1);
1541     QCOMPARE(filter.d.contains(device), true);
1542     QCOMPARE(filter.d.value(device).points.count(), 2);
1543     QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchUpdate);
1544
1545     points[0].state = Qt::TouchPointReleased;
1546     QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchEnd
1547     QCoreApplication::processEvents();
1548     QCOMPARE(filter.d.count(), 1);
1549     QCOMPARE(filter.d.contains(device), true);
1550     QCOMPARE(filter.d.value(device).points.count(), 3);
1551     QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchEnd);
1552 }
1553
1554 void tst_QTouchEvent::testMultiDevice()
1555 {
1556     QTouchDevice *deviceOne = new QTouchDevice;
1557     deviceOne->setType(QTouchDevice::TouchScreen);
1558     QWindowSystemInterface::registerTouchDevice(deviceOne);
1559     QTouchDevice *deviceTwo = new QTouchDevice;
1560     deviceTwo->setType(QTouchDevice::TouchScreen);
1561     QWindowSystemInterface::registerTouchDevice(deviceTwo);
1562
1563     QWindow *w = new QWindow;
1564     w->setGeometry(100, 100, 100, 100);
1565     w->show();
1566     QTest::qWaitForWindowShown(w);
1567
1568     WindowTouchEventFilter filter;
1569     w->installEventFilter(&filter);
1570
1571     QList<QWindowSystemInterface::TouchPoint> pointsOne, pointsTwo;
1572
1573     // deviceOne reports a single point, deviceTwo reports the beginning of a multi-point sequence.
1574     // Even though there is a point with id 0 for both devices, they should be delivered cleanly, independently.
1575     QWindowSystemInterface::TouchPoint tp;
1576     tp.id = 0;
1577     tp.state = Qt::TouchPointPressed;
1578     tp.area = QRectF(120, 120, 20, 20);
1579     pointsOne.append(tp);
1580
1581     pointsTwo.append(tp);
1582     tp.id = 1;
1583     tp.area = QRectF(140, 140, 20, 20);
1584     pointsTwo.append(tp);
1585
1586     QWindowSystemInterface::handleTouchEvent(w, deviceOne, pointsOne);
1587     QWindowSystemInterface::handleTouchEvent(w, deviceTwo, pointsTwo);
1588     QCoreApplication::processEvents();
1589
1590     QCOMPARE(filter.d.contains(deviceOne), true);
1591     QCOMPARE(filter.d.contains(deviceTwo), true);
1592
1593     QCOMPARE(filter.d.value(deviceOne).lastSeenType, QEvent::TouchBegin);
1594     QCOMPARE(filter.d.value(deviceTwo).lastSeenType, QEvent::TouchBegin);
1595     QCOMPARE(filter.d.value(deviceOne).points.count(), 1);
1596     QCOMPARE(filter.d.value(deviceTwo).points.count(), 2);
1597
1598     QCOMPARE(filter.d.value(deviceOne).points.at(0).screenRect(), pointsOne[0].area);
1599     QCOMPARE(filter.d.value(deviceOne).points.at(0).state(), pointsOne[0].state);
1600
1601     QCOMPARE(filter.d.value(deviceTwo).points.at(0).screenRect(), pointsTwo[0].area);
1602     QCOMPARE(filter.d.value(deviceTwo).points.at(0).state(), pointsTwo[0].state);
1603     QCOMPARE(filter.d.value(deviceTwo).points.at(1).screenRect(), pointsTwo[1].area);
1604     QCOMPARE(filter.d.value(deviceTwo).points.at(1).state(), pointsTwo[1].state);
1605 }
1606
1607 QTEST_MAIN(tst_QTouchEvent)
1608
1609 #include "tst_qtouchevent.moc"