From 1256ed05b2f38e9e0364244616474e75655b19f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 30 Sep 2013 10:45:28 +0200 Subject: xcb: Don't connect() to event-dispatcher until we are sure we have one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QCoreApplication sets up the event dispatcher in the constructor, through createEventDispatcher(), which is overridden in QGuiApplication to take the platform-integration into account. The problem is that the platform integration is created before the event dispatcher, so when we create the QXcbConnection we are not guaranteed to have an event dispatcher yet. This is not an issue when using xcb_poll_for_queued_event() in a thread, but for the fallback case we connect to the event-dispatcher's awake() and aboutToBlock() signals. To ensure that we do this only when we have an event dispatcher we post a queued method invocation, that will be processed as one of the first events once there is an event-dispatcher. Change-Id: I623011af447b585884b84c7559737f134aab83e8 Reviewed-by: Jędrzej Nowacki Reviewed-by: Uli Schlachter Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 30 ++++++++++++++++------------ src/plugins/platforms/xcb/qxcbconnection.h | 7 ++++++- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index d6f64d29fd..433758e065 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -290,16 +290,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData()); m_reader = new QXcbEventReader(this); - connect(m_reader, SIGNAL(eventPending()), this, SLOT(processXcbEvents()), Qt::QueuedConnection); - connect(m_reader, SIGNAL(finished()), this, SLOT(processXcbEvents())); - if (!m_reader->startThread()) { - QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents())); - - QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; - connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents())); - connect(dispatcher, SIGNAL(awake()), this, SLOT(processXcbEvents())); - } + m_reader->start(); xcb_extension_t *extensions[] = { &xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id, @@ -977,14 +968,27 @@ QXcbEventReader::QXcbEventReader(QXcbConnection *connection) #endif } -bool QXcbEventReader::startThread() +void QXcbEventReader::start() { if (m_xcb_poll_for_queued_event) { + connect(this, SIGNAL(eventPending()), m_connection, SLOT(processXcbEvents()), Qt::QueuedConnection); + connect(this, SIGNAL(finished()), m_connection, SLOT(processXcbEvents())); QThread::start(); - return true; + } else { + // Must be done after we have an event-dispatcher. By posting a method invocation + // we are sure that by the time the method is called we have an event-dispatcher. + QMetaObject::invokeMethod(this, "registerForEvents", Qt::QueuedConnection); } +} - return false; +void QXcbEventReader::registerForEvents() +{ + QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection->xcb_connection()), QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), m_connection, SLOT(processXcbEvents())); + + QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; + connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(processXcbEvents())); + connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents())); } void QXcbEventReader::run() diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7cabe67a68..0e52b2ec46 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -298,11 +298,14 @@ public: QXcbEventArray *lock(); void unlock(); - bool startThread(); + void start(); signals: void eventPending(); +private slots: + void registerForEvents(); + private: void addEvent(xcb_generic_event_t *event); @@ -574,6 +577,8 @@ private: QByteArray m_startupId; QXcbSystemTrayTracker *m_systemTrayTracker; + + friend class QXcbEventReader; }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) -- cgit v1.2.3