| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2020 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the $MODULE$ of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 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 The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 21 | ** included in the packaging of this file. Please review the following | 
| 22 | ** information to ensure the GNU General Public License requirements will | 
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 24 | ** | 
| 25 | ** $QT_END_LICENSE$ | 
| 26 | ** | 
| 27 | ****************************************************************************/ | 
| 28 |  | 
| 29 | #include <QtGui/QScreen> | 
| 30 | #include <QtWidgets/QGraphicsItem> | 
| 31 | #include <QtWidgets/QGraphicsScene> | 
| 32 | #include <QtWidgets/QGraphicsView> | 
| 33 | #include <QtWidgets/QGraphicsWidget> | 
| 34 | #include <QtWidgets/QWidget> | 
| 35 | #include <QtTest> | 
| 36 | #include <qpa/qwindowsysteminterface.h> | 
| 37 | #include <qpa/qwindowsysteminterface_p.h> | 
| 38 | #include <private/qhighdpiscaling_p.h> | 
| 39 | #include <private/qtouchdevice_p.h> | 
| 40 |  | 
| 41 | class tst_QTouchEventWidget : public QWidget | 
| 42 | { | 
| 43 | public: | 
| 44 |     QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints; | 
| 45 |     bool seenTouchBegin, seenTouchUpdate, seenTouchEnd; | 
| 46 |     bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd; | 
| 47 |     bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd; | 
| 48 |     ulong timestamp; | 
| 49 |     QTouchDevice *deviceFromEvent; | 
| 50 |  | 
| 51 |     explicit tst_QTouchEventWidget(QWidget *parent = nullptr) : QWidget(parent) | 
| 52 |     { | 
| 53 |         reset(); | 
| 54 |     } | 
| 55 |  | 
| 56 |     void reset() | 
| 57 |     { | 
| 58 |         touchBeginPoints.clear(); | 
| 59 |         touchUpdatePoints.clear(); | 
| 60 |         touchEndPoints.clear(); | 
| 61 |         seenTouchBegin = seenTouchUpdate = seenTouchEnd = false; | 
| 62 |         acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true; | 
| 63 |         deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false; | 
| 64 |     } | 
| 65 |  | 
| 66 |     bool event(QEvent *event) override | 
| 67 |     { | 
| 68 |         switch (event->type()) { | 
| 69 |         case QEvent::TouchBegin: | 
| 70 |             if (seenTouchBegin) qWarning(msg: "TouchBegin: already seen a TouchBegin" ); | 
| 71 |             if (seenTouchUpdate) qWarning(msg: "TouchBegin: TouchUpdate cannot happen before TouchBegin" ); | 
| 72 |             if (seenTouchEnd) qWarning(msg: "TouchBegin: TouchEnd cannot happen before TouchBegin" ); | 
| 73 |             seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd; | 
| 74 |             touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints(); | 
| 75 |             timestamp = static_cast<QTouchEvent *>(event)->timestamp(); | 
| 76 |             deviceFromEvent = static_cast<QTouchEvent *>(event)->device(); | 
| 77 |             event->setAccepted(acceptTouchBegin); | 
| 78 |             if (deleteInTouchBegin) | 
| 79 |                 delete this; | 
| 80 |             break; | 
| 81 |         case QEvent::TouchUpdate: | 
| 82 |             if (!seenTouchBegin) qWarning(msg: "TouchUpdate: have not seen TouchBegin" ); | 
| 83 |             if (seenTouchEnd) qWarning(msg: "TouchUpdate: TouchEnd cannot happen before TouchUpdate" ); | 
| 84 |             seenTouchUpdate = seenTouchBegin && !seenTouchEnd; | 
| 85 |             touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints(); | 
| 86 |             timestamp = static_cast<QTouchEvent *>(event)->timestamp(); | 
| 87 |             deviceFromEvent = static_cast<QTouchEvent *>(event)->device(); | 
| 88 |             event->setAccepted(acceptTouchUpdate); | 
| 89 |             if (deleteInTouchUpdate) | 
| 90 |                 delete this; | 
| 91 |             break; | 
| 92 |         case QEvent::TouchEnd: | 
| 93 |             if (!seenTouchBegin) qWarning(msg: "TouchEnd: have not seen TouchBegin" ); | 
| 94 |             if (seenTouchEnd) qWarning(msg: "TouchEnd: already seen a TouchEnd" ); | 
| 95 |             seenTouchEnd = seenTouchBegin && !seenTouchEnd; | 
| 96 |             touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints(); | 
| 97 |             timestamp = static_cast<QTouchEvent *>(event)->timestamp(); | 
| 98 |             deviceFromEvent = static_cast<QTouchEvent *>(event)->device(); | 
| 99 |             event->setAccepted(acceptTouchEnd); | 
| 100 |             if (deleteInTouchEnd) | 
| 101 |                 delete this; | 
| 102 |             break; | 
| 103 |         default: | 
| 104 |             return QWidget::event(event); | 
| 105 |         } | 
| 106 |         return true; | 
| 107 |     } | 
| 108 | }; | 
| 109 |  | 
| 110 | class tst_QTouchEventGraphicsItem : public QGraphicsItem | 
| 111 | { | 
| 112 | public: | 
| 113 |     QList<QTouchEvent::TouchPoint> touchBeginPoints, touchUpdatePoints, touchEndPoints; | 
| 114 |     bool seenTouchBegin, seenTouchUpdate, seenTouchEnd; | 
| 115 |     int touchBeginCounter, touchUpdateCounter, touchEndCounter; | 
| 116 |     bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd; | 
| 117 |     bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd; | 
| 118 |     tst_QTouchEventGraphicsItem **weakpointer; | 
| 119 |  | 
| 120 |     explicit tst_QTouchEventGraphicsItem(QGraphicsItem *parent = nullptr) | 
| 121 |         : QGraphicsItem(parent), weakpointer(0) | 
| 122 |     { | 
| 123 |         reset(); | 
| 124 |     } | 
| 125 |  | 
| 126 |     ~tst_QTouchEventGraphicsItem() | 
| 127 |     { | 
| 128 |         if (weakpointer) | 
| 129 |             *weakpointer = 0; | 
| 130 |     } | 
| 131 |  | 
| 132 |     void reset() | 
| 133 |     { | 
| 134 |         touchBeginPoints.clear(); | 
| 135 |         touchUpdatePoints.clear(); | 
| 136 |         touchEndPoints.clear(); | 
| 137 |         seenTouchBegin = seenTouchUpdate = seenTouchEnd = false; | 
| 138 |         touchBeginCounter = touchUpdateCounter = touchEndCounter = 0; | 
| 139 |         acceptTouchBegin = acceptTouchUpdate = acceptTouchEnd = true; | 
| 140 |         deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false; | 
| 141 |     } | 
| 142 |  | 
| 143 |     QRectF boundingRect() const override { return QRectF(0, 0, 10, 10); } | 
| 144 |     void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override | 
| 145 |     { | 
| 146 |         painter->fillRect(r: QRectF(QPointF(0, 0), boundingRect().size()), c: Qt::yellow); | 
| 147 |     } | 
| 148 |  | 
| 149 |     bool sceneEvent(QEvent *event) override | 
| 150 |     { | 
| 151 |         switch (event->type()) { | 
| 152 |         case QEvent::TouchBegin: | 
| 153 |             if (seenTouchBegin) qWarning(msg: "TouchBegin: already seen a TouchBegin" ); | 
| 154 |             if (seenTouchUpdate) qWarning(msg: "TouchBegin: TouchUpdate cannot happen before TouchBegin" ); | 
| 155 |             if (seenTouchEnd) qWarning(msg: "TouchBegin: TouchEnd cannot happen before TouchBegin" ); | 
| 156 |             seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd; | 
| 157 |             ++touchBeginCounter; | 
| 158 |             touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints(); | 
| 159 |             event->setAccepted(acceptTouchBegin); | 
| 160 |             if (deleteInTouchBegin) | 
| 161 |                 delete this; | 
| 162 |             break; | 
| 163 |         case QEvent::TouchUpdate: | 
| 164 |             if (!seenTouchBegin) qWarning(msg: "TouchUpdate: have not seen TouchBegin" ); | 
| 165 |             if (seenTouchEnd) qWarning(msg: "TouchUpdate: TouchEnd cannot happen before TouchUpdate" ); | 
| 166 |             seenTouchUpdate = seenTouchBegin && !seenTouchEnd; | 
| 167 |             ++touchUpdateCounter; | 
| 168 |             touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints(); | 
| 169 |             event->setAccepted(acceptTouchUpdate); | 
| 170 |             if (deleteInTouchUpdate) | 
| 171 |                 delete this; | 
| 172 |             break; | 
| 173 |         case QEvent::TouchEnd: | 
| 174 |             if (!seenTouchBegin) qWarning(msg: "TouchEnd: have not seen TouchBegin" ); | 
| 175 |             if (seenTouchEnd) qWarning(msg: "TouchEnd: already seen a TouchEnd" ); | 
| 176 |             seenTouchEnd = seenTouchBegin && !seenTouchEnd; | 
| 177 |             ++touchEndCounter; | 
| 178 |             touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints(); | 
| 179 |             event->setAccepted(acceptTouchEnd); | 
| 180 |             if (deleteInTouchEnd) | 
| 181 |                 delete this; | 
| 182 |             break; | 
| 183 |         default: | 
| 184 |             return QGraphicsItem::sceneEvent(event); | 
| 185 |         } | 
| 186 |         return true; | 
| 187 |     } | 
| 188 | }; | 
| 189 |  | 
| 190 | class tst_QTouchEvent : public QObject | 
| 191 | { | 
| 192 |     Q_OBJECT | 
| 193 | public: | 
| 194 |     tst_QTouchEvent(); | 
| 195 |  | 
| 196 | private slots: | 
| 197 |     void cleanup(); | 
| 198 |     void qPointerUniqueId(); | 
| 199 |     void touchDisabledByDefault(); | 
| 200 |     void touchEventAcceptedByDefault(); | 
| 201 |     void touchBeginPropagatesWhenIgnored(); | 
| 202 |     void touchUpdateAndEndNeverPropagate(); | 
| 203 |     void basicRawEventTranslation(); | 
| 204 |     void basicRawEventTranslationOfIds(); | 
| 205 |     void multiPointRawEventTranslationOnTouchScreen(); | 
| 206 |     void multiPointRawEventTranslationOnTouchPad(); | 
| 207 |     void touchOnMultipleTouchscreens(); | 
| 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 *secondaryTouchScreenDevice; | 
| 218 |     QTouchDevice *touchPadDevice; | 
| 219 | }; | 
| 220 |  | 
| 221 | tst_QTouchEvent::tst_QTouchEvent() | 
| 222 |   : touchScreenDevice(QTest::createTouchDevice()) | 
| 223 |   , secondaryTouchScreenDevice(QTest::createTouchDevice()) | 
| 224 |   , touchPadDevice(QTest::createTouchDevice(devType: QTouchDevice::TouchPad)) | 
| 225 | { | 
| 226 | } | 
| 227 |  | 
| 228 | void tst_QTouchEvent::cleanup() | 
| 229 | { | 
| 230 |     QVERIFY(QGuiApplication::topLevelWindows().isEmpty()); | 
| 231 |     QWindowSystemInterfacePrivate::clearPointIdMap(); | 
| 232 | } | 
| 233 |  | 
| 234 | void tst_QTouchEvent::qPointerUniqueId() | 
| 235 | { | 
| 236 |     QPointingDeviceUniqueId id1, id2; | 
| 237 |  | 
| 238 |     QCOMPARE(id1.numericId(), Q_INT64_C(-1)); | 
| 239 |     QVERIFY(!id1.isValid()); | 
| 240 |  | 
| 241 |     QVERIFY(  id1 == id2); | 
| 242 |     QVERIFY(!(id1 != id2)); | 
| 243 |  | 
| 244 |     QSet<QPointingDeviceUniqueId> set; // compile test | 
| 245 |     set.insert(value: id1); | 
| 246 |     set.insert(value: id2); | 
| 247 |     QCOMPARE(set.size(), 1); | 
| 248 |  | 
| 249 |  | 
| 250 |     const auto id3 = QPointingDeviceUniqueId::fromNumericId(id: -1); | 
| 251 |     QCOMPARE(id3.numericId(), Q_INT64_C(-1)); | 
| 252 |     QVERIFY(!id3.isValid()); | 
| 253 |  | 
| 254 |     QVERIFY(  id1 == id3); | 
| 255 |     QVERIFY(!(id1 != id3)); | 
| 256 |  | 
| 257 |     set.insert(value: id3); | 
| 258 |     QCOMPARE(set.size(), 1); | 
| 259 |  | 
| 260 |  | 
| 261 |     const auto id4 = QPointingDeviceUniqueId::fromNumericId(id: 4); | 
| 262 |     QCOMPARE(id4.numericId(), Q_INT64_C(4)); | 
| 263 |     QVERIFY(id4.isValid()); | 
| 264 |  | 
| 265 |     QVERIFY(  id1 != id4); | 
| 266 |     QVERIFY(!(id1 == id4)); | 
| 267 |  | 
| 268 |     set.insert(value: id4); | 
| 269 |     QCOMPARE(set.size(), 2); | 
| 270 | } | 
| 271 |  | 
| 272 | void tst_QTouchEvent::touchDisabledByDefault() | 
| 273 | { | 
| 274 |     // QWidget | 
| 275 |     { | 
| 276 |         // the widget attribute is not enabled by default | 
| 277 |         QWidget widget; | 
| 278 |         QVERIFY(!widget.testAttribute(Qt::WA_AcceptTouchEvents)); | 
| 279 |  | 
| 280 |         // events should not be accepted since they are not enabled | 
| 281 |         QList<QTouchEvent::TouchPoint> touchPoints; | 
| 282 |         touchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 283 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 284 |                                touchScreenDevice, | 
| 285 |                                Qt::NoModifier, | 
| 286 |                                Qt::TouchPointPressed, | 
| 287 |                                touchPoints); | 
| 288 |         QVERIFY(!QApplication::sendEvent(&widget, &touchEvent)); | 
| 289 |         QVERIFY(!touchEvent.isAccepted()); | 
| 290 |     } | 
| 291 |  | 
| 292 |     // QGraphicsView | 
| 293 |     { | 
| 294 |         QGraphicsScene scene; | 
| 295 |         tst_QTouchEventGraphicsItem item; | 
| 296 |         QGraphicsView view(&scene); | 
| 297 |         scene.addItem(item: &item); | 
| 298 |         item.setPos(ax: 100, ay: 100); | 
| 299 |         view.resize(w: 200, h: 200); | 
| 300 |         view.fitInView(rect: scene.sceneRect()); | 
| 301 |  | 
| 302 |         // touch events are not accepted by default | 
| 303 |         QVERIFY(!item.acceptTouchEvents()); | 
| 304 |  | 
| 305 |         // compose an event to the scene that is over the item | 
| 306 |         QTouchEvent::TouchPoint touchPoint(0); | 
| 307 |         touchPoint.setState(Qt::TouchPointPressed); | 
| 308 |         touchPoint.setPos(view.mapFromScene(point: item.mapToScene(point: item.boundingRect().center()))); | 
| 309 |         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); | 
| 310 |         touchPoint.setScenePos(view.mapToScene(point: touchPoint.pos().toPoint())); | 
| 311 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 312 |                                touchScreenDevice, | 
| 313 |                                Qt::NoModifier, | 
| 314 |                                Qt::TouchPointPressed, | 
| 315 |                                (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 316 |         QVERIFY(!QApplication::sendEvent(view.viewport(), &touchEvent)); | 
| 317 |         QVERIFY(!touchEvent.isAccepted()); | 
| 318 |         QVERIFY(!item.seenTouchBegin); | 
| 319 |     } | 
| 320 | } | 
| 321 |  | 
| 322 | void tst_QTouchEvent::touchEventAcceptedByDefault() | 
| 323 | { | 
| 324 |     // QWidget | 
| 325 |     { | 
| 326 |         // enabling touch events should automatically accept touch events | 
| 327 |         QWidget widget; | 
| 328 |         widget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 329 |  | 
| 330 |         // QWidget handles touch event by converting them into a mouse event, so the event is both | 
| 331 |         // accepted and handled (res == true) | 
| 332 |         QList<QTouchEvent::TouchPoint> touchPoints; | 
| 333 |         touchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 334 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 335 |                                touchScreenDevice, | 
| 336 |                                Qt::NoModifier, | 
| 337 |                                Qt::TouchPointPressed, | 
| 338 |                                touchPoints); | 
| 339 |         QVERIFY(QApplication::sendEvent(&widget, &touchEvent)); | 
| 340 |         QVERIFY(!touchEvent.isAccepted()); // Qt 5.X ignores touch events. | 
| 341 |  | 
| 342 |         // tst_QTouchEventWidget does handle, sending succeeds | 
| 343 |         tst_QTouchEventWidget touchWidget; | 
| 344 |         touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 345 |         touchEvent.ignore(); | 
| 346 |         QVERIFY(QApplication::sendEvent(&touchWidget, &touchEvent)); | 
| 347 |         QVERIFY(touchEvent.isAccepted()); | 
| 348 |     } | 
| 349 |  | 
| 350 |     // QGraphicsView | 
| 351 |     { | 
| 352 |         QGraphicsScene scene; | 
| 353 |         tst_QTouchEventGraphicsItem item; | 
| 354 |         QGraphicsView view(&scene); | 
| 355 |         scene.addItem(item: &item); | 
| 356 |         item.setPos(ax: 100, ay: 100); | 
| 357 |         view.resize(w: 200, h: 200); | 
| 358 |         view.fitInView(rect: scene.sceneRect()); | 
| 359 |  | 
| 360 |         // enabling touch events on the item also enables events on the viewport | 
| 361 |         item.setAcceptTouchEvents(true); | 
| 362 |         QVERIFY(view.viewport()->testAttribute(Qt::WA_AcceptTouchEvents)); | 
| 363 |  | 
| 364 |         // compose an event to the scene that is over the item | 
| 365 |         QTouchEvent::TouchPoint touchPoint(0); | 
| 366 |         touchPoint.setState(Qt::TouchPointPressed); | 
| 367 |         touchPoint.setPos(view.mapFromScene(point: item.mapToScene(point: item.boundingRect().center()))); | 
| 368 |         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); | 
| 369 |         touchPoint.setScenePos(view.mapToScene(point: touchPoint.pos().toPoint())); | 
| 370 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 371 |                                touchScreenDevice, | 
| 372 |                                Qt::NoModifier, | 
| 373 |                                Qt::TouchPointPressed, | 
| 374 |                                (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 375 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent)); | 
| 376 |         QVERIFY(touchEvent.isAccepted()); | 
| 377 |         QVERIFY(item.seenTouchBegin); | 
| 378 |     } | 
| 379 | } | 
| 380 |  | 
| 381 | void tst_QTouchEvent::touchBeginPropagatesWhenIgnored() | 
| 382 | { | 
| 383 |     // QWidget | 
| 384 |     { | 
| 385 |         tst_QTouchEventWidget window, child, grandchild; | 
| 386 |         child.setParent(&window); | 
| 387 |         grandchild.setParent(&child); | 
| 388 |  | 
| 389 |         // all widgets accept touch events, grandchild ignores, so child sees the event, but not window | 
| 390 |         window.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 391 |         child.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 392 |         grandchild.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 393 |         grandchild.acceptTouchBegin = false; | 
| 394 |  | 
| 395 |         QList<QTouchEvent::TouchPoint> touchPoints; | 
| 396 |         touchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 397 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 398 |                                touchScreenDevice, | 
| 399 |                                Qt::NoModifier, | 
| 400 |                                Qt::TouchPointPressed, | 
| 401 |                                touchPoints); | 
| 402 |         QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent)); | 
| 403 |         QVERIFY(touchEvent.isAccepted()); | 
| 404 |         QVERIFY(grandchild.seenTouchBegin); | 
| 405 |         QVERIFY(child.seenTouchBegin); | 
| 406 |         QVERIFY(!window.seenTouchBegin); | 
| 407 |  | 
| 408 |         // disable touch on grandchild. even though it doesn't accept it, child should still get the | 
| 409 |         // TouchBegin | 
| 410 |         grandchild.reset(); | 
| 411 |         child.reset(); | 
| 412 |         window.reset(); | 
| 413 |         grandchild.setAttribute(Qt::WA_AcceptTouchEvents, on: false); | 
| 414 |  | 
| 415 |         touchEvent.ignore(); | 
| 416 |         QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent)); | 
| 417 |         QVERIFY(touchEvent.isAccepted()); | 
| 418 |         QVERIFY(!grandchild.seenTouchBegin); | 
| 419 |         QVERIFY(child.seenTouchBegin); | 
| 420 |         QVERIFY(!window.seenTouchBegin); | 
| 421 |     } | 
| 422 |  | 
| 423 |     // QGraphicsView | 
| 424 |     { | 
| 425 |         QGraphicsScene scene; | 
| 426 |         tst_QTouchEventGraphicsItem root, child, grandchild; | 
| 427 |         QGraphicsView view(&scene); | 
| 428 |         scene.addItem(item: &root); | 
| 429 |         root.setPos(ax: 100, ay: 100); | 
| 430 |         child.setParentItem(&root); | 
| 431 |         grandchild.setParentItem(&child); | 
| 432 |         view.resize(w: 200, h: 200); | 
| 433 |         view.fitInView(rect: scene.sceneRect()); | 
| 434 |  | 
| 435 |         // all items accept touch events, grandchild ignores, so child sees the event, but not root | 
| 436 |         root.setAcceptTouchEvents(true); | 
| 437 |         child.setAcceptTouchEvents(true); | 
| 438 |         grandchild.setAcceptTouchEvents(true); | 
| 439 |         grandchild.acceptTouchBegin = false; | 
| 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(point: grandchild.mapToScene(point: grandchild.boundingRect().center()))); | 
| 445 |         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); | 
| 446 |         touchPoint.setScenePos(view.mapToScene(point: touchPoint.pos().toPoint())); | 
| 447 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 448 |                                touchScreenDevice, | 
| 449 |                                Qt::NoModifier, | 
| 450 |                                Qt::TouchPointPressed, | 
| 451 |                                (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 452 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent)); | 
| 453 |         QVERIFY(touchEvent.isAccepted()); | 
| 454 |         QVERIFY(grandchild.seenTouchBegin); | 
| 455 |         QVERIFY(child.seenTouchBegin); | 
| 456 |         QVERIFY(!root.seenTouchBegin); | 
| 457 |     } | 
| 458 |  | 
| 459 |     // QGraphicsView | 
| 460 |     { | 
| 461 |         QGraphicsScene scene; | 
| 462 |         tst_QTouchEventGraphicsItem root, child, grandchild; | 
| 463 |         QGraphicsView view(&scene); | 
| 464 |         scene.addItem(item: &root); | 
| 465 |         root.setPos(ax: 100, ay: 100); | 
| 466 |         child.setParentItem(&root); | 
| 467 |         grandchild.setParentItem(&child); | 
| 468 |         view.resize(w: 200, h: 200); | 
| 469 |         view.fitInView(rect: scene.sceneRect()); | 
| 470 |  | 
| 471 |         // leave touch disabled on grandchild. even though it doesn't accept it, child should | 
| 472 |         // still get the TouchBegin | 
| 473 |         root.setAcceptTouchEvents(true); | 
| 474 |         child.setAcceptTouchEvents(true); | 
| 475 |  | 
| 476 |         // compose an event to the scene that is over the grandchild | 
| 477 |         QTouchEvent::TouchPoint touchPoint(0); | 
| 478 |         touchPoint.setState(Qt::TouchPointPressed); | 
| 479 |         touchPoint.setPos(view.mapFromScene(point: grandchild.mapToScene(point: grandchild.boundingRect().center()))); | 
| 480 |         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); | 
| 481 |         touchPoint.setScenePos(view.mapToScene(point: touchPoint.pos().toPoint())); | 
| 482 |         QTouchEvent touchEvent(QEvent::TouchBegin, | 
| 483 |                                touchScreenDevice, | 
| 484 |                                Qt::NoModifier, | 
| 485 |                                Qt::TouchPointPressed, | 
| 486 |                                (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 487 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent)); | 
| 488 |         QVERIFY(touchEvent.isAccepted()); | 
| 489 |         QVERIFY(!grandchild.seenTouchBegin); | 
| 490 |         QVERIFY(child.seenTouchBegin); | 
| 491 |         QVERIFY(!root.seenTouchBegin); | 
| 492 |     } | 
| 493 | } | 
| 494 |  | 
| 495 | void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() | 
| 496 | { | 
| 497 |     // QWidget | 
| 498 |     { | 
| 499 |         tst_QTouchEventWidget window, child; | 
| 500 |         child.setParent(&window); | 
| 501 |  | 
| 502 |         window.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 503 |         child.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 504 |         child.acceptTouchUpdate = false; | 
| 505 |         child.acceptTouchEnd = false; | 
| 506 |  | 
| 507 |         QList<QTouchEvent::TouchPoint> touchPoints; | 
| 508 |         touchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 509 |         QTouchEvent touchBeginEvent(QEvent::TouchBegin, | 
| 510 |                                     touchScreenDevice, | 
| 511 |                                     Qt::NoModifier, | 
| 512 |                                     Qt::TouchPointPressed, | 
| 513 |                                     touchPoints); | 
| 514 |         QVERIFY(QApplication::sendEvent(&child, &touchBeginEvent)); | 
| 515 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 516 |         QVERIFY(child.seenTouchBegin); | 
| 517 |         QVERIFY(!window.seenTouchBegin); | 
| 518 |  | 
| 519 |         // send the touch update to the child, but ignore it, it doesn't propagate | 
| 520 |         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, | 
| 521 |                                      touchScreenDevice, | 
| 522 |                                      Qt::NoModifier, | 
| 523 |                                      Qt::TouchPointMoved, | 
| 524 |                                      touchPoints); | 
| 525 |         QVERIFY(QApplication::sendEvent(&child, &touchUpdateEvent)); | 
| 526 |         QVERIFY(!touchUpdateEvent.isAccepted()); | 
| 527 |         QVERIFY(child.seenTouchUpdate); | 
| 528 |         QVERIFY(!window.seenTouchUpdate); | 
| 529 |  | 
| 530 |         // send the touch end, same thing should happen as with touch update | 
| 531 |         QTouchEvent touchEndEvent(QEvent::TouchEnd, | 
| 532 |                                   touchScreenDevice, | 
| 533 |                                   Qt::NoModifier, | 
| 534 |                                   Qt::TouchPointReleased, | 
| 535 |                                   touchPoints); | 
| 536 |         QVERIFY(QApplication::sendEvent(&child, &touchEndEvent)); | 
| 537 |         QVERIFY(!touchEndEvent.isAccepted()); | 
| 538 |         QVERIFY(child.seenTouchEnd); | 
| 539 |         QVERIFY(!window.seenTouchEnd); | 
| 540 |     } | 
| 541 |  | 
| 542 |     // QGraphicsView | 
| 543 |     { | 
| 544 |         QGraphicsScene scene; | 
| 545 |         tst_QTouchEventGraphicsItem root, child, grandchild; | 
| 546 |         QGraphicsView view(&scene); | 
| 547 |         scene.addItem(item: &root); | 
| 548 |         root.setPos(ax: 100, ay: 100); | 
| 549 |         child.setParentItem(&root); | 
| 550 |         grandchild.setParentItem(&child); | 
| 551 |         view.resize(w: 200, h: 200); | 
| 552 |         view.fitInView(rect: scene.sceneRect()); | 
| 553 |  | 
| 554 |         root.setAcceptTouchEvents(true); | 
| 555 |         child.setAcceptTouchEvents(true); | 
| 556 |         child.acceptTouchUpdate = false; | 
| 557 |         child.acceptTouchEnd = false; | 
| 558 |  | 
| 559 |         // compose an event to the scene that is over the child | 
| 560 |         QTouchEvent::TouchPoint touchPoint(0); | 
| 561 |         touchPoint.setState(Qt::TouchPointPressed); | 
| 562 |         touchPoint.setPos(view.mapFromScene(point: grandchild.mapToScene(point: grandchild.boundingRect().center()))); | 
| 563 |         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); | 
| 564 |         touchPoint.setScenePos(view.mapToScene(point: touchPoint.pos().toPoint())); | 
| 565 |         QTouchEvent touchBeginEvent(QEvent::TouchBegin, | 
| 566 |                                     touchScreenDevice, | 
| 567 |                                     Qt::NoModifier, | 
| 568 |                                     Qt::TouchPointPressed, | 
| 569 |                                     (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 570 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent)); | 
| 571 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 572 |         QVERIFY(child.seenTouchBegin); | 
| 573 |         QVERIFY(!root.seenTouchBegin); | 
| 574 |  | 
| 575 |         // send the touch update to the child, but ignore it, it doesn't propagate | 
| 576 |         touchPoint.setState(Qt::TouchPointMoved); | 
| 577 |         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, | 
| 578 |                                      touchScreenDevice, | 
| 579 |                                      Qt::NoModifier, | 
| 580 |                                      Qt::TouchPointMoved, | 
| 581 |                                      (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 582 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent)); | 
| 583 |         // the scene accepts the event, since it found an item to send the event to | 
| 584 |         QVERIFY(!touchUpdateEvent.isAccepted()); | 
| 585 |         QVERIFY(child.seenTouchUpdate); | 
| 586 |         QVERIFY(!root.seenTouchUpdate); | 
| 587 |  | 
| 588 |         // send the touch end, same thing should happen as with touch update | 
| 589 |         touchPoint.setState(Qt::TouchPointReleased); | 
| 590 |         QTouchEvent touchEndEvent(QEvent::TouchEnd, | 
| 591 |                                   touchScreenDevice, | 
| 592 |                                   Qt::NoModifier, | 
| 593 |                                   Qt::TouchPointReleased, | 
| 594 |                                   (QList<QTouchEvent::TouchPoint>() << touchPoint)); | 
| 595 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent)); | 
| 596 |         // the scene accepts the event, since it found an item to send the event to | 
| 597 |         QVERIFY(!touchEndEvent.isAccepted()); | 
| 598 |         QVERIFY(child.seenTouchEnd); | 
| 599 |         QVERIFY(!root.seenTouchEnd); | 
| 600 |     } | 
| 601 | } | 
| 602 |  | 
| 603 | QPointF normalized(const QPointF &pos, const QRectF &rect) | 
| 604 | { | 
| 605 |     return QPointF(pos.x() / rect.width(), pos.y() / rect.height()); | 
| 606 | } | 
| 607 |  | 
| 608 | void tst_QTouchEvent::basicRawEventTranslation() | 
| 609 | { | 
| 610 |     tst_QTouchEventWidget touchWidget; | 
| 611 |     touchWidget.setWindowTitle(QTest::currentTestFunction()); | 
| 612 |     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 613 |     touchWidget.setGeometry(ax: 100, ay: 100, aw: 400, ah: 300); | 
| 614 |     touchWidget.show(); | 
| 615 |     QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); | 
| 616 |  | 
| 617 |     QPointF pos = touchWidget.rect().center(); | 
| 618 |     QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint()); | 
| 619 |     QPointF delta(10, 10); | 
| 620 |     QRectF screenGeometry = touchWidget.screen()->geometry(); | 
| 621 |  | 
| 622 |     QTouchEvent::TouchPoint rawTouchPoint; | 
| 623 |     rawTouchPoint.setId(0); | 
| 624 |  | 
| 625 |     // this should be translated to a TouchBegin | 
| 626 |     rawTouchPoint.setState(Qt::TouchPointPressed); | 
| 627 |     rawTouchPoint.setScreenPos(screenPos); | 
| 628 |     rawTouchPoint.setNormalizedPos(normalized(pos: rawTouchPoint.pos(), rect: screenGeometry)); | 
| 629 |     QVector<QPointF> rawPosList; | 
| 630 |     rawPosList << QPointF(12, 34) << QPointF(56, 78); | 
| 631 |     rawTouchPoint.setRawScreenPositions(rawPosList); | 
| 632 |     const ulong timestamp = 1234; | 
| 633 |     QWindow *window = touchWidget.windowHandle(); | 
| 634 |     QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = | 
| 635 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoint, window); | 
| 636 |     QWindowSystemInterface::handleTouchEvent(window, timestamp, device: touchScreenDevice, points: nativeTouchPoints); | 
| 637 |     QCoreApplication::processEvents(); | 
| 638 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 639 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 640 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 641 |     QCOMPARE(touchWidget.touchBeginPoints.count(), 1); | 
| 642 |     QCOMPARE(touchWidget.timestamp, timestamp); | 
| 643 |     QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.first(); | 
| 644 |     const int touchPointId = (QTouchDevicePrivate::get(q: touchScreenDevice)->id << 24) + 1; | 
| 645 |     QCOMPARE(touchBeginPoint.id(), touchPointId); | 
| 646 |     QCOMPARE(touchBeginPoint.state(), rawTouchPoint.state()); | 
| 647 |     QCOMPARE(touchBeginPoint.pos(), pos); | 
| 648 |     QCOMPARE(touchBeginPoint.startPos(), pos); | 
| 649 |     QCOMPARE(touchBeginPoint.lastPos(), pos); | 
| 650 |     QCOMPARE(touchBeginPoint.scenePos(), rawTouchPoint.screenPos()); | 
| 651 |     QCOMPARE(touchBeginPoint.startScenePos(), rawTouchPoint.screenPos()); | 
| 652 |     QCOMPARE(touchBeginPoint.lastScenePos(), rawTouchPoint.screenPos()); | 
| 653 |     QCOMPARE(touchBeginPoint.screenPos(), rawTouchPoint.screenPos()); | 
| 654 |     QCOMPARE(touchBeginPoint.startScreenPos(), rawTouchPoint.screenPos()); | 
| 655 |     QCOMPARE(touchBeginPoint.lastScreenPos(), rawTouchPoint.screenPos()); | 
| 656 |     QCOMPARE(touchBeginPoint.normalizedPos(), rawTouchPoint.normalizedPos()); | 
| 657 |     QCOMPARE(touchBeginPoint.startNormalizedPos(), touchBeginPoint.normalizedPos()); | 
| 658 |     QCOMPARE(touchBeginPoint.lastNormalizedPos(), touchBeginPoint.normalizedPos()); | 
| 659 |     QCOMPARE(touchBeginPoint.pos(), pos); | 
| 660 |     QCOMPARE(touchBeginPoint.screenPos(), rawTouchPoint.screenPos()); | 
| 661 |     QCOMPARE(touchBeginPoint.scenePos(), touchBeginPoint.scenePos()); | 
| 662 |     QCOMPARE(touchBeginPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 663 |     QCOMPARE(touchBeginPoint.pressure(), qreal(1.)); | 
| 664 |     QCOMPARE(touchBeginPoint.velocity(), QVector2D()); | 
| 665 |     if (!QHighDpiScaling::isActive()) | 
| 666 |         QCOMPARE(touchBeginPoint.rawScreenPositions(), rawPosList); | 
| 667 |  | 
| 668 |     // moving the point should translate to TouchUpdate | 
| 669 |     rawTouchPoint.setState(Qt::TouchPointMoved); | 
| 670 |     rawTouchPoint.setScreenPos(screenPos + delta); | 
| 671 |     rawTouchPoint.setNormalizedPos(normalized(pos: rawTouchPoint.pos(), rect: screenGeometry)); | 
| 672 |     nativeTouchPoints = | 
| 673 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoint, window); | 
| 674 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 675 |     QCoreApplication::processEvents(); | 
| 676 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 677 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 678 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 679 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 1); | 
| 680 |     QTouchEvent::TouchPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first(); | 
| 681 |     QCOMPARE(touchUpdatePoint.id(), touchPointId); | 
| 682 |     QCOMPARE(touchUpdatePoint.state(), rawTouchPoint.state()); | 
| 683 |     QCOMPARE(touchUpdatePoint.pos(), pos + delta); | 
| 684 |     QCOMPARE(touchUpdatePoint.startPos(), pos); | 
| 685 |     QCOMPARE(touchUpdatePoint.lastPos(), pos); | 
| 686 |     QCOMPARE(touchUpdatePoint.scenePos(), rawTouchPoint.screenPos()); | 
| 687 |     QCOMPARE(touchUpdatePoint.startScenePos(), screenPos); | 
| 688 |     QCOMPARE(touchUpdatePoint.lastScenePos(), screenPos); | 
| 689 |     QCOMPARE(touchUpdatePoint.screenPos(), rawTouchPoint.screenPos()); | 
| 690 |     QCOMPARE(touchUpdatePoint.startScreenPos(), screenPos); | 
| 691 |     QCOMPARE(touchUpdatePoint.lastScreenPos(), screenPos); | 
| 692 |     QCOMPARE(touchUpdatePoint.normalizedPos(), rawTouchPoint.normalizedPos()); | 
| 693 |     QCOMPARE(touchUpdatePoint.startNormalizedPos(), touchBeginPoint.normalizedPos()); | 
| 694 |     QCOMPARE(touchUpdatePoint.lastNormalizedPos(), touchBeginPoint.normalizedPos()); | 
| 695 |     QCOMPARE(touchUpdatePoint.pos(), pos + delta); | 
| 696 |     QCOMPARE(touchUpdatePoint.screenPos(), rawTouchPoint.screenPos()); | 
| 697 |     QCOMPARE(touchUpdatePoint.scenePos(), touchUpdatePoint.scenePos()); | 
| 698 |     QCOMPARE(touchUpdatePoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 699 |     QCOMPARE(touchUpdatePoint.pressure(), qreal(1.)); | 
| 700 |  | 
| 701 |     // releasing the point translates to TouchEnd | 
| 702 |     rawTouchPoint.setState(Qt::TouchPointReleased); | 
| 703 |     rawTouchPoint.setScreenPos(screenPos + delta + delta); | 
| 704 |     rawTouchPoint.setNormalizedPos(normalized(pos: rawTouchPoint.pos(), rect: screenGeometry)); | 
| 705 |     nativeTouchPoints = | 
| 706 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoint, window); | 
| 707 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 708 |     QCoreApplication::processEvents(); | 
| 709 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 710 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 711 |     QVERIFY(touchWidget.seenTouchEnd); | 
| 712 |     QCOMPARE(touchWidget.touchEndPoints.count(), 1); | 
| 713 |     QTouchEvent::TouchPoint touchEndPoint = touchWidget.touchEndPoints.first(); | 
| 714 |     QCOMPARE(touchEndPoint.id(), touchPointId); | 
| 715 |     QCOMPARE(touchEndPoint.state(), rawTouchPoint.state()); | 
| 716 |     QCOMPARE(touchEndPoint.pos(), pos + delta + delta); | 
| 717 |     QCOMPARE(touchEndPoint.startPos(), pos); | 
| 718 |     QCOMPARE(touchEndPoint.lastPos(), pos + delta); | 
| 719 |     QCOMPARE(touchEndPoint.scenePos(), rawTouchPoint.screenPos()); | 
| 720 |     QCOMPARE(touchEndPoint.startScenePos(), screenPos); | 
| 721 |     QCOMPARE(touchEndPoint.lastScenePos(), screenPos + delta); | 
| 722 |     QCOMPARE(touchEndPoint.screenPos(), rawTouchPoint.screenPos()); | 
| 723 |     QCOMPARE(touchEndPoint.startScreenPos(), screenPos); | 
| 724 |     QCOMPARE(touchEndPoint.lastScreenPos(), screenPos + delta); | 
| 725 |     QCOMPARE(touchEndPoint.normalizedPos(), rawTouchPoint.normalizedPos()); | 
| 726 |     QCOMPARE(touchEndPoint.startNormalizedPos(), touchBeginPoint.normalizedPos()); | 
| 727 |     QCOMPARE(touchEndPoint.lastNormalizedPos(), touchUpdatePoint.normalizedPos()); | 
| 728 |     QCOMPARE(touchEndPoint.pos(), pos + delta + delta); | 
| 729 |     QCOMPARE(touchEndPoint.screenPos(), rawTouchPoint.screenPos()); | 
| 730 |     QCOMPARE(touchEndPoint.scenePos(), touchEndPoint.scenePos()); | 
| 731 |     QCOMPARE(touchEndPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 732 |     QCOMPARE(touchEndPoint.pressure(), qreal(0.)); | 
| 733 | } | 
| 734 |  | 
| 735 | void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() | 
| 736 | { | 
| 737 |     tst_QTouchEventWidget touchWidget; | 
| 738 |     touchWidget.setWindowTitle(QTest::currentTestFunction()); | 
| 739 |     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 740 |     touchWidget.setGeometry(ax: 100, ay: 100, aw: 400, ah: 300); | 
| 741 |  | 
| 742 |     tst_QTouchEventWidget leftWidget(&touchWidget); | 
| 743 |     leftWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 744 |     leftWidget.setGeometry(ax: 0, ay: 100, aw: 100, ah: 100); | 
| 745 |  | 
| 746 |     tst_QTouchEventWidget rightWidget(&touchWidget); | 
| 747 |     rightWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 748 |     rightWidget.setGeometry(ax: 300, ay: 100, aw: 100, ah: 100); | 
| 749 |  | 
| 750 |     touchWidget.show(); | 
| 751 |     QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); | 
| 752 |  | 
| 753 |     QPointF leftPos = leftWidget.rect().center(); | 
| 754 |     QPointF rightPos = rightWidget.rect().center(); | 
| 755 |     QPointF centerPos = touchWidget.rect().center(); | 
| 756 |     QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint()); | 
| 757 |     QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint()); | 
| 758 |     QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint()); | 
| 759 |     QRectF screenGeometry = touchWidget.screen()->geometry(); | 
| 760 |  | 
| 761 |     QList<QTouchEvent::TouchPoint> rawTouchPoints; | 
| 762 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 763 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(1)); | 
| 764 |  | 
| 765 |     // generate TouchBegins on both leftWidget and rightWidget | 
| 766 |     rawTouchPoints[0].setState(Qt::TouchPointPressed); | 
| 767 |     rawTouchPoints[0].setScreenPos(leftScreenPos); | 
| 768 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 769 |     rawTouchPoints[1].setState(Qt::TouchPointPressed); | 
| 770 |     rawTouchPoints[1].setScreenPos(rightScreenPos); | 
| 771 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 772 |     QWindow *window = touchWidget.windowHandle(); | 
| 773 |     QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = | 
| 774 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 775 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 776 |     QCoreApplication::processEvents(); | 
| 777 |     QVERIFY(!touchWidget.seenTouchBegin); | 
| 778 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 779 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 780 |     QVERIFY(leftWidget.seenTouchBegin); | 
| 781 |     QVERIFY(!leftWidget.seenTouchUpdate); | 
| 782 |     QVERIFY(!leftWidget.seenTouchEnd); | 
| 783 |     QVERIFY(rightWidget.seenTouchBegin); | 
| 784 |     QVERIFY(!rightWidget.seenTouchUpdate); | 
| 785 |     QVERIFY(!rightWidget.seenTouchEnd); | 
| 786 |     QCOMPARE(leftWidget.touchBeginPoints.count(), 1); | 
| 787 |     QCOMPARE(rightWidget.touchBeginPoints.count(), 1); | 
| 788 |     const int touchPointId0 = (QTouchDevicePrivate::get(q: touchScreenDevice)->id << 24) + 1; | 
| 789 |     const int touchPointId1 = touchPointId0 + 1; | 
| 790 |     { | 
| 791 |         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchBeginPoints.first(); | 
| 792 |         QCOMPARE(leftTouchPoint.id(), touchPointId0); | 
| 793 |         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); | 
| 794 |         QCOMPARE(leftTouchPoint.pos(), leftPos); | 
| 795 |         QCOMPARE(leftTouchPoint.startPos(), leftPos); | 
| 796 |         QCOMPARE(leftTouchPoint.lastPos(), leftPos); | 
| 797 |         QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos); | 
| 798 |         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos); | 
| 799 |         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos); | 
| 800 |         QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos); | 
| 801 |         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos); | 
| 802 |         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos); | 
| 803 |         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 804 |         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 805 |         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 806 |         QCOMPARE(leftTouchPoint.pos(), leftPos); | 
| 807 |         QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos); | 
| 808 |         QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos); | 
| 809 |         QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 810 |         QCOMPARE(leftTouchPoint.pressure(), qreal(1.)); | 
| 811 |  | 
| 812 |         QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchBeginPoints.first(); | 
| 813 |         QCOMPARE(rightTouchPoint.id(), touchPointId1); | 
| 814 |         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); | 
| 815 |         QCOMPARE(rightTouchPoint.pos(), rightPos); | 
| 816 |         QCOMPARE(rightTouchPoint.startPos(), rightPos); | 
| 817 |         QCOMPARE(rightTouchPoint.lastPos(), rightPos); | 
| 818 |         QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos); | 
| 819 |         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos); | 
| 820 |         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos); | 
| 821 |         QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos); | 
| 822 |         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos); | 
| 823 |         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos); | 
| 824 |         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 825 |         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 826 |         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 827 |         QCOMPARE(rightTouchPoint.pos(), rightPos); | 
| 828 |         QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos); | 
| 829 |         QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos); | 
| 830 |         QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 831 |         QCOMPARE(rightTouchPoint.pressure(), qreal(1.)); | 
| 832 |     } | 
| 833 |  | 
| 834 |     // generate TouchUpdates on both leftWidget and rightWidget | 
| 835 |     rawTouchPoints[0].setState(Qt::TouchPointMoved); | 
| 836 |     rawTouchPoints[0].setScreenPos(centerScreenPos); | 
| 837 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 838 |     rawTouchPoints[1].setState(Qt::TouchPointMoved); | 
| 839 |     rawTouchPoints[1].setScreenPos(centerScreenPos); | 
| 840 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 841 |     nativeTouchPoints = | 
| 842 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 843 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 844 |     QCoreApplication::processEvents(); | 
| 845 |     QVERIFY(!touchWidget.seenTouchBegin); | 
| 846 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 847 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 848 |     QVERIFY(leftWidget.seenTouchBegin); | 
| 849 |     QVERIFY(leftWidget.seenTouchUpdate); | 
| 850 |     QVERIFY(!leftWidget.seenTouchEnd); | 
| 851 |     QVERIFY(rightWidget.seenTouchBegin); | 
| 852 |     QVERIFY(rightWidget.seenTouchUpdate); | 
| 853 |     QVERIFY(!rightWidget.seenTouchEnd); | 
| 854 |     QCOMPARE(leftWidget.touchUpdatePoints.count(), 1); | 
| 855 |     QCOMPARE(rightWidget.touchUpdatePoints.count(), 1); | 
| 856 |     { | 
| 857 |         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchUpdatePoints.first(); | 
| 858 |         QCOMPARE(leftTouchPoint.id(), touchPointId0); | 
| 859 |         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); | 
| 860 |         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); | 
| 861 |         QCOMPARE(leftTouchPoint.startPos(), leftPos); | 
| 862 |         QCOMPARE(leftTouchPoint.lastPos(), leftPos); | 
| 863 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 864 |         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos); | 
| 865 |         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos); | 
| 866 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 867 |         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos); | 
| 868 |         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos); | 
| 869 |         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 870 |         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 871 |         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 872 |         QCOMPARE(leftTouchPoint.pos(), leftWidget.mapFromParent(centerPos.toPoint())); | 
| 873 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 874 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 875 |         QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 876 |         QCOMPARE(leftTouchPoint.pressure(), qreal(1.)); | 
| 877 |  | 
| 878 |         QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchUpdatePoints.first(); | 
| 879 |         QCOMPARE(rightTouchPoint.id(), touchPointId1); | 
| 880 |         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); | 
| 881 |         QCOMPARE(rightTouchPoint.pos(), QPointF(rightWidget.mapFromParent(centerPos.toPoint()))); | 
| 882 |         QCOMPARE(rightTouchPoint.startPos(), rightPos); | 
| 883 |         QCOMPARE(rightTouchPoint.lastPos(), rightPos); | 
| 884 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 885 |         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos); | 
| 886 |         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos); | 
| 887 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 888 |         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos); | 
| 889 |         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos); | 
| 890 |         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 891 |         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 892 |         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 893 |         QCOMPARE(rightTouchPoint.pos(), rightWidget.mapFromParent(centerPos.toPoint())); | 
| 894 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 895 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 896 |         QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 897 |         QCOMPARE(rightTouchPoint.pressure(), qreal(1.)); | 
| 898 |     } | 
| 899 |  | 
| 900 |     // generate TouchEnds on both leftWidget and rightWidget | 
| 901 |     rawTouchPoints[0].setState(Qt::TouchPointReleased); | 
| 902 |     rawTouchPoints[0].setScreenPos(centerScreenPos); | 
| 903 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 904 |     rawTouchPoints[1].setState(Qt::TouchPointReleased); | 
| 905 |     rawTouchPoints[1].setScreenPos(centerScreenPos); | 
| 906 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 907 |     nativeTouchPoints = | 
| 908 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 909 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 910 |     QCoreApplication::processEvents(); | 
| 911 |     QVERIFY(!touchWidget.seenTouchBegin); | 
| 912 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 913 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 914 |     QVERIFY(leftWidget.seenTouchBegin); | 
| 915 |     QVERIFY(leftWidget.seenTouchUpdate); | 
| 916 |     QVERIFY(leftWidget.seenTouchEnd); | 
| 917 |     QVERIFY(rightWidget.seenTouchBegin); | 
| 918 |     QVERIFY(rightWidget.seenTouchUpdate); | 
| 919 |     QVERIFY(rightWidget.seenTouchEnd); | 
| 920 |     QCOMPARE(leftWidget.touchEndPoints.count(), 1); | 
| 921 |     QCOMPARE(rightWidget.touchEndPoints.count(), 1); | 
| 922 |     { | 
| 923 |         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchEndPoints.first(); | 
| 924 |         QCOMPARE(leftTouchPoint.id(), touchPointId0); | 
| 925 |         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); | 
| 926 |         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); | 
| 927 |         QCOMPARE(leftTouchPoint.startPos(), leftPos); | 
| 928 |         QCOMPARE(leftTouchPoint.lastPos(), leftTouchPoint.pos()); | 
| 929 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 930 |         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos); | 
| 931 |         QCOMPARE(leftTouchPoint.lastScenePos(), leftTouchPoint.scenePos()); | 
| 932 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 933 |         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos); | 
| 934 |         QCOMPARE(leftTouchPoint.lastScreenPos(), leftTouchPoint.screenPos()); | 
| 935 |         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 936 |         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 937 |         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 938 |         QCOMPARE(leftTouchPoint.pos(), leftWidget.mapFromParent(centerPos.toPoint())); | 
| 939 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 940 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 941 |         QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 942 |         QCOMPARE(leftTouchPoint.pressure(), qreal(0.)); | 
| 943 |  | 
| 944 |         QTouchEvent::TouchPoint rightTouchPoint = rightWidget.touchEndPoints.first(); | 
| 945 |         QCOMPARE(rightTouchPoint.id(), touchPointId1); | 
| 946 |         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); | 
| 947 |         QCOMPARE(rightTouchPoint.pos(), QPointF(rightWidget.mapFromParent(centerPos.toPoint()))); | 
| 948 |         QCOMPARE(rightTouchPoint.startPos(), rightPos); | 
| 949 |         QCOMPARE(rightTouchPoint.lastPos(), rightTouchPoint.pos()); | 
| 950 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 951 |         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos); | 
| 952 |         QCOMPARE(rightTouchPoint.lastScenePos(), rightTouchPoint.scenePos()); | 
| 953 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 954 |         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos); | 
| 955 |         QCOMPARE(rightTouchPoint.lastScreenPos(), rightTouchPoint.screenPos()); | 
| 956 |         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 957 |         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 958 |         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 959 |         QCOMPARE(rightTouchPoint.pos(), rightWidget.mapFromParent(centerPos.toPoint())); | 
| 960 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 961 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 962 |         QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 963 |         QCOMPARE(rightTouchPoint.pressure(), qreal(0.)); | 
| 964 |     } | 
| 965 | } | 
| 966 |  | 
| 967 | void tst_QTouchEvent::touchOnMultipleTouchscreens() | 
| 968 | { | 
| 969 |     tst_QTouchEventWidget touchWidget; | 
| 970 |     touchWidget.setWindowTitle(QTest::currentTestFunction()); | 
| 971 |     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 972 |     touchWidget.setGeometry(ax: 100, ay: 100, aw: 400, ah: 300); | 
| 973 |     touchWidget.show(); | 
| 974 |     QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); | 
| 975 |     QWindow *window = touchWidget.windowHandle(); | 
| 976 |  | 
| 977 |     QPointF pos = touchWidget.rect().center(); | 
| 978 |     QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint()); | 
| 979 |     QPointF delta(10, 10); | 
| 980 |     QRectF screenGeometry = touchWidget.screen()->geometry(); | 
| 981 |  | 
| 982 |     QVector<QTouchEvent::TouchPoint> rawTouchPoints(3); | 
| 983 |     rawTouchPoints[0].setId(0); | 
| 984 |     rawTouchPoints[1].setId(10); | 
| 985 |     rawTouchPoints[2].setId(11); | 
| 986 |  | 
| 987 |     // this should be translated to a TouchBegin | 
| 988 |     rawTouchPoints[0].setState(Qt::TouchPointPressed); | 
| 989 |     rawTouchPoints[0].setScreenPos(screenPos); | 
| 990 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 991 |     rawTouchPoints[0].setRawScreenPositions({{12, 34}, {56, 78}}); | 
| 992 |     ulong timestamp = 1234; | 
| 993 |     QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = | 
| 994 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window); | 
| 995 |     QWindowSystemInterface::handleTouchEvent(window, timestamp, device: touchScreenDevice, points: nativeTouchPoints); | 
| 996 |     QCoreApplication::processEvents(); | 
| 997 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 998 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 999 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1000 |     QCOMPARE(touchWidget.touchBeginPoints.count(), 1); | 
| 1001 |     QCOMPARE(touchWidget.timestamp, timestamp); | 
| 1002 |     QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.first(); | 
| 1003 |     const int touchPointId = (QTouchDevicePrivate::get(q: touchScreenDevice)->id << 24) + 1; | 
| 1004 |     const int secTouchPointId = (QTouchDevicePrivate::get(q: secondaryTouchScreenDevice)->id << 24) + 2; | 
| 1005 |     QCOMPARE(touchBeginPoint.id(), touchPointId); | 
| 1006 |     QCOMPARE(touchBeginPoint.state(), rawTouchPoints[0].state()); | 
| 1007 |     QCOMPARE(touchBeginPoint.pos(), pos); | 
| 1008 |  | 
| 1009 |     // press a point on secondaryTouchScreenDevice | 
| 1010 |     touchWidget.seenTouchBegin = false; | 
| 1011 |     rawTouchPoints[1].setState(Qt::TouchPointPressed); | 
| 1012 |     rawTouchPoints[1].setScreenPos(screenPos); | 
| 1013 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 1014 |     rawTouchPoints[1].setRawScreenPositions({{90, 100}, {110, 120}}); | 
| 1015 |     nativeTouchPoints = | 
| 1016 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[1], window); | 
| 1017 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: ++timestamp, device: secondaryTouchScreenDevice, points: nativeTouchPoints); | 
| 1018 |     QCoreApplication::processEvents(); | 
| 1019 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1020 |     QCOMPARE(touchWidget.touchBeginPoints.count(), 1); | 
| 1021 |     QCOMPARE(touchWidget.timestamp, timestamp); | 
| 1022 |     touchBeginPoint = touchWidget.touchBeginPoints[0]; | 
| 1023 |     QCOMPARE(touchBeginPoint.id(), (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 2); | 
| 1024 |     QCOMPARE(touchBeginPoint.state(), rawTouchPoints[1].state()); | 
| 1025 |     QCOMPARE(touchBeginPoint.pos(), pos); | 
| 1026 |  | 
| 1027 |     // press another point on secondaryTouchScreenDevice | 
| 1028 |     touchWidget.seenTouchBegin = false; | 
| 1029 |     rawTouchPoints[2].setState(Qt::TouchPointPressed); | 
| 1030 |     rawTouchPoints[2].setScreenPos(screenPos); | 
| 1031 |     rawTouchPoints[2].setNormalizedPos(normalized(pos: rawTouchPoints[2].pos(), rect: screenGeometry)); | 
| 1032 |     rawTouchPoints[2].setRawScreenPositions({{130, 140}, {150, 160}}); | 
| 1033 |     nativeTouchPoints = | 
| 1034 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[2], window); | 
| 1035 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: ++timestamp, device: secondaryTouchScreenDevice, points: nativeTouchPoints); | 
| 1036 |     QCoreApplication::processEvents(); | 
| 1037 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1038 |     QCOMPARE(touchWidget.touchBeginPoints.count(), 1); | 
| 1039 |     QCOMPARE(touchWidget.timestamp, timestamp); | 
| 1040 |     touchBeginPoint = touchWidget.touchBeginPoints[0]; | 
| 1041 |     QCOMPARE(touchBeginPoint.id(), (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 3); | 
| 1042 |     QCOMPARE(touchBeginPoint.state(), rawTouchPoints[2].state()); | 
| 1043 |     QCOMPARE(touchBeginPoint.pos(), pos); | 
| 1044 |  | 
| 1045 |     // moving the first point should translate to TouchUpdate | 
| 1046 |     rawTouchPoints[0].setState(Qt::TouchPointMoved); | 
| 1047 |     rawTouchPoints[0].setScreenPos(screenPos + delta); | 
| 1048 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 1049 |     nativeTouchPoints = | 
| 1050 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window); | 
| 1051 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: ++timestamp, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1052 |     QCoreApplication::processEvents(); | 
| 1053 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1054 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1055 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1056 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 1); | 
| 1057 |     QTouchEvent::TouchPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first(); | 
| 1058 |     QCOMPARE(touchUpdatePoint.id(), touchPointId); | 
| 1059 |     QCOMPARE(touchUpdatePoint.state(), rawTouchPoints[0].state()); | 
| 1060 |     QCOMPARE(touchUpdatePoint.pos(), pos + delta); | 
| 1061 |  | 
| 1062 |     // releasing the first point translates to TouchEnd | 
| 1063 |     rawTouchPoints[0].setState(Qt::TouchPointReleased); | 
| 1064 |     rawTouchPoints[0].setScreenPos(screenPos + delta + delta); | 
| 1065 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 1066 |     nativeTouchPoints = | 
| 1067 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window); | 
| 1068 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: ++timestamp, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1069 |     QCoreApplication::processEvents(); | 
| 1070 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1071 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1072 |     QVERIFY(touchWidget.seenTouchEnd); | 
| 1073 |     QCOMPARE(touchWidget.touchEndPoints.count(), 1); | 
| 1074 |     QTouchEvent::TouchPoint touchEndPoint = touchWidget.touchEndPoints.first(); | 
| 1075 |     QCOMPARE(touchEndPoint.id(), touchPointId); | 
| 1076 |     QCOMPARE(touchEndPoint.state(), rawTouchPoints[0].state()); | 
| 1077 |     QCOMPARE(touchEndPoint.pos(), pos + delta + delta); | 
| 1078 |  | 
| 1079 |     // Widgets don't normally handle this case: if a TouchEnd was seen before, then | 
| 1080 |     // WA_WState_AcceptedTouchBeginEvent will be false, and | 
| 1081 |     // QApplicationPrivate::translateRawTouchEvent will ignore touch events that aren't TouchBegin. | 
| 1082 |     // So we have to set it true.  It _did_ in fact accept the touch begin from the secondary device, | 
| 1083 |     // but it also got a TouchEnd from the primary device in the meantime. | 
| 1084 |     touchWidget.setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, on: true); | 
| 1085 |  | 
| 1086 |     // Releasing one point on the secondary touchscreen does not yet generate TouchEnd. | 
| 1087 |     touchWidget.seenTouchEnd = false; | 
| 1088 |     touchWidget.touchEndPoints.clear(); | 
| 1089 |     rawTouchPoints[1].setState(Qt::TouchPointReleased); | 
| 1090 |     rawTouchPoints[2].setState(Qt::TouchPointStationary); | 
| 1091 |     nativeTouchPoints = | 
| 1092 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[1] << rawTouchPoints[2], window); | 
| 1093 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: ++timestamp, device: secondaryTouchScreenDevice, points: nativeTouchPoints); | 
| 1094 |     QCoreApplication::processEvents(); | 
| 1095 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1096 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1097 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1098 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); | 
| 1099 |     QCOMPARE(touchWidget.touchUpdatePoints[0].id(), secTouchPointId); | 
| 1100 |     QCOMPARE(touchWidget.touchUpdatePoints[1].id(), secTouchPointId + 1); | 
| 1101 |  | 
| 1102 |     // releasing the last point on the secondary touchscreen translates to TouchEnd | 
| 1103 |     touchWidget.seenTouchEnd = false; | 
| 1104 |     rawTouchPoints[2].setState(Qt::TouchPointReleased); | 
| 1105 |     nativeTouchPoints = | 
| 1106 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: QList<QTouchEvent::TouchPoint>() << rawTouchPoints[2], window); | 
| 1107 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: ++timestamp, device: secondaryTouchScreenDevice, points: nativeTouchPoints); | 
| 1108 |     QCoreApplication::processEvents(); | 
| 1109 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1110 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1111 |     QVERIFY(touchWidget.seenTouchEnd); | 
| 1112 |     QCOMPARE(touchWidget.touchEndPoints.count(), 1); | 
| 1113 |     touchEndPoint = touchWidget.touchEndPoints.first(); | 
| 1114 |     QCOMPARE(touchEndPoint.id(), secTouchPointId + 1); | 
| 1115 |     QCOMPARE(touchEndPoint.state(), rawTouchPoints[2].state()); | 
| 1116 | } | 
| 1117 |  | 
| 1118 | void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() | 
| 1119 | { | 
| 1120 |     tst_QTouchEventWidget touchWidget; | 
| 1121 |     touchWidget.setWindowTitle(QTest::currentTestFunction()); | 
| 1122 |     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1123 |     touchWidget.setGeometry(ax: 100, ay: 100, aw: 400, ah: 300); | 
| 1124 |  | 
| 1125 |     tst_QTouchEventWidget leftWidget(&touchWidget); | 
| 1126 |     leftWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1127 |     leftWidget.setGeometry(ax: 0, ay: 100, aw: 100, ah: 100); | 
| 1128 |     leftWidget.acceptTouchBegin =true; | 
| 1129 |  | 
| 1130 |     tst_QTouchEventWidget rightWidget(&touchWidget); | 
| 1131 |     rightWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1132 |     rightWidget.setGeometry(ax: 300, ay: 100, aw: 100, ah: 100); | 
| 1133 |  | 
| 1134 |     touchWidget.show(); | 
| 1135 |     QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); | 
| 1136 |  | 
| 1137 |     QPointF leftPos = leftWidget.rect().center(); | 
| 1138 |     QPointF rightPos = rightWidget.rect().center(); | 
| 1139 |     QPointF centerPos = touchWidget.rect().center(); | 
| 1140 |     QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint()); | 
| 1141 |     QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint()); | 
| 1142 |     QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint()); | 
| 1143 |     QRectF screenGeometry = touchWidget.screen()->geometry(); | 
| 1144 |  | 
| 1145 |     QList<QTouchEvent::TouchPoint> rawTouchPoints; | 
| 1146 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 1147 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(1)); | 
| 1148 |  | 
| 1149 |     // generate TouchBegin on leftWidget only | 
| 1150 |     rawTouchPoints[0].setState(Qt::TouchPointPressed); | 
| 1151 |     rawTouchPoints[0].setScreenPos(leftScreenPos); | 
| 1152 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 1153 |     rawTouchPoints[1].setState(Qt::TouchPointPressed); | 
| 1154 |     rawTouchPoints[1].setScreenPos(rightScreenPos); | 
| 1155 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 1156 |     QWindow *window = touchWidget.windowHandle(); | 
| 1157 |     QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = | 
| 1158 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1159 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchPadDevice, points: nativeTouchPoints); | 
| 1160 |     QCoreApplication::processEvents(); | 
| 1161 |     QVERIFY(!touchWidget.seenTouchBegin); | 
| 1162 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 1163 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1164 |     QEXPECT_FAIL("" , "QTBUG-46266, fails in Qt 5" , Abort); | 
| 1165 |     QVERIFY(!leftWidget.seenTouchBegin); | 
| 1166 |     QVERIFY(!leftWidget.seenTouchUpdate); | 
| 1167 |     QVERIFY(!leftWidget.seenTouchEnd); | 
| 1168 |     QVERIFY(!rightWidget.seenTouchBegin); | 
| 1169 |     QVERIFY(!rightWidget.seenTouchUpdate); | 
| 1170 |     QVERIFY(!rightWidget.seenTouchEnd); | 
| 1171 |     QCOMPARE(leftWidget.touchBeginPoints.count(), 2); | 
| 1172 |     QCOMPARE(rightWidget.touchBeginPoints.count(), 0); | 
| 1173 |     { | 
| 1174 |         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchBeginPoints.at(i: 0); | 
| 1175 |         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id()); | 
| 1176 |         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); | 
| 1177 |         QCOMPARE(leftTouchPoint.pos(), leftPos); | 
| 1178 |         QCOMPARE(leftTouchPoint.startPos(), leftPos); | 
| 1179 |         QCOMPARE(leftTouchPoint.lastPos(), leftPos); | 
| 1180 |         QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos); | 
| 1181 |         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos); | 
| 1182 |         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos); | 
| 1183 |         QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos); | 
| 1184 |         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos); | 
| 1185 |         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos); | 
| 1186 |         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1187 |         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1188 |         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1189 |         QCOMPARE(leftTouchPoint.pos(), leftPos); | 
| 1190 |         QCOMPARE(leftTouchPoint.scenePos(), leftScreenPos); | 
| 1191 |         QCOMPARE(leftTouchPoint.screenPos(), leftScreenPos); | 
| 1192 |         QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 1193 |         QCOMPARE(leftTouchPoint.pressure(), qreal(1.)); | 
| 1194 |  | 
| 1195 |         QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchBeginPoints.at(i: 1); | 
| 1196 |         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id()); | 
| 1197 |         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); | 
| 1198 |         QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()))); | 
| 1199 |         QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()))); | 
| 1200 |         QCOMPARE(rightTouchPoint.lastPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()))); | 
| 1201 |         QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos); | 
| 1202 |         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos); | 
| 1203 |         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos); | 
| 1204 |         QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos); | 
| 1205 |         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos); | 
| 1206 |         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos); | 
| 1207 |         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1208 |         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1209 |         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1210 |         QCOMPARE(rightTouchPoint.pos(), rightWidget.mapFromParent(rightScreenPos.toPoint())); | 
| 1211 |         QCOMPARE(rightTouchPoint.scenePos(), rightScreenPos); | 
| 1212 |         QCOMPARE(rightTouchPoint.screenPos(), rightScreenPos); | 
| 1213 |         QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 1214 |         QCOMPARE(rightTouchPoint.pressure(), qreal(1.)); | 
| 1215 |     } | 
| 1216 |  | 
| 1217 |     // generate TouchUpdate on leftWidget | 
| 1218 |     rawTouchPoints[0].setState(Qt::TouchPointMoved); | 
| 1219 |     rawTouchPoints[0].setScreenPos(centerScreenPos); | 
| 1220 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 1221 |     rawTouchPoints[1].setState(Qt::TouchPointMoved); | 
| 1222 |     rawTouchPoints[1].setScreenPos(centerScreenPos); | 
| 1223 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 1224 |     nativeTouchPoints = | 
| 1225 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1226 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchPadDevice, points: nativeTouchPoints); | 
| 1227 |     QCoreApplication::processEvents(); | 
| 1228 |     QVERIFY(!touchWidget.seenTouchBegin); | 
| 1229 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 1230 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1231 |     QVERIFY(leftWidget.seenTouchBegin); | 
| 1232 |     QVERIFY(leftWidget.seenTouchUpdate); | 
| 1233 |     QVERIFY(!leftWidget.seenTouchEnd); | 
| 1234 |     QVERIFY(!rightWidget.seenTouchBegin); | 
| 1235 |     QVERIFY(!rightWidget.seenTouchUpdate); | 
| 1236 |     QVERIFY(!rightWidget.seenTouchEnd); | 
| 1237 |     QCOMPARE(leftWidget.touchUpdatePoints.count(), 2); | 
| 1238 |     QCOMPARE(rightWidget.touchUpdatePoints.count(), 0); | 
| 1239 |     { | 
| 1240 |         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchUpdatePoints.at(i: 0); | 
| 1241 |         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id()); | 
| 1242 |         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); | 
| 1243 |         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); | 
| 1244 |         QCOMPARE(leftTouchPoint.startPos(), leftPos); | 
| 1245 |         QCOMPARE(leftTouchPoint.lastPos(), leftPos); | 
| 1246 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 1247 |         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos); | 
| 1248 |         QCOMPARE(leftTouchPoint.lastScenePos(), leftScreenPos); | 
| 1249 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 1250 |         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos); | 
| 1251 |         QCOMPARE(leftTouchPoint.lastScreenPos(), leftScreenPos); | 
| 1252 |         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1253 |         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1254 |         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1255 |         QCOMPARE(leftTouchPoint.pos(), leftWidget.mapFromParent(centerPos.toPoint())); | 
| 1256 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 1257 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 1258 |         QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 1259 |         QCOMPARE(leftTouchPoint.pressure(), qreal(1.)); | 
| 1260 |  | 
| 1261 |         QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchUpdatePoints.at(i: 1); | 
| 1262 |         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id()); | 
| 1263 |         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); | 
| 1264 |         QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); | 
| 1265 |         QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()))); | 
| 1266 |         QCOMPARE(rightTouchPoint.lastPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()))); | 
| 1267 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 1268 |         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos); | 
| 1269 |         QCOMPARE(rightTouchPoint.lastScenePos(), rightScreenPos); | 
| 1270 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 1271 |         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos); | 
| 1272 |         QCOMPARE(rightTouchPoint.lastScreenPos(), rightScreenPos); | 
| 1273 |         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1274 |         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1275 |         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1276 |         QCOMPARE(rightTouchPoint.pos(), leftWidget.mapFromParent(centerPos.toPoint())); | 
| 1277 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 1278 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 1279 |         QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 1280 |         QCOMPARE(rightTouchPoint.pressure(), qreal(1.)); | 
| 1281 |     } | 
| 1282 |  | 
| 1283 |     // generate TouchEnd on leftWidget | 
| 1284 |     rawTouchPoints[0].setState(Qt::TouchPointReleased); | 
| 1285 |     rawTouchPoints[0].setScreenPos(centerScreenPos); | 
| 1286 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 1287 |     rawTouchPoints[1].setState(Qt::TouchPointReleased); | 
| 1288 |     rawTouchPoints[1].setScreenPos(centerScreenPos); | 
| 1289 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 1290 |     nativeTouchPoints = | 
| 1291 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1292 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchPadDevice, points: nativeTouchPoints); | 
| 1293 |     QCoreApplication::processEvents(); | 
| 1294 |     QVERIFY(!touchWidget.seenTouchBegin); | 
| 1295 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 1296 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1297 |     QVERIFY(leftWidget.seenTouchBegin); | 
| 1298 |     QVERIFY(leftWidget.seenTouchUpdate); | 
| 1299 |     QVERIFY(leftWidget.seenTouchEnd); | 
| 1300 |     QVERIFY(!rightWidget.seenTouchBegin); | 
| 1301 |     QVERIFY(!rightWidget.seenTouchUpdate); | 
| 1302 |     QVERIFY(!rightWidget.seenTouchEnd); | 
| 1303 |     QCOMPARE(leftWidget.touchEndPoints.count(), 2); | 
| 1304 |     QCOMPARE(rightWidget.touchEndPoints.count(), 0); | 
| 1305 |     { | 
| 1306 |         QTouchEvent::TouchPoint leftTouchPoint = leftWidget.touchEndPoints.at(i: 0); | 
| 1307 |         QCOMPARE(leftTouchPoint.id(), rawTouchPoints[0].id()); | 
| 1308 |         QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); | 
| 1309 |         QCOMPARE(leftTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); | 
| 1310 |         QCOMPARE(leftTouchPoint.startPos(), leftPos); | 
| 1311 |         QCOMPARE(leftTouchPoint.lastPos(), leftTouchPoint.pos()); | 
| 1312 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 1313 |         QCOMPARE(leftTouchPoint.startScenePos(), leftScreenPos); | 
| 1314 |         QCOMPARE(leftTouchPoint.lastScenePos(), leftTouchPoint.scenePos()); | 
| 1315 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 1316 |         QCOMPARE(leftTouchPoint.startScreenPos(), leftScreenPos); | 
| 1317 |         QCOMPARE(leftTouchPoint.lastScreenPos(), leftTouchPoint.screenPos()); | 
| 1318 |         QCOMPARE(leftTouchPoint.normalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1319 |         QCOMPARE(leftTouchPoint.startNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1320 |         QCOMPARE(leftTouchPoint.lastNormalizedPos(), rawTouchPoints[0].normalizedPos()); | 
| 1321 |         QCOMPARE(leftTouchPoint.pos(), leftWidget.mapFromParent(centerPos.toPoint())); | 
| 1322 |         QCOMPARE(leftTouchPoint.scenePos(), centerScreenPos); | 
| 1323 |         QCOMPARE(leftTouchPoint.screenPos(), centerScreenPos); | 
| 1324 |         QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 1325 |         QCOMPARE(leftTouchPoint.pressure(), qreal(0.)); | 
| 1326 |  | 
| 1327 |         QTouchEvent::TouchPoint rightTouchPoint = leftWidget.touchEndPoints.at(i: 1); | 
| 1328 |         QCOMPARE(rightTouchPoint.id(), rawTouchPoints[1].id()); | 
| 1329 |         QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); | 
| 1330 |         QCOMPARE(rightTouchPoint.pos(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); | 
| 1331 |         QCOMPARE(rightTouchPoint.startPos(), QPointF(leftWidget.mapFromGlobal(rightScreenPos.toPoint()))); | 
| 1332 |         QCOMPARE(rightTouchPoint.lastPos(), rightTouchPoint.pos()); | 
| 1333 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 1334 |         QCOMPARE(rightTouchPoint.startScenePos(), rightScreenPos); | 
| 1335 |         QCOMPARE(rightTouchPoint.lastScenePos(), rightTouchPoint.scenePos()); | 
| 1336 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 1337 |         QCOMPARE(rightTouchPoint.startScreenPos(), rightScreenPos); | 
| 1338 |         QCOMPARE(rightTouchPoint.lastScreenPos(), rightTouchPoint.screenPos()); | 
| 1339 |         QCOMPARE(rightTouchPoint.normalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1340 |         QCOMPARE(rightTouchPoint.startNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1341 |         QCOMPARE(rightTouchPoint.lastNormalizedPos(), rawTouchPoints[1].normalizedPos()); | 
| 1342 |         QCOMPARE(rightTouchPoint.pos(), leftWidget.mapFromParent(centerPos.toPoint())); | 
| 1343 |         QCOMPARE(rightTouchPoint.scenePos(), centerScreenPos); | 
| 1344 |         QCOMPARE(rightTouchPoint.screenPos(), centerScreenPos); | 
| 1345 |         QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); | 
| 1346 |         QCOMPARE(rightTouchPoint.pressure(), qreal(0.)); | 
| 1347 |     } | 
| 1348 | } | 
| 1349 |  | 
| 1350 | void tst_QTouchEvent::basicRawEventTranslationOfIds() | 
| 1351 | { | 
| 1352 |     tst_QTouchEventWidget touchWidget; | 
| 1353 |     touchWidget.setWindowTitle(QTest::currentTestFunction()); | 
| 1354 |     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1355 |     touchWidget.setGeometry(ax: 100, ay: 100, aw: 400, ah: 300); | 
| 1356 |     touchWidget.show(); | 
| 1357 |     QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); | 
| 1358 |  | 
| 1359 |     QVarLengthArray<QPointF, 2> pos; | 
| 1360 |     QVarLengthArray<QPointF, 2> screenPos; | 
| 1361 |     for (int i = 0; i < 2; ++i) { | 
| 1362 |         pos << touchWidget.rect().center() + QPointF(20*i, 20*i); | 
| 1363 |         screenPos << touchWidget.mapToGlobal(pos[i].toPoint()); | 
| 1364 |     } | 
| 1365 |     QPointF delta(10, 10); | 
| 1366 |     QRectF screenGeometry = touchWidget.screen()->geometry(); | 
| 1367 |  | 
| 1368 |     QVector<QPointF> rawPosList; | 
| 1369 |     rawPosList << QPointF(12, 34) << QPointF(56, 78); | 
| 1370 |  | 
| 1371 |     QList<QTouchEvent::TouchPoint> rawTouchPoints; | 
| 1372 |  | 
| 1373 |     // Press both points, this should be translated to a TouchBegin | 
| 1374 |     for (int i = 0; i < 2; ++i) { | 
| 1375 |         QTouchEvent::TouchPoint rawTouchPoint; | 
| 1376 |         rawTouchPoint.setId(i); | 
| 1377 |         rawTouchPoint.setState(Qt::TouchPointPressed); | 
| 1378 |         rawTouchPoint.setScreenPos(screenPos[i]); | 
| 1379 |         rawTouchPoint.setNormalizedPos(normalized(pos: rawTouchPoint.pos(), rect: screenGeometry)); | 
| 1380 |         rawTouchPoint.setRawScreenPositions(rawPosList); | 
| 1381 |         rawTouchPoints << rawTouchPoint; | 
| 1382 |     } | 
| 1383 |     QTouchEvent::TouchPoint &p0 = rawTouchPoints[0]; | 
| 1384 |     QTouchEvent::TouchPoint &p1 = rawTouchPoints[1]; | 
| 1385 |  | 
| 1386 |     const ulong timestamp = 1234; | 
| 1387 |     QWindow *window = touchWidget.windowHandle(); | 
| 1388 |     QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = | 
| 1389 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1390 |     QWindowSystemInterface::handleTouchEvent(window, timestamp, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1391 |     QCoreApplication::processEvents(); | 
| 1392 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1393 |     QVERIFY(!touchWidget.seenTouchUpdate); | 
| 1394 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1395 |     QCOMPARE(touchWidget.touchBeginPoints.count(), 2); | 
| 1396 |  | 
| 1397 |     const int initialTouchPointId = (QTouchDevicePrivate::get(q: touchScreenDevice)->id << 24) + 1; | 
| 1398 |  | 
| 1399 |     for (int i = 0; i < touchWidget.touchBeginPoints.count(); ++i) { | 
| 1400 |         QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.at(i); | 
| 1401 |         QCOMPARE(touchBeginPoint.id(), initialTouchPointId + i); | 
| 1402 |         QCOMPARE(touchBeginPoint.state(), rawTouchPoints[i].state()); | 
| 1403 |     } | 
| 1404 |  | 
| 1405 |     // moving the point should translate to TouchUpdate | 
| 1406 |     for (int i = 0; i < rawTouchPoints.count(); ++i) { | 
| 1407 |         QTouchEvent::TouchPoint &p = rawTouchPoints[i]; | 
| 1408 |         p.setState(Qt::TouchPointMoved); | 
| 1409 |         p.setScreenPos(p.screenPos() + delta); | 
| 1410 |         p.setNormalizedPos(normalized(pos: p.pos(), rect: screenGeometry)); | 
| 1411 |     } | 
| 1412 |     nativeTouchPoints = | 
| 1413 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1414 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1415 |     QCoreApplication::processEvents(); | 
| 1416 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1417 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1418 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1419 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); | 
| 1420 |     QCOMPARE(touchWidget.touchUpdatePoints.at(0).id(), initialTouchPointId); | 
| 1421 |     QCOMPARE(touchWidget.touchUpdatePoints.at(1).id(), initialTouchPointId + 1); | 
| 1422 |  | 
| 1423 |     // release last point | 
| 1424 |     p0.setState(Qt::TouchPointStationary); | 
| 1425 |     p1.setState(Qt::TouchPointReleased); | 
| 1426 |  | 
| 1427 |     nativeTouchPoints = | 
| 1428 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1429 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1430 |     QCoreApplication::processEvents(); | 
| 1431 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1432 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1433 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1434 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); | 
| 1435 |     QCOMPARE(touchWidget.touchUpdatePoints[0].id(), initialTouchPointId); | 
| 1436 |     QCOMPARE(touchWidget.touchUpdatePoints[1].id(), initialTouchPointId + 1); | 
| 1437 |  | 
| 1438 |     // Press last point again, id should increase | 
| 1439 |     p1.setState(Qt::TouchPointPressed); | 
| 1440 |     p1.setId(42);   // new id | 
| 1441 |     nativeTouchPoints = | 
| 1442 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1443 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1444 |     QCoreApplication::processEvents(); | 
| 1445 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1446 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1447 |     QVERIFY(!touchWidget.seenTouchEnd); | 
| 1448 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); | 
| 1449 |     QCOMPARE(touchWidget.touchUpdatePoints[0].id(), initialTouchPointId); | 
| 1450 |     QCOMPARE(touchWidget.touchUpdatePoints[1].id(), initialTouchPointId + 2); | 
| 1451 |  | 
| 1452 |     // release everything | 
| 1453 |     p0.setState(Qt::TouchPointReleased); | 
| 1454 |     p1.setState(Qt::TouchPointReleased); | 
| 1455 |     nativeTouchPoints = | 
| 1456 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1457 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1458 |     QCoreApplication::processEvents(); | 
| 1459 |     QVERIFY(touchWidget.seenTouchBegin); | 
| 1460 |     QVERIFY(touchWidget.seenTouchUpdate); | 
| 1461 |     QVERIFY(touchWidget.seenTouchEnd); | 
| 1462 |     QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); | 
| 1463 |     QCOMPARE(touchWidget.touchUpdatePoints[0].id(), initialTouchPointId); | 
| 1464 |     QCOMPARE(touchWidget.touchUpdatePoints[1].id(), initialTouchPointId + 2); | 
| 1465 | } | 
| 1466 |  | 
| 1467 | void tst_QTouchEvent::deleteInEventHandler() | 
| 1468 | { | 
| 1469 |     // QWidget | 
| 1470 |     { | 
| 1471 |         QWidget window; | 
| 1472 |         QPointer<tst_QTouchEventWidget> child1 = new tst_QTouchEventWidget(&window); | 
| 1473 |         QPointer<tst_QTouchEventWidget> child2 = new tst_QTouchEventWidget(&window); | 
| 1474 |         QPointer<tst_QTouchEventWidget> child3 = new tst_QTouchEventWidget(&window); | 
| 1475 |         child1->setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1476 |         child2->setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1477 |         child3->setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1478 |         child1->deleteInTouchBegin = true; | 
| 1479 |         child2->deleteInTouchUpdate = true; | 
| 1480 |         child3->deleteInTouchEnd = true; | 
| 1481 |  | 
| 1482 |         QList<QTouchEvent::TouchPoint> touchPoints; | 
| 1483 |         touchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 1484 |         QTouchEvent touchBeginEvent(QEvent::TouchBegin, | 
| 1485 |                                     touchScreenDevice, | 
| 1486 |                                     Qt::NoModifier, | 
| 1487 |                                     Qt::TouchPointPressed, | 
| 1488 |                                     touchPoints); | 
| 1489 |         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, | 
| 1490 |                                touchScreenDevice, | 
| 1491 |                                Qt::NoModifier, | 
| 1492 |                                Qt::TouchPointStationary, | 
| 1493 |                                touchPoints); | 
| 1494 |         QTouchEvent touchEndEvent(QEvent::TouchEnd, | 
| 1495 |                                touchScreenDevice, | 
| 1496 |                                Qt::NoModifier, | 
| 1497 |                                Qt::TouchPointReleased, | 
| 1498 |                                touchPoints); | 
| 1499 |         touchBeginEvent.ignore(); | 
| 1500 |         QVERIFY(QApplication::sendEvent(child1, &touchBeginEvent)); | 
| 1501 |         // event is handled, but widget should be deleted | 
| 1502 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 1503 |         QVERIFY(child1.isNull()); | 
| 1504 |  | 
| 1505 |         touchBeginEvent.ignore(); | 
| 1506 |         QVERIFY(QApplication::sendEvent(child2, &touchBeginEvent)); | 
| 1507 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 1508 |         QVERIFY(!child2.isNull()); | 
| 1509 |         touchUpdateEvent.ignore(); | 
| 1510 |         QVERIFY(QApplication::sendEvent(child2, &touchUpdateEvent)); | 
| 1511 |         QVERIFY(touchUpdateEvent.isAccepted()); | 
| 1512 |         QVERIFY(child2.isNull()); | 
| 1513 |  | 
| 1514 |         touchBeginEvent.ignore(); | 
| 1515 |         QVERIFY(QApplication::sendEvent(child3, &touchBeginEvent)); | 
| 1516 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 1517 |         QVERIFY(!child3.isNull()); | 
| 1518 |         touchUpdateEvent.ignore(); | 
| 1519 |         QVERIFY(QApplication::sendEvent(child3, &touchUpdateEvent)); | 
| 1520 |         QVERIFY(touchUpdateEvent.isAccepted()); | 
| 1521 |         QVERIFY(!child3.isNull()); | 
| 1522 |         touchEndEvent.ignore(); | 
| 1523 |         QVERIFY(QApplication::sendEvent(child3, &touchEndEvent)); | 
| 1524 |         QVERIFY(touchEndEvent.isAccepted()); | 
| 1525 |         QVERIFY(child3.isNull()); | 
| 1526 |     } | 
| 1527 |  | 
| 1528 |     // QGraphicsView | 
| 1529 |     { | 
| 1530 |         QGraphicsScene scene; | 
| 1531 |         QGraphicsView view(&scene); | 
| 1532 |         QScopedPointer<tst_QTouchEventGraphicsItem> root(new tst_QTouchEventGraphicsItem); | 
| 1533 |         tst_QTouchEventGraphicsItem *child1 = new tst_QTouchEventGraphicsItem(root.data()); | 
| 1534 |         tst_QTouchEventGraphicsItem *child2 = new tst_QTouchEventGraphicsItem(root.data()); | 
| 1535 |         tst_QTouchEventGraphicsItem *child3 = new tst_QTouchEventGraphicsItem(root.data()); | 
| 1536 |         child1->setZValue(1.); | 
| 1537 |         child2->setZValue(0.); | 
| 1538 |         child3->setZValue(-1.); | 
| 1539 |         child1->setAcceptTouchEvents(true); | 
| 1540 |         child2->setAcceptTouchEvents(true); | 
| 1541 |         child3->setAcceptTouchEvents(true); | 
| 1542 |         child1->deleteInTouchBegin = true; | 
| 1543 |         child2->deleteInTouchUpdate = true; | 
| 1544 |         child3->deleteInTouchEnd = true; | 
| 1545 |  | 
| 1546 |         scene.addItem(item: root.data()); | 
| 1547 |         view.resize(w: 200, h: 200); | 
| 1548 |         view.fitInView(rect: scene.sceneRect()); | 
| 1549 |  | 
| 1550 |         QTouchEvent::TouchPoint touchPoint(0); | 
| 1551 |         touchPoint.setState(Qt::TouchPointPressed); | 
| 1552 |         touchPoint.setPos(view.mapFromScene(point: child1->mapToScene(point: child1->boundingRect().center()))); | 
| 1553 |         touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); | 
| 1554 |         touchPoint.setScenePos(view.mapToScene(point: touchPoint.pos().toPoint())); | 
| 1555 |         QList<QTouchEvent::TouchPoint> touchPoints; | 
| 1556 |         touchPoints.append(t: touchPoint); | 
| 1557 |         QTouchEvent touchBeginEvent(QEvent::TouchBegin, | 
| 1558 |                                     touchScreenDevice, | 
| 1559 |                                     Qt::NoModifier, | 
| 1560 |                                     Qt::TouchPointPressed, | 
| 1561 |                                     touchPoints); | 
| 1562 |         touchPoints[0].setState(Qt::TouchPointMoved); | 
| 1563 |         QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, | 
| 1564 |                                touchScreenDevice, | 
| 1565 |                                Qt::NoModifier, | 
| 1566 |                                Qt::TouchPointMoved, | 
| 1567 |                                touchPoints); | 
| 1568 |         touchPoints[0].setState(Qt::TouchPointReleased); | 
| 1569 |         QTouchEvent touchEndEvent(QEvent::TouchEnd, | 
| 1570 |                                touchScreenDevice, | 
| 1571 |                                Qt::NoModifier, | 
| 1572 |                                Qt::TouchPointReleased, | 
| 1573 |                                touchPoints); | 
| 1574 |  | 
| 1575 |         child1->weakpointer = &child1; | 
| 1576 |         touchBeginEvent.ignore(); | 
| 1577 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent)); | 
| 1578 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 1579 |         QVERIFY(!child1); | 
| 1580 |         touchUpdateEvent.ignore(); | 
| 1581 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent)); | 
| 1582 |         QVERIFY(!touchUpdateEvent.isAccepted()); // Qt 5.X ignores touch events. | 
| 1583 |         QVERIFY(!child1); | 
| 1584 |         touchEndEvent.ignore(); | 
| 1585 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent)); | 
| 1586 |         QVERIFY(!touchUpdateEvent.isAccepted()); | 
| 1587 |         QVERIFY(!child1); | 
| 1588 |  | 
| 1589 |         child2->weakpointer = &child2; | 
| 1590 |         touchBeginEvent.ignore(); | 
| 1591 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent)); | 
| 1592 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 1593 |         QVERIFY(child2); | 
| 1594 |         touchUpdateEvent.ignore(); | 
| 1595 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent)); | 
| 1596 |         QVERIFY(!touchUpdateEvent.isAccepted()); | 
| 1597 |         QVERIFY(!child2); | 
| 1598 |         touchEndEvent.ignore(); | 
| 1599 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent)); | 
| 1600 |         QVERIFY(!touchUpdateEvent.isAccepted()); | 
| 1601 |         QVERIFY(!child2); | 
| 1602 |  | 
| 1603 |         child3->weakpointer = &child3; | 
| 1604 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent)); | 
| 1605 |         QVERIFY(touchBeginEvent.isAccepted()); | 
| 1606 |         QVERIFY(child3); | 
| 1607 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent)); | 
| 1608 |         QVERIFY(!touchUpdateEvent.isAccepted()); | 
| 1609 |         QVERIFY(child3); | 
| 1610 |         QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent)); | 
| 1611 |         QVERIFY(!touchEndEvent.isAccepted()); | 
| 1612 |         QVERIFY(!child3); | 
| 1613 |     } | 
| 1614 | } | 
| 1615 |  | 
| 1616 | void tst_QTouchEvent::deleteInRawEventTranslation() | 
| 1617 | { | 
| 1618 |     tst_QTouchEventWidget touchWidget; | 
| 1619 |     touchWidget.setWindowTitle(QTest::currentTestFunction()); | 
| 1620 |     touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1621 |     touchWidget.setGeometry(ax: 100, ay: 100, aw: 300, ah: 300); | 
| 1622 |  | 
| 1623 |     QPointer<tst_QTouchEventWidget> leftWidget = new tst_QTouchEventWidget(&touchWidget); | 
| 1624 |     leftWidget->setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1625 |     leftWidget->setGeometry(ax: 0, ay: 100, aw: 100, ah: 100); | 
| 1626 |     leftWidget->deleteInTouchBegin = true; | 
| 1627 |  | 
| 1628 |     QPointer<tst_QTouchEventWidget> centerWidget = new tst_QTouchEventWidget(&touchWidget); | 
| 1629 |     centerWidget->setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1630 |     centerWidget->setGeometry(ax: 100, ay: 100, aw: 100, ah: 100); | 
| 1631 |     centerWidget->deleteInTouchUpdate = true; | 
| 1632 |  | 
| 1633 |     QPointer<tst_QTouchEventWidget> rightWidget = new tst_QTouchEventWidget(&touchWidget); | 
| 1634 |     rightWidget->setAttribute(Qt::WA_AcceptTouchEvents); | 
| 1635 |     rightWidget->setGeometry(ax: 200, ay: 100, aw: 100, ah: 100); | 
| 1636 |     rightWidget->deleteInTouchEnd = true; | 
| 1637 |  | 
| 1638 |     touchWidget.show(); | 
| 1639 |     QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); | 
| 1640 |  | 
| 1641 |     QPointF leftPos = leftWidget->rect().center(); | 
| 1642 |     QPointF centerPos = centerWidget->rect().center(); | 
| 1643 |     QPointF rightPos = rightWidget->rect().center(); | 
| 1644 |     QPointF leftScreenPos = leftWidget->mapToGlobal(leftPos.toPoint()); | 
| 1645 |     QPointF centerScreenPos = centerWidget->mapToGlobal(centerPos.toPoint()); | 
| 1646 |     QPointF rightScreenPos = rightWidget->mapToGlobal(rightPos.toPoint()); | 
| 1647 |     QRectF screenGeometry = touchWidget.screen()->geometry(); | 
| 1648 |  | 
| 1649 |     QList<QTouchEvent::TouchPoint> rawTouchPoints; | 
| 1650 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(0)); | 
| 1651 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(1)); | 
| 1652 |     rawTouchPoints.append(t: QTouchEvent::TouchPoint(2)); | 
| 1653 |     rawTouchPoints[0].setState(Qt::TouchPointPressed); | 
| 1654 |     rawTouchPoints[0].setScreenPos(leftScreenPos); | 
| 1655 |     rawTouchPoints[0].setNormalizedPos(normalized(pos: rawTouchPoints[0].pos(), rect: screenGeometry)); | 
| 1656 |     rawTouchPoints[1].setState(Qt::TouchPointPressed); | 
| 1657 |     rawTouchPoints[1].setScreenPos(centerScreenPos); | 
| 1658 |     rawTouchPoints[1].setNormalizedPos(normalized(pos: rawTouchPoints[1].pos(), rect: screenGeometry)); | 
| 1659 |     rawTouchPoints[2].setState(Qt::TouchPointPressed); | 
| 1660 |     rawTouchPoints[2].setScreenPos(rightScreenPos); | 
| 1661 |     rawTouchPoints[2].setNormalizedPos(normalized(pos: rawTouchPoints[2].pos(), rect: screenGeometry)); | 
| 1662 |  | 
| 1663 |     // generate begin events on all widgets, the left widget should die | 
| 1664 |     QWindow *window = touchWidget.windowHandle(); | 
| 1665 |     QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = | 
| 1666 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1667 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1668 |     QCoreApplication::processEvents(); | 
| 1669 |     QVERIFY(leftWidget.isNull()); | 
| 1670 |     QVERIFY(!centerWidget.isNull()); | 
| 1671 |     QVERIFY(!rightWidget.isNull()); | 
| 1672 |  | 
| 1673 |     // generate update events on all widget, the center widget should die | 
| 1674 |     rawTouchPoints[0].setState(Qt::TouchPointMoved); | 
| 1675 |     rawTouchPoints[1].setState(Qt::TouchPointMoved); | 
| 1676 |     rawTouchPoints[2].setState(Qt::TouchPointMoved); | 
| 1677 |     nativeTouchPoints = | 
| 1678 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1679 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1680 |     QCoreApplication::processEvents(); | 
| 1681 |  | 
| 1682 |     // generate end events on all widget, the right widget should die | 
| 1683 |     rawTouchPoints[0].setState(Qt::TouchPointReleased); | 
| 1684 |     rawTouchPoints[1].setState(Qt::TouchPointReleased); | 
| 1685 |     rawTouchPoints[2].setState(Qt::TouchPointReleased); | 
| 1686 |     nativeTouchPoints = | 
| 1687 |         QWindowSystemInterfacePrivate::toNativeTouchPoints(pointList: rawTouchPoints, window); | 
| 1688 |     QWindowSystemInterface::handleTouchEvent(window, timestamp: 0, device: touchScreenDevice, points: nativeTouchPoints); | 
| 1689 |     QCoreApplication::processEvents(); | 
| 1690 | } | 
| 1691 |  | 
| 1692 | void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin() | 
| 1693 | { | 
| 1694 |     QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100); | 
| 1695 |     rect->setAcceptTouchEvents(true); | 
| 1696 |  | 
| 1697 |     QGraphicsRectItem *mainRect = new QGraphicsRectItem(0, 0, 100, 100, rect); | 
| 1698 |     mainRect->setBrush(Qt::lightGray); | 
| 1699 |  | 
| 1700 |     QGraphicsRectItem *button = new QGraphicsRectItem(-20, -20, 40, 40, mainRect); | 
| 1701 |     button->setPos(ax: 50, ay: 50); | 
| 1702 |     button->setBrush(Qt::darkGreen); | 
| 1703 |  | 
| 1704 |     QGraphicsView view; | 
| 1705 |     QGraphicsScene scene; | 
| 1706 |     scene.addItem(item: rect); | 
| 1707 |     scene.setSceneRect(x: 0,y: 0,w: 100,h: 100); | 
| 1708 |     view.setScene(&scene); | 
| 1709 |  | 
| 1710 |     view.show(); | 
| 1711 |     QVERIFY(QTest::qWaitForWindowExposed(&view)); | 
| 1712 |  | 
| 1713 |     QPoint centerPos = view.mapFromScene(point: rect->boundingRect().center()); | 
| 1714 |     // Touch the button | 
| 1715 |     QTest::touchEvent(widget: view.viewport(), device: touchScreenDevice).press(touchId: 0, pt: centerPos, window: static_cast<QWindow *>(0)); | 
| 1716 |     QTest::touchEvent(widget: view.viewport(), device: touchScreenDevice).release(touchId: 0, pt: centerPos, window: static_cast<QWindow *>(0)); | 
| 1717 |     // Touch outside of the button | 
| 1718 |     QTest::touchEvent(widget: view.viewport(), device: touchScreenDevice).press(touchId: 0, pt: view.mapFromScene(point: QPoint(10, 10)), window: static_cast<QWindow *>(0)); | 
| 1719 |     QTest::touchEvent(widget: view.viewport(), device: touchScreenDevice).release(touchId: 0, pt: view.mapFromScene(point: QPoint(10, 10)), window: static_cast<QWindow *>(0)); | 
| 1720 | } | 
| 1721 |  | 
| 1722 | void tst_QTouchEvent::touchBeginWithGraphicsWidget() | 
| 1723 | { | 
| 1724 |     if (QHighDpiScaling::isActive()) | 
| 1725 |         QSKIP("Fails when scaling is active" ); | 
| 1726 |     QGraphicsScene scene; | 
| 1727 |     QGraphicsView view(&scene); | 
| 1728 |     view.setWindowTitle(QTest::currentTestFunction()); | 
| 1729 |     QScopedPointer<tst_QTouchEventGraphicsItem> root(new tst_QTouchEventGraphicsItem); | 
| 1730 |     root->setAcceptTouchEvents(true); | 
| 1731 |     scene.addItem(item: root.data()); | 
| 1732 |  | 
| 1733 |     QScopedPointer<QGraphicsWidget> glassWidget(new QGraphicsWidget); | 
| 1734 |     glassWidget->setMinimumSize(aw: 100, ah: 100); | 
| 1735 |     scene.addItem(item: glassWidget.data()); | 
| 1736 |  | 
| 1737 |     view.setAlignment(Qt::AlignLeft | Qt::AlignTop); | 
| 1738 |     const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); | 
| 1739 |     view.resize(availableGeometry.size() - QSize(100, 100)); | 
| 1740 |     view.move(availableGeometry.topLeft() + QPoint(50, 50)); | 
| 1741 |     view.fitInView(rect: scene.sceneRect()); | 
| 1742 |     view.show(); | 
| 1743 |     QVERIFY(QTest::qWaitForWindowExposed(&view)); | 
| 1744 |  | 
| 1745 |     QTest::touchEvent(widget: &view, device: touchScreenDevice) | 
| 1746 |             .press(touchId: 0, pt: view.mapFromScene(point: root->mapToScene(ax: 3,ay: 3)), widget: view.viewport()); | 
| 1747 |     QTest::touchEvent(widget: &view, device: touchScreenDevice) | 
| 1748 |             .stationary(touchId: 0) | 
| 1749 |             .press(touchId: 1, pt: view.mapFromScene(point: root->mapToScene(ax: 6,ay: 6)), widget: view.viewport()); | 
| 1750 |     QTest::touchEvent(widget: &view, device: touchScreenDevice) | 
| 1751 |             .release(touchId: 0, pt: view.mapFromScene(point: root->mapToScene(ax: 3,ay: 3)), widget: view.viewport()) | 
| 1752 |             .release(touchId: 1, pt: view.mapFromScene(point: root->mapToScene(ax: 6,ay: 6)), widget: view.viewport()); | 
| 1753 |  | 
| 1754 |     QTRY_COMPARE(root->touchBeginCounter, 1); | 
| 1755 |     QCOMPARE(root->touchUpdateCounter, 1); | 
| 1756 |     QCOMPARE(root->touchEndCounter, 1); | 
| 1757 |     QCOMPARE(root->touchUpdatePoints.size(), 2); | 
| 1758 |  | 
| 1759 |     root->reset(); | 
| 1760 |     glassWidget->setWindowFlags(Qt::Window); // make the glassWidget a panel | 
| 1761 |  | 
| 1762 |     QTest::touchEvent(widget: &view, device: touchScreenDevice) | 
| 1763 |             .press(touchId: 0, pt: view.mapFromScene(point: root->mapToScene(ax: 3,ay: 3)), widget: view.viewport()); | 
| 1764 |     QTest::touchEvent(widget: &view, device: touchScreenDevice) | 
| 1765 |             .stationary(touchId: 0) | 
| 1766 |             .press(touchId: 1, pt: view.mapFromScene(point: root->mapToScene(ax: 6,ay: 6)), widget: view.viewport()); | 
| 1767 |     QTest::touchEvent(widget: &view, device: touchScreenDevice) | 
| 1768 |             .release(touchId: 0, pt: view.mapFromScene(point: root->mapToScene(ax: 3,ay: 3)), widget: view.viewport()) | 
| 1769 |             .release(touchId: 1, pt: view.mapFromScene(point: root->mapToScene(ax: 6,ay: 6)), widget: view.viewport()); | 
| 1770 |  | 
| 1771 |     QCOMPARE(root->touchBeginCounter, 0); | 
| 1772 |     QCOMPARE(root->touchUpdateCounter, 0); | 
| 1773 |     QCOMPARE(root->touchEndCounter, 0); | 
| 1774 | } | 
| 1775 |  | 
| 1776 | class WindowTouchEventFilter : public QObject | 
| 1777 | { | 
| 1778 |     Q_OBJECT | 
| 1779 | public: | 
| 1780 |     bool eventFilter(QObject *obj, QEvent *event) override; | 
| 1781 |     struct TouchInfo { | 
| 1782 |         QList<QTouchEvent::TouchPoint> points; | 
| 1783 |         QEvent::Type lastSeenType; | 
| 1784 |     }; | 
| 1785 |     QMap<QTouchDevice *, TouchInfo> d; | 
| 1786 | }; | 
| 1787 |  | 
| 1788 | bool WindowTouchEventFilter::eventFilter(QObject *, QEvent *event) | 
| 1789 | { | 
| 1790 |     if (event->type() == QEvent::TouchBegin | 
| 1791 |             || event->type() == QEvent::TouchUpdate | 
| 1792 |             || event->type() == QEvent::TouchEnd) { | 
| 1793 |         QTouchEvent *te = static_cast<QTouchEvent *>(event); | 
| 1794 |         TouchInfo &td = d[te->device()]; | 
| 1795 |         if (event->type() == QEvent::TouchBegin) | 
| 1796 |             td.points.clear(); | 
| 1797 |         td.points.append(t: te->touchPoints()); | 
| 1798 |         td.lastSeenType = event->type(); | 
| 1799 |     } | 
| 1800 |     return false; | 
| 1801 | } | 
| 1802 |  | 
| 1803 | void tst_QTouchEvent::testQGuiAppDelivery() | 
| 1804 | { | 
| 1805 |     QWindow w; | 
| 1806 |     w.setGeometry(posx: 100, posy: 100, w: 100, h: 100); | 
| 1807 |     w.show(); | 
| 1808 |     QVERIFY(QTest::qWaitForWindowExposed(&w)); | 
| 1809 |  | 
| 1810 |     WindowTouchEventFilter filter; | 
| 1811 |     w.installEventFilter(filterObj: &filter); | 
| 1812 |  | 
| 1813 |     QList<QWindowSystemInterface::TouchPoint> points; | 
| 1814 |  | 
| 1815 |     // Pass empty list, should be ignored. | 
| 1816 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: 0, points); | 
| 1817 |     QCoreApplication::processEvents(); | 
| 1818 |     QCOMPARE(filter.d.isEmpty(), true); | 
| 1819 |  | 
| 1820 |     QWindowSystemInterface::TouchPoint tp; | 
| 1821 |     tp.id = 0; | 
| 1822 |     tp.state = Qt::TouchPointPressed; | 
| 1823 |     tp.area = QRectF(120, 120, 20, 20); | 
| 1824 |     points.append(t: tp); | 
| 1825 |  | 
| 1826 |     // Pass 0 as device, should be ignored. | 
| 1827 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: 0, points); | 
| 1828 |     QCoreApplication::processEvents(); | 
| 1829 |     QCOMPARE(filter.d.isEmpty(), true); | 
| 1830 |  | 
| 1831 |     // Now the real thing. | 
| 1832 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: touchScreenDevice, points); // TouchBegin | 
| 1833 |     QCoreApplication::processEvents(); | 
| 1834 |     QCOMPARE(filter.d.count(), 1); | 
| 1835 |     QCOMPARE(filter.d.contains(touchScreenDevice), true); | 
| 1836 |     QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 1); | 
| 1837 |     QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchBegin); | 
| 1838 |  | 
| 1839 |     points[0].state = Qt::TouchPointMoved; | 
| 1840 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: touchScreenDevice, points); // TouchUpdate | 
| 1841 |     QCoreApplication::processEvents(); | 
| 1842 |     QCOMPARE(filter.d.count(), 1); | 
| 1843 |     QCOMPARE(filter.d.contains(touchScreenDevice), true); | 
| 1844 |     QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 2); | 
| 1845 |     QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchUpdate); | 
| 1846 |  | 
| 1847 |     points[0].state = Qt::TouchPointReleased; | 
| 1848 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: touchScreenDevice, points); // TouchEnd | 
| 1849 |     QCoreApplication::processEvents(); | 
| 1850 |     QCOMPARE(filter.d.count(), 1); | 
| 1851 |     QCOMPARE(filter.d.contains(touchScreenDevice), true); | 
| 1852 |     QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 3); | 
| 1853 |     QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchEnd); | 
| 1854 | } | 
| 1855 |  | 
| 1856 | void tst_QTouchEvent::testMultiDevice() | 
| 1857 | { | 
| 1858 |     QTouchDevice *deviceTwo = QTest::createTouchDevice(); | 
| 1859 |  | 
| 1860 |     QWindow w; | 
| 1861 |     w.setGeometry(posx: 100, posy: 100, w: 100, h: 100); | 
| 1862 |     w.show(); | 
| 1863 |     QVERIFY(QTest::qWaitForWindowExposed(&w)); | 
| 1864 |  | 
| 1865 |     WindowTouchEventFilter filter; | 
| 1866 |     w.installEventFilter(filterObj: &filter); | 
| 1867 |  | 
| 1868 |     QList<QWindowSystemInterface::TouchPoint> pointsOne, pointsTwo; | 
| 1869 |  | 
| 1870 |     // touchScreenDevice reports a single point, deviceTwo reports the beginning of a multi-point sequence. | 
| 1871 |     // Even though there is a point with id 0 for both devices, they should be delivered cleanly, independently. | 
| 1872 |     QWindowSystemInterface::TouchPoint tp; | 
| 1873 |     tp.id = 0; | 
| 1874 |     tp.state = Qt::TouchPointPressed; | 
| 1875 |     const QPoint screenOrigin = w.screen()->geometry().topLeft(); | 
| 1876 |     const QRectF area0(120, 120, 20, 20); | 
| 1877 |     tp.area = QHighDpi::toNative(value: area0, scaleFactor: QHighDpiScaling::factor(context: &w), origin: screenOrigin); | 
| 1878 |     pointsOne.append(t: tp); | 
| 1879 |  | 
| 1880 |     pointsTwo.append(t: tp); | 
| 1881 |     tp.id = 1; | 
| 1882 |     const QRectF area1(140, 140, 20, 20); | 
| 1883 |     tp.area = QHighDpi::toNative(value: area1, scaleFactor: QHighDpiScaling::factor(context: &w), origin: screenOrigin); | 
| 1884 |     pointsTwo.append(t: tp); | 
| 1885 |  | 
| 1886 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: touchScreenDevice, points: pointsOne); | 
| 1887 |     QWindowSystemInterface::handleTouchEvent(window: &w, device: deviceTwo, points: pointsTwo); | 
| 1888 |     QCoreApplication::processEvents(); | 
| 1889 |  | 
| 1890 |     QCOMPARE(filter.d.contains(touchScreenDevice), true); | 
| 1891 |     QCOMPARE(filter.d.contains(deviceTwo), true); | 
| 1892 |  | 
| 1893 |     QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchBegin); | 
| 1894 |     QCOMPARE(filter.d.value(deviceTwo).lastSeenType, QEvent::TouchBegin); | 
| 1895 |     QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 1); | 
| 1896 |     QCOMPARE(filter.d.value(deviceTwo).points.count(), 2); | 
| 1897 |  | 
| 1898 |     QCOMPARE(filter.d.value(touchScreenDevice).points.at(0).screenPos(), area0.center()); | 
| 1899 |     QCOMPARE(filter.d.value(touchScreenDevice).points.at(0).ellipseDiameters(), area0.size()); | 
| 1900 |     QCOMPARE(filter.d.value(touchScreenDevice).points.at(0).state(), pointsOne[0].state); | 
| 1901 |  | 
| 1902 |     QCOMPARE(filter.d.value(deviceTwo).points.at(0).screenPos(), area0.center()); | 
| 1903 |     QCOMPARE(filter.d.value(deviceTwo).points.at(0).ellipseDiameters(), area0.size()); | 
| 1904 |     QCOMPARE(filter.d.value(deviceTwo).points.at(0).state(), pointsTwo[0].state); | 
| 1905 |     QCOMPARE(filter.d.value(deviceTwo).points.at(1).screenPos(), area1.center()); | 
| 1906 |     QCOMPARE(filter.d.value(deviceTwo).points.at(1).state(), pointsTwo[1].state); | 
| 1907 | } | 
| 1908 |  | 
| 1909 | QTEST_MAIN(tst_QTouchEvent) | 
| 1910 |  | 
| 1911 | #include "tst_qtouchevent.moc" | 
| 1912 |  |