From 66050f2ac875d451bec31e0d8ff507795b5b18d6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 21 May 2015 15:12:21 +0200 Subject: [PATCH] Make event delivery from testlib synchronous Directly process events delivered from testlib in QGuiApplication. The old code put these events into the QPA event queue leading to race conditions with plugins delivering native events from a secondary thread. Change-Id: I5646b1014f681593d487c9d1e65053ba06206411 Reviewed-by: Simon Hausmann --- src/gui/kernel/qwindowsysteminterface.cpp | 70 ++++++++++++++--------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 629bd02cd2..de8e5fbe64 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -811,12 +811,25 @@ 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) { - QWindowSystemInterface::handleMouseEvent(w, local, global, b, mods); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) { - QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + + // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms + // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for + // shortcut overriding on other platforms. +#if defined(Q_OS_OSX) + if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text)) + return; +#endif // Q_OS_OSX + + QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) @@ -824,35 +837,38 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count); } -static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt) -{ - QWindowSystemInterface::TouchPoint p; - p.id = pt.id(); - p.flags = pt.flags(); - p.normalPosition = pt.normalizedPos(); - p.area = pt.screenRect(); - p.pressure = pt.pressure(); - p.state = pt.state(); - p.velocity = pt.velocity(); - p.rawPositions = pt.rawScreenPositions(); - return p; -} -static QList touchPointList(const QList& pointList) -{ - QList newList; - Q_FOREACH (QTouchEvent::TouchPoint p, pointList) - { - newList.append(touchPoint(p)); - } - return newList; -} - -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, const QList &points, Qt::KeyboardModifiers mods = Qt::NoModifier) { - QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + + if (!points.size()) // Touch events must have at least one point + return; + + if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. + return; + + QEvent::Type type; + Qt::TouchPointStates states; + + QList::const_iterator point = points.constBegin(); + QList::const_iterator end = points.constEnd(); + while (point != end) { + states |= point->state(); + ++point; + } + + // Determine the event type based on the combined point states. + type = QEvent::TouchUpdate; + if (states == Qt::TouchPointPressed) + type = QEvent::TouchBegin; + else if (states == Qt::TouchPointReleased) + type = QEvent::TouchEnd; + + QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } QWindowSystemEventHandler::~QWindowSystemEventHandler()