partially working paste
[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_CLIENT_MESSAGE:
446         HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
447     case XCB_ENTER_NOTIFY:
448         HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
449     case XCB_LEAVE_NOTIFY:
450         HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
451     case XCB_FOCUS_IN:
452         HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
453     case XCB_FOCUS_OUT:
454         HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
455     case XCB_KEY_PRESS:
456         HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
457     case XCB_KEY_RELEASE:
458         HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
459     case XCB_MAPPING_NOTIFY:
460         m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
461         break;
462     case XCB_SELECTION_REQUEST:
463         m_clipboard->handleSelectionRequest((xcb_selection_request_event_t *)event);
464         break;
465     case XCB_SELECTION_CLEAR:
466         qDebug() << "XCB_SELECTION_CLEAR";
467         handled = false;
468         break;
469     case XCB_SELECTION_NOTIFY:
470         qDebug() << "XCB_SELECTION_NOTIFY";
471         handled = false;
472         break;
473     default:
474         handled = false;
475         break;
476     }
477     if (handled)
478         printXcbEvent("Handled XCB event", event);
479     else
480         printXcbEvent("Unhandled XCB event", event);
481 }
482
483 void QXcbConnection::processXcbEvents()
484 {
485     while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection()))
486         eventqueue.append(event);
487
488     for(int i = 0; i < eventqueue.size(); ++i) {
489         xcb_generic_event_t *event = eventqueue.at(i);
490         if (!event)
491             continue;
492
493         uint response_type = event->response_type & ~0x80;
494
495         if (!response_type) {
496             handleXcbError((xcb_generic_error_t *)event);
497         } else {
498             handleXcbEvent(event);
499         }
500
501         free(event);
502     }
503
504     eventqueue.clear();
505
506     xcb_flush(xcb_connection());
507 }
508
509 xcb_generic_event_t *QXcbConnection::checkEvent(int type)
510 {
511     while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection()))
512         eventqueue.append(event);
513
514     for (int i = 0; i < eventqueue.size(); ++i) {
515         xcb_generic_event_t *event = eventqueue.at(i);
516         if (event->response_type == type) {
517             eventqueue[i] = 0;
518             return event;
519         }
520     }
521     return 0;
522 }
523
524 static const char * xcb_atomnames = {
525     // window-manager <-> client protocols
526     "WM_PROTOCOLS\0"
527     "WM_DELETE_WINDOW\0"
528     "WM_TAKE_FOCUS\0"
529     "_NET_WM_PING\0"
530     "_NET_WM_CONTEXT_HELP\0"
531     "_NET_WM_SYNC_REQUEST\0"
532     "_NET_WM_SYNC_REQUEST_COUNTER\0"
533
534     // ICCCM window state
535     "WM_STATE\0"
536     "WM_CHANGE_STATE\0"
537
538     // Session management
539     "WM_CLIENT_LEADER\0"
540     "WM_WINDOW_ROLE\0"
541     "SM_CLIENT_ID\0"
542
543     // Clipboard
544     "CLIPBOARD\0"
545     "INCR\0"
546     "TARGETS\0"
547     "MULTIPLE\0"
548     "TIMESTAMP\0"
549     "SAVE_TARGETS\0"
550     "CLIP_TEMPORARY\0"
551     "_QT_SELECTION\0"
552     "_QT_CLIPBOARD_SENTINEL\0"
553     "_QT_SELECTION_SENTINEL\0"
554     "CLIPBOARD_MANAGER\0"
555
556     "RESOURCE_MANAGER\0"
557
558     "_XSETROOT_ID\0"
559
560     "_QT_SCROLL_DONE\0"
561     "_QT_INPUT_ENCODING\0"
562
563     "_MOTIF_WM_HINTS\0"
564
565     "DTWM_IS_RUNNING\0"
566     "ENLIGHTENMENT_DESKTOP\0"
567     "_DT_SAVE_MODE\0"
568     "_SGI_DESKS_MANAGER\0"
569
570     // EWMH (aka NETWM)
571     "_NET_SUPPORTED\0"
572     "_NET_VIRTUAL_ROOTS\0"
573     "_NET_WORKAREA\0"
574
575     "_NET_MOVERESIZE_WINDOW\0"
576     "_NET_WM_MOVERESIZE\0"
577
578     "_NET_WM_NAME\0"
579     "_NET_WM_ICON_NAME\0"
580     "_NET_WM_ICON\0"
581
582     "_NET_WM_PID\0"
583
584     "_NET_WM_WINDOW_OPACITY\0"
585
586     "_NET_WM_STATE\0"
587     "_NET_WM_STATE_ABOVE\0"
588     "_NET_WM_STATE_BELOW\0"
589     "_NET_WM_STATE_FULLSCREEN\0"
590     "_NET_WM_STATE_MAXIMIZED_HORZ\0"
591     "_NET_WM_STATE_MAXIMIZED_VERT\0"
592     "_NET_WM_STATE_MODAL\0"
593     "_NET_WM_STATE_STAYS_ON_TOP\0"
594     "_NET_WM_STATE_DEMANDS_ATTENTION\0"
595
596     "_NET_WM_USER_TIME\0"
597     "_NET_WM_USER_TIME_WINDOW\0"
598     "_NET_WM_FULL_PLACEMENT\0"
599
600     "_NET_WM_WINDOW_TYPE\0"
601     "_NET_WM_WINDOW_TYPE_DESKTOP\0"
602     "_NET_WM_WINDOW_TYPE_DOCK\0"
603     "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
604     "_NET_WM_WINDOW_TYPE_MENU\0"
605     "_NET_WM_WINDOW_TYPE_UTILITY\0"
606     "_NET_WM_WINDOW_TYPE_SPLASH\0"
607     "_NET_WM_WINDOW_TYPE_DIALOG\0"
608     "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
609     "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
610     "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
611     "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
612     "_NET_WM_WINDOW_TYPE_COMBO\0"
613     "_NET_WM_WINDOW_TYPE_DND\0"
614     "_NET_WM_WINDOW_TYPE_NORMAL\0"
615     "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
616
617     "_KDE_NET_WM_FRAME_STRUT\0"
618
619     "_NET_STARTUP_INFO\0"
620     "_NET_STARTUP_INFO_BEGIN\0"
621
622     "_NET_SUPPORTING_WM_CHECK\0"
623
624     "_NET_WM_CM_S0\0"
625
626     "_NET_SYSTEM_TRAY_VISUAL\0"
627
628     "_NET_ACTIVE_WINDOW\0"
629
630     // Property formats
631     "COMPOUND_TEXT\0"
632     "TEXT\0"
633     "UTF8_STRING\0"
634
635     // xdnd
636     "XdndEnter\0"
637     "XdndPosition\0"
638     "XdndStatus\0"
639     "XdndLeave\0"
640     "XdndDrop\0"
641     "XdndFinished\0"
642     "XdndTypeList\0"
643     "XdndActionList\0"
644
645     "XdndSelection\0"
646
647     "XdndAware\0"
648     "XdndProxy\0"
649
650     "XdndActionCopy\0"
651     "XdndActionLink\0"
652     "XdndActionMove\0"
653     "XdndActionPrivate\0"
654
655     // Motif DND
656     "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
657     "_MOTIF_DRAG_INITIATOR_INFO\0"
658     "_MOTIF_DRAG_RECEIVER_INFO\0"
659     "_MOTIF_DRAG_WINDOW\0"
660     "_MOTIF_DRAG_TARGETS\0"
661
662     "XmTRANSFER_SUCCESS\0"
663     "XmTRANSFER_FAILURE\0"
664
665     // Xkb
666     "_XKB_RULES_NAMES\0"
667
668     // XEMBED
669     "_XEMBED\0"
670     "_XEMBED_INFO\0"
671
672     // Wacom old. (before version 0.10)
673     "Wacom Stylus\0"
674     "Wacom Cursor\0"
675     "Wacom Eraser\0"
676
677     // Tablet
678     "STYLUS\0"
679     "ERASER\0"
680 };
681
682 xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
683 {
684     return m_allAtoms[atom];
685 }
686
687 void QXcbConnection::initializeAllAtoms() {
688     const char *names[QXcbAtom::NAtoms];
689     const char *ptr = xcb_atomnames;
690
691     int i = 0;
692     while (*ptr) {
693         names[i++] = ptr;
694         while (*ptr)
695             ++ptr;
696         ++ptr;
697     }
698
699     Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);
700
701     QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
702     settings_atom_name += m_displayName;
703     names[i++] = settings_atom_name;
704
705     xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
706
707     Q_ASSERT(i == QXcbAtom::NAtoms);
708     for (i = 0; i < QXcbAtom::NAtoms; ++i)
709         cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
710
711     for (i = 0; i < QXcbAtom::NAtoms; ++i) {
712         xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
713         m_allAtoms[i] = reply->atom;
714         free(reply);
715     }
716 }
717
718 xcb_atom_t QXcbConnection::internAtom(const char *name)
719 {
720     if (!name || *name == 0)
721         return XCB_NONE;
722
723     xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
724     xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
725     int atom = reply->atom;
726     free(reply);
727     return atom;
728 }
729
730 QByteArray QXcbConnection::atomName(xcb_atom_t atom)
731 {
732     xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name_unchecked(xcb_connection(), atom);
733     xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, 0);
734     QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
735     free(reply);
736     return result;
737 }
738
739 void QXcbConnection::sync()
740 {
741     // from xcb_aux_sync
742     xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
743     free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
744 }
745
746 #if defined(XCB_USE_EGL)
747 bool QXcbConnection::hasEgl() const
748 {
749     return m_has_egl;
750 }
751 #endif // defined(XCB_USE_EGL)
752
753 #ifdef XCB_USE_DRI2
754 void QXcbConnection::initializeDri2()
755 {
756     xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection,
757                                                                            m_screens[0]->root(),
758                                                                            XCB_DRI2_DRIVER_TYPE_DRI);
759
760     xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection,
761                                                                 connect_cookie, NULL);
762
763     if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
764         qDebug() << "Failed to connect to dri2";
765         return;
766     }
767
768     m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect),
769                                                     xcb_dri2_connect_device_name_length (connect));
770     delete connect;
771
772     int fd = open(m_dri2_device_name.constData(), O_RDWR);
773     if (fd < 0) {
774         qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
775         m_dri2_device_name = QByteArray();
776         return;
777     }
778
779     drm_magic_t magic;
780     if (drmGetMagic(fd, &magic)) {
781         qDebug() << "Failed to get drmMagic";
782         return;
783     }
784
785     xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection,
786                                                                                          m_screens[0]->root(), magic);
787     xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
788                                                                               authenticate_cookie, NULL);
789     if (authenticate == NULL || !authenticate->authenticated) {
790         fprintf(stderr, "DRI2: failed to authenticate\n");
791         free(authenticate);
792         return;
793     }
794
795     delete authenticate;
796
797     EGLDisplay display = eglGetDRMDisplayMESA(fd);
798     if (!display) {
799         fprintf(stderr, "failed to create display\n");
800         return;
801     }
802
803     m_egl_display = display;
804     EGLint major,minor;
805     if (!eglInitialize(display, &major, &minor)) {
806         fprintf(stderr, "failed to initialize display\n");
807         return;
808     }
809 }
810
811 bool QXcbConnection::hasSupportForDri2() const
812 {
813     if (!m_dri2_support_probed) {
814         xcb_generic_error_t *error = 0;
815
816         xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
817         xcb_prefetch_extension_data (m_connection, &xcb_dri2_id);
818
819         xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
820                                                                                          XCB_XFIXES_MAJOR_VERSION,
821                                                                                          XCB_XFIXES_MINOR_VERSION);
822
823         xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection,
824                                                                                     XCB_DRI2_MAJOR_VERSION,
825                                                                                     XCB_DRI2_MINOR_VERSION);
826
827         xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
828                                                                                          xfixes_query_cookie, &error);
829         if (!xfixes_query || error || xfixes_query->major_version < 2) {
830             delete error;
831             delete xfixes_query;
832             return false;
833         }
834         delete xfixes_query;
835
836         xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection,
837                                                                                    dri2_query_cookie, &error);
838         if (!dri2_query || error) {
839             delete error;
840             delete dri2_query;
841             return false;
842         }
843
844         QXcbConnection *that = const_cast<QXcbConnection *>(this);
845         that->m_dri2_major = dri2_query->major_version;
846         that->m_dri2_minor = dri2_query->minor_version;
847
848         that->m_has_support_for_dri2 = true;
849         that->m_dri2_support_probed = true;
850     }
851     return m_has_support_for_dri2;
852 }
853 #endif //XCB_USE_DRI2