xcb: Only create listener window when needed

The xcb QPA plugin uses a separate thread for getting events from the
X11 server in a race-free manner. This thread has to be stopped when
shutting down.  This is done by causing the X11 server to send a special
event that causes the thread to exit when it sees it. (Also, the thread
exits if the xcb connection goes into an error state, but that does not
matter here)

So this event listener window is only needed when Qt is sending events
to itself. This means that it does not have to be kept around and
instead can be created only when needed.

Since this window does not stay around for long, it does not need a
name. However, it does need the list of screens to find the correct root
window, so destroy screens later.

Change-Id: Ib4104cbc3f372fa5d1391bcf5a633a158409862f
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Uli Schlachter 2013-11-11 20:05:56 +01:00 committed by The Qt Project
parent 88609e6da4
commit 7e468353c3
2 changed files with 13 additions and 24 deletions

View File

@ -319,23 +319,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXRandr();
updateScreens();
m_connectionEventListener = xcb_generate_id(m_connection);
xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
m_connectionEventListener, m_screens.at(0)->root(),
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
m_screens.at(0)->screen()->root_visual, 0, 0);
#ifndef QT_NO_DEBUG
QByteArray ba("Qt xcb connection listener window");
Q_XCB_CALL(xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_connectionEventListener,
atom(QXcbAtom::_NET_WM_NAME),
atom(QXcbAtom::UTF8_STRING),
8,
ba.length(),
ba.constData()));
#endif
initializeGLX();
initializeXFixes();
initializeXRender();
@ -372,9 +355,6 @@ QXcbConnection::~QXcbConnection()
#ifndef QT_NO_DRAGANDDROP
delete m_drag;
#endif
// Delete screens in reverse order to avoid crash in case of multiple screens
while (!m_screens.isEmpty())
delete m_screens.takeLast();
#ifdef XCB_USE_XINPUT2_MAEMO
finalizeXInput2Maemo();
@ -389,6 +369,10 @@ QXcbConnection::~QXcbConnection()
delete m_reader;
// Delete screens in reverse order to avoid crash in case of multiple screens
while (!m_screens.isEmpty())
delete m_screens.takeLast();
#ifdef XCB_USE_EGL
if (m_has_egl)
eglTerminate(m_egl_display);
@ -1066,14 +1050,21 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
xcb_client_message_event_t event;
memset(&event, 0, sizeof(event));
const xcb_window_t eventListener = xcb_generate_id(m_connection);
Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
eventListener, m_screens.at(0)->root(),
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
m_screens.at(0)->screen()->root_visual, 0, 0));
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.sequence = 0;
event.window = m_connectionEventListener;
event.window = eventListener;
event.type = atom(a);
event.data.data32[0] = id;
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener));
xcb_flush(xcb_connection());
}

View File

@ -517,8 +517,6 @@ private:
QByteArray m_displayName;
xcb_window_t m_connectionEventListener;
QXcbKeyboard *m_keyboard;
#ifndef QT_NO_CLIPBOARD
QXcbClipboard *m_clipboard;