From a461bb1ff5b5f310244bae1691b08e7135aeda0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 19 May 2014 08:58:37 +0200 Subject: Flush xcb connection before EventDispatcher is going to block The non-threaded QXcbEventReader invokes processXcbEvents when the EventDispatcher is about to block. This method ensures that the xcb connection is going to flush. Applications can use low level xcb code in that case without having to ensure to flush the connection before going to block again. With the threaded QXcbEventReader this didn't work and applications which for example changed a window property and waited for the matching property notify event were stalled. This change ensures that also in the threaded case the connection gets flushed when the EventDispatcher is going to block. Change-Id: If1dc5eb96e2f1bde10b7a40af550b0608c62f70c Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 9 +++++++++ src/plugins/platforms/xcb/qxcbconnection.h | 6 +++++- src/plugins/platforms/xcb/qxcbintegration.cpp | 5 ++++- 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1b72bb0da1..7f23c84cb9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1028,6 +1028,15 @@ void QXcbEventReader::registerForEvents() connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents())); } +void QXcbEventReader::registerEventDispatcher(QAbstractEventDispatcher *dispatcher) +{ + // flush the xcb connection before the EventDispatcher is going to block + // In the non-threaded case processXcbEvents is called before going to block, + // which flushes the connection. + if (m_xcb_poll_for_queued_event) + connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(flush())); +} + void QXcbEventReader::run() { xcb_generic_event_t *event; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 6c9ccbcc2f..0bfc2f8f76 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -311,6 +311,8 @@ public: void start(); + void registerEventDispatcher(QAbstractEventDispatcher *dispatcher); + signals: void eventPending(); @@ -410,7 +412,6 @@ public: void sync(); - void flush() { xcb_flush(m_connection); } void handleXcbError(xcb_generic_error_t *error); void handleXcbEvent(xcb_generic_event_t *event); @@ -464,8 +465,11 @@ public: void handleEnterEvent(const xcb_enter_notify_event_t *); #endif + QXcbEventReader *eventReader() const { return m_reader; } + public slots: void syncWindow(QXcbWindow *window); + void flush() { xcb_flush(m_connection); } private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index ddb164bf07..1b1c20f02c 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -303,7 +303,10 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const { - return createUnixEventDispatcher(); + QAbstractEventDispatcher *dispatcher = createUnixEventDispatcher(); + for (int i = 0; i < m_connections.size(); i++) + m_connections[i]->eventReader()->registerEventDispatcher(dispatcher); + return dispatcher; } void QXcbIntegration::initialize() -- cgit v1.2.3