1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the plugins of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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>
56 typedef int (*PtrXcursorLibraryLoadCursor)(void *, const char *);
58 static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0;
60 static xcb_font_t cursorFont = 0;
61 static int cursorCount = 0;
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 };
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 };
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};
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
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 };
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};
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};
236 static const uint8_t * const cursor_bits20[] = {
237 forbidden_bits, forbiddenm_bits
240 static const char * const cursorNames[] = {
265 QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
266 : QXcbObject(conn), m_screen(screen)
271 cursorFont = xcb_generate_id(xcb_connection());
272 const char *cursorStr = "cursor";
273 xcb_open_font(xcb_connection(), cursorFont, strlen(cursorStr), cursorStr);
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();
283 ptrXcursorLibraryLoadCursor =
284 (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
288 QXcbCursor::~QXcbCursor()
291 xcb_close_font(xcb_connection(), cursorFont);
295 void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget)
298 if (widget && widget->handle())
299 w = static_cast<QXcbWindow *>(widget->handle());
301 // No X11 cursor control when there is no widget under the cursor
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);
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);
320 static int cursorIdForShape(int cshape)
324 case Qt::ArrowCursor:
325 cursorId = XC_left_ptr;
327 case Qt::UpArrowCursor:
328 cursorId = XC_center_ptr;
330 case Qt::CrossCursor:
331 cursorId = XC_crosshair;
336 case Qt::IBeamCursor:
339 case Qt::SizeAllCursor:
342 case Qt::PointingHandCursor:
345 case Qt::SizeBDiagCursor:
346 cursorId = XC_top_right_corner;
348 case Qt::SizeFDiagCursor:
349 cursorId = XC_bottom_right_corner;
351 case Qt::SizeVerCursor:
352 case Qt::SplitVCursor:
353 cursorId = XC_sb_v_double_arrow;
355 case Qt::SizeHorCursor:
356 case Qt::SplitHCursor:
357 cursorId = XC_sb_h_double_arrow;
359 case Qt::WhatsThisCursor:
360 cursorId = XC_question_arrow;
362 case Qt::ForbiddenCursor:
363 cursorId = XC_circle;
374 xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
376 xcb_cursor_t cursor = 0;
377 xcb_connection_t *conn = xcb_connection();
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,
382 xcb_pixmap_t mp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
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]),
391 xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
392 const_cast<uint8_t*>(cursor_bits16[i + 1]),
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]),
402 xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
403 const_cast<uint8_t*>(cursor_bits32[i + 1]),
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]),
414 xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
415 const_cast<uint8_t*>(cursor_bits20[i + 1]),
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),
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),
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);
443 xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
445 xcb_connection_t *conn = xcb_connection();
446 int cursorId = cursorIdForShape(cshape);
447 xcb_cursor_t cursor = XCB_NONE;
451 if (ptrXcursorLibraryLoadCursor && cshape >= 0 && cshape < Qt::LastCursor) {
452 void *dpy = connection()->xlib_display();
453 // special case for non-standard dnd-* cursors
455 case Qt::DragCopyCursor:
456 cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
458 case Qt::DragMoveCursor:
459 cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
461 case Qt::DragLinkCursor:
462 cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
468 cursor = ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
474 // Non-standard X11 cursors are created from bitmaps
475 cursor = createNonStandardCursor(cshape);
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);
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);
493 xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
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);
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,
506 xcb_free_pixmap(conn, cp);
507 xcb_free_pixmap(conn, mp);
513 void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask)
517 xcb_screen_iterator_t it = xcb_setup_roots_iterator(c->setup());
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);
525 *pos = QPoint(reply->root_x, reply->root_y);
529 *keybMask = reply->mask;
535 xcb_screen_next(&it);
539 QPoint QXcbCursor::pos() const
542 queryPointer(connection(), 0, &p);
546 void QXcbCursor::setPos(const QPoint &pos)
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());