Cleanup code for copy/paste of text
[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     "TEXT\0"
632     "UTF8_STRING\0"
633
634     // xdnd
635     "XdndEnter\0"
636     "XdndPosition\0"
637     "XdndStatus\0"
638     "XdndLeave\0"
639     "XdndDrop\0"
640     "XdndFinished\0"
641     "XdndTypeList\0"
642     "XdndActionList\0"
643
644     "XdndSelection\0"
645
646     "XdndAware\0"
647     "XdndProxy\0"
648
649     "XdndActionCopy\0"
650     "XdndActionLink\0"
651     "XdndActionMove\0"
652     "XdndActionPrivate\0"
653
654     // Motif DND
655     "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
656     "_MOTIF_DRAG_INITIATOR_INFO\0"
657     "_MOTIF_DRAG_RECEIVER_INFO\0"
658     "_MOTIF_DRAG_WINDOW\0"
659     "_MOTIF_DRAG_TARGETS\0"
660
661     "XmTRANSFER_SUCCESS\0"
662     "XmTRANSFER_FAILURE\0"
663
664     // Xkb
665     "_XKB_RULES_NAMES\0"
666
667     // XEMBED
668     "_XEMBED\0"
669     "_XEMBED_INFO\0"
670
671     // Wacom old. (before version 0.10)
672     "Wacom Stylus\0"
673     "Wacom Cursor\0"
674     "Wacom Eraser\0"
675
676     // Tablet
677     "STYLUS\0"
678     "ERASER\0"
679 };
680
681 xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
682 {
683     return m_allAtoms[atom];
684 }
685
686 void QXcbConnection::initializeAllAtoms() {
687     const char *names[QXcbAtom::NAtoms];
688     const char *ptr = xcb_atomnames;
689
690     int i = 0;
691     while (*ptr) {
692         names[i++] = ptr;
693         while (*ptr)
694             ++ptr;
695         ++ptr;
696     }
697
698     Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);
699
700     QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
701     settings_atom_name += m_displayName;
702     names[i++] = settings_atom_name;
703
704     xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
705
706     Q_ASSERT(i == QXcbAtom::NAtoms);
707     for (i = 0; i < QXcbAtom::NAtoms; ++i)
708         cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
709
710     for (i = 0; i < QXcbAtom::NAtoms; ++i) {
711         xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
712         m_allAtoms[i] = reply->atom;
713         free(reply);
714     }
715 }
716
717 xcb_atom_t QXcbConnection::internAtom(const char *name)
718 {
719     if (!name || *name == 0)
720         return XCB_NONE;
721
722     xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
723     xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
724     int atom = reply->atom;
725     free(reply);
726     return atom;
727 }
728
729 QByteArray QXcbConnection::atomName(xcb_atom_t atom)
730 {
731     xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name_unchecked(xcb_connection(), atom);
732     xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, 0);
733     QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
734     free(reply);
735     return result;
736 }
737
738 void QXcbConnection::sync()
739 {
740     // from xcb_aux_sync
741     xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
742     free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
743 }
744
745 #if defined(XCB_USE_EGL)
746 bool QXcbConnection::hasEgl() const
747 {
748     return m_has_egl;
749 }
750 #endif // defined(XCB_USE_EGL)
751
752 #ifdef XCB_USE_DRI2
753 void QXcbConnection::initializeDri2()
754 {
755     xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection,
756                                                                            m_screens[0]->root(),
757                                                                            XCB_DRI2_DRIVER_TYPE_DRI);
758
759     xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection,
760                                                                 connect_cookie, NULL);
761
762     if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
763         qDebug() << "Failed to connect to dri2";
764         return;
765     }
766
767     m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect),
768                                                     xcb_dri2_connect_device_name_length (connect));
769     delete connect;
770
771     int fd = open(m_dri2_device_name.constData(), O_RDWR);
772     if (fd < 0) {
773         qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
774         m_dri2_device_name = QByteArray();
775         return;
776     }
777
778     drm_magic_t magic;
779     if (drmGetMagic(fd, &magic)) {
780         qDebug() << "Failed to get drmMagic";
781         return;
782     }
783
784     xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection,
785                                                                                          m_screens[0]->root(), magic);
786     xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
787                                                                               authenticate_cookie, NULL);
788     if (authenticate == NULL || !authenticate->authenticated) {
789         fprintf(stderr, "DRI2: failed to authenticate\n");
790         free(authenticate);
791         return;
792     }
793
794     delete authenticate;
795
796     EGLDisplay display = eglGetDRMDisplayMESA(fd);
797     if (!display) {
798         fprintf(stderr, "failed to create display\n");
799         return;
800     }
801
802     m_egl_display = display;
803     EGLint major,minor;
804     if (!eglInitialize(display, &major, &minor)) {
805         fprintf(stderr, "failed to initialize display\n");
806         return;
807     }
808 }
809
810 bool QXcbConnection::hasSupportForDri2() const
811 {
812     if (!m_dri2_support_probed) {
813         xcb_generic_error_t *error = 0;
814
815         xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
816         xcb_prefetch_extension_data (m_connection, &xcb_dri2_id);
817
818         xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
819                                                                                          XCB_XFIXES_MAJOR_VERSION,
820                                                                                          XCB_XFIXES_MINOR_VERSION);
821
822         xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection,
823                                                                                     XCB_DRI2_MAJOR_VERSION,
824                                                                                     XCB_DRI2_MINOR_VERSION);
825
826         xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
827                                                                                          xfixes_query_cookie, &error);
828         if (!xfixes_query || error || xfixes_query->major_version < 2) {
829             delete error;
830             delete xfixes_query;
831             return false;
832         }
833         delete xfixes_query;
834
835         xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection,
836                                                                                    dri2_query_cookie, &error);
837         if (!dri2_query || error) {
838             delete error;
839             delete dri2_query;
840             return false;
841         }
842
843         QXcbConnection *that = const_cast<QXcbConnection *>(this);
844         that->m_dri2_major = dri2_query->major_version;
845         that->m_dri2_minor = dri2_query->minor_version;
846
847         that->m_has_support_for_dri2 = true;
848         that->m_dri2_support_probed = true;
849     }
850     return m_has_support_for_dri2;
851 }
852 #endif //XCB_USE_DRI2