1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the plugins of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtGui/private/qguiapplication_p.h>
43 #include <QtCore/QDebug>
45 #include "qxcbconnection.h"
46 #include "qxcbkeyboard.h"
47 #include "qxcbscreen.h"
48 #include "qxcbwindow.h"
49 #include "qxcbclipboard.h"
51 #include "qxcbwmsupport.h"
53 #include <QtAlgorithms>
54 #include <QSocketNotifier>
55 #include <QAbstractEventDispatcher>
60 #include <xcb/xfixes.h>
64 #include <X11/Xlib-xcb.h>
65 #include <X11/Xlibint.h>
69 #include <xcb/render.h>
72 #ifdef XCB_USE_EGL //dont pull in eglext prototypes
81 #define MESA_EGL_NO_X11_HEADERS
82 #define EGL_EGLEXT_PROTOTYPES
84 #include <EGL/eglext.h>
89 QXcbConnection::QXcbConnection(const char *displayName)
90 : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
91 #ifdef XCB_USE_XINPUT2_MAEMO
97 , m_dri2_support_probed(false)
98 , m_has_support_for_dri2(false)
100 , xfixes_first_event(0)
105 Display *dpy = XOpenDisplay(m_displayName.constData());
106 m_primaryScreen = DefaultScreen(dpy);
107 m_connection = XGetXCBConnection(dpy);
108 XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
109 m_xlib_display = dpy;
111 EGLDisplay eglDisplay = eglGetDisplay(dpy);
112 m_egl_display = eglDisplay;
114 eglBindAPI(EGL_OPENGL_ES_API);
115 m_has_egl = eglInitialize(eglDisplay,&major,&minor);
118 m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen);
119 #endif //XCB_USE_XLIB
122 qDebug("Successfully connected to display %s", m_displayName.constData());
124 m_reader = new QXcbEventReader(this);
125 #ifdef XCB_POLL_FOR_QUEUED_EVENT
126 connect(m_reader, SIGNAL(eventPending()), this, SLOT(processXcbEvents()), Qt::QueuedConnection);
129 QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this);
130 connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents()));
132 QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
133 connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents()));
134 connect(dispatcher, SIGNAL(awake()), this, SLOT(processXcbEvents()));
137 xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
139 m_setup = xcb_get_setup(xcb_connection());
141 initializeAllAtoms();
143 m_time = XCB_CURRENT_TIME;
145 xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
147 int screenNumber = 0;
149 m_screens << new QXcbScreen(this, it.data, screenNumber++);
150 xcb_screen_next(&it);
153 m_connectionEventListener = xcb_generate_id(m_connection);
154 xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
155 m_connectionEventListener, m_screens.at(0)->root(),
156 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
157 m_screens.at(0)->screen()->root_visual, 0, 0);
161 #ifdef XCB_USE_XINPUT2_MAEMO
165 m_wmSupport.reset(new QXcbWMSupport(this));
166 m_keyboard = new QXcbKeyboard(this);
167 m_clipboard = new QXcbClipboard(this);
168 m_drag = new QXcbDrag(this);
176 QXcbConnection::~QXcbConnection()
180 qDeleteAll(m_screens);
182 #ifdef XCB_USE_XINPUT2_MAEMO
186 #ifdef XCB_POLL_FOR_QUEUED_EVENT
187 sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
193 XCloseDisplay((Display *)m_xlib_display);
195 xcb_disconnect(xcb_connection());
201 void QXcbConnection::addWindow(xcb_window_t id, QXcbWindow *window)
203 m_mapper.insert(id, window);
206 void QXcbConnection::removeWindow(xcb_window_t id)
211 QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
213 return m_mapper.value(id, 0);
216 #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
218 event_t *e = (event_t *)event; \
219 if (QXcbWindow *platformWindow = platformWindowFromId(e->windowMember)) \
220 platformWindow->handler(e); \
224 #define HANDLE_KEYBOARD_EVENT(event_t, handler) \
226 event_t *e = (event_t *)event; \
227 if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) \
228 m_keyboard->handler(platformWindow, e); \
232 //#define XCB_EVENT_DEBUG
234 void printXcbEvent(const char *message, xcb_generic_event_t *event)
236 #ifdef XCB_EVENT_DEBUG
237 #define PRINT_XCB_EVENT(ev) \
239 qDebug("%s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \
242 switch (event->response_type & ~0x80) {
243 PRINT_XCB_EVENT(XCB_KEY_PRESS);
244 PRINT_XCB_EVENT(XCB_KEY_RELEASE);
245 PRINT_XCB_EVENT(XCB_BUTTON_PRESS);
246 PRINT_XCB_EVENT(XCB_BUTTON_RELEASE);
247 PRINT_XCB_EVENT(XCB_MOTION_NOTIFY);
248 PRINT_XCB_EVENT(XCB_ENTER_NOTIFY);
249 PRINT_XCB_EVENT(XCB_LEAVE_NOTIFY);
250 PRINT_XCB_EVENT(XCB_FOCUS_IN);
251 PRINT_XCB_EVENT(XCB_FOCUS_OUT);
252 PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY);
253 PRINT_XCB_EVENT(XCB_EXPOSE);
254 PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE);
255 PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY);
256 PRINT_XCB_EVENT(XCB_CREATE_NOTIFY);
257 PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY);
258 PRINT_XCB_EVENT(XCB_UNMAP_NOTIFY);
259 PRINT_XCB_EVENT(XCB_MAP_NOTIFY);
260 PRINT_XCB_EVENT(XCB_MAP_REQUEST);
261 PRINT_XCB_EVENT(XCB_REPARENT_NOTIFY);
262 PRINT_XCB_EVENT(XCB_CONFIGURE_NOTIFY);
263 PRINT_XCB_EVENT(XCB_CONFIGURE_REQUEST);
264 PRINT_XCB_EVENT(XCB_GRAVITY_NOTIFY);
265 PRINT_XCB_EVENT(XCB_RESIZE_REQUEST);
266 PRINT_XCB_EVENT(XCB_CIRCULATE_NOTIFY);
267 PRINT_XCB_EVENT(XCB_CIRCULATE_REQUEST);
268 PRINT_XCB_EVENT(XCB_PROPERTY_NOTIFY);
269 PRINT_XCB_EVENT(XCB_SELECTION_CLEAR);
270 PRINT_XCB_EVENT(XCB_SELECTION_REQUEST);
271 PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY);
272 PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY);
273 PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
274 PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
276 qDebug("%s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
284 const char *xcb_errors[] =
307 const char *xcb_protocol_request_codes[] =
311 "ChangeWindowAttributes",
312 "GetWindowAttributes",
339 "ChangeActivePointerGrab",
389 "CopyColormapAndFree",
392 "ListInstalledColormaps",
409 "ChangeKeyboardMapping",
410 "GetKeyboardMapping",
411 "ChangeKeyboardControl",
412 "GetKeyboardControl",
414 "ChangePointerControl",
427 "SetModifierMapping",
428 "GetModifierMapping",
433 void QXcbConnection::log(const char *file, int line, int sequence)
435 QMutexLocker locker(&m_callLogMutex);
437 info.sequence = sequence;
444 void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
446 uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
447 uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
449 qDebug("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
450 int(error->error_code), xcb_errors[clamped_error_code],
451 int(error->sequence), int(error->resource_id),
452 int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
453 int(error->minor_code));
455 QMutexLocker locker(&m_callLogMutex);
457 for (; i < m_callLog.size(); ++i) {
458 if (m_callLog.at(i).sequence == error->sequence) {
459 qDebug("Caused by: %s:%d", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
461 } else if (m_callLog.at(i).sequence > error->sequence) {
462 qDebug("Caused some time before: %s:%d", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
464 qDebug("and after: %s:%d", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line);
468 if (i == m_callLog.size() && !m_callLog.isEmpty())
469 qDebug("Caused some time after: %s:%d", qPrintable(m_callLog.first().file), m_callLog.first().line);
473 void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
477 QMutexLocker locker(&m_callLogMutex);
479 for (; i < m_callLog.size(); ++i)
480 if (m_callLog.at(i).sequence >= event->sequence)
482 m_callLog.remove(0, i);
487 uint response_type = event->response_type & ~0x80;
489 switch (response_type) {
491 HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
492 case XCB_BUTTON_PRESS:
493 HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
494 case XCB_BUTTON_RELEASE:
495 HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
496 case XCB_MOTION_NOTIFY:
497 HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
498 case XCB_CONFIGURE_NOTIFY:
499 HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
501 HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
502 case XCB_UNMAP_NOTIFY:
503 HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
504 case XCB_CLIENT_MESSAGE:
505 handleClientMessageEvent((xcb_client_message_event_t *)event);
506 case XCB_ENTER_NOTIFY:
507 HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
508 case XCB_LEAVE_NOTIFY:
509 HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
511 HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
513 HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
515 HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
516 case XCB_KEY_RELEASE:
517 HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
518 case XCB_MAPPING_NOTIFY:
519 m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
521 case XCB_SELECTION_REQUEST:
523 xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
524 if (sr->selection == atom(QXcbAtom::XdndSelection))
525 m_drag->handleSelectionRequest(sr);
527 m_clipboard->handleSelectionRequest(sr);
530 case XCB_SELECTION_CLEAR:
531 setTime(((xcb_selection_clear_event_t *)event)->time);
532 m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event);
535 case XCB_SELECTION_NOTIFY:
536 setTime(((xcb_selection_notify_event_t *)event)->time);
537 qDebug() << "XCB_SELECTION_NOTIFY";
540 case XCB_PROPERTY_NOTIFY:
541 HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
543 #ifdef XCB_USE_XINPUT2_MAEMO
545 handleGenericEvent((xcb_ge_event_t*)event);
554 if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
555 setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp);
556 m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
563 // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any.
564 // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events.
565 Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent((Display*)m_xlib_display, response_type, 0);
567 XESetWireToEvent((Display*)m_xlib_display, response_type, proc);
569 event->sequence = LastKnownRequestProcessed(m_xlib_display);
570 proc((Display*)m_xlib_display, &dummy, (xEvent*)event);
576 printXcbEvent("Handled XCB event", event);
578 printXcbEvent("Unhandled XCB event", event);
581 void QXcbConnection::addPeekFunc(PeekFunc f)
583 m_peekFuncs.append(f);
586 #ifdef XCB_POLL_FOR_QUEUED_EVENT
587 void QXcbEventReader::run()
589 xcb_generic_event_t *event;
590 while (m_connection && (event = xcb_wait_for_event(m_connection->xcb_connection()))) {
593 while (m_connection && (event = xcb_poll_for_queued_event(m_connection->xcb_connection())))
599 for (int i = 0; i < m_events.size(); ++i)
600 free(m_events.at(i));
604 void QXcbEventReader::addEvent(xcb_generic_event_t *event)
606 if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE
607 && ((xcb_client_message_event_t *)event)->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
612 QList<xcb_generic_event_t *> *QXcbEventReader::lock()
615 #ifndef XCB_POLL_FOR_QUEUED_EVENT
616 while (xcb_generic_event_t *event = xcb_poll_for_event(m_connection->xcb_connection()))
622 void QXcbEventReader::unlock()
627 void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
629 xcb_client_message_event_t event;
630 memset(&event, 0, sizeof(event));
632 event.response_type = XCB_CLIENT_MESSAGE;
635 event.window = m_connectionEventListener;
636 event.type = atom(a);
637 event.data.data32[0] = id;
639 Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
640 xcb_flush(xcb_connection());
643 void QXcbConnection::processXcbEvents()
645 QList<xcb_generic_event_t *> *eventqueue = m_reader->lock();
647 for(int i = 0; i < eventqueue->size(); ++i) {
648 xcb_generic_event_t *event = eventqueue->at(i);
651 (*eventqueue)[i] = 0;
653 uint response_type = event->response_type & ~0x80;
655 if (!response_type) {
656 handleXcbError((xcb_generic_error_t *)event);
658 QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
659 while (it != m_peekFuncs.end()) {
660 // These callbacks return true if the event is what they were
661 // waiting for, remove them from the list in that case.
663 it = m_peekFuncs.erase(it);
668 handleXcbEvent(event);
679 // Indicate with a null event that the event the callbacks are waiting for
680 // is not in the queue currently.
681 Q_FOREACH (PeekFunc f, m_peekFuncs)
685 xcb_flush(xcb_connection());
688 void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event)
690 if (event->format != 32)
693 if (event->type == atom(QXcbAtom::XdndStatus)) {
694 drag()->handleStatus(event, false);
695 } else if (event->type == atom(QXcbAtom::XdndFinished)) {
696 drag()->handleFinished(event, false);
699 QXcbWindow *window = platformWindowFromId(event->window);
703 window->handleClientMessageEvent(event);
706 xcb_generic_event_t *QXcbConnection::checkEvent(int type)
708 QList<xcb_generic_event_t *> *eventqueue = m_reader->lock();
710 for (int i = 0; i < eventqueue->size(); ++i) {
711 xcb_generic_event_t *event = eventqueue->at(i);
712 if (event && event->response_type == type) {
713 (*eventqueue)[i] = 0;
724 static const char * xcb_atomnames = {
725 // window-manager <-> client protocols
730 "_NET_WM_CONTEXT_HELP\0"
731 "_NET_WM_SYNC_REQUEST\0"
732 "_NET_WM_SYNC_REQUEST_COUNTER\0"
734 // ICCCM window state
738 // Session management
752 "_QT_CLIPBOARD_SENTINEL\0"
753 "_QT_SELECTION_SENTINEL\0"
754 "CLIPBOARD_MANAGER\0"
761 "_QT_INPUT_ENCODING\0"
763 "_QT_CLOSE_CONNECTION\0"
768 "ENLIGHTENMENT_DESKTOP\0"
770 "_SGI_DESKS_MANAGER\0"
774 "_NET_VIRTUAL_ROOTS\0"
777 "_NET_MOVERESIZE_WINDOW\0"
778 "_NET_WM_MOVERESIZE\0"
781 "_NET_WM_ICON_NAME\0"
786 "_NET_WM_WINDOW_OPACITY\0"
789 "_NET_WM_STATE_ABOVE\0"
790 "_NET_WM_STATE_BELOW\0"
791 "_NET_WM_STATE_FULLSCREEN\0"
792 "_NET_WM_STATE_MAXIMIZED_HORZ\0"
793 "_NET_WM_STATE_MAXIMIZED_VERT\0"
794 "_NET_WM_STATE_MODAL\0"
795 "_NET_WM_STATE_STAYS_ON_TOP\0"
796 "_NET_WM_STATE_DEMANDS_ATTENTION\0"
798 "_NET_WM_USER_TIME\0"
799 "_NET_WM_USER_TIME_WINDOW\0"
800 "_NET_WM_FULL_PLACEMENT\0"
802 "_NET_WM_WINDOW_TYPE\0"
803 "_NET_WM_WINDOW_TYPE_DESKTOP\0"
804 "_NET_WM_WINDOW_TYPE_DOCK\0"
805 "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
806 "_NET_WM_WINDOW_TYPE_MENU\0"
807 "_NET_WM_WINDOW_TYPE_UTILITY\0"
808 "_NET_WM_WINDOW_TYPE_SPLASH\0"
809 "_NET_WM_WINDOW_TYPE_DIALOG\0"
810 "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
811 "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
812 "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
813 "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
814 "_NET_WM_WINDOW_TYPE_COMBO\0"
815 "_NET_WM_WINDOW_TYPE_DND\0"
816 "_NET_WM_WINDOW_TYPE_NORMAL\0"
817 "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
819 "_KDE_NET_WM_FRAME_STRUT\0"
821 "_NET_STARTUP_INFO\0"
822 "_NET_STARTUP_INFO_BEGIN\0"
824 "_NET_SUPPORTING_WM_CHECK\0"
828 "_NET_SYSTEM_TRAY_VISUAL\0"
830 "_NET_ACTIVE_WINDOW\0"
854 "XdndActionPrivate\0"
857 "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
858 "_MOTIF_DRAG_INITIATOR_INFO\0"
859 "_MOTIF_DRAG_RECEIVER_INFO\0"
860 "_MOTIF_DRAG_WINDOW\0"
861 "_MOTIF_DRAG_TARGETS\0"
863 "XmTRANSFER_SUCCESS\0"
864 "XmTRANSFER_FAILURE\0"
873 // Wacom old. (before version 0.10)
887 "Button Wheel Down\0"
888 "Button Horiz Wheel Left\0"
889 "Button Horiz Wheel Right\0"
890 "Abs MT Position X\0"
891 "Abs MT Position Y\0"
892 "Abs MT Touch Major\0"
893 "Abs MT Touch Minor\0"
895 "Abs MT Tracking ID\0"
899 xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
901 return m_allAtoms[atom];
904 void QXcbConnection::initializeAllAtoms() {
905 const char *names[QXcbAtom::NAtoms];
906 const char *ptr = xcb_atomnames;
916 Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);
918 QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
919 settings_atom_name += m_displayName;
920 names[i++] = settings_atom_name;
922 xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
924 Q_ASSERT(i == QXcbAtom::NAtoms);
925 for (i = 0; i < QXcbAtom::NAtoms; ++i)
926 cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
928 for (i = 0; i < QXcbAtom::NAtoms; ++i) {
929 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
930 m_allAtoms[i] = reply->atom;
935 xcb_atom_t QXcbConnection::internAtom(const char *name)
937 if (!name || *name == 0)
940 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
941 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
942 int atom = reply->atom;
947 QByteArray QXcbConnection::atomName(xcb_atom_t atom)
952 xcb_generic_error_t *error = 0;
953 xcb_get_atom_name_cookie_t cookie = Q_XCB_CALL(xcb_get_atom_name(xcb_connection(), atom));
954 xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, &error);
956 qWarning() << "QXcbConnection::atomName: bad Atom" << atom;
959 QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
966 const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
968 xcb_format_iterator_t iterator =
969 xcb_setup_pixmap_formats_iterator(m_setup);
971 while (iterator.rem) {
972 xcb_format_t *format = iterator.data;
973 if (format->depth == depth)
975 xcb_format_next(&iterator);
981 void QXcbConnection::sync()
984 xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
985 free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
988 void QXcbConnection::initializeXFixes()
990 xcb_generic_error_t *error = 0;
991 const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
992 xfixes_first_event = reply->first_event;
994 xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
995 XCB_XFIXES_MAJOR_VERSION,
996 XCB_XFIXES_MINOR_VERSION);
997 xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
998 xfixes_query_cookie, &error);
999 if (!xfixes_query || error || xfixes_query->major_version < 2) {
1000 qWarning("Failed to initialize XFixes");
1002 xfixes_first_event = 0;
1008 void QXcbConnection::initializeXRender()
1010 #ifdef XCB_USE_RENDER
1011 xcb_generic_error_t *error = 0;
1012 xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection,
1013 XCB_RENDER_MAJOR_VERSION,
1014 XCB_RENDER_MINOR_VERSION);
1015 xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
1016 xrender_query_cookie, &error);
1017 if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
1018 qWarning("Failed to initialize XRender");
1021 free(xrender_query);
1025 #if defined(XCB_USE_EGL)
1026 bool QXcbConnection::hasEgl() const
1030 #endif // defined(XCB_USE_EGL)
1033 void QXcbConnection::initializeDri2()
1035 xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection,
1036 m_screens[0]->root(),
1037 XCB_DRI2_DRIVER_TYPE_DRI);
1039 xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection,
1040 connect_cookie, NULL);
1042 if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
1043 qDebug() << "Failed to connect to dri2";
1047 m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect),
1048 xcb_dri2_connect_device_name_length (connect));
1051 int fd = open(m_dri2_device_name.constData(), O_RDWR);
1053 qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
1054 m_dri2_device_name = QByteArray();
1059 if (drmGetMagic(fd, &magic)) {
1060 qDebug() << "Failed to get drmMagic";
1064 xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection,
1065 m_screens[0]->root(), magic);
1066 xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
1067 authenticate_cookie, NULL);
1068 if (authenticate == NULL || !authenticate->authenticated) {
1069 qWarning("DRI2: failed to authenticate");
1074 delete authenticate;
1076 EGLDisplay display = eglGetDRMDisplayMESA(fd);
1078 qWarning("failed to create display");
1082 m_egl_display = display;
1084 if (!eglInitialize(display, &major, &minor)) {
1085 qWarning("failed to initialize display");
1090 bool QXcbConnection::hasSupportForDri2() const
1092 if (!m_dri2_support_probed) {
1093 xcb_generic_error_t *error = 0;
1095 xcb_prefetch_extension_data (m_connection, &xcb_dri2_id);
1097 xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection,
1098 XCB_DRI2_MAJOR_VERSION,
1099 XCB_DRI2_MINOR_VERSION);
1101 xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection,
1102 dri2_query_cookie, &error);
1103 if (!dri2_query || error) {
1109 QXcbConnection *that = const_cast<QXcbConnection *>(this);
1110 that->m_dri2_major = dri2_query->major_version;
1111 that->m_dri2_minor = dri2_query->minor_version;
1113 that->m_has_support_for_dri2 = true;
1114 that->m_dri2_support_probed = true;
1116 return m_has_support_for_dri2;
1118 #endif //XCB_USE_DRI2