From acf7c8073b0c8a0440c62f66469865f8bf1decd5 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 31 Jan 2018 12:54:40 +0100 Subject: QQuickWindow: obey AA_SynthesizeMouseForUnhandledTouchEvents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, AA_SynthesizeMouseForUnhandledTouchEvents has only affected behavior of QGuiApplicationPrivate::processTouchEvent, but had no effect in Qt Quick. QQuickWindow also accepts the touch event just to make sure that QGuiApplication will not synthesize mouse from touch, because it would be redundant: QQuickWindow does that for itself. Now we make it have an effect in Qt Quick too: skip mouse synthesis if it is set to false. This provides a way to simplify the event delivery. If you set it false, then you cannot manipulate old mouse-only items like MouseArea and Flickable on a touchscreen. (You can of course use event handlers for that.) [ChangeLog][QtQuick][QQuickWindow] You can now disable touch->mouse event synthesis in QtQuick by calling qGuiApp.setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); This will simplify and speed up event delivery, and it will also prevent any and all interaction with mouse-only items like MouseArea and Flickable on a touchscreen. Task-number: QTBUG-52748 Change-Id: I71f1731b5abaeabd9dbce1112cd23bc97d24c12a Reviewed-by: Qt CI Bot Reviewed-by: Jan Arve Sæther --- .../flickableinterop/tst_flickableinterop.cpp | 10 --- .../tst_qquickpointerhandler.cpp | 73 ++++++++++++++-------- tests/auto/quick/qquickwindow/tst_qquickwindow.cpp | 4 +- tests/auto/quick/touchmouse/tst_touchmouse.cpp | 64 ++++++++++++------- .../quickwidgets/qquickwidget/tst_qquickwidget.cpp | 4 +- 5 files changed, 92 insertions(+), 63 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index 2d8b16cadd..e544eedf05 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -57,8 +57,6 @@ public: {} private slots: - void initTestCase(); - void touchTapButton_data(); void touchTapButton(); void touchDragFlickableBehindButton_data(); @@ -96,14 +94,6 @@ void tst_FlickableInterop::createView(QScopedPointer &window, const QVERIFY(window->rootObject() != nullptr); } -void tst_FlickableInterop::initTestCase() -{ - // This test assumes that we don't get synthesized mouse events from QGuiApplication - qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); - - QQmlDataTest::initTestCase(); -} - void tst_FlickableInterop::touchTapButton_data() { QTest::addColumn("buttonName"); diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp index 0158d864c4..2a9ec272fa 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp @@ -223,6 +223,7 @@ public: private slots: void initTestCase(); + void touchEventDelivery_data(); void touchEventDelivery(); void mouseEventDelivery(); void touchReleaseOutside_data(); @@ -274,16 +275,23 @@ void tst_PointerHandlers::createView(QScopedPointer &window, const c void tst_PointerHandlers::initTestCase() { - // This test assumes that we don't get synthesized mouse events from QGuiApplication - qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); - QQmlDataTest::initTestCase(); qmlRegisterType("Qt.test", 1, 0, "EventItem"); qmlRegisterType("Qt.test", 1, 0, "EventHandler"); } +void tst_PointerHandlers::touchEventDelivery_data() +{ + QTest::addColumn("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents + QTest::newRow("no synth") << false; + QTest::newRow("synth") << true; +} + void tst_PointerHandlers::touchEventDelivery() { + QFETCH(bool, synthMouse); + qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse); + QScopedPointer windowPtr; createView(windowPtr, "singleitem.qml"); QQuickView * window = windowPtr.data(); @@ -295,19 +303,20 @@ void tst_PointerHandlers::touchEventDelivery() QPoint p1 = QPoint(20, 20); QTest::touchEvent(window, touchDevice).press(0, p1, window); QQuickTouchUtils::flush(window); - QTRY_COMPARE(eventItem1->eventList.size(), 3); + QTRY_COMPARE(eventItem1->eventList.size(), synthMouse ? 3 : 2); QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab); QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, NoGrab); - QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab); + if (synthMouse) + QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab); p1 += QPoint(10, 0); QTest::touchEvent(window, touchDevice).move(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 4); - QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 3); + QCOMPARE_EVENT(eventItem1->eventList.size() - 1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab); QTest::touchEvent(window, touchDevice).release(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 5); - QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 5 : 4); + QCOMPARE_EVENT(eventItem1->eventList.size() - 1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab); eventItem1->eventList.clear(); // Accept touch @@ -343,33 +352,42 @@ void tst_PointerHandlers::touchEventDelivery() p1 = QPoint(20, 20); QTest::touchEvent(window, touchDevice).press(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 3 : 2); QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab); QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, NoGrab); - QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive); - QCOMPARE(window->mouseGrabberItem(), eventItem1); + if (synthMouse) + QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive); + QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr); QPointF localPos = eventItem1->mapFromScene(p1); QPointF scenePos = p1; // item is at 0,0 QCOMPARE(eventItem1->eventList.at(1).posWrtItem, localPos); QCOMPARE(eventItem1->eventList.at(1).posWrtScene, scenePos); - QCOMPARE(eventItem1->eventList.at(2).posWrtItem, localPos); - QCOMPARE(eventItem1->eventList.at(2).posWrtScene, scenePos); + if (synthMouse) { + QCOMPARE(eventItem1->eventList.at(2).posWrtItem, localPos); + QCOMPARE(eventItem1->eventList.at(2).posWrtScene, scenePos); + } p1 += QPoint(10, 0); QTest::touchEvent(window, touchDevice).move(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 6); - QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab); - QCOMPARE_EVENT(4, Event::TouchDestination, QEvent::TouchUpdate, Qt::TouchPointMoved, NoGrab); - QCOMPARE_EVENT(5, Event::MouseDestination, QEvent::MouseMove, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 6 : 3); + if (synthMouse) { + QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab); + QCOMPARE_EVENT(4, Event::TouchDestination, QEvent::TouchUpdate, Qt::TouchPointMoved, NoGrab); + QCOMPARE_EVENT(5, Event::MouseDestination, QEvent::MouseMove, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive); + } QTest::touchEvent(window, touchDevice).release(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 10); - QCOMPARE_EVENT(6, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab); - QCOMPARE_EVENT(7, Event::TouchDestination, QEvent::TouchEnd, Qt::TouchPointReleased, NoGrab); - QCOMPARE_EVENT(8, Event::MouseDestination, QEvent::MouseButtonRelease, Qt::TouchPointReleased, NoGrab); - QCOMPARE_EVENT(9, Event::MouseDestination, QEvent::UngrabMouse, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 10 : 4); + if (synthMouse) { + QCOMPARE_EVENT(6, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab); + QCOMPARE_EVENT(7, Event::TouchDestination, QEvent::TouchEnd, Qt::TouchPointReleased, NoGrab); + QCOMPARE_EVENT(8, Event::MouseDestination, QEvent::MouseButtonRelease, Qt::TouchPointReleased, NoGrab); + QCOMPARE_EVENT(9, Event::MouseDestination, QEvent::UngrabMouse, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive); + } else { + QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab); + } eventItem1->eventList.clear(); // wait to avoid getting a double click event @@ -382,18 +400,19 @@ void tst_PointerHandlers::touchEventDelivery() p1 = QPoint(20, 20); QTest::touchEvent(window, touchDevice).press(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 3 : 2); QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab); QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, NoGrab); - QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab); + if (synthMouse) + QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab); QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr); p1 += QPoint(10, 0); QTest::touchEvent(window, touchDevice).move(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 3); QTest::touchEvent(window, touchDevice).release(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 5); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 5 : 4); eventItem1->eventList.clear(); // wait to avoid getting a double click event diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index e0f1207ebe..578ae56cca 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -1234,8 +1234,8 @@ void tst_qquickwindow::synthMouseFromTouch() QTest::touchEvent(window.data(), touchDevice).move(0, p2, window.data()); QTest::touchEvent(window.data(), touchDevice).release(0, p2, window.data()); - QCOMPARE(item->m_touchEvents.count(), 3); - QCOMPARE(item->m_mouseEvents.count(), acceptTouch ? 0 : 3); + QCOMPARE(item->m_touchEvents.count(), !synthMouse && !acceptTouch ? 1 : 3); + QCOMPARE(item->m_mouseEvents.count(), (acceptTouch || !synthMouse) ? 0 : 3); QCOMPARE(window->m_mouseEvents.count(), 0); for (const QMouseEvent &ev : item->m_mouseEvents) QCOMPARE(ev.source(), Qt::MouseEventSynthesizedByQt); diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 2fc56c2ad8..052d81b6de 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -176,6 +176,7 @@ public: private slots: void initTestCase(); + void simpleTouchEvent_data(); void simpleTouchEvent(); void testEventFilter(); void mouse(); @@ -226,15 +227,22 @@ QQuickView *tst_TouchMouse::createView() void tst_TouchMouse::initTestCase() { - // This test assumes that we don't get synthesized mouse events from QGuiApplication - qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); - QQmlDataTest::initTestCase(); qmlRegisterType("Qt.test", 1, 0, "EventItem"); } +void tst_TouchMouse::simpleTouchEvent_data() +{ + QTest::addColumn("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents + QTest::newRow("no synth") << false; + QTest::newRow("synth") << true; +} + void tst_TouchMouse::simpleTouchEvent() { + QFETCH(bool, synthMouse); + qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse); + QScopedPointer window(createView()); window->setSource(testFileUrl("singleitem.qml")); window->show(); @@ -251,16 +259,16 @@ void tst_TouchMouse::simpleTouchEvent() QTest::touchEvent(window.data(), device).press(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); // Get a touch and then mouse event offered - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); p1 += QPoint(10, 0); QTest::touchEvent(window.data(), device).move(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); // Not accepted, no updates - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); QTest::touchEvent(window.data(), device).release(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); eventItem1->eventList.clear(); // Accept touch @@ -288,10 +296,11 @@ void tst_TouchMouse::simpleTouchEvent() p1 = QPoint(20, 20); QTest::touchEvent(window.data(), device).press(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); - QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); - QCOMPARE(window->mouseGrabberItem(), eventItem1); + if (synthMouse) + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr); QPoint localPos = eventItem1->mapFromScene(p1).toPoint(); QPoint globalPos = window->mapToGlobal(p1); @@ -299,21 +308,31 @@ void tst_TouchMouse::simpleTouchEvent() QCOMPARE(eventItem1->eventList.at(0).points.at(0).pos().toPoint(), localPos); QCOMPARE(eventItem1->eventList.at(0).points.at(0).scenePos().toPoint(), scenePos); QCOMPARE(eventItem1->eventList.at(0).points.at(0).screenPos().toPoint(), globalPos); - QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos); - QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos); + if (synthMouse) { + QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos); + QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos); + } p1 += QPoint(10, 0); QTest::touchEvent(window.data(), device).move(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 4); - QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate); - QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 1); + if (synthMouse) { + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); + } + // else, if there was no synth-mouse and we didn't accept the touch, + // TouchUpdate was not sent to eventItem1 either. QTest::touchEvent(window.data(), device).release(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 7); - QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd); - QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease); - QCOMPARE(eventItem1->eventList.at(6).type, QEvent::UngrabMouse); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 7 : 1); + if (synthMouse) { + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd); + QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease); + QCOMPARE(eventItem1->eventList.at(6).type, QEvent::UngrabMouse); + } + // else, if there was no synth-mouse and we didn't accept the touch, + // TouchEnd was not sent to eventItem1 either. eventItem1->eventList.clear(); // wait to avoid getting a double click event @@ -326,16 +345,17 @@ void tst_TouchMouse::simpleTouchEvent() p1 = QPoint(20, 20); QTest::touchEvent(window.data(), device).press(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); - QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + if (synthMouse) + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); p1 += QPoint(10, 0); QTest::touchEvent(window.data(), device).move(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); QTest::touchEvent(window.data(), device).release(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1); eventItem1->eventList.clear(); // wait to avoid getting a double click event diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index af358925fe..e523274d0a 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -614,8 +614,8 @@ void tst_qquickwidget::synthMouseFromTouch() QTest::touchEvent(&window, device).move(0, p2, &window); QTest::touchEvent(&window, device).release(0, p2, &window); - QCOMPARE(item->m_touchEvents.count(), 3); - QCOMPARE(item->m_mouseEvents.count(), acceptTouch ? 0 : 3); + QCOMPARE(item->m_touchEvents.count(), !synthMouse && !acceptTouch ? 1 : 3); + QCOMPARE(item->m_mouseEvents.count(), (acceptTouch || !synthMouse) ? 0 : 3); QCOMPARE(childView->m_mouseEvents.count(), 0); for (const QMouseEvent &ev : item->m_mouseEvents) QCOMPARE(ev.source(), Qt::MouseEventSynthesizedByQt); -- cgit v1.2.3