summaryrefslogtreecommitdiffstats
path: root/src/testlib/qtestmouse.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib/qtestmouse.h')
-rw-r--r--src/testlib/qtestmouse.h146
1 files changed, 59 insertions, 87 deletions
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index 4848462be6..567d80c521 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtTest module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTESTMOUSE_H
#define QTESTMOUSE_H
@@ -77,7 +41,6 @@ namespace QTest
{
enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove };
- 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.
@@ -85,13 +48,22 @@ namespace QTest
// to depend on platform themes.
static const int mouseDoubleClickInterval = 500;
-/*! \internal
-
- This function mocks all mouse events by bypassing the windowing system. The
- result is that the mouse events do not come from the system via Qt platform
- plugins, but are created on the spot and immediately available for processing
- by Qt.
-*/
+ /*! \internal
+ This function creates a QPA mouse event of type specified by \a action
+ and calls QWindowSystemInterface::handleMouseEvent(), simulating the
+ windowing system and bypassing the platform plugin. \a delay is the
+ amount of time to be added to the simulated clock so that
+ QInputEvent::timestamp() will be greater than that of the previous
+ 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)
{
@@ -101,23 +73,19 @@ namespace QTest
// pos is in window local coordinates
const QSize windowSize = window->geometry().size();
if (windowSize.width() <= pos.x() || windowSize.height() <= pos.y()) {
- QTest::qWarn(qPrintable(QString::fromLatin1("Mouse event at %1, %2 occurs outside of target window (%3x%4).")
- .arg(pos.x()).arg(pos.y()).arg(windowSize.width()).arg(windowSize.height())));
+ qWarning("Mouse event at %d, %d occurs outside target window (%dx%d).",
+ pos.x(), pos.y(), windowSize.width(), windowSize.height());
}
- if (delay == -1 || delay < defaultMouseDelay())
- delay = defaultMouseDelay();
- if (delay > 0) {
- QTest::qWait(delay);
- lastMouseTimestamp += delay;
- }
+ int actualDelay = (delay == -1 || delay < defaultMouseDelay()) ? defaultMouseDelay() : delay;
+ lastMouseTimestamp += qMax(1, actualDelay);
if (pos.isNull())
pos = QPoint(window->width() / 2, window->height() / 2);
- QTEST_ASSERT(uint(stateKey) == 0 || stateKey & Qt::KeyboardModifierMask);
+ QTEST_ASSERT(!stateKey || stateKey & Qt::KeyboardModifierMask);
- stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask);
+ stateKey &= Qt::KeyboardModifierMask;
QPointF global = window->mapToGlobal(pos);
QPointer<QWindow> w(window);
@@ -128,30 +96,29 @@ namespace QTest
case MouseDClick:
qtestMouseButtons.setFlag(button, true);
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonPress,
- stateKey, ++lastMouseTimestamp);
+ stateKey, lastMouseTimestamp);
qtestMouseButtons.setFlag(button, false);
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonRelease,
- stateKey, ++lastMouseTimestamp);
+ stateKey, lastMouseTimestamp);
Q_FALLTHROUGH();
case MousePress:
case MouseClick:
qtestMouseButtons.setFlag(button, true);
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, button, QEvent::MouseButtonPress,
- stateKey, ++lastMouseTimestamp);
- lastMouseButton = button; // ### unsued
+ stateKey, lastMouseTimestamp);
if (action == MousePress)
break;
Q_FALLTHROUGH();
case MouseRelease:
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; // ### unsued
+ stateKey, lastMouseTimestamp);
+ if (delay == -1)
+ lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated
break;
case MouseMove:
qt_handleMouseEvent(w, pos, global, qtestMouseButtons, Qt::NoButton, QEvent::MouseMove,
- stateKey, ++lastMouseTimestamp);
+ stateKey, lastMouseTimestamp);
break;
default:
QTEST_ASSERT(false);
@@ -196,10 +163,7 @@ namespace QTest
if (delay == -1 || delay < defaultMouseDelay())
delay = defaultMouseDelay();
- if (delay > 0) {
- QTest::qWait(delay);
- lastMouseTimestamp += delay;
- }
+ lastMouseTimestamp += qMax(1, delay);
if (action == MouseClick) {
mouseEvent(MousePress, widget, button, stateKey, pos);
@@ -207,43 +171,51 @@ namespace QTest
return;
}
- QTEST_ASSERT(stateKey == 0 || stateKey & Qt::KeyboardModifierMask);
+ QTEST_ASSERT(!stateKey || stateKey & Qt::KeyboardModifierMask);
- stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask);
+ stateKey &= Qt::KeyboardModifierMask;
- QMouseEvent me(QEvent::User, QPointF(), Qt::LeftButton, QTestPrivate::qtestMouseButtons, stateKey, QPointingDevice::primaryPointingDevice());
+ QEvent::Type meType = QEvent::None;
+ using namespace QTestPrivate;
switch (action)
{
case MousePress:
- me = QMouseEvent(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, button, stateKey, QPointingDevice::primaryPointingDevice());
- me.setTimestamp(++lastMouseTimestamp);
+ qtestMouseButtons.setFlag(button, true);
+ meType = QEvent::MouseButtonPress;
break;
case MouseRelease:
- me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, Qt::MouseButton(), stateKey, QPointingDevice::primaryPointingDevice());
- me.setTimestamp(++lastMouseTimestamp);
- lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated
+ qtestMouseButtons.setFlag(button, false);
+ meType = QEvent::MouseButtonRelease;
break;
case MouseDClick:
- me = QMouseEvent(QEvent::MouseButtonDblClick, pos, widget->mapToGlobal(pos), button, button, stateKey, QPointingDevice::primaryPointingDevice());
- me.setTimestamp(++lastMouseTimestamp);
+ qtestMouseButtons.setFlag(button, true);
+ meType = QEvent::MouseButtonDblClick;
break;
case MouseMove:
- QCursor::setPos(widget->mapToGlobal(pos));
-#ifdef Q_OS_MAC
- QTest::qWait(20);
-#else
- qApp->processEvents();
-#endif
- return;
+ // ### Qt 7: compatibility with < Qt 6.3, we should not rely on QCursor::setPos
+ // for generating mouse move events, and code that depends on QCursor::pos should
+ // be tested using QCursor::setPos explicitly.
+ if (qtestMouseButtons == Qt::NoButton) {
+ QCursor::setPos(widget->mapToGlobal(pos));
+ qApp->processEvents();
+ return;
+ }
+ meType = QEvent::MouseMove;
+ break;
default:
QTEST_ASSERT(false);
}
+ QMouseEvent me(meType, pos, widget->mapToGlobal(pos), button, qtestMouseButtons, stateKey, QPointingDevice::primaryPointingDevice());
+ me.setTimestamp(lastMouseTimestamp);
+ if (action == MouseRelease) // avoid double clicks being generated
+ lastMouseTimestamp += mouseDoubleClickInterval;
+
QSpontaneKeyEvent::setSpontaneous(&me);
if (!qApp->notify(widget, &me)) {
static const char *const mouseActionNames[] =
{ "MousePress", "MouseRelease", "MouseClick", "MouseDClick", "MouseMove" };
- QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget");
- QTest::qWarn(warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])).toLatin1().data());
+ qWarning("Mouse event \"%s\" not accepted by receiving widget",
+ mouseActionNames[static_cast<int>(action)]);
}
#endif
}