Implement threaded synchronous WS events

Make handleWindowSystemEvent() support being called
from secondary threads in synchronousWindowSystemEvent
mode.

This is implemented by posting the event to the Gui
event queue (which will wake the Qt Gui thread), and
then calling flushWindowSystemEvents which will block
the calling thread until the event has been processed.

Change-Id: I7e8e68c1e0290c17105563268e316b0f8205b3ce
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
bb10
Morten Johan Sørvig 2015-04-29 13:17:31 +02:00
parent ac9643c85f
commit ee767c838a
2 changed files with 26 additions and 8 deletions

View File

@ -442,18 +442,33 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e
windowSystemEventQueue.remove(event);
}
void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev)
{
windowSystemEventQueue.append(ev);
QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher();
if (dispatcher)
dispatcher->wakeUp();
}
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
{
bool accepted = true;
if (synchronousWindowSystemEvents) {
QGuiApplicationPrivate::processWindowSystemEvent(ev);
accepted = ev->eventAccepted;
delete ev;
if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
// Process the event immediately on the current thread and return the accepted state.
QGuiApplicationPrivate::processWindowSystemEvent(ev);
accepted = ev->eventAccepted;
delete ev;
} else {
// Post the event on the Qt main thread queue and flush the queue.
// This will wake up the Gui thread which will process the event.
// Return the accepted state for the last event on the queue,
// which is the event posted by this function.
postWindowSystemEvent(ev);
accepted = QWindowSystemInterface::flushWindowSystemEvents();
}
} else {
windowSystemEventQueue.append(ev);
QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher();
if (dispatcher)
dispatcher->wakeUp();
postWindowSystemEvent(ev);
}
return accepted;
}
@ -636,9 +651,11 @@ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl
return false;
}
if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
// Post a FlushEvents event which will trigger a call back to
// deferredFlushWindowSystemEvents from the Gui thread.
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
QWindowSystemInterfacePrivate::postWindowSystemEvent(e);
QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
} else {
sendWindowSystemEvents(flags);

View File

@ -482,6 +482,7 @@ public:
static WindowSystemEvent *getNonUserInputWindowSystemEvent();
static WindowSystemEvent *peekWindowSystemEvent(EventType t);
static void removeWindowSystemEvent(WindowSystemEvent *event);
static void postWindowSystemEvent(WindowSystemEvent *ev);
static bool handleWindowSystemEvent(WindowSystemEvent *ev);
static QElapsedTimer eventTime;