aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Arve Sæther <jan-arve.saether@qt.io>2019-02-04 15:16:45 +0100
committerJan Arve Sæther <jan-arve.saether@qt.io>2019-02-06 10:01:59 +0000
commit8ab6ded97633bf7f74e7ca4de35ed56d07f358d8 (patch)
treedd5a5c5f047b9b961872f0b24d96a447eaa9ad0e
parent78c1fcbc49f56463064eef738a475d9018357b24 (diff)
Fix bug where QQMPH kept an exclusive grab when no buttons were pressed
This happened if you moved the mouse while doing a multitouch operation. More specifically this caused the bug: 1. Open qtdeclarative/tests/manual/pointer/map.qml 2. Rotate the map with two fingers (Do not release fingers). 3. Move mouse (no buttons pressed). 4. Release both fingers. 5. Move mouse again (error: the draghandler has a grab and thus the map is dragged even if no buttons are down). This happened because if you moved the mouse while having two fingers down, Windows would generate a *mouse*move* event with Left button or Right button pressed (which wasn't the case on the physical device but it's probably because of a bug in how mouse events are synthesized from touch on Windows). This caused the QQuickMultiPointHandler to do a passive grab. Then, when releasing the fingers it would not send a mouse release event (just plain touch release events), so the QQuickMultiPointHandler would keep the passive grab it had. All subsequent mouse move events would then be dispatched to the QQuickMultiPointHandler where it would assume that the button was pressed until it got a release event (but button was never pressed so that wouldn't happen). Eventually it would perform an exclusive grab, and dragging was initiated. Change-Id: I42b3133c5fde93c7f92f1cb28705156a69f9ad1c Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml61
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp46
3 files changed, 111 insertions, 0 deletions
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index 228c99bb12..baa68e5e53 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -162,6 +162,10 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe
bool stealingAllowed = event->isPressEvent() || event->isReleaseEvent();
for (int i = 0; i < c; ++i) {
QQuickEventPoint *p = event->point(i);
+ if (QQuickPointerMouseEvent *me = event->asPointerMouseEvent()) {
+ if (me->buttons() == Qt::NoButton)
+ continue;
+ }
if (!stealingAllowed) {
QObject *exclusiveGrabber = p->exclusiveGrabber();
if (exclusiveGrabber && exclusiveGrabber != this && !canGrab(p))
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
new file mode 100644
index 0000000000..08b85aef50
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests 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
+
+Item {
+ id: root
+ objectName: "DragHandler_and_PinchHandler"
+ width: 640
+ height: 480
+
+ Rectangle {
+ id: rect
+ objectName: "Rect"
+ color: dragHandler.active ? "blue" : (pinchHandler.active ? "magenta" : "grey")
+ width: 200; height: 200; x: 100; y: 100
+
+ PinchHandler {
+ id: pinchHandler
+ objectName: "PinchHandler"
+ }
+ DragHandler {
+ id: dragHandler
+ objectName: "DragHandler"
+ }
+
+ Text {
+ color: "white"
+ anchors.centerIn: parent
+ horizontalAlignment: Text.AlignHCenter
+ text: rect.objectName + "\n"
+ + "rotation:" + rect.rotation + "\n"
+ + dragHandler.centroid.position.x.toFixed(1) + "," + dragHandler.centroid.position.y.toFixed(1)
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 0c544ef484..eb210c2112 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -60,6 +60,7 @@ private slots:
void touchDragMultiSliders();
void touchPassiveGrabbers_data();
void touchPassiveGrabbers();
+ void touchPinchAndMouseMove();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -521,6 +522,51 @@ void tst_DragHandler::touchPassiveGrabbers()
QQuickTouchUtils::flush(window);
}
+void tst_DragHandler::touchPinchAndMouseMove()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draghandler_and_pinchhandler.qml");
+ QQuickView *window = windowPtr.data();
+ QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>(QLatin1String("Rect"));
+ QQuickPointerHandler *pinchHandler = window->rootObject()->findChild<QQuickPointerHandler*>(QLatin1String("PinchHandler"));
+
+ QPoint p1(150,200);
+ QPoint p2(250,200);
+
+ // Trigger a scale pinch, PinchHandler should activate
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+ touch.press(1, p1).press(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ QPoint delta(10,0);
+ for (int i = 0; i < 10 && !pinchHandler->active(); ++i) {
+ p1-=delta;
+ p2+=delta;
+ touch.move(1, p1).move(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(pinchHandler->active(), true);
+
+ // While having the touch points pressed, send wrong mouse event as MS Windows did:
+ // * A MoveMove with LeftButton down
+ // (in order to synthesize that, qtestMouseButtons needs to be modified)
+ // (This will make the DragHandler do a passive grab)
+ QTestPrivate::qtestMouseButtons = Qt::LeftButton;
+ QTest::mouseMove(window, p1 + delta);
+
+ touch.release(1, p1).release(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+
+ // Now move the mouse with no buttons down and check if the rect did not move
+ // At this point, no touch points are pressed and no mouse buttons are pressed.
+ QTestPrivate::qtestMouseButtons = Qt::NoButton;
+ QSignalSpy rectMovedSpy(rect, SIGNAL(xChanged()));
+ for (int i = 0; i < 10; ++i) {
+ p1 += delta;
+ QTest::mouseMove(window, p1);
+ QCOMPARE(rectMovedSpy.count(), 0);
+ }
+}
+
QTEST_MAIN(tst_DragHandler)
#include "tst_qquickdraghandler.moc"