Add PLUGIN_CLASS_NAME to qtbase plugins
[profile/ivi/qtbase.git] / src / plugins / platforms / xcb / qxcbcursor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qxcbcursor.h"
43 #include "qxcbconnection.h"
44 #include "qxcbwindow.h"
45 #include "qxcbimage.h"
46 #include <QtCore/QLibrary>
47 #include <QtGui/QWindow>
48 #include <QtGui/QBitmap>
49 #include <QtGui/private/qguiapplication_p.h>
50 #include <X11/cursorfont.h>
51 #include <xcb/xfixes.h>
52 #include <xcb/xcb_image.h>
53
54 QT_BEGIN_NAMESPACE
55
56 typedef int (*PtrXcursorLibraryLoadCursor)(void *, const char *);
57 #ifdef XCB_USE_XLIB
58 static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0;
59 #endif
60 static xcb_font_t cursorFont = 0;
61 static int cursorCount = 0;
62
63 static uint8_t cur_blank_bits[] = {
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
67
68 static const uint8_t cur_ver_bits[] = {
69     0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
70     0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
71     0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
72 static const uint8_t mcur_ver_bits[] = {
73     0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
74     0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
75     0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
76 static const uint8_t cur_hor_bits[] = {
77     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
78     0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
79     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
80 static const uint8_t mcur_hor_bits[] = {
81     0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
82     0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
83     0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
84 static const uint8_t cur_bdiag_bits[] = {
85     0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
86     0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
87     0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
88 static const uint8_t mcur_bdiag_bits[] = {
89     0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
90     0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
91     0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
92 static const uint8_t cur_fdiag_bits[] = {
93     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
94     0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
95     0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
96 static const uint8_t mcur_fdiag_bits[] = {
97     0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
98     0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
99     0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
100 static const uint8_t *cursor_bits16[] = {
101     cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits,
102     cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits,
103     0, 0, cur_blank_bits, cur_blank_bits };
104
105 static const uint8_t vsplit_bits[] = {
106     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108     0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
109     0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
110     0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
111     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
112     0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
113     0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
114     0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
117 static const uint8_t vsplitm_bits[] = {
118     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
120     0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
121     0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
122     0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
123     0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
124     0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
125     0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
126     0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
127     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
129 static const uint8_t hsplit_bits[] = {
130     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132     0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
133     0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
134     0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
135     0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
136     0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
137     0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
138     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
141 static const uint8_t hsplitm_bits[] = {
142     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144     0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
145     0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
146     0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
147     0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
148     0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
149     0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
150     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
153 static const uint8_t whatsthis_bits[] = {
154     0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
155     0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
156     0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
157     0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00,
158     0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00,
159     0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00,
160     0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
165 static const uint8_t whatsthism_bits[] = {
166     0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
167     0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
168     0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
169     0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00,
170     0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00,
171     0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00,
172     0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
177 static const uint8_t busy_bits[] = {
178     0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
179     0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
180     0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
181     0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00,
182     0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00,
183     0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00,
184     0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00,
185     0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
186     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
189 static const uint8_t busym_bits[] = {
190     0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
191     0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
192     0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
193     0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00,
194     0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00,
195     0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00,
196     0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00,
197     0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
198     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
201
202 static const uint8_t * const cursor_bits32[] = {
203     vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
204     0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits
205 };
206
207 static const uint8_t forbidden_bits[] = {
208     0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
209     0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
210     0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
211     0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
212
213 static const uint8_t forbiddenm_bits[] = {
214     0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
215     0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
216     0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
217     0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
218
219 static const uint8_t openhand_bits[] = {
220     0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
221     0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
222     0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
223 static const uint8_t openhandm_bits[] = {
224     0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
225     0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
226     0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
227 static const uint8_t closedhand_bits[] = {
228     0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
229     0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
230     0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
231 static const uint8_t closedhandm_bits[] = {
232     0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
233     0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
234     0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
235
236 static const uint8_t * const cursor_bits20[] = {
237     forbidden_bits, forbiddenm_bits
238 };
239
240 static const char * const cursorNames[] = {
241     "left_ptr",
242     "up_arrow",
243     "cross",
244     "wait",
245     "ibeam",
246     "size_ver",
247     "size_hor",
248     "size_bdiag",
249     "size_fdiag",
250     "size_all",
251     "blank",
252     "split_v",
253     "split_h",
254     "pointing_hand",
255     "forbidden",
256     "whats_this",
257     "left_ptr_watch",
258     "openhand",
259     "closedhand",
260     "copy",
261     "move",
262     "link"
263 };
264
265 QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
266     : QXcbObject(conn), m_screen(screen)
267 {
268     if (cursorCount++)
269         return;
270
271     cursorFont = xcb_generate_id(xcb_connection());
272     const char *cursorStr = "cursor";
273     xcb_open_font(xcb_connection(), cursorFont, strlen(cursorStr), cursorStr);
274
275 #ifdef XCB_USE_XLIB
276     QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
277     bool xcursorFound = xcursorLib.load();
278     if (!xcursorFound) { // try without the version number
279         xcursorLib.setFileName(QLatin1String("Xcursor"));
280         xcursorFound = xcursorLib.load();
281     }
282     if (xcursorFound)
283         ptrXcursorLibraryLoadCursor =
284             (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
285 #endif
286 }
287
288 QXcbCursor::~QXcbCursor()
289 {
290     if (!--cursorCount)
291         xcb_close_font(xcb_connection(), cursorFont);
292 }
293
294 #ifndef QT_NO_CURSOR
295 void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget)
296 {
297     QXcbWindow *w = 0;
298     if (widget && widget->handle())
299         w = static_cast<QXcbWindow *>(widget->handle());
300     else
301         // No X11 cursor control when there is no widget under the cursor
302         return;
303     
304     xcb_cursor_t c;
305     if (cursor->shape() == Qt::BitmapCursor) {
306         qint64 id = cursor->pixmap().cacheKey();
307         if (!m_bitmapCursorMap.contains(id))
308             m_bitmapCursorMap.insert(id, createBitmapCursor(cursor));
309         c = m_bitmapCursorMap.value(id);
310     } else {
311         int id = cursor->shape();
312         if (!m_shapeCursorMap.contains(id))
313             m_shapeCursorMap.insert(id, createFontCursor(cursor->shape()));
314         c = m_shapeCursorMap.value(id);
315     }
316
317     w->setCursor(c);
318 }
319
320 static int cursorIdForShape(int cshape)
321 {
322     int cursorId = 0;
323     switch (cshape) {
324     case Qt::ArrowCursor:
325         cursorId = XC_left_ptr;
326         break;
327     case Qt::UpArrowCursor:
328         cursorId = XC_center_ptr;
329         break;
330     case Qt::CrossCursor:
331         cursorId = XC_crosshair;
332         break;
333     case Qt::WaitCursor:
334         cursorId = XC_watch;
335         break;
336     case Qt::IBeamCursor:
337         cursorId = XC_xterm;
338         break;
339     case Qt::SizeAllCursor:
340         cursorId = XC_fleur;
341         break;
342     case Qt::PointingHandCursor:
343         cursorId = XC_hand2;
344         break;
345     case Qt::SizeBDiagCursor:
346         cursorId = XC_top_right_corner;
347         break;
348     case Qt::SizeFDiagCursor:
349         cursorId = XC_bottom_right_corner;
350         break;
351     case Qt::SizeVerCursor:
352     case Qt::SplitVCursor:
353         cursorId = XC_sb_v_double_arrow;
354         break;
355     case Qt::SizeHorCursor:
356     case Qt::SplitHCursor:
357         cursorId = XC_sb_h_double_arrow;
358         break;
359     case Qt::WhatsThisCursor:
360         cursorId = XC_question_arrow;
361         break;
362     case Qt::ForbiddenCursor:
363         cursorId = XC_circle;
364         break;
365     case Qt::BusyCursor:
366         cursorId = XC_watch;
367         break;
368     default:
369         break;
370     }
371     return cursorId;
372 }
373
374 xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
375 {
376     xcb_cursor_t cursor = 0;
377     xcb_connection_t *conn = xcb_connection();
378
379     if (cshape == Qt::BlankCursor) {
380         xcb_pixmap_t cp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
381                                                              1, 0, 0, 0);
382         xcb_pixmap_t mp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
383                                                              1, 0, 0, 0);
384         cursor = xcb_generate_id(conn);
385         xcb_create_cursor(conn, cursor, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
386     } else if (cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor) {
387         int i = (cshape - Qt::SizeVerCursor) * 2;
388         xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
389                                                              const_cast<uint8_t*>(cursor_bits16[i]),
390                                                              16, 16, 1, 0, 0, 0);
391         xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
392                                                               const_cast<uint8_t*>(cursor_bits16[i + 1]),
393                                                               16, 16, 1, 0, 0, 0);
394         cursor = xcb_generate_id(conn);
395         xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
396     } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
397                || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
398         int i = (cshape - Qt::SplitVCursor) * 2;
399         xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
400                                                              const_cast<uint8_t*>(cursor_bits32[i]),
401                                                              32, 32, 1, 0, 0, 0);
402         xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
403                                                               const_cast<uint8_t*>(cursor_bits32[i + 1]),
404                                                               32, 32, 1, 0, 0, 0);
405         int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
406                   || cshape == Qt::BusyCursor) ? 0 : 16;
407         cursor = xcb_generate_id(conn);
408         xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, hs, hs);
409     } else if (cshape == Qt::ForbiddenCursor) {
410         int i = (cshape - Qt::ForbiddenCursor) * 2;
411         xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
412                                                              const_cast<uint8_t*>(cursor_bits20[i]),
413                                                              20, 20, 1, 0, 0, 0);
414         xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
415                                                               const_cast<uint8_t*>(cursor_bits20[i + 1]),
416                                                               20, 20, 1, 0, 0, 0);
417         cursor = xcb_generate_id(conn);
418         xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 10, 10);
419     } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
420         bool open = cshape == Qt::OpenHandCursor;
421         xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
422                                                              const_cast<uint8_t*>(open ? openhand_bits : closedhand_bits),
423                                                              16, 16, 1, 0, 0, 0);
424         xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
425                                                              const_cast<uint8_t*>(open ? openhandm_bits : closedhandm_bits),
426                                                              16, 16, 1, 0, 0, 0);
427         cursor = xcb_generate_id(conn);
428         xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
429     } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
430                || cshape == Qt::DragLinkCursor) {
431         QImage image = QGuiApplicationPrivate::instance()->getPixmapCursor(static_cast<Qt::CursorShape>(cshape)).toImage();
432         if (!image.isNull()) {
433             xcb_pixmap_t pm = qt_xcb_XPixmapFromBitmap(m_screen, image);
434             xcb_pixmap_t pmm = qt_xcb_XPixmapFromBitmap(m_screen, image.createAlphaMask());
435             cursor = xcb_generate_id(conn);
436             xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
437         }
438     }
439
440     return cursor;
441 }
442
443 xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
444 {
445     xcb_connection_t *conn = xcb_connection();
446     int cursorId = cursorIdForShape(cshape);
447     xcb_cursor_t cursor = XCB_NONE;
448
449     // Try Xcursor first
450 #ifdef XCB_USE_XLIB
451     if (ptrXcursorLibraryLoadCursor && cshape >= 0 && cshape < Qt::LastCursor) {
452         void *dpy = connection()->xlib_display();
453         // special case for non-standard dnd-* cursors
454         switch (cshape) {
455         case Qt::DragCopyCursor:
456             cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
457             break;
458         case Qt::DragMoveCursor:
459             cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
460             break;
461         case Qt::DragLinkCursor:
462             cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
463             break;
464         default:
465             break;
466         }
467         if (!cursor)
468             cursor = ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
469     }
470     if (cursor)
471         return cursor;
472 #endif
473
474     // Non-standard X11 cursors are created from bitmaps
475     cursor = createNonStandardCursor(cshape);
476
477     // Create a glpyh cursor if everything else failed
478     if (!cursor && cursorId) {
479         cursor = xcb_generate_id(conn);
480         xcb_create_glyph_cursor(conn, cursor, cursorFont, cursorFont,
481                                 cursorId, cursorId + 1,
482                                 0xFFFF, 0xFFFF, 0xFFFF, 0, 0, 0);
483     }
484
485     if (cursor && cshape >= 0 && cshape < Qt::LastCursor) {
486         const char *name = cursorNames[cshape];
487         xcb_xfixes_set_cursor_name(conn, cursor, strlen(name), name);
488     }
489
490     return cursor;
491 }
492
493 xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
494 {
495     xcb_connection_t *conn = xcb_connection();
496     QPoint spot = cursor->hotSpot();
497     xcb_cursor_t c = XCB_NONE;
498     if (cursor->pixmap().depth() > 1)
499         c = qt_xcb_createCursorXRender(m_screen, cursor->pixmap().toImage(), spot);
500     if (!c) {
501         xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage());
502         xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage());
503         c = xcb_generate_id(conn);
504         xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF,
505                           spot.x(), spot.y());
506         xcb_free_pixmap(conn, cp);
507         xcb_free_pixmap(conn, mp);
508     }
509     return c;
510 }
511 #endif
512
513 void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask)
514 {
515     if (pos)
516         *pos = QPoint();
517     xcb_screen_iterator_t it = xcb_setup_roots_iterator(c->setup());
518     while (it.rem) {
519         xcb_window_t root = it.data->root;
520         xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root);
521         xcb_generic_error_t *err = 0;
522         xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err);
523         if (!err && reply) {
524             if (pos)
525                 *pos = QPoint(reply->root_x, reply->root_y);
526             if (rootWin)
527                 *rootWin = root;
528             if (keybMask)
529                 *keybMask = reply->mask;
530             free(reply);
531             return;
532         }
533         free(err);
534         free(reply);
535         xcb_screen_next(&it);
536     }
537 }
538
539 QPoint QXcbCursor::pos() const
540 {
541     QPoint p;
542     queryPointer(connection(), 0, &p);
543     return p;
544 }
545
546 void QXcbCursor::setPos(const QPoint &pos)
547 {
548     xcb_window_t root;
549     queryPointer(connection(), &root, 0);
550     xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x(), pos.y());
551     xcb_flush(xcb_connection());
552 }
553
554 QT_END_NAMESPACE