1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcursor.h"
41
42#include <qcoreapplication.h>
43#include <qbitmap.h>
44#include <qimage.h>
45#include <qdatastream.h>
46#include <qvariant.h>
47#include <private/qcursor_p.h>
48#include <qdebug.h>
49
50#include <qpa/qplatformcursor.h>
51#include <private/qguiapplication_p.h>
52#include <private/qhighdpiscaling_p.h>
53
54QT_BEGIN_NAMESPACE
55
56/*!
57 \class QCursor
58
59 \brief The QCursor class provides a mouse cursor with an arbitrary
60 shape.
61
62 \inmodule QtGui
63 \ingroup appearance
64 \ingroup shared
65
66
67 This class is mainly used to create mouse cursors that are
68 associated with particular widgets and to get and set the position
69 of the mouse cursor.
70
71 Qt has a number of standard cursor shapes, but you can also make
72 custom cursor shapes based on a QBitmap, a mask and a hotspot.
73
74 To associate a cursor with a widget, use QWidget::setCursor(). To
75 associate a cursor with all widgets (normally for a short period
76 of time), use QGuiApplication::setOverrideCursor().
77
78 To set a cursor shape use QCursor::setShape() or use the QCursor
79 constructor which takes the shape as argument, or you can use one
80 of the predefined cursors defined in the \l Qt::CursorShape enum.
81
82 If you want to create a cursor with your own bitmap, either use
83 the QCursor constructor which takes a bitmap and a mask or the
84 constructor which takes a pixmap as arguments.
85
86 To set or get the position of the mouse cursor use the static
87 methods QCursor::pos() and QCursor::setPos().
88
89 \b{Note:} It is possible to create a QCursor before
90 QGuiApplication, but it is not useful except as a place-holder for a
91 real QCursor created after QGuiApplication. Attempting to use a
92 QCursor that was created before QGuiApplication will result in a
93 crash.
94
95 \section1 A Note for X11 Users
96
97 On X11, Qt supports the \l{Xcursor}{Xcursor}
98 library, which allows for full color icon themes. The table below
99 shows the cursor name used for each Qt::CursorShape value. If a
100 cursor cannot be found using the name shown below, a standard X11
101 cursor will be used instead. Note: X11 does not provide
102 appropriate cursors for all possible Qt::CursorShape values. It
103 is possible that some cursors will be taken from the Xcursor
104 theme, while others will use an internal bitmap cursor.
105
106 \table
107 \header \li Shape \li Qt::CursorShape Value \li Cursor Name
108 \li Shape \li Qt::CursorShape Value \li Cursor Name
109 \row \li \inlineimage cursor-arrow.png
110 \li Qt::ArrowCursor \li \c left_ptr
111 \li \inlineimage cursor-sizev.png
112 \li Qt::SizeVerCursor \li \c size_ver
113 \row \li \inlineimage cursor-uparrow.png
114 \li Qt::UpArrowCursor \li \c up_arrow
115 \li \inlineimage cursor-sizeh.png
116 \li Qt::SizeHorCursor \li \c size_hor
117 \row \li \inlineimage cursor-cross.png
118 \li Qt::CrossCursor \li \c cross
119 \li \inlineimage cursor-sizeb.png
120 \li Qt::SizeBDiagCursor \li \c size_bdiag
121 \row \li \inlineimage cursor-ibeam.png
122 \li Qt::IBeamCursor \li \c ibeam
123 \li \inlineimage cursor-sizef.png
124 \li Qt::SizeFDiagCursor \li \c size_fdiag
125 \row \li \inlineimage cursor-wait.png
126 \li Qt::WaitCursor \li \c wait
127 \li \inlineimage cursor-sizeall.png
128 \li Qt::SizeAllCursor \li \c size_all
129 \row \li \inlineimage cursor-busy.png
130 \li Qt::BusyCursor \li \c left_ptr_watch
131 \li \inlineimage cursor-vsplit.png
132 \li Qt::SplitVCursor \li \c split_v
133 \row \li \inlineimage cursor-forbidden.png
134 \li Qt::ForbiddenCursor \li \c forbidden
135 \li \inlineimage cursor-hsplit.png
136 \li Qt::SplitHCursor \li \c split_h
137 \row \li \inlineimage cursor-hand.png
138 \li Qt::PointingHandCursor \li \c pointing_hand
139 \li \inlineimage cursor-openhand.png
140 \li Qt::OpenHandCursor \li \c openhand
141 \row \li \inlineimage cursor-whatsthis.png
142 \li Qt::WhatsThisCursor \li \c whats_this
143 \li \inlineimage cursor-closedhand.png
144 \li Qt::ClosedHandCursor \li \c closedhand
145 \row \li
146 \li Qt::DragMoveCursor \li \c dnd-move or \c move
147 \li
148 \li Qt::DragCopyCursor \li \c dnd-copy or \c copy
149 \row \li
150 \li Qt::DragLinkCursor \li \c dnd-link or \c link
151 \endtable
152
153 \sa QWidget, {fowler}{GUI Design Handbook: Cursors}
154*/
155
156/*!
157 \fn QCursor::QCursor(QCursor &&other)
158 \since 5.5
159
160 Move-constructs a cursor from \a other. After being moved from,
161 the only valid operations on \a other are destruction and
162 (move and copy) assignment. The effects of calling any other
163 member function on a moved-from instance are undefined.
164*/
165
166/*!
167 \fn QCursor &QCursor::operator=(QCursor &&other)
168
169 Move-assigns \a other to this QCursor instance.
170
171 \since 5.2
172*/
173
174/*!
175 \fn void QCursor::swap(QCursor &other)
176
177 Swaps this cursor with the \a other cursor.
178
179 \since 5.7
180 */
181
182/*!
183 \fn QPoint QCursor::pos(const QScreen *screen)
184
185 Returns the position of the cursor (hot spot) of the \a screen
186 in global screen coordinates.
187
188 You can call QWidget::mapFromGlobal() to translate it to widget
189 coordinates.
190
191 \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
192*/
193QPoint QCursor::pos(const QScreen *screen)
194{
195 if (screen) {
196 if (const QPlatformCursor *cursor = screen->handle()->cursor()) {
197 const QPlatformScreen *ps = screen->handle();
198 QPoint nativePos = cursor->pos();
199 ps = ps->screenForPosition(nativePos);
200 return QHighDpi::fromNativePixels(nativePos, ps->screen());
201 }
202 }
203 return QGuiApplicationPrivate::lastCursorPosition.toPoint();
204}
205
206/*!
207 \fn QPoint QCursor::pos()
208
209 Returns the position of the cursor (hot spot) of
210 the primary screen in global screen coordinates.
211
212 You can call QWidget::mapFromGlobal() to translate it to widget
213 coordinates.
214
215 \note The position is queried from the windowing system. If mouse events are generated
216 via other means (e.g., via QWindowSystemInterface in a unit test), those fake mouse
217 moves will not be reflected in the returned value.
218
219 \note On platforms where there is no windowing system or cursors are not available, the returned
220 position is based on the mouse move events generated via QWindowSystemInterface.
221
222 \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
223*/
224QPoint QCursor::pos()
225{
226 return QCursor::pos(QGuiApplication::primaryScreen());
227}
228
229/*!
230 \fn void QCursor::setPos(QScreen *screen, int x, int y)
231
232 Moves the cursor (hot spot) of the \a screen to the global
233 screen position (\a x, \a y).
234
235 You can call QWidget::mapToGlobal() to translate widget
236 coordinates to global screen coordinates.
237
238 \note Calling this function results in changing the cursor position through the windowing
239 system. The windowing system will typically respond by sending mouse events to the application's
240 window. This means that the usage of this function should be avoided in unit tests and
241 everywhere where fake mouse events are being injected via QWindowSystemInterface because the
242 windowing system's mouse state (with regards to buttons for example) may not match the state in
243 the application-generated events.
244
245 \note On platforms where there is no windowing system or cursors are not available, this
246 function may do nothing.
247
248 \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
249*/
250void QCursor::setPos(QScreen *screen, int x, int y)
251{
252 if (screen) {
253 if (QPlatformCursor *cursor = screen->handle()->cursor()) {
254 const QPoint devicePos = QHighDpi::toNativePixels(QPoint(x, y), screen);
255 // Need to check, since some X servers generate null mouse move
256 // events, causing looping in applications which call setPos() on
257 // every mouse move event.
258 if (devicePos != cursor->pos())
259 cursor->setPos(devicePos);
260 }
261 }
262}
263
264/*!
265 \fn void QCursor::setPos(int x, int y)
266
267 Moves the cursor (hot spot) of the primary screen
268 to the global screen position (\a x, \a y).
269
270 You can call QWidget::mapToGlobal() to translate widget
271 coordinates to global screen coordinates.
272
273 \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
274*/
275void QCursor::setPos(int x, int y)
276{
277 QCursor::setPos(QGuiApplication::primaryScreen(), x, y);
278}
279
280#ifndef QT_NO_CURSOR
281
282/*!
283 \fn void QCursor::setPos (const QPoint &p)
284
285 \overload
286
287 Moves the cursor (hot spot) to the global screen position at point
288 \a p.
289*/
290
291/*!
292 \fn void QCursor::setPos (QScreen *screen,const QPoint &p)
293
294 \overload
295
296 Moves the cursor (hot spot) to the global screen position of the
297 \a screen at point \a p.
298*/
299
300/*****************************************************************************
301 QCursor stream functions
302 *****************************************************************************/
303
304#ifndef QT_NO_DATASTREAM
305
306
307/*!
308 \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
309 \relates QCursor
310
311 Writes the \a cursor to the \a stream.
312
313 \sa {Serializing Qt Data Types}
314*/
315
316QDataStream &operator<<(QDataStream &s, const QCursor &c)
317{
318 s << (qint16)c.shape(); // write shape id to stream
319 if (c.shape() == Qt::BitmapCursor) { // bitmap cursor
320 bool isPixmap = false;
321 if (s.version() >= 7) {
322 isPixmap = !c.pixmap().isNull();
323 s << isPixmap;
324 }
325 if (isPixmap)
326 s << c.pixmap();
327 else
328 s << c.bitmap(Qt::ReturnByValue) << c.mask(Qt::ReturnByValue);
329 s << c.hotSpot();
330 }
331 return s;
332}
333
334/*!
335 \fn QDataStream &operator>>(QDataStream &stream, QCursor &cursor)
336 \relates QCursor
337
338 Reads the \a cursor from the \a stream.
339
340 \sa {Serializing Qt Data Types}
341*/
342
343QDataStream &operator>>(QDataStream &s, QCursor &c)
344{
345 qint16 shape;
346 s >> shape; // read shape id from stream
347 if (shape == Qt::BitmapCursor) { // read bitmap cursor
348 bool isPixmap = false;
349 if (s.version() >= 7)
350 s >> isPixmap;
351 if (isPixmap) {
352 QPixmap pm;
353 QPoint hot;
354 s >> pm >> hot;
355 c = QCursor(pm, hot.x(), hot.y());
356 } else {
357 QBitmap bm, bmm;
358 QPoint hot;
359 s >> bm >> bmm >> hot;
360 c = QCursor(bm, bmm, hot.x(), hot.y());
361 }
362 } else {
363 c.setShape((Qt::CursorShape)shape); // create cursor with shape
364 }
365 return s;
366}
367#endif // QT_NO_DATASTREAM
368
369
370/*!
371 Constructs a custom pixmap cursor.
372
373 \a pixmap is the image. It is usual to give it a mask (set using
374 QPixmap::setMask()). \a hotX and \a hotY define the cursor's hot
375 spot.
376
377 If \a hotX is negative, it is set to the \c{pixmap().width()/2}.
378 If \a hotY is negative, it is set to the \c{pixmap().height()/2}.
379
380 Valid cursor sizes depend on the display hardware (or the
381 underlying window system). We recommend using 32 x 32 cursors,
382 because this size is supported on all platforms. Some platforms
383 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
384
385 \sa QPixmap::QPixmap(), QPixmap::setMask()
386*/
387
388QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
389 : d(nullptr)
390{
391 QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
392 QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither);
393 QBitmap bmm = pixmap.mask();
394 if (!bmm.isNull()) {
395 QBitmap nullBm;
396 bm.setMask(nullBm);
397 }
398 else if (!pixmap.mask().isNull()) {
399 QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
400 bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither);
401 }
402 else {
403 bmm = QBitmap(bm.size());
404 bmm.fill(Qt::color1);
405 }
406
407 d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio());
408 d->pixmap = pixmap;
409}
410
411
412
413/*!
414 Constructs a custom bitmap cursor.
415
416 \a bitmap and
417 \a mask make up the bitmap.
418 \a hotX and
419 \a hotY define the cursor's hot spot.
420
421 If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
422 If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
423
424 The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
425 \list
426 \li B=1 and M=1 gives black.
427 \li B=0 and M=1 gives white.
428 \li B=0 and M=0 gives transparent.
429 \li B=1 and M=0 gives an XOR'd result under Windows, undefined
430 results on all other platforms.
431 \endlist
432
433 Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
434 draw 1-pixels in the bitmaps.
435
436 Valid cursor sizes depend on the display hardware (or the
437 underlying window system). We recommend using 32 x 32 cursors,
438 because this size is supported on all platforms. Some platforms
439 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
440
441 \sa QBitmap::QBitmap(), QBitmap::setMask()
442*/
443
444QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
445 : d(nullptr)
446{
447 d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0);
448}
449
450/*!
451 Constructs a cursor with the default arrow shape.
452*/
453QCursor::QCursor()
454{
455 if (!QCursorData::initialized) {
456 if (QCoreApplication::startingUp()) {
457 d = nullptr;
458 return;
459 }
460 QCursorData::initialize();
461 }
462 QCursorData *c = qt_cursorTable[0];
463 c->ref.ref();
464 d = c;
465}
466
467/*!
468 Constructs a cursor with the specified \a shape.
469
470 See \l Qt::CursorShape for a list of shapes.
471
472 \sa setShape()
473*/
474QCursor::QCursor(Qt::CursorShape shape)
475 : d(nullptr)
476{
477 if (!QCursorData::initialized)
478 QCursorData::initialize();
479 setShape(shape);
480}
481
482/*!
483 \fn bool QCursor::operator==(const QCursor &lhs, const QCursor &rhs)
484 \since 5.10
485
486 Equality operator. Returns \c true if \a lhs and \a rhs
487 have the same \l{QCursor::}{shape()} and, in the case of
488 \l{Qt::BitmapCursor}{bitmap cursors}, the same \l{QCursor::}{hotSpot()}
489 and either the same \l{QCursor::}{pixmap()} or the same
490 \l{QCursor::}{bitmap()} and \l{QCursor::}{mask()}.
491
492 \note When comparing bitmap cursors, this function only
493 compares the bitmaps' \l{QPixmap::cacheKey()}{cache keys},
494 not each pixel.
495
496 \sa operator!=(const QCursor &lhs, const QCursor &rhs)
497*/
498bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept
499{
500 if (lhs.d == rhs.d)
501 return true; // Copy or same shape
502
503 // Check pixmaps or bitmaps cache keys. Notice that having BitmapCursor
504 // shape implies either non-null pixmap or non-null bitmap and mask
505 if (lhs.shape() == Qt::BitmapCursor && rhs.shape() == Qt::BitmapCursor
506 && lhs.hotSpot() == rhs.hotSpot()) {
507 if (!lhs.d->pixmap.isNull())
508 return lhs.d->pixmap.cacheKey() == rhs.d->pixmap.cacheKey();
509
510 if (!rhs.d->pixmap.isNull())
511 return false;
512
513 return lhs.d->bm->cacheKey() == rhs.d->bm->cacheKey()
514 && lhs.d->bmm->cacheKey() == rhs.d->bmm->cacheKey();
515 }
516
517 return false;
518}
519
520/*!
521 \fn bool QCursor::operator!=(const QCursor &lhs, const QCursor &rhs)
522 \since 5.10
523
524 Inequality operator. Returns the equivalent of !(\a lhs == \a rhs).
525
526 \sa operator==(const QCursor &lhs, const QCursor &rhs)
527*/
528
529/*!
530 Returns the cursor shape identifier. The return value is one of
531 the \l Qt::CursorShape enum values (cast to an int).
532
533 \sa setShape()
534*/
535Qt::CursorShape QCursor::shape() const
536{
537 if (!QCursorData::initialized)
538 QCursorData::initialize();
539 return d->cshape;
540}
541
542/*!
543 Sets the cursor to the shape identified by \a shape.
544
545 See \l Qt::CursorShape for the list of cursor shapes.
546
547 \sa shape()
548*/
549void QCursor::setShape(Qt::CursorShape shape)
550{
551 if (!QCursorData::initialized)
552 QCursorData::initialize();
553 QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : nullptr;
554 if (!c)
555 c = qt_cursorTable[0];
556 c->ref.ref();
557 if (!d) {
558 d = c;
559 } else {
560 if (!d->ref.deref())
561 delete d;
562 d = c;
563 }
564}
565
566/*!
567 \fn QBitmap QCursor::bitmap(Qt::ReturnByValueConstant) const
568 \since 5.15
569 \obsolete Use the overload without argument instead.
570
571 Returns the cursor bitmap, or a null bitmap if it is one of the
572 standard cursors.
573
574 Previously, Qt provided a version of \c bitmap() which returned the bitmap
575 by-pointer. That version is now removed. To maintain compatibility
576 with old code, this function was provided to differentiate between the by-pointer
577 function and the by-value function.
578*/
579
580/*!
581 Returns the cursor bitmap, or a null bitmap if it is one of the
582 standard cursors.
583*/
584QBitmap QCursor::bitmap() const
585{
586 if (!QCursorData::initialized)
587 QCursorData::initialize();
588 if (d->bm)
589 return *(d->bm);
590 return QBitmap();
591}
592
593/*!
594 \fn QBitmap QCursor::mask(Qt::ReturnByValueConstant) const
595 \since 5.15
596 \obsolete Use the overload without argument instead.
597
598 Returns the cursor bitmap mask, or a null bitmap if it is one of the
599 standard cursors.
600
601 Previously, Qt provided a version of \c mask() which returned the bitmap
602 by-pointer. That version is now removed. To maintain compatibility
603 with old code, this function was provided to differentiate between the by-pointer
604 function and the by-value function.
605*/
606
607/*!
608 Returns the cursor bitmap mask, or a null bitmap if it is one of the
609 standard cursors.
610*/
611QBitmap QCursor::mask() const
612{
613 if (!QCursorData::initialized)
614 QCursorData::initialize();
615 if (d->bmm)
616 return *(d->bmm);
617 return QBitmap();
618}
619
620/*!
621 Returns the cursor pixmap. This is only valid if the cursor is a
622 pixmap cursor.
623*/
624
625QPixmap QCursor::pixmap() const
626{
627 if (!QCursorData::initialized)
628 QCursorData::initialize();
629 return d->pixmap;
630}
631
632/*!
633 Returns the cursor hot spot, or (0, 0) if it is one of the
634 standard cursors.
635*/
636
637QPoint QCursor::hotSpot() const
638{
639 if (!QCursorData::initialized)
640 QCursorData::initialize();
641 return QPoint(d->hx, d->hy);
642}
643
644/*!
645 Constructs a copy of the cursor \a c.
646*/
647
648QCursor::QCursor(const QCursor &c)
649{
650 if (!QCursorData::initialized)
651 QCursorData::initialize();
652 d = c.d;
653 d->ref.ref();
654}
655
656/*!
657 Destroys the cursor.
658*/
659
660QCursor::~QCursor()
661{
662 if (d && !d->ref.deref())
663 delete d;
664}
665
666
667/*!
668 Assigns \a c to this cursor and returns a reference to this
669 cursor.
670*/
671
672QCursor &QCursor::operator=(const QCursor &c)
673{
674 if (!QCursorData::initialized)
675 QCursorData::initialize();
676 if (c.d)
677 c.d->ref.ref();
678 if (d && !d->ref.deref())
679 delete d;
680 d = c.d;
681 return *this;
682}
683
684/*!
685 Returns the cursor as a QVariant.
686*/
687QCursor::operator QVariant() const
688{
689 return QVariant::fromValue(*this);
690}
691
692#ifndef QT_NO_DEBUG_STREAM
693QDebug operator<<(QDebug dbg, const QCursor &c)
694{
695 QDebugStateSaver saver(dbg);
696 dbg.nospace() << "QCursor(Qt::CursorShape(" << c.shape() << "))";
697 return dbg;
698}
699#endif
700
701/*****************************************************************************
702 Internal QCursorData class
703 *****************************************************************************/
704
705QCursorData *qt_cursorTable[Qt::LastCursor + 1];
706bool QCursorData::initialized = false;
707
708QCursorData::QCursorData(Qt::CursorShape s)
709 : ref(1), cshape(s), bm(nullptr), bmm(nullptr), hx(0), hy(0)
710{
711}
712
713QCursorData::~QCursorData()
714{
715 delete bm;
716 delete bmm;
717}
718
719/*! \internal */
720void QCursorData::cleanup()
721{
722 if(!QCursorData::initialized)
723 return;
724
725 for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
726 // In case someone has a static QCursor defined with this shape
727 if (!qt_cursorTable[shape]->ref.deref())
728 delete qt_cursorTable[shape];
729 qt_cursorTable[shape] = nullptr;
730 }
731 QCursorData::initialized = false;
732}
733
734/*! \internal */
735void QCursorData::initialize()
736{
737 if (QCursorData::initialized)
738 return;
739 for (int shape = 0; shape <= Qt::LastCursor; ++shape)
740 qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
741 QCursorData::initialized = true;
742}
743
744QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
745{
746 if (!QCursorData::initialized)
747 QCursorData::initialize();
748 if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
749 qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
750 QCursorData *c = qt_cursorTable[0];
751 c->ref.ref();
752 return c;
753 }
754 QCursorData *d = new QCursorData;
755 d->bm = new QBitmap(bitmap);
756 d->bmm = new QBitmap(mask);
757 d->cshape = Qt::BitmapCursor;
758 d->hx = hotX >= 0 ? hotX : bitmap.width() / 2 / devicePixelRatio;
759 d->hy = hotY >= 0 ? hotY : bitmap.height() / 2 / devicePixelRatio;
760
761 return d;
762}
763
764void QCursorData::update()
765{
766}
767
768QT_END_NAMESPACE
769#endif // QT_NO_CURSOR
770
771