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
180/*!
181 \fn QPoint QCursor::pos(const QScreen *screen)
182
183 Returns the position of the cursor (hot spot) of the \a screen
184 in global screen coordinates.
185
186 You can call QWidget::mapFromGlobal() to translate it to widget
187 coordinates.
188
189 \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
190*/
191QPoint QCursor::pos(const QScreen *screen)
192{
193 if (screen) {
194 if (const QPlatformCursor *cursor = screen->handle()->cursor()) {
195 const QPlatformScreen *ps = screen->handle();
196 QPoint nativePos = cursor->pos();
197 ps = ps->screenForPosition(nativePos);
198 return QHighDpi::fromNativePixels(nativePos, ps->screen());
199 }
200 }
201 return QGuiApplicationPrivate::lastCursorPosition.toPoint();
202}
203
204/*!
205 \fn QPoint QCursor::pos()
206
207 Returns the position of the cursor (hot spot) of
208 the primary screen in global screen coordinates.
209
210 You can call QWidget::mapFromGlobal() to translate it to widget
211 coordinates.
212
213 \note The position is queried from the windowing system. If mouse events are generated
214 via other means (e.g., via QWindowSystemInterface in a unit test), those fake mouse
215 moves will not be reflected in the returned value.
216
217 \note On platforms where there is no windowing system or cursors are not available, the returned
218 position is based on the mouse move events generated via QWindowSystemInterface.
219
220 \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
221*/
222QPoint QCursor::pos()
223{
224 return QCursor::pos(QGuiApplication::primaryScreen());
225}
226
227/*!
228 \fn void QCursor::setPos(QScreen *screen, int x, int y)
229
230 Moves the cursor (hot spot) of the \a screen to the global
231 screen position (\a x, \a y).
232
233 You can call QWidget::mapToGlobal() to translate widget
234 coordinates to global screen coordinates.
235
236 \note Calling this function results in changing the cursor position through the windowing
237 system. The windowing system will typically respond by sending mouse events to the application's
238 window. This means that the usage of this function should be avoided in unit tests and
239 everywhere where fake mouse events are being injected via QWindowSystemInterface because the
240 windowing system's mouse state (with regards to buttons for example) may not match the state in
241 the application-generated events.
242
243 \note On platforms where there is no windowing system or cursors are not available, this
244 function may do nothing.
245
246 \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
247*/
248void QCursor::setPos(QScreen *screen, int x, int y)
249{
250 if (screen) {
251 if (QPlatformCursor *cursor = screen->handle()->cursor()) {
252 const QPoint devicePos = QHighDpi::toNativePixels(QPoint(x, y), screen);
253 // Need to check, since some X servers generate null mouse move
254 // events, causing looping in applications which call setPos() on
255 // every mouse move event.
256 if (devicePos != cursor->pos())
257 cursor->setPos(devicePos);
258 }
259 }
260}
261
262/*!
263 \fn void QCursor::setPos(int x, int y)
264
265 Moves the cursor (hot spot) of the primary screen
266 to the global screen position (\a x, \a y).
267
268 You can call QWidget::mapToGlobal() to translate widget
269 coordinates to global screen coordinates.
270
271 \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen()
272*/
273void QCursor::setPos(int x, int y)
274{
275 QCursor::setPos(QGuiApplication::primaryScreen(), x, y);
276}
277
278#ifndef QT_NO_CURSOR
279
280/*!
281 \fn void QCursor::setPos (const QPoint &p)
282
283 \overload
284
285 Moves the cursor (hot spot) to the global screen position at point
286 \a p.
287*/
288
289/*!
290 \fn void QCursor::setPos (QScreen *screen,const QPoint &p)
291
292 \overload
293
294 Moves the cursor (hot spot) to the global screen position of the
295 \a screen at point \a p.
296*/
297
298/*****************************************************************************
299 QCursor stream functions
300 *****************************************************************************/
301
302#ifndef QT_NO_DATASTREAM
303
304
305/*!
306 \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
307 \relates QCursor
308
309 Writes the \a cursor to the \a stream.
310
311 \sa {Serializing Qt Data Types}
312*/
313
314QDataStream &operator<<(QDataStream &s, const QCursor &c)
315{
316 s << (qint16)c.shape(); // write shape id to stream
317 if (c.shape() == Qt::BitmapCursor) { // bitmap cursor
318 bool isPixmap = false;
319 if (s.version() >= 7) {
320 isPixmap = !c.pixmap().isNull();
321 s << isPixmap;
322 }
323 if (isPixmap)
324 s << c.pixmap();
325 else
326 s << *c.bitmap() << *c.mask();
327 s << c.hotSpot();
328 }
329 return s;
330}
331
332/*!
333 \fn QDataStream &operator>>(QDataStream &stream, QCursor &cursor)
334 \relates QCursor
335
336 Reads the \a cursor from the \a stream.
337
338 \sa {Serializing Qt Data Types}
339*/
340
341QDataStream &operator>>(QDataStream &s, QCursor &c)
342{
343 qint16 shape;
344 s >> shape; // read shape id from stream
345 if (shape == Qt::BitmapCursor) { // read bitmap cursor
346 bool isPixmap = false;
347 if (s.version() >= 7)
348 s >> isPixmap;
349 if (isPixmap) {
350 QPixmap pm;
351 QPoint hot;
352 s >> pm >> hot;
353 c = QCursor(pm, hot.x(), hot.y());
354 } else {
355 QBitmap bm, bmm;
356 QPoint hot;
357 s >> bm >> bmm >> hot;
358 c = QCursor(bm, bmm, hot.x(), hot.y());
359 }
360 } else {
361 c.setShape((Qt::CursorShape)shape); // create cursor with shape
362 }
363 return s;
364}
365#endif // QT_NO_DATASTREAM
366
367
368/*!
369 Constructs a custom pixmap cursor.
370
371 \a pixmap is the image. It is usual to give it a mask (set using
372 QPixmap::setMask()). \a hotX and \a hotY define the cursor's hot
373 spot.
374
375 If \a hotX is negative, it is set to the \c{pixmap().width()/2}.
376 If \a hotY is negative, it is set to the \c{pixmap().height()/2}.
377
378 Valid cursor sizes depend on the display hardware (or the
379 underlying window system). We recommend using 32 x 32 cursors,
380 because this size is supported on all platforms. Some platforms
381 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
382
383 \sa QPixmap::QPixmap(), QPixmap::setMask()
384*/
385
386QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
387 : d(0)
388{
389 QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
390 QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither);
391 QBitmap bmm = pixmap.mask();
392 if (!bmm.isNull()) {
393 QBitmap nullBm;
394 bm.setMask(nullBm);
395 }
396 else if (!pixmap.mask().isNull()) {
397 QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
398 bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither);
399 }
400 else {
401 bmm = QBitmap(bm.size());
402 bmm.fill(Qt::color1);
403 }
404
405 d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio());
406 d->pixmap = pixmap;
407}
408
409
410
411/*!
412 Constructs a custom bitmap cursor.
413
414 \a bitmap and
415 \a mask make up the bitmap.
416 \a hotX and
417 \a hotY define the cursor's hot spot.
418
419 If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
420 If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
421
422 The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
423 \list
424 \li B=1 and M=1 gives black.
425 \li B=0 and M=1 gives white.
426 \li B=0 and M=0 gives transparent.
427 \li B=1 and M=0 gives an XOR'd result under Windows, undefined
428 results on all other platforms.
429 \endlist
430
431 Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
432 draw 1-pixels in the bitmaps.
433
434 Valid cursor sizes depend on the display hardware (or the
435 underlying window system). We recommend using 32 x 32 cursors,
436 because this size is supported on all platforms. Some platforms
437 also support 16 x 16, 48 x 48, and 64 x 64 cursors.
438
439 \sa QBitmap::QBitmap(), QBitmap::setMask()
440*/
441
442QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
443 : d(0)
444{
445 d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0);
446}
447
448/*!
449 Constructs a cursor with the default arrow shape.
450*/
451QCursor::QCursor()
452{
453 if (!QCursorData::initialized) {
454 if (QCoreApplication::startingUp()) {
455 d = 0;
456 return;
457 }
458 QCursorData::initialize();
459 }
460 QCursorData *c = qt_cursorTable[0];
461 c->ref.ref();
462 d = c;
463}
464
465/*!
466 Constructs a cursor with the specified \a shape.
467
468 See \l Qt::CursorShape for a list of shapes.
469
470 \sa setShape()
471*/
472QCursor::QCursor(Qt::CursorShape shape)
473 : d(0)
474{
475 if (!QCursorData::initialized)
476 QCursorData::initialize();
477 setShape(shape);
478}
479
480/*!
481 \fn bool operator==(const QCursor &lhs, const QCursor &rhs)
482 \relates QCursor
483 \since 5.10
484
485 Equality operator. Returns \c true if \a lhs and \a rhs
486 have the same \l{QCursor::}{shape()} and, in the case of
487 \l{Qt::BitmapCursor}{bitmap cursors}, the same \l{QCursor::}{hotSpot()}
488 and either the same \l{QCursor::}{pixmap()} or the same
489 \l{QCursor::}{bitmap()} and \l{QCursor::}{mask()}.
490
491 \note When comparing bitmap cursors, this function only
492 compares the bitmaps' \l{QPixmap::cacheKey()}{cache keys},
493 not each pixel.
494
495 \sa operator!=(const QCursor &lhs, const QCursor &rhs)
496*/
497bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept
498{
499 if (lhs.d == rhs.d)
500 return true; // Copy or same shape
501
502 // Check pixmaps or bitmaps cache keys. Notice that having BitmapCursor
503 // shape implies either non-null pixmap or non-null bitmap and mask
504 if (lhs.shape() == Qt::BitmapCursor && rhs.shape() == Qt::BitmapCursor
505 && lhs.hotSpot() == rhs.hotSpot()) {
506 if (!lhs.d->pixmap.isNull())
507 return lhs.d->pixmap.cacheKey() == rhs.d->pixmap.cacheKey();
508
509 if (!rhs.d->pixmap.isNull())
510 return false;
511
512 return lhs.d->bm->cacheKey() == rhs.d->bm->cacheKey()
513 && lhs.d->bmm->cacheKey() == rhs.d->bmm->cacheKey();
514 }
515
516 return false;
517}
518
519/*!
520 \fn bool operator!=(const QCursor &lhs, const QCursor &rhs)
521 \relates QCursor
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] : 0;
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 Returns the cursor bitmap, or \nullptr if it is one of the
568 standard cursors.
569*/
570const QBitmap *QCursor::bitmap() const
571{
572 if (!QCursorData::initialized)
573 QCursorData::initialize();
574 return d->bm;
575}
576
577/*!
578 Returns the cursor bitmap mask, or \nullptr if it is one of the
579 standard cursors.
580*/
581
582const QBitmap *QCursor::mask() const
583{
584 if (!QCursorData::initialized)
585 QCursorData::initialize();
586 return d->bmm;
587}
588
589/*!
590 Returns the cursor pixmap. This is only valid if the cursor is a
591 pixmap cursor.
592*/
593
594QPixmap QCursor::pixmap() const
595{
596 if (!QCursorData::initialized)
597 QCursorData::initialize();
598 return d->pixmap;
599}
600
601/*!
602 Returns the cursor hot spot, or (0, 0) if it is one of the
603 standard cursors.
604*/
605
606QPoint QCursor::hotSpot() const
607{
608 if (!QCursorData::initialized)
609 QCursorData::initialize();
610 return QPoint(d->hx, d->hy);
611}
612
613/*!
614 Constructs a copy of the cursor \a c.
615*/
616
617QCursor::QCursor(const QCursor &c)
618{
619 if (!QCursorData::initialized)
620 QCursorData::initialize();
621 d = c.d;
622 d->ref.ref();
623}
624
625/*!
626 Destroys the cursor.
627*/
628
629QCursor::~QCursor()
630{
631 if (d && !d->ref.deref())
632 delete d;
633}
634
635
636/*!
637 Assigns \a c to this cursor and returns a reference to this
638 cursor.
639*/
640
641QCursor &QCursor::operator=(const QCursor &c)
642{
643 if (!QCursorData::initialized)
644 QCursorData::initialize();
645 if (c.d)
646 c.d->ref.ref();
647 if (d && !d->ref.deref())
648 delete d;
649 d = c.d;
650 return *this;
651}
652
653/*!
654 Returns the cursor as a QVariant.
655*/
656QCursor::operator QVariant() const
657{
658 return QVariant(QVariant::Cursor, this);
659}
660
661#ifndef QT_NO_DEBUG_STREAM
662QDebug operator<<(QDebug dbg, const QCursor &c)
663{
664 QDebugStateSaver saver(dbg);
665 dbg.nospace() << "QCursor(Qt::CursorShape(" << c.shape() << "))";
666 return dbg;
667}
668#endif
669
670/*****************************************************************************
671 Internal QCursorData class
672 *****************************************************************************/
673
674QCursorData *qt_cursorTable[Qt::LastCursor + 1];
675bool QCursorData::initialized = false;
676
677QCursorData::QCursorData(Qt::CursorShape s)
678 : ref(1), cshape(s), bm(0), bmm(0), hx(0), hy(0)
679{
680}
681
682QCursorData::~QCursorData()
683{
684 delete bm;
685 delete bmm;
686}
687
688/*! \internal */
689void QCursorData::cleanup()
690{
691 if(!QCursorData::initialized)
692 return;
693
694 for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
695 // In case someone has a static QCursor defined with this shape
696 if (!qt_cursorTable[shape]->ref.deref())
697 delete qt_cursorTable[shape];
698 qt_cursorTable[shape] = 0;
699 }
700 QCursorData::initialized = false;
701}
702
703/*! \internal */
704void QCursorData::initialize()
705{
706 if (QCursorData::initialized)
707 return;
708 for (int shape = 0; shape <= Qt::LastCursor; ++shape)
709 qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
710 QCursorData::initialized = true;
711}
712
713QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
714{
715 if (!QCursorData::initialized)
716 QCursorData::initialize();
717 if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
718 qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
719 QCursorData *c = qt_cursorTable[0];
720 c->ref.ref();
721 return c;
722 }
723 QCursorData *d = new QCursorData;
724 d->bm = new QBitmap(bitmap);
725 d->bmm = new QBitmap(mask);
726 d->cshape = Qt::BitmapCursor;
727 d->hx = hotX >= 0 ? hotX : bitmap.width() / 2 / devicePixelRatio;
728 d->hy = hotY >= 0 ? hotY : bitmap.height() / 2 / devicePixelRatio;
729
730 return d;
731}
732
733void QCursorData::update()
734{
735}
736
737QT_END_NAMESPACE
738#endif // QT_NO_CURSOR
739
740