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 | |