diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-08-25 13:39:07 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2011-08-26 09:19:01 +0200 |
commit | 794c81c1eab54cb58f2143ab3efc90e9c4bf9092 (patch) | |
tree | 75a2f9b0bcd886ed9bf8c9e10123ca2d449b8a4a /src/plugins/platforms/xcb/qxcbconnection.h | |
parent | 7b686abdd5bedcb32b5dbd19655df2e43f6242fd (diff) |
Move XCB event reading to a separate thread.
Work-around for bug in XCB which causes a xcb_wait_for_reply to block
if xcb_poll_for_events() is called simultaneously from a different
thread. If the XCB version is too old this work-around causes even
more problems, so we kill two birds with one stone by only using the
work-around if the XCB version has the recent
xcb_poll_for_queue_event() function, which we also need to read
events from a separate thread with reasonable efficiency.
Change-Id: I8a899dad6ded381ce42cba0112e77da3c8aa6887
Reviewed-on: http://codereview.qt.nokia.com/3612
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection.h')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 6a80f57972..8c05fe23e4 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -46,7 +46,9 @@ #include <QHash> #include <QList> +#include <QMutex> #include <QObject> +#include <QThread> #include <QVector> #define Q_XCB_DEBUG @@ -100,6 +102,9 @@ namespace QXcbAtom { _QT_SCROLL_DONE, _QT_INPUT_ENCODING, + // Qt/XCB specific + _QT_CLOSE_CONNECTION, + _MOTIF_WM_HINTS, DTWM_IS_RUNNING, @@ -222,6 +227,33 @@ namespace QXcbAtom { }; } +class QXcbEventReader : public QThread +{ + Q_OBJECT +public: + QXcbEventReader(xcb_connection_t *connection) + : m_connection(connection) + { + } + +#ifdef XCB_POLL_FOR_QUEUED_EVENT + void run(); +#endif + + QList<xcb_generic_event_t *> *lock(); + void unlock(); + +signals: + void eventPending(); + +private: + void addEvent(xcb_generic_event_t *event); + + QMutex m_mutex; + QList<xcb_generic_event_t *> m_events; + xcb_connection_t *m_connection; +}; + class QAbstractEventDispatcher; class QXcbConnection : public QObject { @@ -314,6 +346,8 @@ private: QByteArray m_displayName; + xcb_window_t m_connectionEventListener; + QXcbKeyboard *m_keyboard; QXcbClipboard *m_clipboard; QXcbDrag *m_drag; @@ -322,7 +356,7 @@ private: #if defined(XCB_USE_XLIB) void *m_xlib_display; #endif - + QXcbEventReader *m_reader; #ifdef XCB_USE_DRI2 uint32_t m_dri2_major; uint32_t m_dri2_minor; @@ -345,7 +379,6 @@ private: template <typename cookie_t> friend cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, int line); #endif - QVector<xcb_generic_event_t *> eventqueue; WindowMapper m_mapper; @@ -359,16 +392,17 @@ private: template<typename T> xcb_generic_event_t *QXcbConnection::checkEvent(const T &checker) { - while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) - eventqueue.append(event); + QList<xcb_generic_event_t *> *eventqueue = m_reader->lock(); - for (int i = 0; i < eventqueue.size(); ++i) { - xcb_generic_event_t *event = eventqueue.at(i); + for (int i = 0; i < eventqueue->size(); ++i) { + xcb_generic_event_t *event = eventqueue->at(i); if (checker.check(event)) { - eventqueue[i] = 0; + (*eventqueue)[i] = 0; + m_reader->unlock(); return event; } } + m_reader->unlock(); return 0; } |