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

Last change on this file since 1023 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

File size: 16.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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 \row \o
145 \o Qt::DragMoveCursor \o \c dnd-move or \c move
146 \o
147 \o Qt::DragCopyCursor \o \c dnd-copy or \c copy
148 \row \o
149 \o Qt::DragLinkCursor \o \c dnd-link or \c link
150 \endtable
151
152 \sa QWidget, {fowler}{GUI Design Handbook: Cursors}
153*/
154
155/*!
156 \fn HCURSOR_or_HANDLE QCursor::handle() const
157
158 Returns a platform-specific cursor handle. The \c
159 HCURSOR_or_HANDLE type is \c HCURSOR on Windows and Qt::HANDLE on X11
160 and Mac OS X. On \l{Qt for Embedded Linux} it is an integer.
161
162 \warning Using the value returned by this function is not
163 portable.
164*/
165
166/*!
167 \fn QCursor::QCursor(HCURSOR cursor)
168
169 Constructs a Qt cursor from the given Windows \a cursor.
170
171 \warning This function is only available on Windows.
172
173 \sa handle()
174*/
175
176/*!
177 \fn QCursor::QCursor(Qt::HANDLE handle)
178
179 Constructs a Qt cursor from the given \a handle.
180
181 \warning This function is only available on X11.
182
183 \sa handle()
184*/
185
186/*!
187 \fn QPoint QCursor::pos()
188
189 Returns the position of the cursor (hot spot) in global screen
190 coordinates.
191
192 You can call QWidget::mapFromGlobal() to translate it to widget
193 coordinates.
194
195 \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
196*/
197
198/*!
199 \fn void QCursor::setPos(int x, int y)
200
201 Moves the cursor (hot spot) to the global screen position (\a x,
202 \a y).
203
204 You can call QWidget::mapToGlobal() to translate widget
205 coordinates to global screen coordinates.
206
207 \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
208*/
209
210/*!
211 \fn void QCursor::setPos (const QPoint &p)
212
213 \overload
214
215 Moves the cursor (hot spot) to the global screen position at point
216 \a p.
217*/
218
219/*****************************************************************************
220 QCursor stream functions
221 *****************************************************************************/
222
223#ifndef QT_NO_DATASTREAM
224
225
226/*!
227 \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
228 \relates QCursor
229
230 Writes the \a cursor to the \a stream.
231
232 \sa {Serializing Qt Data Types}
233*/
234
235QDataStream &operator<<(QDataStream &s, const QCursor &c)
236{
237 s << (qint16)c.shape(); // write shape id to stream
238 if (c.shape() == Qt::BitmapCursor) { // bitmap cursor
239 bool isPixmap = false;
240 if (s.version() >= 7) {
241 isPixmap = !c.pixmap().isNull();
242 s << isPixmap;
243 }
244 if (isPixmap)
245 s << c.pixmap();
246 else
247 s << *c.bitmap() << *c.mask();
248 s << c.hotSpot();
249 }
250 return s;
251}
252
253/*!
254 \fn QDataStream &operator>>(QDataStream &stream, QCursor &cursor)
255 \relates QCursor
256
257 Reads the \a cursor from the \a stream.
258
259 \sa {Serializing Qt Data Types}
260*/
261
262QDataStream &operator>>(QDataStream &s, QCursor &c)
263{
264 qint16 shape;
265 s >> shape; // read shape id from stream
266 if (shape == Qt::BitmapCursor) { // read bitmap cursor
267 bool isPixmap = false;
268 if (s.version() >= 7)
269 s >> isPixmap;
270 if (isPixmap) {
271 QPixmap pm;
272 QPoint hot;
273 s >> pm >> hot;
274 c = QCursor(pm, hot.x(), hot.y());
275 } else {
276 QBitmap bm, bmm;
277 QPoint hot;
278 s >> bm >> bmm >> hot;
279 c = QCursor(bm, bmm, hot.x(), hot.y());
280 }
281 } else {
282 c.setShape((Qt::CursorShape)shape); // create cursor with shape
283 }
284 return s;
285}
286#endif // QT_NO_DATASTREAM
287
288
289/*!
290 Constructs a custom pixmap cursor.
291
292 \a pixmap is the image. It is usual to give it a mask (set using
293 QPixmap::setMask()). \a hotX and \a hotY define the cursor's hot
294 spot.
295
296 If \a hotX is negative, it is set to the \c{pixmap().width()/2}.
297 If \a hotY is negative, it is set to the \c{pixmap().height()/2}.
298
299 Valid cursor sizes depend on the display hardware (or the
300 underlying window system). We recommend using 32 x 32 cursors,
301 because this size is supported on all platforms. Some platforms
302 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
303
304 \note On Windows CE, the cursor size is fixed. If the pixmap
305 is bigger than the system size, it will be scaled.
306
307 \sa QPixmap::QPixmap(), QPixmap::setMask()
308*/
309
310QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
311 : d(0)
312{
313 QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
314 QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither);
315 QBitmap bmm = pixmap.mask();
316 if (!bmm.isNull()) {
317 QBitmap nullBm;
318 bm.setMask(nullBm);
319 }
320 else if (!pixmap.mask().isNull()) {
321 QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
322 bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither);
323 }
324 else {
325 bmm = QBitmap(bm.size());
326 bmm.fill(Qt::color1);
327 }
328
329 d = QCursorData::setBitmap(bm, bmm, hotX, hotY);
330 d->pixmap = pixmap;
331}
332
333
334
335/*!
336 Constructs a custom bitmap cursor.
337
338 \a bitmap and
339 \a mask make up the bitmap.
340 \a hotX and
341 \a hotY define the cursor's hot spot.
342
343 If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
344 If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
345
346 The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
347 \list
348 \o B=1 and M=1 gives black.
349 \o B=0 and M=1 gives white.
350 \o B=0 and M=0 gives transparent.
351 \o B=1 and M=0 gives an XOR'd result under Windows, undefined
352 results on all other platforms.
353 \endlist
354
355 Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
356 draw 1-pixels in the bitmaps.
357
358 Valid cursor sizes depend on the display hardware (or the
359 underlying window system). We recommend using 32 x 32 cursors,
360 because this size is supported on all platforms. Some platforms
361 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
362
363 \note On Windows CE, the cursor size is fixed. If the pixmap
364 is bigger than the system size, it will be scaled.
365
366 \sa QBitmap::QBitmap(), QBitmap::setMask()
367*/
368
369QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
370 : d(0)
371{
372 d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
373}
374
375QCursorData *qt_cursorTable[Qt::LastCursor + 1];
376bool QCursorData::initialized = false;
377
378/*! \internal */
379void QCursorData::cleanup()
380{
381 if(!QCursorData::initialized)
382 return;
383
384 for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
385 // In case someone has a static QCursor defined with this shape
386 if (!qt_cursorTable[shape]->ref.deref())
387 delete qt_cursorTable[shape];
388 qt_cursorTable[shape] = 0;
389 }
390 QCursorData::initialized = false;
391}
392
393/*! \internal */
394void QCursorData::initialize()
395{
396 if (QCursorData::initialized)
397 return;
398#ifdef Q_WS_MAC
399 // DRSWAT - Not Needed Cocoa or Carbon
400 //InitCursor();
401#endif
402 for (int shape = 0; shape <= Qt::LastCursor; ++shape)
403 qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
404 QCursorData::initialized = true;
405}
406
407/*!
408 Constructs a cursor with the default arrow shape.
409*/
410QCursor::QCursor()
411{
412 if (!QCursorData::initialized) {
413 if (QApplication::startingUp()) {
414 d = 0;
415 return;
416 }
417 QCursorData::initialize();
418 }
419 QCursorData *c = qt_cursorTable[0];
420 c->ref.ref();
421 d = c;
422}
423
424/*!
425 Constructs a cursor with the specified \a shape.
426
427 See \l Qt::CursorShape for a list of shapes.
428
429 \sa setShape()
430*/
431QCursor::QCursor(Qt::CursorShape shape)
432 : d(0)
433{
434 if (!QCursorData::initialized)
435 QCursorData::initialize();
436 setShape(shape);
437}
438
439
440/*!
441 Returns the cursor shape identifier. The return value is one of
442 the \l Qt::CursorShape enum values (cast to an int).
443
444 \sa setShape()
445*/
446Qt::CursorShape QCursor::shape() const
447{
448 if (!QCursorData::initialized)
449 QCursorData::initialize();
450 return d->cshape;
451}
452
453/*!
454 Sets the cursor to the shape identified by \a shape.
455
456 See \l Qt::CursorShape for the list of cursor shapes.
457
458 \sa shape()
459*/
460void QCursor::setShape(Qt::CursorShape shape)
461{
462 if (!QCursorData::initialized)
463 QCursorData::initialize();
464 QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : 0;
465 if (!c)
466 c = qt_cursorTable[0];
467 c->ref.ref();
468 if (!d) {
469 d = c;
470 } else {
471 if (!d->ref.deref())
472 delete d;
473 d = c;
474 }
475}
476
477/*!
478 Returns the cursor bitmap, or 0 if it is one of the standard
479 cursors.
480*/
481const QBitmap *QCursor::bitmap() const
482{
483 if (!QCursorData::initialized)
484 QCursorData::initialize();
485 return d->bm;
486}
487
488/*!
489 Returns the cursor bitmap mask, or 0 if it is one of the standard
490 cursors.
491*/
492
493const QBitmap *QCursor::mask() const
494{
495 if (!QCursorData::initialized)
496 QCursorData::initialize();
497 return d->bmm;
498}
499
500/*!
501 Returns the cursor pixmap. This is only valid if the cursor is a
502 pixmap cursor.
503*/
504
505QPixmap QCursor::pixmap() const
506{
507 if (!QCursorData::initialized)
508 QCursorData::initialize();
509 return d->pixmap;
510}
511
512/*!
513 Returns the cursor hot spot, or (0, 0) if it is one of the
514 standard cursors.
515*/
516
517QPoint QCursor::hotSpot() const
518{
519 if (!QCursorData::initialized)
520 QCursorData::initialize();
521 return QPoint(d->hx, d->hy);
522}
523
524/*!
525 Constructs a copy of the cursor \a c.
526*/
527
528QCursor::QCursor(const QCursor &c)
529{
530 if (!QCursorData::initialized)
531 QCursorData::initialize();
532 d = c.d;
533 d->ref.ref();
534}
535
536/*!
537 Destroys the cursor.
538*/
539
540QCursor::~QCursor()
541{
542 if (d && !d->ref.deref())
543 delete d;
544}
545
546
547/*!
548 Assigns \a c to this cursor and returns a reference to this
549 cursor.
550*/
551
552QCursor &QCursor::operator=(const QCursor &c)
553{
554 if (!QCursorData::initialized)
555 QCursorData::initialize();
556 if (c.d)
557 c.d->ref.ref();
558 if (d && !d->ref.deref())
559 delete d;
560 d = c.d;
561 return *this;
562}
563
564/*!
565 Returns the cursor as a QVariant.
566*/
567QCursor::operator QVariant() const
568{
569 return QVariant(QVariant::Cursor, this);
570}
571QT_END_NAMESPACE
572#endif // QT_NO_CURSOR
573
Note: See TracBrowser for help on using the repository browser.