Allow flushing window system events from other thread

For platform plugins such as the Android plugin, we need to
make sure an event is delivered and handled before continuing
execution (e.g. when doing an expose event to report that the
EGL surface has been destroyed when the app goes into the
background.)

Change-Id: Ibd381baafa93f111dbc887d4cf9d9ca37429b186
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2013-02-28 14:07:04 +01:00 committed by The Qt Project
parent dedec0b305
commit 05a61de622
4 changed files with 36 additions and 2 deletions

View File

@ -1279,6 +1279,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
case QWindowSystemInterfacePrivate::ApplicationStateChanged:
QGuiApplicationPrivate::processApplicationStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e));
break;
case QWindowSystemInterfacePrivate::FlushEvents:
QWindowSystemInterface::deferredFlushWindowSystemEvents();
break;
case QWindowSystemInterfacePrivate::Close:
QGuiApplicationPrivate::processCloseEvent(
static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e));

View File

@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE
QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
bool QWindowSystemInterfacePrivate::synchronousWindowsSystemEvents = false;
QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
QMutex QWindowSystemInterfacePrivate::flushEventMutex;
//------------------------------------------------------------
//
@ -514,9 +516,25 @@ void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion &regi
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::deferredFlushWindowSystemEvents()
{
Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread());
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
flushWindowSystemEvents();
QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
}
void QWindowSystemInterface::flushWindowSystemEvents()
{
sendWindowSystemEventsImplementation(QEventLoop::AllEvents);
if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent();
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
} else {
sendWindowSystemEventsImplementation(QEventLoop::AllEvents);
}
}
bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)

View File

@ -186,6 +186,7 @@ public:
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
static void setSynchronousWindowsSystemEvents(bool enable);
static void flushWindowSystemEvents();
static void deferredFlushWindowSystemEvents();
static int windowSystemEventsQueued();
private:

View File

@ -58,6 +58,7 @@
#include <QPointer>
#include <QMutex>
#include <QList>
#include <QWaitCondition>
QT_BEGIN_NAMESPACE
@ -89,7 +90,8 @@ public:
TabletLeaveProximity = UserInputEvent | 0x16,
PlatformPanel = UserInputEvent | 0x17,
ContextMenu = UserInputEvent | 0x18,
ApplicationStateChanged = 0x19
ApplicationStateChanged = 0x19,
FlushEvents = 0x20
};
class WindowSystemEvent {
@ -162,6 +164,13 @@ public:
Qt::ApplicationState newState;
};
class FlushEventsEvent : public WindowSystemEvent {
public:
FlushEventsEvent()
: WindowSystemEvent(FlushEvents)
{ }
};
class UserEvent : public WindowSystemEvent {
public:
UserEvent(QWindow * w, ulong time, EventType t)
@ -432,6 +441,9 @@ public:
static QElapsedTimer eventTime;
static bool synchronousWindowsSystemEvents;
static QWaitCondition eventsFlushed;
static QMutex flushEventMutex;
static QList<QTouchEvent::TouchPoint> convertTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, QEvent::Type *type);
};