XCB plugin compile fix.
[profile/ivi/qtbase.git] / src / plugins / platforms / xcb / qxcbconnection.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the plugins of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qxcbconnection.h"
43 #include "qxcbkeyboard.h"
44 #include "qxcbscreen.h"
45 #include "qxcbwindow.h"
46
47 #include <QtAlgorithms>
48 #include <QSocketNotifier>
49 #include <QtGui/private/qguiapplication_p.h>
50 #include <QAbstractEventDispatcher>
51
52 #include <QtCore/QDebug>
53
54 #include <stdio.h>
55 #include <errno.h>
56
57 #ifdef XCB_USE_XLIB
58 #include <X11/Xlib.h>
59 #include <X11/Xlib-xcb.h>
60 #endif
61
62 #ifdef XCB_USE_EGL //dont pull in eglext prototypes
63 #include <EGL/egl.h>
64 #endif
65
66 #ifdef XCB_USE_DRI2
67 #include <xcb/dri2.h>
68 #include <xcb/xfixes.h>
69 extern "C" {
70 #include <xf86drm.h>
71 }
72 #define MESA_EGL_NO_X11_HEADERS
73 #define EGL_EGLEXT_PROTOTYPES
74 #include <EGL/egl.h>
75 #include <EGL/eglext.h>
76 #endif
77
78 QXcbConnection::QXcbConnection(const char *displayName)
79     : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
80 #ifdef XCB_USE_DRI2
81     , m_dri2_major(0)
82     , m_dri2_minor(0)
83     , m_dri2_support_probed(false)
84     , m_has_support_for_dri2(false)
85 #endif
86 {
87     int primaryScreen = 0;
88
89 #ifdef XCB_USE_XLIB
90     Display *dpy = XOpenDisplay(m_displayName.constData());
91     primaryScreen = DefaultScreen(dpy);
92     m_connection = XGetXCBConnection(dpy);
93     XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
94     m_xlib_display = dpy;
95 #ifdef XCB_USE_EGL
96     EGLDisplay eglDisplay = eglGetDisplay(dpy);
97     m_egl_display = eglDisplay;
98     EGLint major, minor;
99     eglBindAPI(EGL_OPENGL_ES_API);
100     m_has_egl = eglInitialize(eglDisplay,&major,&minor);
101 #endif //XCB_USE_EGL
102 #else
103     m_connection = xcb_connect(m_displayName.constData(), &primaryScreen);
104
105 #endif //XCB_USE_XLIB
106     m_setup = xcb_get_setup(xcb_connection());
107
108     initializeAllAtoms();
109
110     xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
111
112     int screenNumber = 0;
113     while (it.rem) {
114         m_screens << new QXcbScreen(this, it.data, screenNumber++);
115         xcb_screen_next(&it);
116     }
117
118     m_keyboard = new QXcbKeyboard(this);
119
120 #ifdef XCB_USE_DRI2
121     initializeDri2();
122 #endif
123
124     QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this);
125     connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents()));
126
127     QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(qApp->thread());
128     connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents()));
129
130     sync();
131 }
132
133 QXcbConnection::~QXcbConnection()
134 {
135     qDeleteAll(m_screens);
136
137 #ifdef XCB_USE_XLIB
138     XCloseDisplay((Display *)m_xlib_display);
139 #else
140     xcb_disconnect(xcb_connection());
141 #endif
142
143     delete m_keyboard;
144 }
145
146 void QXcbConnection::addWindow(xcb_window_t id, QXcbWindow *window)
147 {
148     m_mapper.insert(id, window);
149 }
150
151 void QXcbConnection::removeWindow(xcb_window_t id)
152 {
153     m_mapper.remove(id);
154 }
155
156 QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
157 {
158     return m_mapper.value(id, 0);
159 }
160
161 #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
162 { \
163     event_t *e = (event_t *)event; \
164     if (QXcbWindow *platformWindow = platformWindowFromId(e->windowMember)) \
165         platformWindow->handler(e); \
166 } \
167 break;
168
169 #define HANDLE_KEYBOARD_EVENT(event_t, handler) \
170 { \
171     event_t *e = (event_t *)event; \
172     if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) \
173         m_keyboard->handler(platformWindow->window(), e); \
174 } \
175 break;
176
177 //#define XCB_EVENT_DEBUG
178
179 void printXcbEvent(const char *message, xcb_generic_event_t *event)
180 {
181 #ifdef XCB_EVENT_DEBUG
182 #define PRINT_XCB_EVENT(ev) \
183     case ev: \
184         printf("%s: %d - %s - sequence: %d\n", message, int(ev), #ev, event->sequence); \
185         break;
186
187     switch (event->response_type & ~0x80) {
188     PRINT_XCB_EVENT(XCB_KEY_PRESS);
189     PRINT_XCB_EVENT(XCB_KEY_RELEASE);
190     PRINT_XCB_EVENT(XCB_BUTTON_PRESS);
191     PRINT_XCB_EVENT(XCB_BUTTON_RELEASE);
192     PRINT_XCB_EVENT(XCB_MOTION_NOTIFY);
193     PRINT_XCB_EVENT(XCB_ENTER_NOTIFY);
194     PRINT_XCB_EVENT(XCB_LEAVE_NOTIFY);
195     PRINT_XCB_EVENT(XCB_FOCUS_IN);
196     PRINT_XCB_EVENT(XCB_FOCUS_OUT);
197     PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY);
198     PRINT_XCB_EVENT(XCB_EXPOSE);
199     PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE);
200     PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY);
201     PRINT_XCB_EVENT(XCB_CREATE_NOTIFY);
202     PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY);
203     PRINT_XCB_EVENT(XCB_UNMAP_NOTIFY);
204     PRINT_XCB_EVENT(XCB_MAP_NOTIFY);
205     PRINT_XCB_EVENT(XCB_MAP_REQUEST);
206     PRINT_XCB_EVENT(XCB_REPARENT_NOTIFY);
207     PRINT_XCB_EVENT(XCB_CONFIGURE_NOTIFY);
208     PRINT_XCB_EVENT(XCB_CONFIGURE_REQUEST);
209     PRINT_XCB_EVENT(XCB_GRAVITY_NOTIFY);
210     PRINT_XCB_EVENT(XCB_RESIZE_REQUEST);
211     PRINT_XCB_EVENT(XCB_CIRCULATE_NOTIFY);
212     PRINT_XCB_EVENT(XCB_CIRCULATE_REQUEST);
213     PRINT_XCB_EVENT(XCB_PROPERTY_NOTIFY);
214     PRINT_XCB_EVENT(XCB_SELECTION_CLEAR);
215     PRINT_XCB_EVENT(XCB_SELECTION_REQUEST);
216     PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY);
217     PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY);
218     PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
219     PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
220     default:
221         printf("%s: unknown event - response_type: %d - sequence: %d\n", message, int(event->response_type & ~0x80), int(event->sequence));
222     }
223 #else
224     Q_UNUSED(message);
225     Q_UNUSED(event);
226 #endif
227 }
228
229 const char *xcb_errors[] =
230 {
231     "Success",
232     "BadRequest",
233     "BadValue",
234     "BadWindow",
235     "BadPixmap",
236     "BadAtom",
237     "BadCursor",
238     "BadFont",
239     "BadMatch",
240     "BadDrawable",
241     "BadAccess",
242     "BadAlloc",
243     "BadColor",
244     "BadGC",
245     "BadIDChoice",
246     "BadName",
247     "BadLength",
248     "BadImplementation",
249     "Unknown"
250 };
251
252 const char *xcb_protocol_request_codes[] =
253 {
254     "Null",
255     "CreateWindow",
256     "ChangeWindowAttributes",
257     "GetWindowAttributes",
258     "DestroyWindow",
259     "DestroySubwindows",
260     "ChangeSaveSet",
261     "ReparentWindow",
262     "MapWindow",
263     "MapSubwindows",
264     "UnmapWindow",
265     "UnmapSubwindows",
266     "ConfigureWindow",
267     "CirculateWindow",
268     "GetGeometry",
269     "QueryTree",
270     "InternAtom",
271     "GetAtomName",
272     "ChangeProperty",
273     "DeleteProperty",
274     "GetProperty",
275     "ListProperties",
276     "SetSelectionOwner",
277     "GetSelectionOwner",
278     "ConvertSelection",
279     "SendEvent",
280     "GrabPointer",
281     "UngrabPointer",
282     "GrabButton",
283     "UngrabButton",
284     "ChangeActivePointerGrab",
285     "GrabKeyboard",
286     "UngrabKeyboard",
287     "GrabKey",
288     "UngrabKey",
289     "AllowEvents",
290     "GrabServer",
291     "UngrabServer",
292     "QueryPointer",
293     "GetMotionEvents",
294     "TranslateCoords",
295     "WarpPointer",
296     "SetInputFocus",
297     "GetInputFocus",
298     "QueryKeymap",
299     "OpenFont",
300     "CloseFont",
301     "QueryFont",
302     "QueryTextExtents",
303     "ListFonts",
304     "ListFontsWithInfo",
305     "SetFontPath",
306     "GetFontPath",
307     "CreatePixmap",
308     "FreePixmap",
309     "CreateGC",
310     "ChangeGC",
311     "CopyGC",
312     "SetDashes",
313     "SetClipRectangles",
314     "FreeGC",
315     "ClearArea",
316     "CopyArea",
317     "CopyPlane",
318     "PolyPoint",
319     "PolyLine",
320     "PolySegment",
321     "PolyRectangle",
322     "PolyArc",
323     "FillPoly",
324     "PolyFillRectangle",
325     "PolyFillArc",
326     "PutImage",
327     "GetImage",
328     "PolyText8",
329     "PolyText16",
330     "ImageText8",
331     "ImageText16",
332     "CreateColormap",
333     "FreeColormap",
334     "CopyColormapAndFree",
335     "InstallColormap",
336     "UninstallColormap",
337     "ListInstalledColormaps",
338     "AllocColor",
339     "AllocNamedColor",
340     "AllocColorCells",
341     "AllocColorPlanes",
342     "FreeColors",
343     "StoreColors",
344     "StoreNamedColor",
345     "QueryColors",
346     "LookupColor",
347     "CreateCursor",
348     "CreateGlyphCursor",
349     "FreeCursor",
350     "RecolorCursor",
351     "QueryBestSize",
352     "QueryExtension",
353     "ListExtensions",
354     "ChangeKeyboardMapping",
355     "GetKeyboardMapping",
356     "ChangeKeyboardControl",
357     "GetKeyboardControl",
358     "Bell",
359     "ChangePointerControl",
360     "GetPointerControl",
361     "SetScreenSaver",
362     "GetScreenSaver",
363     "ChangeHosts",
364     "ListHosts",
365     "SetAccessControl",
366     "SetCloseDownMode",
367     "KillClient",
368     "RotateProperties",
369     "ForceScreenSaver",
370     "SetPointerMapping",
371     "GetPointerMapping",
372     "SetModifierMapping",
373     "GetModifierMapping",
374     "Unknown"
375 };
376
377 #ifdef Q_XCB_DEBUG
378 void QXcbConnection::log(const char *file, int line, int sequence)
379 {
380     CallInfo info;
381     info.sequence = sequence;
382     info.file = file;
383     info.line = line;
384     m_callLog << info;
385 }
386 #endif
387
388 void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
389 {
390     uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
391     uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
392
393     printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n",
394            int(error->error_code), xcb_errors[clamped_error_code],
395            int(error->sequence), int(error->resource_id),
396            int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
397            int(error->minor_code));
398 #ifdef Q_XCB_DEBUG
399     int i = 0;
400     for (; i < m_callLog.size(); ++i) {
401         if (m_callLog.at(i).sequence == error->sequence) {
402             printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
403             break;
404         } else if (m_callLog.at(i).sequence > error->sequence) {
405             printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
406             if (i > 0)
407                 printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line);
408             break;
409         }
410     }
411     if (i == m_callLog.size() && !m_callLog.isEmpty())
412         printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line);
413 #endif
414 }
415
416 void QXcbConnection::processXcbEvents()
417 {
418     while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) {
419         bool handled = true;
420
421         uint response_type = event->response_type & ~0x80;
422
423         if (!response_type) {
424             handleXcbError((xcb_generic_error_t *)event);
425             continue;
426         }
427
428 #ifdef Q_XCB_DEBUG
429         {
430             int i = 0;
431             for (; i < m_callLog.size(); ++i)
432                 if (m_callLog.at(i).sequence >= event->sequence)
433                     break;
434             m_callLog.remove(0, i);
435         }
436 #endif
437
438         switch (response_type) {
439         case XCB_EXPOSE:
440             HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
441         case XCB_BUTTON_PRESS:
442             HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
443         case XCB_BUTTON_RELEASE:
444             HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
445         case XCB_MOTION_NOTIFY:
446             HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
447         case XCB_CONFIGURE_NOTIFY:
448             HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
449         case XCB_CLIENT_MESSAGE:
450             HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
451         case XCB_ENTER_NOTIFY:
452             HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
453         case XCB_LEAVE_NOTIFY:
454             HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
455         case XCB_FOCUS_IN:
456             HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
457         case XCB_FOCUS_OUT:
458             HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
459         case XCB_KEY_PRESS:
460             HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
461         case XCB_KEY_RELEASE:
462             HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
463         case XCB_MAPPING_NOTIFY:
464             m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
465             break;
466         default:
467             handled = false;
468             break;
469         }
470         if (handled)
471             printXcbEvent("Handled XCB event", event);
472         else
473             printXcbEvent("Unhandled XCB event", event);
474     }
475
476     xcb_flush(xcb_connection());
477 }
478
479 static const char * xcb_atomnames = {
480     // window-manager <-> client protocols
481     "WM_PROTOCOLS\0"
482     "WM_DELETE_WINDOW\0"
483     "WM_TAKE_FOCUS\0"
484     "_NET_WM_PING\0"
485     "_NET_WM_CONTEXT_HELP\0"
486     "_NET_WM_SYNC_REQUEST\0"
487     "_NET_WM_SYNC_REQUEST_COUNTER\0"
488
489     // ICCCM window state
490     "WM_STATE\0"
491     "WM_CHANGE_STATE\0"
492
493     // Session management
494     "WM_CLIENT_LEADER\0"
495     "WM_WINDOW_ROLE\0"
496     "SM_CLIENT_ID\0"
497
498     // Clipboard
499     "CLIPBOARD\0"
500     "INCR\0"
501     "TARGETS\0"
502     "MULTIPLE\0"
503     "TIMESTAMP\0"
504     "SAVE_TARGETS\0"
505     "CLIP_TEMPORARY\0"
506     "_QT_SELECTION\0"
507     "_QT_CLIPBOARD_SENTINEL\0"
508     "_QT_SELECTION_SENTINEL\0"
509     "CLIPBOARD_MANAGER\0"
510
511     "RESOURCE_MANAGER\0"
512
513     "_XSETROOT_ID\0"
514
515     "_QT_SCROLL_DONE\0"
516     "_QT_INPUT_ENCODING\0"
517
518     "_MOTIF_WM_HINTS\0"
519
520     "DTWM_IS_RUNNING\0"
521     "ENLIGHTENMENT_DESKTOP\0"
522     "_DT_SAVE_MODE\0"
523     "_SGI_DESKS_MANAGER\0"
524
525     // EWMH (aka NETWM)
526     "_NET_SUPPORTED\0"
527     "_NET_VIRTUAL_ROOTS\0"
528     "_NET_WORKAREA\0"
529
530     "_NET_MOVERESIZE_WINDOW\0"
531     "_NET_WM_MOVERESIZE\0"
532
533     "_NET_WM_NAME\0"
534     "_NET_WM_ICON_NAME\0"
535     "_NET_WM_ICON\0"
536
537     "_NET_WM_PID\0"
538
539     "_NET_WM_WINDOW_OPACITY\0"
540
541     "_NET_WM_STATE\0"
542     "_NET_WM_STATE_ABOVE\0"
543     "_NET_WM_STATE_BELOW\0"
544     "_NET_WM_STATE_FULLSCREEN\0"
545     "_NET_WM_STATE_MAXIMIZED_HORZ\0"
546     "_NET_WM_STATE_MAXIMIZED_VERT\0"
547     "_NET_WM_STATE_MODAL\0"
548     "_NET_WM_STATE_STAYS_ON_TOP\0"
549     "_NET_WM_STATE_DEMANDS_ATTENTION\0"
550
551     "_NET_WM_USER_TIME\0"
552     "_NET_WM_USER_TIME_WINDOW\0"
553     "_NET_WM_FULL_PLACEMENT\0"
554
555     "_NET_WM_WINDOW_TYPE\0"
556     "_NET_WM_WINDOW_TYPE_DESKTOP\0"
557     "_NET_WM_WINDOW_TYPE_DOCK\0"
558     "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
559     "_NET_WM_WINDOW_TYPE_MENU\0"
560     "_NET_WM_WINDOW_TYPE_UTILITY\0"
561     "_NET_WM_WINDOW_TYPE_SPLASH\0"
562     "_NET_WM_WINDOW_TYPE_DIALOG\0"
563     "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
564     "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
565     "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
566     "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
567     "_NET_WM_WINDOW_TYPE_COMBO\0"
568     "_NET_WM_WINDOW_TYPE_DND\0"
569     "_NET_WM_WINDOW_TYPE_NORMAL\0"
570     "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
571
572     "_KDE_NET_WM_FRAME_STRUT\0"
573
574     "_NET_STARTUP_INFO\0"
575     "_NET_STARTUP_INFO_BEGIN\0"
576
577     "_NET_SUPPORTING_WM_CHECK\0"
578
579     "_NET_WM_CM_S0\0"
580
581     "_NET_SYSTEM_TRAY_VISUAL\0"
582
583     "_NET_ACTIVE_WINDOW\0"
584
585     // Property formats
586     "COMPOUND_TEXT\0"
587     "TEXT\0"
588     "UTF8_STRING\0"
589
590     // xdnd
591     "XdndEnter\0"
592     "XdndPosition\0"
593     "XdndStatus\0"
594     "XdndLeave\0"
595     "XdndDrop\0"
596     "XdndFinished\0"
597     "XdndTypeList\0"
598     "XdndActionList\0"
599
600     "XdndSelection\0"
601
602     "XdndAware\0"
603     "XdndProxy\0"
604
605     "XdndActionCopy\0"
606     "XdndActionLink\0"
607     "XdndActionMove\0"
608     "XdndActionPrivate\0"
609
610     // Motif DND
611     "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
612     "_MOTIF_DRAG_INITIATOR_INFO\0"
613     "_MOTIF_DRAG_RECEIVER_INFO\0"
614     "_MOTIF_DRAG_WINDOW\0"
615     "_MOTIF_DRAG_TARGETS\0"
616
617     "XmTRANSFER_SUCCESS\0"
618     "XmTRANSFER_FAILURE\0"
619
620     // Xkb
621     "_XKB_RULES_NAMES\0"
622
623     // XEMBED
624     "_XEMBED\0"
625     "_XEMBED_INFO\0"
626
627     // Wacom old. (before version 0.10)
628     "Wacom Stylus\0"
629     "Wacom Cursor\0"
630     "Wacom Eraser\0"
631
632     // Tablet
633     "STYLUS\0"
634     "ERASER\0"
635 };
636
637 xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
638 {
639     return m_allAtoms[atom];
640 }
641
642 void QXcbConnection::initializeAllAtoms() {
643     const char *names[QXcbAtom::NAtoms];
644     const char *ptr = xcb_atomnames;
645
646     int i = 0;
647     while (*ptr) {
648         names[i++] = ptr;
649         while (*ptr)
650             ++ptr;
651         ++ptr;
652     }
653
654     Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);
655
656     QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
657     settings_atom_name += m_displayName;
658     names[i++] = settings_atom_name;
659
660     xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
661
662     Q_ASSERT(i == QXcbAtom::NAtoms);
663     for (i = 0; i < QXcbAtom::NAtoms; ++i)
664         cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
665
666     for (i = 0; i < QXcbAtom::NAtoms; ++i)
667         m_allAtoms[i] = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0)->atom;
668 }
669
670 void QXcbConnection::sync()
671 {
672     // from xcb_aux_sync
673     xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
674     free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
675 }
676
677 #if defined(XCB_USE_EGL)
678 bool QXcbConnection::hasEgl() const
679 {
680     return m_has_egl;
681 }
682 #endif // defined(XCB_USE_EGL)
683
684 #ifdef XCB_USE_DRI2
685 void QXcbConnection::initializeDri2()
686 {
687     xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection,
688                                                                            m_screens[0]->root(),
689                                                                            XCB_DRI2_DRIVER_TYPE_DRI);
690
691     xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection,
692                                                                 connect_cookie, NULL);
693
694     if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
695         qDebug() << "Failed to connect to dri2";
696         return;
697     }
698
699     m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect),
700                                                     xcb_dri2_connect_device_name_length (connect));
701     delete connect;
702
703     int fd = open(m_dri2_device_name.constData(), O_RDWR);
704     if (fd < 0) {
705         qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
706         m_dri2_device_name = QByteArray();
707         return;
708     }
709
710     drm_magic_t magic;
711     if (drmGetMagic(fd, &magic)) {
712         qDebug() << "Failed to get drmMagic";
713         return;
714     }
715
716     xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection,
717                                                                                          m_screens[0]->root(), magic);
718     xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
719                                                                               authenticate_cookie, NULL);
720     if (authenticate == NULL || !authenticate->authenticated) {
721         fprintf(stderr, "DRI2: failed to authenticate\n");
722         free(authenticate);
723         return;
724     }
725
726     delete authenticate;
727
728     EGLDisplay display = eglGetDRMDisplayMESA(fd);
729     if (!display) {
730         fprintf(stderr, "failed to create display\n");
731         return;
732     }
733
734     m_egl_display = display;
735     EGLint major,minor;
736     if (!eglInitialize(display, &major, &minor)) {
737         fprintf(stderr, "failed to initialize display\n");
738         return;
739     }
740 }
741
742 bool QXcbConnection::hasSupportForDri2() const
743 {
744     if (!m_dri2_support_probed) {
745         xcb_generic_error_t *error = 0;
746
747         xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
748         xcb_prefetch_extension_data (m_connection, &xcb_dri2_id);
749
750         xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
751                                                                                          XCB_XFIXES_MAJOR_VERSION,
752                                                                                          XCB_XFIXES_MINOR_VERSION);
753
754         xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection,
755                                                                                     XCB_DRI2_MAJOR_VERSION,
756                                                                                     XCB_DRI2_MINOR_VERSION);
757
758         xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
759                                                                                          xfixes_query_cookie, &error);
760         if (!xfixes_query || error || xfixes_query->major_version < 2) {
761             delete error;
762             delete xfixes_query;
763             return false;
764         }
765         delete xfixes_query;
766
767         xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection,
768                                                                                    dri2_query_cookie, &error);
769         if (!dri2_query || error) {
770             delete error;
771             delete dri2_query;
772             return false;
773         }
774
775         QXcbConnection *that = const_cast<QXcbConnection *>(this);
776         that->m_dri2_major = dri2_query->major_version;
777         that->m_dri2_minor = dri2_query->minor_version;
778
779         that->m_has_support_for_dri2 = true;
780         that->m_dri2_support_probed = true;
781     }
782     return m_has_support_for_dri2;
783 }
784 #endif //XCB_USE_DRI2