Coverage Report

Created: 2026-06-30 07:44

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