summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbconnection.h
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-08-25 13:39:07 +0200
committerLars Knoll <lars.knoll@nokia.com>2011-08-26 09:19:01 +0200
commit794c81c1eab54cb58f2143ab3efc90e9c4bf9092 (patch)
tree75a2f9b0bcd886ed9bf8c9e10123ca2d449b8a4a /src/plugins/platforms/xcb/qxcbconnection.h
parent7b686abdd5bedcb32b5dbd19655df2e43f6242fd (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.h48
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;
}