QtBase  v6.3.1
qcursor.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 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 
55 
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  }
204 }
205 
225 {
227 }
228 
250 void QCursor::setPos(QScreen *screen, int x, int y)
251 {
252  if (screen) {
253  if (QPlatformCursor *cursor = screen->handle()->cursor()) {
254  const QPoint pos(x, y);
256  // Need to check, since some X servers generate null mouse move
257  // events, causing looping in applications which call setPos() on
258  // every mouse move event.
259  if (devicePos != cursor->pos())
260  cursor->setPos(devicePos);
261  }
262  }
263 }
264 
276 void QCursor::setPos(int x, int y)
277 {
279 }
280 
281 #ifndef QT_NO_CURSOR
282 
301 /*****************************************************************************
302  QCursor stream functions
303  *****************************************************************************/
304 
305 #ifndef QT_NO_DATASTREAM
306 
307 
318 {
319  s << (qint16)c.shape(); // write shape id to stream
320  if (c.shape() == Qt::BitmapCursor) { // bitmap cursor
321  bool isPixmap = false;
322  if (s.version() >= 7) {
323  isPixmap = !c.pixmap().isNull();
324  s << isPixmap;
325  }
326  if (isPixmap)
327  s << c.pixmap();
328  else
329  s << c.bitmap(Qt::ReturnByValue) << c.mask(Qt::ReturnByValue);
330  s << c.hotSpot();
331  }
332  return s;
333 }
334 
345 {
346  qint16 shape;
347  s >> shape; // read shape id from stream
348  if (shape == Qt::BitmapCursor) { // read bitmap cursor
349  bool isPixmap = false;
350  if (s.version() >= 7)
351  s >> isPixmap;
352  if (isPixmap) {
353  QPixmap pm;
354  QPoint hot;
355  s >> pm >> hot;
356  c = QCursor(pm, hot.x(), hot.y());
357  } else {
358  QBitmap bm, bmm;
359  QPoint hot;
360  s >> bm >> bmm >> hot;
361  c = QCursor(bm, bmm, hot.x(), hot.y());
362  }
363  } else {
364  c.setShape((Qt::CursorShape)shape); // create cursor with shape
365  }
366  return s;
367 }
368 #endif // QT_NO_DATASTREAM
369 
370 
389 QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
390  : d(nullptr)
391 {
394  QBitmap bmm = pixmap.mask();
395  if (!bmm.isNull()) {
396  QBitmap nullBm;
397  bm.setMask(nullBm);
398  }
399  else if (!pixmap.mask().isNull()) {
402  }
403  else {
404  bmm = QBitmap(bm.size());
405  bmm.fill(Qt::color1);
406  }
407 
408  d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio());
409  d->pixmap = pixmap;
410 }
411 
412 
413 
445 QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
446  : d(nullptr)
447 {
448  d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0);
449 }
450 
455 {
458  d = nullptr;
459  return;
460  }
462  }
464  c->ref.ref();
465  d = c;
466 }
467 
476  : d(nullptr)
477 {
480  setShape(shape);
481 }
482 
499 bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept
500 {
501  if (lhs.d == rhs.d)
502  return true; // Copy or same shape
503 
504  // Check pixmaps or bitmaps cache keys. Notice that having BitmapCursor
505  // shape implies either non-null pixmap or non-null bitmap and mask
506  if (lhs.shape() == Qt::BitmapCursor && rhs.shape() == Qt::BitmapCursor
507  && lhs.hotSpot() == rhs.hotSpot()) {
508  if (!lhs.d->pixmap.isNull())
509  return lhs.d->pixmap.cacheKey() == rhs.d->pixmap.cacheKey();
510 
511  if (!rhs.d->pixmap.isNull())
512  return false;
513 
514  return lhs.d->bm->cacheKey() == rhs.d->bm->cacheKey()
515  && lhs.d->bmm->cacheKey() == rhs.d->bmm->cacheKey();
516  }
517 
518  return false;
519 }
520 
536 {
539  return d->cshape;
540 }
541 
550 {
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 
585 {
588  if (d->bm)
589  return *(d->bm);
590  return QBitmap();
591 }
592 
612 {
615  if (d->bmm)
616  return *(d->bmm);
617  return QBitmap();
618 }
619 
626 {
629  return d->pixmap;
630 }
631 
638 {
641  return QPoint(d->hx, d->hy);
642 }
643 
649 {
652  d = c.d;
653  d->ref.ref();
654 }
655 
661 {
662  if (d && !d->ref.deref())
663  delete d;
664 }
665 
666 
673 {
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 
687 QCursor::operator QVariant() const
688 {
689  return QVariant::fromValue(*this);
690 }
691 
692 #ifndef QT_NO_DEBUG_STREAM
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 
706 bool QCursorData::initialized = false;
707 
709  : ref(1), cshape(s), bm(nullptr), bmm(nullptr), hx(0), hy(0)
710 {
711 }
712 
714 {
715  delete bm;
716  delete bmm;
717 }
718 
721 {
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 
736 {
738  return;
739  for (int shape = 0; shape <= Qt::LastCursor; ++shape)
740  qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
742 }
743 
744 QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
745 {
748  if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
749  qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
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 
765 {
766 }
767 
769 #endif // QT_NO_CURSOR
770 
bool ref() noexcept
Definition: qbasicatomic.h:101
bool deref() noexcept
Definition: qbasicatomic.h:102
The QBitmap class provides monochrome (1-bit depth) pixmaps.
Definition: qbitmap.h:52
static QBitmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Definition: qbitmap.cpp:206
static bool startingUp()
QBitmap * bm
Definition: qcursor_p.h:74
short hx
Definition: qcursor_p.h:76
static bool initialized
Definition: qcursor_p.h:77
QBitmap * bmm
Definition: qcursor_p.h:74
QPixmap pixmap
Definition: qcursor_p.h:75
QCursorData(Qt::CursorShape s=Qt::ArrowCursor)
Definition: qcursor.cpp:708
Qt::CursorShape cshape
Definition: qcursor_p.h:73
static QCursorData * setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
Definition: qcursor.cpp:744
void update()
Definition: qcursor.cpp:764
short hy
Definition: qcursor_p.h:76
static void initialize()
Definition: qcursor.cpp:735
static void cleanup()
Definition: qcursor.cpp:720
QAtomicInt ref
Definition: qcursor_p.h:72
The QCursor class provides a mouse cursor with an arbitrary shape.
Definition: qcursor.h:81
QBitmap bitmap() const
Definition: qcursor.cpp:584
QPixmap pixmap() const
Definition: qcursor.cpp:625
~QCursor()
Definition: qcursor.cpp:660
static void setPos(int x, int y)
Definition: qcursor.cpp:276
Qt::CursorShape shape() const
Definition: qcursor.cpp:535
static QPoint pos()
Definition: qcursor.cpp:224
QCursor & operator=(const QCursor &cursor)
Definition: qcursor.cpp:672
QCursor()
Definition: qcursor.cpp:454
QPoint hotSpot() const
Definition: qcursor.cpp:637
void setShape(Qt::CursorShape newShape)
Definition: qcursor.cpp:549
QBitmap mask() const
Definition: qcursor.cpp:611
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
operator>>(QDataStream &ds, qfloat16 &f)
Definition: qfloat16.cpp:344
operator<<(QDataStream &ds, qfloat16 f)
Definition: qfloat16.cpp:327
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
QDebug & nospace()
Definition: qdebug.h:113
Convenience class for custom QDebug operators.
Definition: qdebug.h:176
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
QScreen * primaryScreen
the primary (or default) screen of the application.
static struct QGuiApplicationPrivate::QLastCursorPosition lastCursorPosition
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:73
@ Format_Indexed8
Definition: qimage.h:81
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const &
Definition: qimage.h:160
The QPixmap class is an off-screen image representation that can be used as a paint device.
Definition: qpixmap.h:63
QImage toImage() const
Definition: qpixmap.cpp:443
QSize size() const
Definition: qpixmap.cpp:528
bool isNull() const
Definition: qpixmap.cpp:491
QBitmap mask() const
Definition: qpixmap.cpp:1395
void setMask(const QBitmap &)
Definition: qpixmap.cpp:578
void fill(const QColor &fillColor=Qt::white)
Definition: qpixmap.cpp:883
qreal devicePixelRatio() const
Definition: qpixmap.cpp:611
virtual QPlatformCursor * cursor() const
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
constexpr int x() const noexcept
Definition: qpoint.h:155
constexpr int y() const noexcept
Definition: qpoint.h:160
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition: qscreen.h:68
QScreen * virtualSiblingAt(QPoint point)
Definition: qscreen.cpp:716
QPlatformScreen * handle() const
Definition: qscreen.cpp:177
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
QRhiGraphicsPipeline * ps
QCursor cursor
T toNativePixels(const T &value, const C *context)
T fromNativePixels(const T &value, const C *context)
@ AvoidDither
Definition: qnamespace.h:523
@ ThresholdDither
Definition: qnamespace.h:517
CursorShape
Definition: qnamespace.h:1176
@ BitmapCursor
Definition: qnamespace.h:1200
@ LastCursor
Definition: qnamespace.h:1199
@ color1
Definition: qnamespace.h:60
@ ReturnByValue
Definition: qnamespace.h:1733
QCursorData * qt_cursorTable[Qt::LastCursor+1]
Definition: qcursor.cpp:705
short qint16
Definition: qglobal.h:285
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
unsigned int uint
Definition: qglobal.h:334
#define qWarning
Definition: qlogging.h:179
GLint GLint GLint GLint GLint x
[0]
GLint ref
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint y
const GLubyte * c
Definition: qopenglext.h:12701
GLint void * img
Definition: qopenglext.h:233
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
Definition: qopenglext.h:5182
GLdouble s
[6]
Definition: qopenglext.h:235
QScreen * screen
[1]
Definition: main.cpp:76
QObject::connect nullptr
QBitmap bm(8, 8, arrow_bits, true)
widget render & pixmap
#define rhs