1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtGui module 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 <qdebug.h>
43#include <qdatastream.h>
44#include <private/qcursor_p.h>
45#include <private/qt_x11_p.h>
46#include <private/qapplication_p.h>
47#include <qbitmap.h>
48#include <qcursor.h>
49#include <X11/cursorfont.h>
50
51#include <qlibrary.h>
52
53#ifndef QT_NO_XCURSOR
54# include <X11/Xcursor/Xcursor.h>
55#endif // QT_NO_XCURSOR
56
57#ifndef QT_NO_XFIXES
58#ifndef Status
59#define Status int
60#endif
61# include <X11/extensions/Xfixes.h>
62#endif // QT_NO_XFIXES
63
64#include "qx11info_x11.h"
65#include <private/qpixmap_x11_p.h>
66
67QT_BEGIN_NAMESPACE
68
69// Define QT_USE_APPROXIMATE_CURSORS when compiling if you REALLY want to
70// use the ugly X11 cursors.
71
72/*****************************************************************************
73 Internal QCursorData class
74 *****************************************************************************/
75
76QCursorData::QCursorData(Qt::CursorShape s)
77 : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(0), pm(0), pmm(0)
78{
79 ref = 1;
80}
81
82QCursorData::~QCursorData()
83{
84 Display *dpy = X11 ? X11->display : (Display*)0;
85
86 // Add in checking for the display too as on HP-UX
87 // we seem to get a core dump as the cursor data is
88 // deleted again from main() on exit...
89 if (hcurs && dpy)
90 XFreeCursor(dpy, hcurs);
91 if (pm && dpy)
92 XFreePixmap(dpy, pm);
93 if (pmm && dpy)
94 XFreePixmap(dpy, pmm);
95 delete bm;
96 delete bmm;
97}
98
99#ifndef QT_NO_CURSOR
100QCursor::QCursor(Qt::HANDLE cursor)
101{
102 if (!QCursorData::initialized)
103 QCursorData::initialize();
104 d = new QCursorData(Qt::CustomCursor);
105 d->hcurs = cursor;
106}
107
108#endif
109
110QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
111{
112 if (!QCursorData::initialized)
113 QCursorData::initialize();
114 if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
115 qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
116 QCursorData *c = qt_cursorTable[0];
117 c->ref.ref();
118 return c;
119 }
120 QCursorData *d = new QCursorData;
121 d->ref = 1;
122
123 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
124 d->bm = new QBitmap(qt_toX11Pixmap(bitmap));
125 d->bmm = new QBitmap(qt_toX11Pixmap(mask));
126
127 d->hcurs = 0;
128 d->cshape = Qt::BitmapCursor;
129 d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
130 d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
131 d->fg.red = 0x0000;
132 d->fg.green = 0x0000;
133 d->fg.blue = 0x0000;
134 d->bg.red = 0xffff;
135 d->bg.green = 0xffff;
136 d->bg.blue = 0xffff;
137 return d;
138}
139
140
141
142#ifndef QT_NO_CURSOR
143Qt::HANDLE QCursor::handle() const
144{
145 if (!QCursorData::initialized)
146 QCursorData::initialize();
147 if (!d->hcurs)
148 d->update();
149 return d->hcurs;
150}
151#endif
152
153QPoint QCursor::pos()
154{
155 Window root;
156 Window child;
157 int root_x, root_y, win_x, win_y;
158 uint buttons;
159 Display* dpy = X11->display;
160 for (int i = 0; i < ScreenCount(dpy); ++i) {
161 if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
162 &win_x, &win_y, &buttons))
163
164 return QPoint(root_x, root_y);
165 }
166 return QPoint();
167}
168
169/*! \internal
170*/
171#ifndef QT_NO_CURSOR
172int QCursor::x11Screen()
173{
174 Window root;
175 Window child;
176 int root_x, root_y, win_x, win_y;
177 uint buttons;
178 Display* dpy = X11->display;
179 for (int i = 0; i < ScreenCount(dpy); ++i) {
180 if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
181 &win_x, &win_y, &buttons))
182 return i;
183 }
184 return -1;
185}
186#endif
187
188void QCursor::setPos(int x, int y)
189{
190 QPoint current, target(x, y);
191
192 // this is copied from pos(), since we need the screen number for the correct
193 // root window in the XWarpPointer call
194 Window root;
195 Window child;
196 int root_x, root_y, win_x, win_y;
197 uint buttons;
198 Display* dpy = X11->display;
199 int screen;
200 for (screen = 0; screen < ScreenCount(dpy); ++screen) {
201 if (XQueryPointer(dpy, QX11Info::appRootWindow(screen), &root, &child, &root_x, &root_y,
202 &win_x, &win_y, &buttons)) {
203 current = QPoint(root_x, root_y);
204 break;
205 }
206 }
207
208 if (screen >= ScreenCount(dpy))
209 return;
210
211 // Need to check, since some X servers generate null mouse move
212 // events, causing looping in applications which call setPos() on
213 // every mouse move event.
214 //
215 if (current == target)
216 return;
217
218 XWarpPointer(X11->display, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y);
219}
220
221
222/*!
223 \internal
224
225 Creates the cursor.
226*/
227
228void QCursorData::update()
229{
230 if (!QCursorData::initialized)
231 QCursorData::initialize();
232 if (hcurs)
233 return;
234
235 Display *dpy = X11->display;
236 Window rootwin = QX11Info::appRootWindow();
237
238 if (cshape == Qt::BitmapCursor) {
239 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
240#ifndef QT_NO_XRENDER
241 if (!pixmap.isNull() && X11->use_xrender) {
242 pixmap = qt_toX11Pixmap(pixmap);
243 hcurs = XRenderCreateCursor (X11->display, pixmap.x11PictureHandle(), hx, hy);
244 } else
245#endif
246 {
247 hcurs = XCreatePixmapCursor(dpy, bm->handle(), bmm->handle(), &fg, &bg, hx, hy);
248 }
249 return;
250 }
251
252 static const char *cursorNames[] = {
253 "left_ptr",
254 "up_arrow",
255 "cross",
256 "wait",
257 "ibeam",
258 "size_ver",
259 "size_hor",
260 "size_bdiag",
261 "size_fdiag",
262 "size_all",
263 "blank",
264 "split_v",
265 "split_h",
266 "pointing_hand",
267 "forbidden",
268 "whats_this",
269 "left_ptr_watch",
270 "openhand",
271 "closedhand",
272 "copy",
273 "move",
274 "link"
275 };
276
277#ifndef QT_NO_XCURSOR
278 if (X11->ptrXcursorLibraryLoadCursor) {
279 // special case for non-standard dnd-* cursors
280 switch (cshape) {
281 case Qt::DragCopyCursor:
282 hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
283 break;
284 case Qt::DragMoveCursor:
285 hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
286 break;
287 case Qt::DragLinkCursor:
288 hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
289 break;
290 default:
291 break;
292 }
293 if (!hcurs)
294 hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
295 }
296 if (hcurs)
297 return;
298#endif // QT_NO_XCURSOR
299
300 static const uchar cur_blank_bits[] = {
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
304
305 // Non-standard X11 cursors are created from bitmaps
306
307#ifndef QT_USE_APPROXIMATE_CURSORS
308 static const uchar cur_ver_bits[] = {
309 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
310 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
311 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
312 static const uchar mcur_ver_bits[] = {
313 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
314 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
315 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
316 static const uchar cur_hor_bits[] = {
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
318 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
320 static const uchar mcur_hor_bits[] = {
321 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
322 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
323 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
324 static const uchar cur_bdiag_bits[] = {
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
326 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
327 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
328 static const uchar mcur_bdiag_bits[] = {
329 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
330 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
331 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
332 static const uchar cur_fdiag_bits[] = {
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
334 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
335 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
336 static const uchar mcur_fdiag_bits[] = {
337 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
338 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
339 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
340 static const uchar *cursor_bits16[] = {
341 cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits,
342 cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits,
343 0, 0, cur_blank_bits, cur_blank_bits };
344
345 static const uchar vsplit_bits[] = {
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
349 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
350 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
352 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
353 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
354 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
357 static const uchar vsplitm_bits[] = {
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
360 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
361 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
362 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
363 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
364 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
365 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
366 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
369 static const uchar hsplit_bits[] = {
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
373 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
374 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
375 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
376 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
377 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
381 static const uchar hsplitm_bits[] = {
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
385 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
386 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
387 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
388 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
389 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
393 static const uchar whatsthis_bits[] = {
394 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
395 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
396 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
397 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00,
398 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00,
399 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00,
400 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
405 static const uchar whatsthism_bits[] = {
406 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
407 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
408 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
409 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00,
410 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00,
411 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00,
412 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
417 static const uchar busy_bits[] = {
418 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
419 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
420 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
421 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00,
422 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00,
423 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00,
424 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00,
425 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
429 static const uchar busym_bits[] = {
430 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
431 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
432 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
433 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00,
434 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00,
435 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00,
436 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00,
437 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
441
442 static const uchar * const cursor_bits32[] = {
443 vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
444 0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits
445 };
446
447 static const uchar forbidden_bits[] = {
448 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
449 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
450 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
451 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
452
453 static const uchar forbiddenm_bits[] = {
454 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
455 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
456 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
457 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
458
459 static const uchar openhand_bits[] = {
460 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
461 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
462 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
463 static const uchar openhandm_bits[] = {
464 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
465 0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
466 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
467 static const uchar closedhand_bits[] = {
468 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
469 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
470 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
471 static const uchar closedhandm_bits[] = {
472 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
473 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
474 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
475
476 static const uchar * const cursor_bits20[] = {
477 forbidden_bits, forbiddenm_bits
478 };
479
480 if ((cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor)
481 || cshape == Qt::BlankCursor) {
482 XColor bg, fg;
483 bg.red = 255 << 8;
484 bg.green = 255 << 8;
485 bg.blue = 255 << 8;
486 fg.red = 0;
487 fg.green = 0;
488 fg.blue = 0;
489 int i = (cshape - Qt::SizeVerCursor) * 2;
490 pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i]), 16, 16);
491 pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i + 1]), 16, 16);
492 hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
493 } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
494 || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
495 XColor bg, fg;
496 bg.red = 255 << 8;
497 bg.green = 255 << 8;
498 bg.blue = 255 << 8;
499 fg.red = 0;
500 fg.green = 0;
501 fg.blue = 0;
502 int i = (cshape - Qt::SplitVCursor) * 2;
503 pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i]), 32, 32);
504 pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i + 1]), 32, 32);
505 int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
506 || cshape == Qt::BusyCursor) ? 0 : 16;
507 hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, hs, hs);
508 } else if (cshape == Qt::ForbiddenCursor) {
509 XColor bg, fg;
510 bg.red = 255 << 8;
511 bg.green = 255 << 8;
512 bg.blue = 255 << 8;
513 fg.red = 0;
514 fg.green = 0;
515 fg.blue = 0;
516 int i = (cshape - Qt::ForbiddenCursor) * 2;
517 pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i]), 20, 20);
518 pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i + 1]), 20, 20);
519 hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 10, 10);
520 } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
521 XColor bg, fg;
522 bg.red = 255 << 8;
523 bg.green = 255 << 8;
524 bg.blue = 255 << 8;
525 fg.red = 0;
526 fg.green = 0;
527 fg.blue = 0;
528 bool open = cshape == Qt::OpenHandCursor;
529 pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhand_bits : closedhand_bits), 16, 16);
530 pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhandm_bits : closedhandm_bits), 16, 16);
531 hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
532 } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
533 || cshape == Qt::DragLinkCursor) {
534 XColor bg, fg;
535 bg.red = 255 << 8;
536 bg.green = 255 << 8;
537 bg.blue = 255 << 8;
538 fg.red = 0;
539 fg.green = 0;
540 fg.blue = 0;
541 QImage image = QApplicationPrivate::instance()->getPixmapCursor(cshape).toImage();
542 pm = QX11PixmapData::createBitmapFromImage(image);
543 pmm = QX11PixmapData::createBitmapFromImage(image.createAlphaMask().convertToFormat(QImage::Format_MonoLSB));
544 hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
545 }
546
547 if (hcurs)
548 {
549#ifndef QT_NO_XFIXES
550 if (X11->use_xfixes && X11->ptrXFixesSetCursorName)
551 X11->ptrXFixesSetCursorName(dpy, hcurs, cursorNames[cshape]);
552#endif /* ! QT_NO_XFIXES */
553 return;
554 }
555
556#endif /* ! QT_USE_APPROXIMATE_CURSORS */
557
558 uint sh;
559 switch (cshape) { // map Q cursor to X cursor
560 case Qt::ArrowCursor:
561 sh = XC_left_ptr;
562 break;
563 case Qt::UpArrowCursor:
564 sh = XC_center_ptr;
565 break;
566 case Qt::CrossCursor:
567 sh = XC_crosshair;
568 break;
569 case Qt::WaitCursor:
570 sh = XC_watch;
571 break;
572 case Qt::IBeamCursor:
573 sh = XC_xterm;
574 break;
575 case Qt::SizeAllCursor:
576 sh = XC_fleur;
577 break;
578 case Qt::PointingHandCursor:
579 sh = XC_hand2;
580 break;
581#ifdef QT_USE_APPROXIMATE_CURSORS
582 case Qt::SizeBDiagCursor:
583 sh = XC_top_right_corner;
584 break;
585 case Qt::SizeFDiagCursor:
586 sh = XC_bottom_right_corner;
587 break;
588 case Qt::BlankCursor:
589 XColor bg, fg;
590 bg.red = 255 << 8;
591 bg.green = 255 << 8;
592 bg.blue = 255 << 8;
593 fg.red = 0;
594 fg.green = 0;
595 fg.blue = 0;
596 pm = XCreateBitmapFromData(dpy, rootwin, cur_blank_bits, 16, 16);
597 pmm = XCreateBitmapFromData(dpy, rootwin, cur_blank_bits, 16, 16);
598 hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
599 return;
600 break;
601 case Qt::SizeVerCursor:
602 case Qt::SplitVCursor:
603 sh = XC_sb_v_double_arrow;
604 break;
605 case Qt::SizeHorCursor:
606 case Qt::SplitHCursor:
607 sh = XC_sb_h_double_arrow;
608 break;
609 case Qt::WhatsThisCursor:
610 sh = XC_question_arrow;
611 break;
612 case Qt::ForbiddenCursor:
613 sh = XC_circle;
614 break;
615 case Qt::BusyCursor:
616 sh = XC_watch;
617 break;
618 case Qt::DragCopyCursor:
619 sh = XC_tcross;
620 break;
621 case Qt::DragLinkCursor:
622 sh = XC_center_ptr;
623 break;
624 case Qt::DragMoveCursor:
625 sh = XC_top_left_arrow;
626 break;
627#endif /* QT_USE_APPROXIMATE_CURSORS */
628 default:
629 qWarning("QCursor::update: Invalid cursor shape %d", cshape);
630 return;
631 }
632 hcurs = XCreateFontCursor(dpy, sh);
633
634#ifndef QT_NO_XFIXES
635 if (X11->use_xfixes && X11->ptrXFixesSetCursorName)
636 X11->ptrXFixesSetCursorName(dpy, hcurs, cursorNames[cshape]);
637#endif /* ! QT_NO_XFIXES */
638}
639
640QT_END_NAMESPACE
641