From 0f94430a0fba5509d2d756832cb44a266d1d2e86 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 6 Oct 2022 16:54:14 +0200 Subject: testlib: make it possible to test double-clicks with discrete events The timestamp will no longer be incremented by 500ms after a mouse release if the delay has been explicitly specified. The default delay is 1 ms since f5010c49a37729375e37e6fe8cea60dd4b880d83 but the running timestamp was unconditionally post-incremented by 500ms after every mouse release, to prevent double-clicks, which were always deemed as unintended (because we have a mouseDClick function for that). Now, we do that 500ms increment only if the user has not provided a delay value in the function argument at all. We have often found it useful in our own tests to generate double-clicks "the hard way", by sending indivdual events, so as to be able to check state in some target object at each step, as shown in the new snippet. [ChangeLog][QtTest] QTest::mouseRelease() and mouseClick() can now be used to test double-clicks, by specifying a realistic timestamp delay. Fixes: QTBUG-102441 Change-Id: I8e8d242061f79efb4c6e02638645e03661a9cd92 Reviewed-by: Richard Moe Gustavsen --- .../code/src_qtestlib_qtestcase_snippet.cpp | 13 +++++++++++++ src/testlib/qtestcase.qdoc | 22 ++++++++++++++++++++-- src/testlib/qtestmouse.h | 14 ++++++++++---- 3 files changed, 43 insertions(+), 6 deletions(-) (limited to 'src/testlib') diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp index e64e9daecf..aa24746522 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp @@ -119,3 +119,16 @@ char *toString(const MyType &t) return repr; } //! [34] + +//! [35] +QSignalSpy doubleClickSpy(target, &TargetClass::doubleClicked); +const QPoint p(1, 2); +QTest::mousePress(&myWindow, Qt::LeftButton, Qt::NoModifier, p); +QVERIFY(target.isPressed()); +QTest::mouseRelease(&myWindow, Qt::LeftButton, Qt::NoModifier, p, 10); +QCOMPARE(target.isPressed(), false); +QTest::mousePress(&myWindow, Qt::LeftButton, Qt::NoModifier, p, 10); +QCOMPARE(target.pressCount(), 2); +QTest::mouseRelease(&myWindow, Qt::LeftButton, Qt::NoModifier, p, 10); +QCOMPARE(doubleClickSpy.count(), 1); +//! [35] diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc index 654687c880..e2181c816b 100644 --- a/src/testlib/qtestcase.qdoc +++ b/src/testlib/qtestcase.qdoc @@ -1260,7 +1260,16 @@ on a \a widget. The position of the release is defined by \a pos; the default position is the center of the widget. If \a delay is specified, the test will wait for the specified amount of - milliseconds before releasing the button. + milliseconds before releasing the button; otherwise, it will wait for a + default amount of time (1 ms), which can be overridden via + \l {Testing Options}{command-line arguments}. + + \note If you wish to test a double-click by sending events individually, + specify a short delay, greater than the default, on both mouse release events. + The total of the delays for the press, release, press and release must be + less than QStyleHints::mouseDoubleClickInterval(). But if you don't need + to check state between events, it's better to use QTest::mouseDClick(). + \snippet code/src_qtestlib_qtestcase_snippet.cpp 35 \sa QTest::mousePress(), QTest::mouseClick() */ @@ -1273,7 +1282,16 @@ on a \a window. The position of the release is defined by \a pos; the default position is the center of the window. If \a delay is specified, the test will wait for the specified amount of - milliseconds before releasing the button. + milliseconds before releasing the button; otherwise, it will wait for a + default amount of time (1 ms), which can be overridden via + \l {Testing Options}{command-line arguments}. + + \note If you wish to test a double-click by sending events individually, + specify a short delay, greater than the default, on both mouse release events. + The total of the delays for the press, release, press and release must be + less than QStyleHints::mouseDoubleClickInterval(). But if you don't need + to check state between events, it's better to use QTest::mouseDClick(). + \snippet code/src_qtestlib_qtestcase_snippet.cpp 35 \sa QTest::mousePress(), QTest::mouseClick() */ diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h index 37e8d4eab5..01a3c9c6b5 100644 --- a/src/testlib/qtestmouse.h +++ b/src/testlib/qtestmouse.h @@ -57,6 +57,12 @@ namespace QTest event. We expect all event-handling code to rely on the event timestamps, not the system clock; therefore tests can be run faster than real-time. + + If \a delay is not given, a default minimum mouse delay is used, and + unintended double-click events are prevented by incrementing the + timestamp by 500ms after each mouse release. Therefore, to test + double-clicks, it's necessary to give a realistic \a delay value (for + example, 10ms). */ static void mouseEvent(MouseAction action, QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) @@ -71,9 +77,8 @@ namespace QTest pos.x(), pos.y(), windowSize.width(), windowSize.height()); } - if (delay == -1 || delay < defaultMouseDelay()) - delay = defaultMouseDelay(); - lastMouseTimestamp += qMax(1, delay); + int actualDelay = (delay == -1 || delay < defaultMouseDelay()) ? defaultMouseDelay() : delay; + lastMouseTimestamp += qMax(1, actualDelay); if (pos.isNull()) pos = QPoint(window->width() / 2, window->height() / 2); @@ -108,7 +113,8 @@ namespace QTest qtestMouseButtons.setFlag(button, false); qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonRelease, stateKey, lastMouseTimestamp); - lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated + if (delay == -1) + lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated break; case MouseMove: qt_handleMouseEvent(w, pos, global, qtestMouseButtons, Qt::NoButton, QEvent::MouseMove, -- cgit v1.2.3