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