diff options
author | Lars Knoll <lars.knoll@digia.com> | 2015-06-02 08:43:17 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-06-02 08:02:35 +0000 |
commit | beef975f92e42143c464d68afa6b8cd4f7ef7389 (patch) | |
tree | 147efd478a0e3e9b693684522adb20a3674268eb /src/testlib | |
parent | d83bd9c6f5abd936b853029bf7030ebb4792f9fb (diff) |
Cleanup the mouse event handling in testlib
Calling QCursor::setPos() to emulate mouse move events
is a rather bad idea, as it creates round trips through
the server, leading to timing issues etc.
In addition, we should not call qapp->notify(), but rather
route the events through the proper QPA interface. This
is required to properly generate all other events such
as enter/leave etc. As this breaks existing tests,
put the new behavior behind an #ifdef for now. Like this,
we can fix tests one by one, and then turn on the define by
default for 5.6 (with a changelog message).
We emulate timestamps to avoid creating double clicks
by mistake. In addition, fix QGuiApplication::processMouseEvent
to not push events back into the QPA event queue (as this is
a bad hack and breaks the new testing system).
Change-Id: I71774cb56674d7fb66b9a7cf1e1ada1629536408
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/testlib')
-rw-r--r-- | src/testlib/qtestmouse.h | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h index 2cf84a7ea0..5f69463867 100644 --- a/src/testlib/qtestmouse.h +++ b/src/testlib/qtestmouse.h @@ -45,6 +45,7 @@ #include <QtTest/qtestspontaneevent.h> #include <QtCore/qpoint.h> #include <QtCore/qstring.h> +#include <QtCore/qpointer.h> #include <QtGui/qevent.h> #include <QtGui/qwindow.h> @@ -57,7 +58,7 @@ QT_BEGIN_NAMESPACE -Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); +Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp); namespace QTest { @@ -83,7 +84,8 @@ namespace QTest QTest::qWarn("Mouse event occurs outside of target window."); } - static Qt::MouseButton lastButton = Qt::NoButton; + static Qt::MouseButton lastButton = Qt::NoButton; + static int timestamp = 0; if (delay == -1 || delay < defaultMouseDelay()) delay = defaultMouseDelay(); @@ -93,42 +95,38 @@ namespace QTest if (pos.isNull()) pos = window->geometry().center(); - if (action == MouseClick) { - mouseEvent(MousePress, window, button, stateKey, pos); - mouseEvent(MouseRelease, window, button, stateKey, pos); - return; - } QTEST_ASSERT(uint(stateKey) == 0 || stateKey & Qt::KeyboardModifierMask); stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask); + QPointF global = window->mapToGlobal(pos); + QPointer<QWindow> w(window); switch (action) { - case MousePress: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey); - lastButton = button; - break; - case MouseRelease: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey); - lastButton = Qt::NoButton; + case MouseDClick: + qt_handleMouseEvent(w, pos, global, button, stateKey, timestamp); + qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++timestamp); + // fall through + case MousePress: + case MouseClick: + qt_handleMouseEvent(w, pos, global, button, stateKey, ++timestamp); + lastButton = button; + if (action == MousePress) break; - case MouseDClick: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey); - qWait(10); - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey); - qWait(20); - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey); - qWait(10); - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey); - break; - case MouseMove: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),lastButton,stateKey); - // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system - // which is highly undesired here. Tests must avoid relying on QCursor. - break; - default: - QTEST_ASSERT(false); + // fall through + case MouseRelease: + qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++timestamp); + timestamp += 500; // avoid double clicks being generated + lastButton = Qt::NoButton; + break; + case MouseMove: + qt_handleMouseEvent(w, pos, global, lastButton, stateKey, ++timestamp); + // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system + // which is highly undesired here. Tests must avoid relying on QCursor. + break; + default: + QTEST_ASSERT(false); } waitForEvents(); } @@ -153,6 +151,15 @@ namespace QTest Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) { QTEST_ASSERT(widget); + + if (pos.isNull()) + pos = widget->rect().center(); + +#ifdef QTEST_QPA_MOUSE_HANDLING + QWindow *w = widget->window()->windowHandle(); + QTEST_ASSERT(w); + mouseEvent(action, w, button, stateKey, w->mapFromGlobal(widget->mapToGlobal(pos)), delay); +#else extern int Q_TESTLIB_EXPORT defaultMouseDelay(); if (delay == -1 || delay < defaultMouseDelay()) @@ -160,9 +167,6 @@ namespace QTest if (delay > 0) QTest::qWait(delay); - if (pos.isNull()) - pos = widget->rect().center(); - if (action == MouseClick) { mouseEvent(MousePress, widget, button, stateKey, pos); mouseEvent(MouseRelease, widget, button, stateKey, pos); @@ -203,7 +207,7 @@ namespace QTest 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()); } - +#endif } inline void mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, |