Coverage Report

Created: 2025-07-16 07:53

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