xcb: Don't connect() to event-dispatcher until we are sure we have one
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 <jedrzej.nowacki@digia.com> Reviewed-by: Uli Schlachter <psychon@znc.in> Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
parent
99b3e68f20
commit
1256ed05b2
@ -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()
|
||||
|
@ -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()))
|
||||
|
Loading…
Reference in New Issue
Block a user