summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2015-06-02 08:43:17 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-06-02 08:02:35 +0000
commitbeef975f92e42143c464d68afa6b8cd4f7ef7389 (patch)
tree147efd478a0e3e9b693684522adb20a3674268eb
parentd83bd9c6f5abd936b853029bf7030ebb4792f9fb (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>
-rw-r--r--src/gui/kernel/qguiapplication.cpp10
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp4
-rw-r--r--src/testlib/qtestmouse.h72
3 files changed, 46 insertions, 40 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 4146ddd8ba..024578ccdd 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1695,12 +1695,14 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
// A mouse event should not change both position and buttons at the same time. Instead we
// should first send a move event followed by a button changed event. Since this is not the case
// with the current event, we split it in two.
- QWindowSystemInterfacePrivate::MouseEvent *mouseButtonEvent = new QWindowSystemInterfacePrivate::MouseEvent(
+ QWindowSystemInterfacePrivate::MouseEvent mouseButtonEvent(
e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers);
if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic)
- mouseButtonEvent->flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
- QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(mouseButtonEvent);
- stateChange = Qt::NoButton;
+ mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
+ e->buttons = buttons;
+ processMouseEvent(e);
+ processMouseEvent(&mouseButtonEvent);
+ return;
}
QWindow *window = e->window.data();
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index de8e5fbe64..823387b702 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -810,8 +810,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo
}
#endif
-Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) {
- unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed();
+Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
+{
QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized);
QGuiApplicationPrivate::processWindowSystemEvent(&e);
}
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,