source: trunk/src/gui/kernel/qcursor.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 15.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qcursor.h"
43
44#ifndef QT_NO_CURSOR
45
46#include <qapplication.h>
47#include <qbitmap.h>
48#include <qimage.h>
49#include <qdatastream.h>
50#include <qvariant.h>
51#include <private/qcursor_p.h>
52
53QT_BEGIN_NAMESPACE
54
55/*!
56 \class QCursor
57
58 \brief The QCursor class provides a mouse cursor with an arbitrary
59 shape.
60
61 \ingroup appearance
62 \ingroup shared
63
64
65 This class is mainly used to create mouse cursors that are
66 associated with particular widgets and to get and set the position
67 of the mouse cursor.
68
69 Qt has a number of standard cursor shapes, but you can also make
70 custom cursor shapes based on a QBitmap, a mask and a hotspot.
71
72 To associate a cursor with a widget, use QWidget::setCursor(). To
73 associate a cursor with all widgets (normally for a short period
74 of time), use QApplication::setOverrideCursor().
75
76 To set a cursor shape use QCursor::setShape() or use the QCursor
77 constructor which takes the shape as argument, or you can use one
78 of the predefined cursors defined in the \l Qt::CursorShape enum.
79
80 If you want to create a cursor with your own bitmap, either use
81 the QCursor constructor which takes a bitmap and a mask or the
82 constructor which takes a pixmap as arguments.
83
84 To set or get the position of the mouse cursor use the static
85 methods QCursor::pos() and QCursor::setPos().
86
87 \bold{Note:} It is possible to create a QCursor before
88 QApplication, but it is not useful except as a place-holder for a
89 real QCursor created after QApplication. Attempting to use a
90 QCursor that was created before QApplication will result in a
91 crash.
92
93 \section1 A Note for X11 Users
94
95 On X11, Qt supports the \link
96 http://www.xfree86.org/4.3.0/Xcursor.3.html Xcursor\endlink
97 library, which allows for full color icon themes. The table below
98 shows the cursor name used for each Qt::CursorShape value. If a
99 cursor cannot be found using the name shown below, a standard X11
100 cursor will be used instead. Note: X11 does not provide
101 appropriate cursors for all possible Qt::CursorShape values. It
102 is possible that some cursors will be taken from the Xcursor
103 theme, while others will use an internal bitmap cursor.
104
105 \table
106 \header \o Shape \o Qt::CursorShape Value \o Cursor Name
107 \o Shape \o Qt::CursorShape Value \o Cursor Name
108 \row \o \inlineimage cursor-arrow.png
109 \o Qt::ArrowCursor \o \c left_ptr
110 \o \inlineimage cursor-sizev.png
111 \o Qt::SizeVerCursor \o \c size_ver
112 \row \o \inlineimage cursor-uparrow.png
113 \o Qt::UpArrowCursor \o \c up_arrow
114 \o \inlineimage cursor-sizeh.png
115 \o Qt::SizeHorCursor \o \c size_hor
116 \row \o \inlineimage cursor-cross.png
117 \o Qt::CrossCursor \o \c cross
118 \o \inlineimage cursor-sizeb.png
119 \o Qt::SizeBDiagCursor \o \c size_bdiag
120 \row \o \inlineimage cursor-ibeam.png
121 \o Qt::IBeamCursor \o \c ibeam
122 \o \inlineimage cursor-sizef.png
123 \o Qt::SizeFDiagCursor \o \c size_fdiag
124 \row \o \inlineimage cursor-wait.png
125 \o Qt::WaitCursor \o \c wait
126 \o \inlineimage cursor-sizeall.png
127 \o Qt::SizeAllCursor \o \c size_all
128 \row \o \inlineimage cursor-busy.png
129 \o Qt::BusyCursor \o \c left_ptr_watch
130 \o \inlineimage cursor-vsplit.png
131 \o Qt::SplitVCursor \o \c split_v
132 \row \o \inlineimage cursor-forbidden.png
133 \o Qt::ForbiddenCursor \o \c forbidden
134 \o \inlineimage cursor-hsplit.png
135 \o Qt::SplitHCursor \o \c split_h
136 \row \o \inlineimage cursor-hand.png
137 \o Qt::PointingHandCursor \o \c pointing_hand
138 \o \inlineimage cursor-openhand.png
139 \o Qt::OpenHandCursor \o \c openhand
140 \row \o \inlineimage cursor-whatsthis.png
141 \o Qt::WhatsThisCursor \o \c whats_this
142 \o \inlineimage cursor-closedhand.png
143 \o Qt::ClosedHandCursor \o \c closedhand
144 \endtable
145
146 \sa QWidget, {fowler}{GUI Design Handbook: Cursors}
147*/
148
149/*!
150 \fn HCURSOR_or_HANDLE QCursor::handle() const
151
152 Returns a platform-specific cursor handle. The \c
153 HCURSOR_or_HANDLE type is \c HCURSOR on Windows and Qt::HANDLE on X11
154 and Mac OS X. On \l{Qt for Embedded Linux} it is an integer.
155
156 \warning Using the value returned by this function is not
157 portable.
158*/
159
160/*!
161 \fn QCursor::QCursor(HCURSOR cursor)
162
163 Constructs a Qt cursor from the given Windows \a cursor.
164
165 \warning This function is only available on Windows.
166
167 \sa handle()
168*/
169
170/*!
171 \fn QCursor::QCursor(Qt::HANDLE handle)
172
173 Constructs a Qt cursor from the given \a handle.
174
175 \warning This function is only available on X11.
176
177 \sa handle()
178*/
179
180/*!
181 \fn QPoint QCursor::pos()
182
183 Returns the position of the cursor (hot spot) in global screen
184 coordinates.
185
186 You can call QWidget::mapFromGlobal() to translate it to widget
187 coordinates.
188
189 \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
190*/
191
192/*!
193 \fn void QCursor::setPos(int x, int y)
194
195 Moves the cursor (hot spot) to the global screen position (\a x,
196 \a y).
197
198 You can call QWidget::mapToGlobal() to translate widget
199 coordinates to global screen coordinates.
200
201 \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
202*/
203
204/*!
205 \fn void QCursor::setPos (const QPoint &p)
206
207 \overload
208
209 Moves the cursor (hot spot) to the global screen position at point
210 \a p.
211*/
212
213/*****************************************************************************
214 QCursor stream functions
215 *****************************************************************************/
216
217#ifndef QT_NO_DATASTREAM
218
219
220/*!
221 \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
222 \relates QCursor
223
224 Writes the \a cursor to the \a stream.
225
226 \sa {Format of the QDataStream operators}
227*/
228
229QDataStream &operator<<(QDataStream &s, const QCursor &c)
230{
231 s << (qint16)c.shape(); // write shape id to stream
232 if (c.shape() == Qt::BitmapCursor) { // bitmap cursor
233 bool isPixmap = false;
234 if (s.version() >= 7) {
235 isPixmap = !c.pixmap().isNull();
236 s << isPixmap;
237 }
238 if (isPixmap)
239 s << c.pixmap();
240 else
241 s << *c.bitmap() << *c.mask();
242 s << c.hotSpot();
243 }
244 return s;
245}
246
247/*!
248 \fn QDataStream &operator>>(QDataStream &stream, QCursor &cursor)
249 \relates QCursor
250
251 Reads the \a cursor from the \a stream.
252
253 \sa {Format of the QDataStream operators}
254*/
255
256QDataStream &operator>>(QDataStream &s, QCursor &c)
257{
258 qint16 shape;
259 s >> shape; // read shape id from stream
260 if (shape == Qt::BitmapCursor) { // read bitmap cursor
261 bool isPixmap = false;
262 if (s.version() >= 7)
263 s >> isPixmap;
264 if (isPixmap) {
265 QPixmap pm;
266 QPoint hot;
267 s >> pm >> hot;
268 c = QCursor(pm, hot.x(), hot.y());
269 } else {
270 QBitmap bm, bmm;
271 QPoint hot;
272 s >> bm >> bmm >> hot;
273 c = QCursor(bm, bmm, hot.x(), hot.y());
274 }
275 } else {
276 c.setShape((Qt::CursorShape)shape); // create cursor with shape
277 }
278 return s;
279}
280#endif // QT_NO_DATASTREAM
281
282
283/*!
284 Constructs a custom pixmap cursor.
285
286 \a pixmap is the image. It is usual to give it a mask (set using
287 QPixmap::setMask()). \a hotX and \a hotY define the cursor's hot
288 spot.
289
290 If \a hotX is negative, it is set to the \c{pixmap().width()/2}.
291 If \a hotY is negative, it is set to the \c{pixmap().height()/2}.
292
293 Valid cursor sizes depend on the display hardware (or the
294 underlying window system). We recommend using 32 x 32 cursors,
295 because this size is supported on all platforms. Some platforms
296 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
297
298 \note On Windows CE, the cursor size is fixed. If the pixmap
299 is bigger than the system size, it will be scaled.
300
301 \sa QPixmap::QPixmap(), QPixmap::setMask()
302*/
303
304QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
305 : d(0)
306{
307 QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
308 QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither);
309 QBitmap bmm = pixmap.mask();
310 if (!bmm.isNull()) {
311 QBitmap nullBm;
312 bm.setMask(nullBm);
313 }
314 else if (!pixmap.mask().isNull()) {
315 QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
316 bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither);
317 }
318 else {
319 bmm = QBitmap(bm.size());
320 bmm.fill(Qt::color1);
321 }
322
323 d = QCursorData::setBitmap(bm, bmm, hotX, hotY);
324 d->pixmap = pixmap;
325}
326
327
328
329/*!
330 Constructs a custom bitmap cursor.
331
332 \a bitmap and
333 \a mask make up the bitmap.
334 \a hotX and
335 \a hotY define the cursor's hot spot.
336
337 If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
338 If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
339
340 The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
341 \list
342 \o B=1 and M=1 gives black.
343 \o B=0 and M=1 gives white.
344 \o B=0 and M=0 gives transparent.
345 \o B=1 and M=0 gives an XOR'd result under Windows, undefined
346 results on all other platforms.
347 \endlist
348
349 Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
350 draw 1-pixels in the bitmaps.
351
352 Valid cursor sizes depend on the display hardware (or the
353 underlying window system). We recommend using 32 x 32 cursors,
354 because this size is supported on all platforms. Some platforms
355 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
356
357 \note On Windows CE, the cursor size is fixed. If the pixmap
358 is bigger than the system size, it will be scaled.
359
360 \sa QBitmap::QBitmap(), QBitmap::setMask()
361*/
362
363QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
364 : d(0)
365{
366 d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
367}
368
369QCursorData *qt_cursorTable[Qt::LastCursor + 1];
370bool QCursorData::initialized = false;
371
372/*! \internal */
373void QCursorData::cleanup()
374{
375 if(!QCursorData::initialized)
376 return;
377
378 for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
379 // In case someone has a static QCursor defined with this shape
380 if (!qt_cursorTable[shape]->ref.deref())
381 delete qt_cursorTable[shape];
382 qt_cursorTable[shape] = 0;
383 }
384 QCursorData::initialized = false;
385}
386
387/*! \internal */
388void QCursorData::initialize()
389{
390 if (QCursorData::initialized)
391 return;
392#ifdef Q_WS_MAC
393 // DRSWAT - Not Needed Cocoa or Carbon
394 //InitCursor();
395#endif
396 for (int shape = 0; shape <= Qt::LastCursor; ++shape)
397 qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
398 QCursorData::initialized = true;
399}
400
401/*!
402 Constructs a cursor with the default arrow shape.
403*/
404QCursor::QCursor()
405{
406 if (!QCursorData::initialized) {
407 if (QApplication::startingUp()) {
408 d = 0;
409 return;
410 }
411 QCursorData::initialize();
412 }
413 QCursorData *c = qt_cursorTable[0];
414 c->ref.ref();
415 d = c;
416}
417
418/*!
419 Constructs a cursor with the specified \a shape.
420
421 See \l Qt::CursorShape for a list of shapes.
422
423 \sa setShape()
424*/
425QCursor::QCursor(Qt::CursorShape shape)
426 : d(0)
427{
428 if (!QCursorData::initialized)
429 QCursorData::initialize();
430 setShape(shape);
431}
432
433
434/*!
435 Returns the cursor shape identifier. The return value is one of
436 the \l Qt::CursorShape enum values (cast to an int).
437
438 \sa setShape()
439*/
440Qt::CursorShape QCursor::shape() const
441{
442 if (!QCursorData::initialized)
443 QCursorData::initialize();
444 return d->cshape;
445}
446
447/*!
448 Sets the cursor to the shape identified by \a shape.
449
450 See \l Qt::CursorShape for the list of cursor shapes.
451
452 \sa shape()
453*/
454void QCursor::setShape(Qt::CursorShape shape)
455{
456 if (!QCursorData::initialized)
457 QCursorData::initialize();
458 QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : 0;
459 if (!c)
460 c = qt_cursorTable[0];
461 c->ref.ref();
462 if (!d) {
463 d = c;
464 } else {
465 if (!d->ref.deref())
466 delete d;
467 d = c;
468 }
469}
470
471/*!
472 Returns the cursor bitmap, or 0 if it is one of the standard
473 cursors.
474*/
475const QBitmap *QCursor::bitmap() const
476{
477 if (!QCursorData::initialized)
478 QCursorData::initialize();
479 return d->bm;
480}
481
482/*!
483 Returns the cursor bitmap mask, or 0 if it is one of the standard
484 cursors.
485*/
486
487const QBitmap *QCursor::mask() const
488{
489 if (!QCursorData::initialized)
490 QCursorData::initialize();
491 return d->bmm;
492}
493
494/*!
495 Returns the cursor pixmap. This is only valid if the cursor is a
496 pixmap cursor.
497*/
498
499QPixmap QCursor::pixmap() const
500{
501 if (!QCursorData::initialized)
502 QCursorData::initialize();
503 return d->pixmap;
504}
505
506/*!
507 Returns the cursor hot spot, or (0, 0) if it is one of the
508 standard cursors.
509*/
510
511QPoint QCursor::hotSpot() const
512{
513 if (!QCursorData::initialized)
514 QCursorData::initialize();
515 return QPoint(d->hx, d->hy);
516}
517
518/*!
519 Constructs a copy of the cursor \a c.
520*/
521
522QCursor::QCursor(const QCursor &c)
523{
524 if (!QCursorData::initialized)
525 QCursorData::initialize();
526 d = c.d;
527 d->ref.ref();
528}
529
530/*!
531 Destroys the cursor.
532*/
533
534QCursor::~QCursor()
535{
536 if (d && !d->ref.deref())
537 delete d;
538}
539
540
541/*!
542 Assigns \a c to this cursor and returns a reference to this
543 cursor.
544*/
545
546QCursor &QCursor::operator=(const QCursor &c)
547{
548 if (!QCursorData::initialized)
549 QCursorData::initialize();
550 if (c.d)
551 c.d->ref.ref();
552 if (d && !d->ref.deref())
553 delete d;
554 d = c.d;
555 return *this;
556}
557
558/*!
559 Returns the cursor as a QVariant.
560*/
561QCursor::operator QVariant() const
562{
563 return QVariant(QVariant::Cursor, this);
564}
565QT_END_NAMESPACE
566#endif // QT_NO_CURSOR
567
Note: See TracBrowser for help on using the repository browser.