summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/testlib/qtestcase.cpp6
-rw-r--r--src/testlib/qtestmouse.h26
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp35
-rw-r--r--tests/auto/testlib/selftests/mouse/mouse.pro7
-rw-r--r--tests/auto/testlib/selftests/mouse/tst_mouse.cpp215
-rw-r--r--tests/auto/testlib/selftests/selftests.pri3
6 files changed, 263 insertions, 29 deletions
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 497470464f..7e9c03dbd4 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -268,6 +268,11 @@ static bool isValidSlot(const QMetaMethod &sl)
|| name == "init" || name == "cleanup");
}
+namespace QTestPrivate
+{
+ Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons = Qt::NoButton;
+}
+
namespace QTest
{
class WatchDog;
@@ -1074,6 +1079,7 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
: table.testData(curDataIndex));
+ QTestPrivate::qtestMouseButtons = Qt::NoButton;
if (watchDog)
watchDog->beginTest();
invokeTestOnData(index);
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index fa524fd8ca..e2835828a1 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -68,11 +68,16 @@ Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, con
Qt::MouseButtons state, Qt::MouseButton button,
QEvent::Type type, Qt::KeyboardModifiers mods, int timestamp);
+namespace QTestPrivate
+{
+ extern Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons;
+}
+
namespace QTest
{
enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove };
- extern Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton;
+ extern Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton; // ### unsued
extern Q_TESTLIB_EXPORT int lastMouseTimestamp;
// This value is used to emulate timestamps to avoid creating double clicks by mistake.
@@ -117,30 +122,35 @@ namespace QTest
QPointF global = window->mapToGlobal(pos);
QPointer<QWindow> w(window);
+ using namespace QTestPrivate;
switch (action)
{
case MouseDClick:
- qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress,
+ qtestMouseButtons.setFlag(button, true);
+ qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonPress,
stateKey, ++lastMouseTimestamp);
- qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
+ qtestMouseButtons.setFlag(button, false);
+ qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonRelease,
stateKey, ++lastMouseTimestamp);
Q_FALLTHROUGH();
case MousePress:
case MouseClick:
- qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress,
+ qtestMouseButtons.setFlag(button, true);
+ qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonPress,
stateKey, ++lastMouseTimestamp);
- lastMouseButton = button;
+ lastMouseButton = button; // ### unsued
if (action == MousePress)
break;
Q_FALLTHROUGH();
case MouseRelease:
- qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
+ qtestMouseButtons.setFlag(button, false);
+ qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonRelease,
stateKey, ++lastMouseTimestamp);
lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated
- lastMouseButton = Qt::NoButton;
+ lastMouseButton = Qt::NoButton; // ### unsued
break;
case MouseMove:
- qt_handleMouseEvent(w, pos, global, lastMouseButton, Qt::NoButton, QEvent::MouseMove,
+ qt_handleMouseEvent(w, pos, global, qtestMouseButtons, Qt::NoButton, QEvent::MouseMove,
stateKey, ++lastMouseTimestamp);
break;
default:
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index 18723458f6..34754670de 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -2320,49 +2320,44 @@ void tst_QWindow::generatedMouseMove()
{
InputTestWindow w;
w.setGeometry(QRect(m_availableTopLeft + QPoint(100, 100), m_testWindowSize));
+ w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
w.show();
QVERIFY(QTest::qWaitForWindowActive(&w));
QPoint point(10, 10);
QPoint step(2, 2);
QVERIFY(w.mouseMovedCount == 0);
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::NoButton, Qt::NoButton, QEvent::MouseMove);
- QCoreApplication::processEvents();
+ QTest::mouseMove(&w, point);
QVERIFY(w.mouseMovedCount == 1);
- // Press that does not change position should not generate mouse move
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress);
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton | Qt::RightButton, Qt::RightButton, QEvent::MouseButtonPress);
- QCoreApplication::processEvents();
+ // A press event that does not change position should not generate mouse move
+ QTest::mousePress(&w, Qt::LeftButton, 0, point);
+ QTest::mousePress(&w, Qt::RightButton, 0, point);
+
QVERIFY(w.mouseMovedCount == 1);
- // Test moves generated for mouse release
+ // Verify that a move event is generated for a mouse release event that changes position
point += step;
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::RightButton, Qt::LeftButton, QEvent::MouseButtonRelease);
- QCoreApplication::processEvents();
+ QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
QVERIFY(w.mouseMovedCount == 2);
QVERIFY(w.buttonStateInGeneratedMove == (Qt::LeftButton | Qt::RightButton));
point += step;
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::NoButton, Qt::RightButton, QEvent::MouseButtonRelease);
- QCoreApplication::processEvents();
+ QTest::mouseRelease(&w, Qt::RightButton, 0, point);
QVERIFY(w.mouseMovedCount == 3);
QVERIFY(w.buttonStateInGeneratedMove == Qt::RightButton);
- // Test moves generated for mouse press
+ // Verify that a move event is generated for a mouse press event that changes position
point += step;
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress);
- QCoreApplication::processEvents();
+ QTest::mousePress(&w, Qt::LeftButton, 0, point);
QVERIFY(w.mouseMovedCount == 4);
QVERIFY(w.buttonStateInGeneratedMove == Qt::NoButton);
point += step;
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton | Qt::RightButton, Qt::RightButton, QEvent::MouseButtonPress);
- QCoreApplication::processEvents();
+ QTest::mousePress(&w, Qt::RightButton, 0, point);
QVERIFY(w.mouseMovedCount == 5);
QVERIFY(w.buttonStateInGeneratedMove == Qt::LeftButton);
- // Release that does not change position should not generate mouse move
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::LeftButton, Qt::RightButton, QEvent::MouseButtonRelease);
- QWindowSystemInterface::handleMouseEvent(&w, point, point, Qt::NoButton, Qt::LeftButton, QEvent::MouseButtonRelease);
- QCoreApplication::processEvents();
+ // A release event that does not change position should not generate mouse move
+ QTest::mouseRelease(&w, Qt::RightButton, 0, point);
+ QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
QVERIFY(w.mouseMovedCount == 5);
}
diff --git a/tests/auto/testlib/selftests/mouse/mouse.pro b/tests/auto/testlib/selftests/mouse/mouse.pro
new file mode 100644
index 0000000000..7c06b8aa64
--- /dev/null
+++ b/tests/auto/testlib/selftests/mouse/mouse.pro
@@ -0,0 +1,7 @@
+SOURCES += tst_mouse.cpp
+QT += testlib testlib-private gui gui-private
+
+mac:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = mouse
diff --git a/tests/auto/testlib/selftests/mouse/tst_mouse.cpp b/tests/auto/testlib/selftests/mouse/tst_mouse.cpp
new file mode 100644
index 0000000000..3c731cde69
--- /dev/null
+++ b/tests/auto/testlib/selftests/mouse/tst_mouse.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <QtGui/QWindow>
+#include <QtGui/QCursor>
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+namespace QTestPrivate {
+extern Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons; // from qtestcase.cpp
+}
+QT_END_NAMESPACE
+
+class tst_Mouse : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void stateHandlingPart1_data();
+ void stateHandlingPart1();
+ void stateHandlingPart2();
+ void deterministicEvents_data();
+ void deterministicEvents();
+};
+
+class MouseWindow : public QWindow
+{
+public:
+ Qt::MouseButtons stateInMouseMove = Qt::NoButton;
+ int moveCount = 0;
+ int pressCount = 0;
+
+protected:
+ void mousePressEvent(QMouseEvent *)
+ {
+ pressCount++;
+ }
+
+ void mouseMoveEvent(QMouseEvent *e)
+ {
+ moveCount++;
+ stateInMouseMove = e->buttons();
+ }
+};
+
+void tst_Mouse::stateHandlingPart1_data()
+{
+ QTest::addColumn<bool>("dummy");
+ QTest::newRow("dummy-1") << true;
+ QTest::newRow("dummy-2") << true;
+}
+
+void tst_Mouse::stateHandlingPart1()
+{
+ QFETCH(bool, dummy);
+ Q_UNUSED(dummy);
+
+ QWindow w;
+ w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
+ w.show();
+ w.setGeometry(100, 100, 200, 200);
+ QVERIFY(QTest::qWaitForWindowActive(&w));
+
+ QPoint point(10, 10);
+ QPoint step(1, 1);
+
+ // verify that we have a clean state after the previous data set
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
+
+ QTest::mousePress(&w, Qt::LeftButton, 0, point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton);
+ QTest::mousePress(&w, Qt::RightButton, 0, point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
+ QTest::mouseMove(&w, point += step);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
+ QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
+ QTest::mouseMove(&w, point += step);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
+ // test invalid input - left button was already released
+ QTest::mouseRelease(&w, Qt::LeftButton, 0, point += point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
+ // test invalid input - right button is already pressed
+ QTest::mousePress(&w, Qt::RightButton, 0, point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
+ // now continue with valid input
+ QTest::mouseRelease(&w, Qt::RightButton, 0, point += point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
+ QTest::mouseMove(&w, point += step);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
+
+ // exit this test function with some button in a pressed state
+ QTest::mousePress(&w, Qt::LeftButton, 0, point);
+ QTest::mousePress(&w, Qt::RightButton, 0, point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
+}
+
+void tst_Mouse::stateHandlingPart2()
+{
+ MouseWindow w;
+ w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
+ w.show();
+ w.setGeometry(100, 100, 200, 200);
+ QVERIFY(QTest::qWaitForWindowActive(&w));
+
+ // verify that we have a clean state after stateHandlingPart1()
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
+
+#if !QT_CONFIG(cursor)
+ QSKIP("This part of the test requires the QCursor API");
+#else
+ // The windowing system's view on a current button state might be different
+ // from the qtestlib's mouse button state. This test verifies that the mouse
+ // events generated by the system are adjusted to reflect qtestlib's view
+ // on the current button state.
+ // SKIP: not convinced yet that there is a valid use case for this.
+
+ QSKIP("Not implemented beyond this point!");
+
+ QPoint point(40, 40);
+ QTest::mousePress(&w, Qt::LeftButton, 0, point);
+ QTest::mousePress(&w, Qt::RightButton, 0, point);
+ QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
+ w.moveCount = 0;
+ // The windowing system will send mouse events with no buttons set
+ QPoint moveToPoint = w.mapToGlobal(point + QPoint(1, 1));
+ if (QCursor::pos() == moveToPoint)
+ moveToPoint += QPoint(1, 1);
+ QCursor::setPos(moveToPoint);
+ QTRY_COMPARE(w.moveCount, 1);
+ // Verify that qtestlib adjusted the button state
+ QCOMPARE(w.stateInMouseMove, Qt::LeftButton | Qt::RightButton);
+#endif
+}
+
+void tst_Mouse::deterministicEvents_data()
+{
+ QTest::addColumn<bool>("firstRun");
+ QTest::newRow("first-run-true") << true;
+ QTest::newRow("first-run-false") << false;
+}
+
+void tst_Mouse::deterministicEvents()
+{
+ /* QGuiApplication uses QGuiApplicationPrivate::lastCursorPosition to
+ determine if it needs to generate an additional mouse move event for
+ mouse press/release. Verify that this property is reset to it's default
+ value, ensuring deterministic event generation behavior. Not resetting
+ this value might affect event generation for subsequent tests runs (in
+ unlikely case where a subsquent test does a mouse press in a pos that is
+ equal to QGuiApplicationPrivate::lastCursorPosition, not causing mouse
+ move to be generated.
+ NOTE: running this test alone as in "./mouse deterministicEvents:first-run-false"
+ won't test what this test is designed to test. */
+
+ QSKIP("Not implemented!");
+
+ /* It is undecided how and at what scope we want to handle reseting
+ lastCursorPosition, or perhaps Qt should not be generating mouse move
+ events as documented in QGuiApplicationPrivate::processMouseEvent(),
+ then the problem would go away - ### Qt6 ? */
+
+ QVERIFY(qIsInf(QGuiApplicationPrivate::lastCursorPosition.x()));
+ QVERIFY(qIsInf(QGuiApplicationPrivate::lastCursorPosition.y()));
+
+ QFETCH(bool, firstRun);
+
+ MouseWindow w;
+ w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
+ w.show();
+ w.setGeometry(100, 100, 200, 200);
+ QVERIFY(QTest::qWaitForWindowActive(&w));
+
+ QCOMPARE(w.pressCount, 0);
+ QCOMPARE(w.moveCount, 0);
+ static QPoint m_cachedLastCursorPosition;
+ if (firstRun) {
+ QTest::mousePress(&w, Qt::LeftButton, 0, QPoint(40, 40));
+ m_cachedLastCursorPosition = QGuiApplicationPrivate::lastCursorPosition.toPoint();
+ } else {
+ QPoint point = w.mapFromGlobal(m_cachedLastCursorPosition);
+ QTest::mousePress(&w, Qt::LeftButton, 0, point);
+ }
+ QCOMPARE(w.pressCount, 1);
+ QCOMPARE(w.moveCount, 1);
+}
+
+QTEST_MAIN(tst_Mouse)
+#include "tst_mouse.moc"
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index 42c62d3b55..079f3f7959 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -47,7 +47,8 @@ SUBPROGRAMS = \
verbose2 \
verifyexceptionthrown \
warnings \
- xunit
+ xunit \
+ mouse
INCLUDEPATH += ../../../../shared/
HEADERS += ../../../../shared/emulationdetector.h