aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2018-12-04 12:27:23 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2018-12-10 10:06:53 +0000
commitf8f0f0835a971a658f4ee2ae386e448338b1a7d7 (patch)
treee3c84916a2b5e8f5e1f19c8dd5034e5487dd9b7a
parentecec3d45ece7f0754f2bdede3aaadb13ab71e3c4 (diff)
TapHandler: ignore scroll events and native gestures
During a 2-finger press (to emulate right click on a trackpad), the OS may also generate a QWheelEvent with ScrollBegin phase just in case scrolling starts. This must not prematurely deactivate the TapHandler. Also if a gesture or wheel event begins as the very first event after an application starts, ensure that subsequent mouse events are not mis-delivered as wheel or gesture events. Fixes: QTBUG-71955 Change-Id: Ic12e116483ab9ad37c4ac3b1d10ccb62e1349e0a Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp4
-rw-r--r--src/quick/items/qquickwindow.cpp9
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml41
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp39
4 files changed, 89 insertions, 4 deletions
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index e97722d6b7..d480d3b491 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -107,6 +107,10 @@ static bool dragOverThreshold(const QQuickEventPoint *point)
bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point)
{
+ if (!point->pointerEvent()->asPointerMouseEvent() &&
+ !point->pointerEvent()->asPointerTouchEvent() &&
+ !point->pointerEvent()->asPointerTabletEvent() )
+ return false;
// If the user has not violated any constraint, it could be a tap.
// Otherwise we want to give up the grab so that a competing handler
// (e.g. DragHandler) gets a chance to take over.
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 83a1268d1d..dd5960e925 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2246,13 +2246,14 @@ QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointer
{
// Search for a matching reusable event object.
for (QQuickPointerEvent *e : pointerEventInstances) {
- // If device can generate native gestures (e.g. a trackpad), there might be two QQuickPointerEvents:
- // QQuickPointerNativeGestureEvent and QQuickPointerTouchEvent. Use eventType to disambiguate.
+ // If device can generate native gestures (e.g. a trackpad), there might be multiple QQuickPointerEvents:
+ // QQuickPointerNativeGestureEvent, QQuickPointerScrollEvent, and QQuickPointerTouchEvent.
+ // Use eventType to disambiguate.
#if QT_CONFIG(gestures)
- if (eventType == QEvent::NativeGesture && !qobject_cast<QQuickPointerNativeGestureEvent*>(e))
+ if ((eventType == QEvent::NativeGesture) != bool(e->asPointerNativeGestureEvent()))
continue;
#endif
- if (eventType == QEvent::Wheel && !qobject_cast<QQuickPointerScrollEvent*>(e))
+ if ((eventType == QEvent::Wheel) != bool(e->asPointerScrollEvent()))
continue;
// Otherwise we assume there's only one event type per device.
// More disambiguation tests might need to be added above if that changes later.
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
new file mode 100644
index 0000000000..aea01c154c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ width: 320
+ height: 240
+ color: rightTap.pressed ? "tomato" : "beige"
+ TapHandler {
+ id: rightTap
+ objectName: "right button TapHandler"
+ longPressThreshold: 0.5
+ acceptedButtons: Qt.RightButton
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index 467c964001..ab6fa0dbe4 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -69,6 +69,7 @@ private slots:
void mouseLongPress();
void buttonsMultiTouch();
void componentUserBehavioralOverride();
+ void rightLongPressIgnoreWheel();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -622,6 +623,44 @@ void tst_TapHandler::componentUserBehavioralOverride()
QCOMPARE(userGrabChangedSpy.count(), 2);
}
+void tst_TapHandler::rightLongPressIgnoreWheel()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "rightTapHandler.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickTapHandler *tap = window->rootObject()->findChild<QQuickTapHandler*>();
+ QVERIFY(tap);
+ QSignalSpy tappedSpy(tap, SIGNAL(tapped(QQuickEventPoint *)));
+ QSignalSpy longPressedSpy(tap, SIGNAL(longPressed()));
+ QPoint p1(100, 100);
+
+ // Mouse wheel with ScrollBegin phase (because as soon as two fingers are touching
+ // the trackpad, it will send such an event: QTBUG-71955)
+ {
+ QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0),
+ Qt::NoButton, Qt::NoModifier, Qt::ScrollBegin, false, Qt::MouseEventNotSynthesized);
+ QGuiApplication::sendEvent(window, &wheelEvent);
+ }
+
+ // Press
+ QTest::mousePress(window, Qt::RightButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(tap->isPressed(), true);
+
+ // Mouse wheel ScrollEnd phase
+ QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0),
+ Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd, false, Qt::MouseEventNotSynthesized);
+ QGuiApplication::sendEvent(window, &wheelEvent);
+ QTRY_COMPARE(longPressedSpy.count(), 1);
+ QCOMPARE(tap->isPressed(), true);
+ QCOMPARE(tappedSpy.count(), 0);
+
+ // Release
+ QTest::mouseRelease(window, Qt::RightButton, Qt::NoModifier, p1, 500);
+ QTRY_COMPARE(tap->isPressed(), false);
+ QCOMPARE(tappedSpy.count(), 0);
+}
+
QTEST_MAIN(tst_TapHandler)
#include "tst_qquicktaphandler.moc"