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>
68 #include <xcb/render.h>
71 #ifdef XCB_USE_EGL //dont pull in eglext prototypes
80 #define MESA_EGL_NO_X11_HEADERS
81 #define EGL_EGLEXT_PROTOTYPES
83 #include <EGL/eglext.h>
86 QXcbConnection::QXcbConnection(const char *displayName)
87 : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
91 , m_dri2_support_probed(false)
92 , m_has_support_for_dri2(false)
94 , xfixes_first_event(0)
99 Display *dpy = XOpenDisplay(m_displayName.constData());
100 m_primaryScreen = DefaultScreen(dpy);
101 m_connection = XGetXCBConnection(dpy);
102 XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
103 m_xlib_display = dpy;
105 EGLDisplay eglDisplay = eglGetDisplay(dpy);
106 m_egl_display = eglDisplay;
108 eglBindAPI(EGL_OPENGL_ES_API);
109 m_has_egl = eglInitialize(eglDisplay,&major,&minor);
112 m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen);
113 #endif //XCB_USE_XLIB
116 printf("Successfully connected to display %s\n", m_displayName.constData());
118 m_reader = new QXcbEventReader(m_connection);
119 #ifdef XCB_POLL_FOR_QUEUED_EVENT
120 connect(m_reader, SIGNAL(eventPending()), this, SLOT(processXcbEvents()), Qt::QueuedConnection);
123 QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this);
124 connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents()));
126 QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
127 connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents()));
128 connect(dispatcher, SIGNAL(awake()), this, SLOT(processXcbEvents()));
131 xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
133 m_setup = xcb_get_setup(xcb_connection());
135 initializeAllAtoms();
137 m_time = XCB_CURRENT_TIME;
139 xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
141 int screenNumber = 0;
143 m_screens << new QXcbScreen(this, it.data, screenNumber++);
144 xcb_screen_next(&it);
147 m_connectionEventListener = xcb_generate_id(m_connection);
148 xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
149 m_connectionEventListener, m_screens.at(0)->root(),
150 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
151 m_screens.at(0)->screen()->root_visual, 0, 0);
156 m_wmSupport = new QXcbWMSupport(this);
157 m_keyboard = new QXcbKeyboard(this);
158 m_clipboard = new QXcbClipboard(this);
159 m_drag = new QXcbDrag(this);
167 QXcbConnection::~QXcbConnection()
171 qDeleteAll(m_screens);
173 #ifdef XCB_POLL_FOR_QUEUED_EVENT
174 sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
180 XCloseDisplay((Display *)m_xlib_display);
182 xcb_disconnect(xcb_connection());
188 void QXcbConnection::addWindow(xcb_window_t id, QXcbWindow *window)
190 m_mapper.insert(id, window);
193 void QXcbConnection::removeWindow(xcb_window_t id)
198 QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
200 return m_mapper.value(id, 0);
203 #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
205 event_t *e = (event_t *)event; \
206 if (QXcbWindow *platformWindow = platformWindowFromId(e->windowMember)) \
207 platformWindow->handler(e); \
211 #define HANDLE_KEYBOARD_EVENT(event_t, handler) \
213 event_t *e = (event_t *)event; \
214 if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) \
215 m_keyboard->handler(platformWindow, e); \
219 //#define XCB_EVENT_DEBUG
221 void printXcbEvent(const char *message, xcb_generic_event_t *event)
223 #ifdef XCB_EVENT_DEBUG
224 #define PRINT_XCB_EVENT(ev) \
226 printf("%s: %d - %s - sequence: %d\n", message, int(ev), #ev, event->sequence); \
229 switch (event->response_type & ~0x80) {
230 PRINT_XCB_EVENT(XCB_KEY_PRESS);
231 PRINT_XCB_EVENT(XCB_KEY_RELEASE);
232 PRINT_XCB_EVENT(XCB_BUTTON_PRESS);
233 PRINT_XCB_EVENT(XCB_BUTTON_RELEASE);
234 PRINT_XCB_EVENT(XCB_MOTION_NOTIFY);
235 PRINT_XCB_EVENT(XCB_ENTER_NOTIFY);
236 PRINT_XCB_EVENT(XCB_LEAVE_NOTIFY);
237 PRINT_XCB_EVENT(XCB_FOCUS_IN);
238 PRINT_XCB_EVENT(XCB_FOCUS_OUT);
239 PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY);
240 PRINT_XCB_EVENT(XCB_EXPOSE);
241 PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE);
242 PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY);
243 PRINT_XCB_EVENT(XCB_CREATE_NOTIFY);
244 PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY);
245 PRINT_XCB_EVENT(XCB_UNMAP_NOTIFY);
246 PRINT_XCB_EVENT(XCB_MAP_NOTIFY);
247 PRINT_XCB_EVENT(XCB_MAP_REQUEST);
248 PRINT_XCB_EVENT(XCB_REPARENT_NOTIFY);
249 PRINT_XCB_EVENT(XCB_CONFIGURE_NOTIFY);
250 PRINT_XCB_EVENT(XCB_CONFIGURE_REQUEST);
251 PRINT_XCB_EVENT(XCB_GRAVITY_NOTIFY);
252 PRINT_XCB_EVENT(XCB_RESIZE_REQUEST);
253 PRINT_XCB_EVENT(XCB_CIRCULATE_NOTIFY);
254 PRINT_XCB_EVENT(XCB_CIRCULATE_REQUEST);
255 PRINT_XCB_EVENT(XCB_PROPERTY_NOTIFY);
256 PRINT_XCB_EVENT(XCB_SELECTION_CLEAR);
257 PRINT_XCB_EVENT(XCB_SELECTION_REQUEST);
258 PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY);
259 PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY);
260 PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
261 PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
263 printf("%s: unknown event - response_type: %d - sequence: %d\n", message, int(event->response_type & ~0x80), int(event->sequence));
271 const char *xcb_errors[] =
294 const char *xcb_protocol_request_codes[] =
298 "ChangeWindowAttributes",
299 "GetWindowAttributes",
326 "ChangeActivePointerGrab",
376 "CopyColormapAndFree",
379 "ListInstalledColormaps",
396 "ChangeKeyboardMapping",
397 "GetKeyboardMapping",
398 "ChangeKeyboardControl",
399 "GetKeyboardControl",
401 "ChangePointerControl",
414 "SetModifierMapping",
415 "GetModifierMapping",
420 void QXcbConnection::log(const char *file, int line, int sequence)
423 info.sequence = sequence;
430 void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
432 uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
433 uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
435 printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n",
436 int(error->error_code), xcb_errors[clamped_error_code],
437 int(error->sequence), int(error->resource_id),
438 int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
439 int(error->minor_code));
442 for (; i < m_callLog.size(); ++i) {
443 if (m_callLog.at(i).sequence == error->sequence) {
444 printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
446 } else if (m_callLog.at(i).sequence > error->sequence) {
447 printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
449 printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line);
453 if (i == m_callLog.size() && !m_callLog.isEmpty())
454 printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line);
458 void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
463 for (; i < m_callLog.size(); ++i)
464 if (m_callLog.at(i).sequence >= event->sequence)
466 m_callLog.remove(0, i);
471 uint response_type = event->response_type & ~0x80;
473 switch (response_type) {
475 HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
476 case XCB_BUTTON_PRESS:
477 HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
478 case XCB_BUTTON_RELEASE:
479 HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
480 case XCB_MOTION_NOTIFY:
481 HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
482 case XCB_CONFIGURE_NOTIFY:
483 HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
485 HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
486 case XCB_UNMAP_NOTIFY:
487 HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
488 case XCB_CLIENT_MESSAGE:
489 handleClientMessageEvent((xcb_client_message_event_t *)event);
490 case XCB_ENTER_NOTIFY:
491 HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
492 case XCB_LEAVE_NOTIFY:
493 HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
495 HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
497 HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
499 HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
500 case XCB_KEY_RELEASE:
501 HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
502 case XCB_MAPPING_NOTIFY:
503 m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
505 case XCB_SELECTION_REQUEST:
507 xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
508 if (sr->selection == atom(QXcbAtom::XdndSelection))
509 m_drag->handleSelectionRequest(sr);
511 m_clipboard->handleSelectionRequest(sr);
514 case XCB_SELECTION_CLEAR:
515 setTime(((xcb_selection_clear_event_t *)event)->time);
516 m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event);
519 case XCB_SELECTION_NOTIFY:
520 setTime(((xcb_selection_notify_event_t *)event)->time);
521 qDebug() << "XCB_SELECTION_NOTIFY";
524 case XCB_PROPERTY_NOTIFY:
525 setTime(((xcb_property_notify_event_t *)event)->time);
526 // qDebug() << "XCB_PROPERTY_NOTIFY";
535 if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
536 setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp);
537 m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
543 printXcbEvent("Handled XCB event", event);
545 printXcbEvent("Unhandled XCB event", event);
548 void QXcbConnection::addPeekFunc(PeekFunc f)
550 m_peekFuncs.append(f);
553 #ifdef XCB_POLL_FOR_QUEUED_EVENT
554 void QXcbEventReader::run()
556 xcb_generic_event_t *event;
557 while (m_connection && (event = xcb_wait_for_event(m_connection))) {
560 while (m_connection && (event = xcb_poll_for_queued_event(m_connection)))
566 for (int i = 0; i < m_events.size(); ++i)
567 free(m_events.at(i));
571 void QXcbEventReader::addEvent(xcb_generic_event_t *event)
573 if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE
574 && ((xcb_client_message_event_t *)event)->type == QXcbAtom::_QT_CLOSE_CONNECTION)
579 QList<xcb_generic_event_t *> *QXcbEventReader::lock()
582 #ifndef XCB_POLL_FOR_QUEUED_EVENT
583 while (xcb_generic_event_t *event = xcb_poll_for_event(m_connection))
589 void QXcbEventReader::unlock()
594 void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom atom, uint id)
596 xcb_client_message_event_t event;
597 memset(&event, 0, sizeof(event));
599 event.response_type = XCB_CLIENT_MESSAGE;
602 event.window = m_connectionEventListener;
604 event.data.data32[0] = id;
606 Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
607 xcb_flush(xcb_connection());
610 void QXcbConnection::processXcbEvents()
612 QList<xcb_generic_event_t *> *eventqueue = m_reader->lock();
614 for(int i = 0; i < eventqueue->size(); ++i) {
615 xcb_generic_event_t *event = eventqueue->at(i);
618 (*eventqueue)[i] = 0;
620 uint response_type = event->response_type & ~0x80;
622 if (!response_type) {
623 handleXcbError((xcb_generic_error_t *)event);
625 QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
626 while (it != m_peekFuncs.end()) {
627 // These callbacks return true if the event is what they were
628 // waiting for, remove them from the list in that case.
630 it = m_peekFuncs.erase(it);
634 handleXcbEvent(event);
644 // Indicate with a null event that the event the callbacks are waiting for
645 // is not in the queue currently.
646 Q_FOREACH (PeekFunc f, m_peekFuncs)
650 xcb_flush(xcb_connection());
653 void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event)
655 if (event->format != 32)
658 if (event->type == atom(QXcbAtom::XdndStatus)) {
659 drag()->handleStatus(event, false);
660 } else if (event->type == atom(QXcbAtom::XdndFinished)) {
661 drag()->handleFinished(event, false);
664 QXcbWindow *window = platformWindowFromId(event->window);
668 window->handleClientMessageEvent(event);
671 xcb_generic_event_t *QXcbConnection::checkEvent(int type)
673 QList<xcb_generic_event_t *> *eventqueue = m_reader->lock();
675 for (int i = 0; i < eventqueue->size(); ++i) {
676 xcb_generic_event_t *event = eventqueue->at(i);
677 if (event->response_type == type) {
678 (*eventqueue)[i] = 0;
689 static const char * xcb_atomnames = {
690 // window-manager <-> client protocols
695 "_NET_WM_CONTEXT_HELP\0"
696 "_NET_WM_SYNC_REQUEST\0"
697 "_NET_WM_SYNC_REQUEST_COUNTER\0"
699 // ICCCM window state
703 // Session management
717 "_QT_CLIPBOARD_SENTINEL\0"
718 "_QT_SELECTION_SENTINEL\0"
719 "CLIPBOARD_MANAGER\0"
726 "_QT_INPUT_ENCODING\0"
728 "_QT_CLOSE_CONNECTION\0"
733 "ENLIGHTENMENT_DESKTOP\0"
735 "_SGI_DESKS_MANAGER\0"
739 "_NET_VIRTUAL_ROOTS\0"
742 "_NET_MOVERESIZE_WINDOW\0"
743 "_NET_WM_MOVERESIZE\0"
746 "_NET_WM_ICON_NAME\0"
751 "_NET_WM_WINDOW_OPACITY\0"
754 "_NET_WM_STATE_ABOVE\0"
755 "_NET_WM_STATE_BELOW\0"
756 "_NET_WM_STATE_FULLSCREEN\0"
757 "_NET_WM_STATE_MAXIMIZED_HORZ\0"
758 "_NET_WM_STATE_MAXIMIZED_VERT\0"
759 "_NET_WM_STATE_MODAL\0"
760 "_NET_WM_STATE_STAYS_ON_TOP\0"
761 "_NET_WM_STATE_DEMANDS_ATTENTION\0"
763 "_NET_WM_USER_TIME\0"
764 "_NET_WM_USER_TIME_WINDOW\0"
765 "_NET_WM_FULL_PLACEMENT\0"
767 "_NET_WM_WINDOW_TYPE\0"
768 "_NET_WM_WINDOW_TYPE_DESKTOP\0"
769 "_NET_WM_WINDOW_TYPE_DOCK\0"
770 "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
771 "_NET_WM_WINDOW_TYPE_MENU\0"
772 "_NET_WM_WINDOW_TYPE_UTILITY\0"
773 "_NET_WM_WINDOW_TYPE_SPLASH\0"
774 "_NET_WM_WINDOW_TYPE_DIALOG\0"
775 "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
776 "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
777 "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
778 "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
779 "_NET_WM_WINDOW_TYPE_COMBO\0"
780 "_NET_WM_WINDOW_TYPE_DND\0"
781 "_NET_WM_WINDOW_TYPE_NORMAL\0"
782 "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
784 "_KDE_NET_WM_FRAME_STRUT\0"
786 "_NET_STARTUP_INFO\0"
787 "_NET_STARTUP_INFO_BEGIN\0"
789 "_NET_SUPPORTING_WM_CHECK\0"
793 "_NET_SYSTEM_TRAY_VISUAL\0"
795 "_NET_ACTIVE_WINDOW\0"
819 "XdndActionPrivate\0"
822 "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
823 "_MOTIF_DRAG_INITIATOR_INFO\0"
824 "_MOTIF_DRAG_RECEIVER_INFO\0"
825 "_MOTIF_DRAG_WINDOW\0"
826 "_MOTIF_DRAG_TARGETS\0"
828 "XmTRANSFER_SUCCESS\0"
829 "XmTRANSFER_FAILURE\0"
838 // Wacom old. (before version 0.10)
848 xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
850 return m_allAtoms[atom];
853 void QXcbConnection::initializeAllAtoms() {
854 const char *names[QXcbAtom::NAtoms];
855 const char *ptr = xcb_atomnames;
865 Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);
867 QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
868 settings_atom_name += m_displayName;
869 names[i++] = settings_atom_name;
871 xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
873 Q_ASSERT(i == QXcbAtom::NAtoms);
874 for (i = 0; i < QXcbAtom::NAtoms; ++i)
875 cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
877 for (i = 0; i < QXcbAtom::NAtoms; ++i) {
878 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
879 m_allAtoms[i] = reply->atom;
884 xcb_atom_t QXcbConnection::internAtom(const char *name)
886 if (!name || *name == 0)
889 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
890 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
891 int atom = reply->atom;
896 QByteArray QXcbConnection::atomName(xcb_atom_t atom)
901 xcb_generic_error_t *error = 0;
902 xcb_get_atom_name_cookie_t cookie = Q_XCB_CALL(xcb_get_atom_name(xcb_connection(), atom));
903 xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, &error);
905 qWarning() << "QXcbConnection::atomName: bad Atom" << atom;
908 QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
915 const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
917 xcb_format_iterator_t iterator =
918 xcb_setup_pixmap_formats_iterator(m_setup);
920 while (iterator.rem) {
921 xcb_format_t *format = iterator.data;
922 if (format->depth == depth)
924 xcb_format_next(&iterator);
930 void QXcbConnection::sync()
933 xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
934 free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
937 void QXcbConnection::initializeXFixes()
939 xcb_generic_error_t *error = 0;
940 const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
941 xfixes_first_event = reply->first_event;
943 xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
944 XCB_XFIXES_MAJOR_VERSION,
945 XCB_XFIXES_MINOR_VERSION);
946 xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
947 xfixes_query_cookie, &error);
948 if (!xfixes_query || error || xfixes_query->major_version < 2) {
949 qWarning("Failed to initialize XFixes");
951 xfixes_first_event = 0;
957 void QXcbConnection::initializeXRender()
959 #ifdef XCB_USE_RENDER
960 xcb_generic_error_t *error = 0;
961 xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection,
962 XCB_RENDER_MAJOR_VERSION,
963 XCB_RENDER_MINOR_VERSION);
964 xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
965 xrender_query_cookie, &error);
966 if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
967 qWarning("Failed to initialize XRender");
974 #if defined(XCB_USE_EGL)
975 bool QXcbConnection::hasEgl() const
979 #endif // defined(XCB_USE_EGL)
982 void QXcbConnection::initializeDri2()
984 xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection,
985 m_screens[0]->root(),
986 XCB_DRI2_DRIVER_TYPE_DRI);
988 xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection,
989 connect_cookie, NULL);
991 if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
992 qDebug() << "Failed to connect to dri2";
996 m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect),
997 xcb_dri2_connect_device_name_length (connect));
1000 int fd = open(m_dri2_device_name.constData(), O_RDWR);
1002 qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
1003 m_dri2_device_name = QByteArray();
1008 if (drmGetMagic(fd, &magic)) {
1009 qDebug() << "Failed to get drmMagic";
1013 xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection,
1014 m_screens[0]->root(), magic);
1015 xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
1016 authenticate_cookie, NULL);
1017 if (authenticate == NULL || !authenticate->authenticated) {
1018 fprintf(stderr, "DRI2: failed to authenticate\n");
1023 delete authenticate;
1025 EGLDisplay display = eglGetDRMDisplayMESA(fd);
1027 fprintf(stderr, "failed to create display\n");
1031 m_egl_display = display;
1033 if (!eglInitialize(display, &major, &minor)) {
1034 fprintf(stderr, "failed to initialize display\n");
1039 bool QXcbConnection::hasSupportForDri2() const
1041 if (!m_dri2_support_probed) {
1042 xcb_generic_error_t *error = 0;
1044 xcb_prefetch_extension_data (m_connection, &xcb_dri2_id);
1046 xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection,
1047 XCB_DRI2_MAJOR_VERSION,
1048 XCB_DRI2_MINOR_VERSION);
1050 xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection,
1051 dri2_query_cookie, &error);
1052 if (!dri2_query || error) {
1058 QXcbConnection *that = const_cast<QXcbConnection *>(this);
1059 that->m_dri2_major = dri2_query->major_version;
1060 that->m_dri2_minor = dri2_query->minor_version;
1062 that->m_has_support_for_dri2 = true;
1063 that->m_dri2_support_probed = true;
1065 return m_has_support_for_dri2;
1067 #endif //XCB_USE_DRI2