summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2017-08-03 09:24:27 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2017-08-04 11:19:19 +0000
commit341bfcd1eaa9116c143e3b7d3219ef04c7b8a0cb (patch)
treeac81466643a74fe7b1a2de74099081d10d21143f /src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
parentb12fd1fa9d0b64e3cb66fa68c85392dbde8e175b (diff)
glib dispatcher: ensure all window system events are flushed
... when QCoreApplication::processEvents() returns. This is the expected behavior according to the documentation. Checked also the QUnixEventDispatcherQPA dispatcher, which did work according to the documentation. The sequence of events that causes the bad behavior: 1) XCB plugin sends a signals whenever there are new XCB events available for processing. This signal is connected to QXcbConnection::processXcbEvents, which will cause XCB events to be added to the QWindowSystemInterface (QWSI) event queue. 2) When QCoreApplication::processEvents() is called, glib event dispatcher does one iteration on all attached event sources. First it checks which sources are ready, and after that starts dispatching events from each source that reported to be ready. 3) In the case when there are no events in QWSI event queue, the source that handles QWSI event dispatcing returns 'false'; If at the same iteration the source that sends posted events (via QCoreApplication::sendPostedEvents()) has returned 'true' and one of the posted events is to call QXcbConnection::processXcbEvents (due to signal from step 1) then we get an assert in the following code: QCoreApplication::processEvents(); Q_ASSERT(QWindowSystemInterface::windowSystemEventsQueued() == 0); This happens because QXcbConnection::processXcbEvents has posted new events, but they were not dispatched in this iteration. They would be dispatched in the next iteration. Events being dispatched on subsequent iteration doesn't really matter for Qt application, but is inconsistent from API point of view. If we were populating QWSI queue from non-Gui thread, then it would be possible that windowSystemEventsQueued() != 0, but that is not the case on XCB (don't know about other platforms). The issue could be fixed by always returning true from "check source" and then simply dispatch 0 events at "dispatch" step if there isn't any in the queue. But a better solution is to remove the event source all together. It is completely unnecessary to have this indirection, when we can handle QWSI event dispatch directly from Qt (like we do, for example, in QUnixEventDispatcherQPA and QWinRTEventDispatcher). Not having Glib event source for QWSI events would have also avoided issues that were fixed by fbb485d4f6985643b27da3cc6c5b5f960c32e74d. Note, after this re-factoring QWindowSystemInterface::nonUserInputEventsQueued is now unused, but I left it in as the API by itself is all right. Task-number: QTBUG-62297 Change-Id: Ia245b835676bd87e63bf02b67036b42a3b1593cc Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp')
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp56
1 files changed, 2 insertions, 54 deletions
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
index dc4785071f..06f0aa6747 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
@@ -48,78 +48,26 @@
QT_BEGIN_NAMESPACE
-struct GUserEventSource
-{
- GSource source;
- QPAEventDispatcherGlib *q;
-};
-
-static gboolean userEventSourcePrepare(GSource *source, gint *timeout)
-{
- Q_UNUSED(timeout)
- GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
- QPAEventDispatcherGlib *dispatcher = userEventSource->q;
- if (dispatcher->m_flags & QEventLoop::ExcludeUserInputEvents)
- return QWindowSystemInterface::nonUserInputEventsQueued();
- else
- return QWindowSystemInterface::windowSystemEventsQueued() > 0;
-}
-
-static gboolean userEventSourceCheck(GSource *source)
-{
- return userEventSourcePrepare(source, 0);
-}
-
-static gboolean userEventSourceDispatch(GSource *source, GSourceFunc, gpointer)
-{
- GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
- QPAEventDispatcherGlib *dispatcher = userEventSource->q;
- QWindowSystemInterface::sendWindowSystemEvents(dispatcher->m_flags);
- return true;
-}
-
-static GSourceFuncs userEventSourceFuncs = {
- userEventSourcePrepare,
- userEventSourceCheck,
- userEventSourceDispatch,
- NULL,
- NULL,
- NULL
-};
-
QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context)
: QEventDispatcherGlibPrivate(context)
{
- Q_Q(QPAEventDispatcherGlib);
- userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs,
- sizeof(GUserEventSource)));
- userEventSource->q = q;
- g_source_set_can_recurse(&userEventSource->source, true);
- g_source_attach(&userEventSource->source, mainContext);
}
-
QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent)
: QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent)
, m_flags(QEventLoop::AllEvents)
{
- Q_D(QPAEventDispatcherGlib);
- d->userEventSource->q = this;
}
QPAEventDispatcherGlib::~QPAEventDispatcherGlib()
{
- Q_D(QPAEventDispatcherGlib);
-
- g_source_destroy(&d->userEventSource->source);
- g_source_unref(&d->userEventSource->source);
- d->userEventSource = 0;
}
bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
{
m_flags = flags;
- return QEventDispatcherGlib::processEvents(m_flags);
+ const bool didSendEvents = QEventDispatcherGlib::processEvents(m_flags);
+ return QWindowSystemInterface::sendWindowSystemEvents(m_flags) || didSendEvents;
}
QT_END_NAMESPACE