OSDN Git Service

QCursor rewrite
authorIvailo Monev <xakepa10@gmail.com>
Mon, 14 Nov 2022 00:33:31 +0000 (02:33 +0200)
committerIvailo Monev <xakepa10@gmail.com>
Mon, 14 Nov 2022 00:33:31 +0000 (02:33 +0200)
X may or may not copy the pixmaps so handles have to be kept until cursor
data destruction

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
src/gui/kernel/qapplication_x11.cpp
src/gui/kernel/qcursor.cpp
src/gui/kernel/qcursor.h
src/gui/kernel/qcursor_p.h
src/gui/kernel/qcursor_x11.cpp
src/gui/kernel/qdnd_x11.cpp
tests/auto/qdatastream/tst_qdatastream.cpp

index 3747093..ec9feba 100644 (file)
@@ -1201,11 +1201,6 @@ void qt_init(QApplicationPrivate *priv, Display *display,
     // initialize key mapper
     QKeyMapper::changeKeyboard();
 
-    // Misc. initialization
-#ifndef QT_NO_CURSOR
-    QCursorData::initialize();
-#endif // QT_NO_CURSOR
-
     qApp->setObjectName(qApp->applicationName());
 
     for (int screen = 0; screen < qt_x11Data->screenCount; ++screen) {
@@ -1264,9 +1259,6 @@ void qt_cleanup()
 #endif
 
     QPixmapCache::clear();
-#ifndef QT_NO_CURSOR
-    QCursorData::cleanup();
-#endif // QT_NO_CURSOR
 
     // Reset the error handlers
     XSync(qt_x11Data->display, False); // sync first to process all possible errors
index cb9f8b5..4c58bb2 100644 (file)
@@ -23,8 +23,6 @@
 
 #ifndef QT_NO_CURSOR
 
-#include "qapplication.h"
-#include "qbitmap.h"
 #include "qimage.h"
 #include "qdatastream.h"
 #include "qvariant.h"
@@ -46,8 +44,8 @@ QT_BEGIN_NAMESPACE
     associated with particular widgets and to get and set the position
     of the mouse cursor.
 
-    Qt has a number of standard cursor shapes, but you can also make
-    custom cursor shapes based on a QBitmap, a mask and a hotspot.
+    Katie has a number of standard cursor shapes, but you can also make
+    custom cursor shapes based on a QPixmap and a hotspot.
 
     To associate a cursor with a widget, use QWidget::setCursor(). To
     associate a cursor with all widgets (normally for a short period
@@ -57,9 +55,8 @@ QT_BEGIN_NAMESPACE
     constructor which takes the shape as argument, or you can use one
     of the predefined cursors defined in the \l Qt::CursorShape enum.
 
-    If you want to create a cursor with your own bitmap, either use
-    the QCursor constructor which takes a bitmap and a mask or the
-    constructor which takes a pixmap as arguments.
+    If you want to create a cursor with your own pixmap, use the
+    QCursor constructor which takes a pixmap as arguments.
 
     To set or get the position of the mouse cursor use the static
     methods QCursor::pos() and QCursor::setPos().
@@ -80,7 +77,7 @@ QT_BEGIN_NAMESPACE
     cursor will be used instead. Note: X11 does not provide
     appropriate cursors for all possible Qt::CursorShape values. It
     is possible that some cursors will be taken from the Xcursor
-    theme, while others will use an internal bitmap cursor.
+    theme, while others will use an internal pixmap cursor.
 
     \table
     \header \o Shape \o Qt::CursorShape Value \o Cursor Name
@@ -133,27 +130,15 @@ QT_BEGIN_NAMESPACE
 */
 
 /*!
-    \fn HCURSOR_or_HANDLE QCursor::handle() const
+    \fn Qt::HANDLE QCursor::handle() const
 
-    Returns a platform-specific cursor handle. The \c
-    HCURSOR_or_HANDLE type is \c HCURSOR on Windows and Qt::HANDLE on X11
-    and Mac OS X. On \l{Qt for Embedded Linux} it is an integer.
+    Returns a platform-specific cursor handle, Qt::HANDLE on X11/
 
     \warning Using the value returned by this function is not
     portable.
 */
 
 /*!
-    \fn QCursor::QCursor(HCURSOR cursor)
-
-    Constructs a Qt cursor from the given Windows \a cursor.
-
-    \warning This function is only available on Windows.
-
-    \sa handle()
-*/
-
-/*!
     \fn QCursor::QCursor(Qt::HANDLE handle)
 
     Constructs a Qt cursor from the given \a handle.
@@ -201,8 +186,6 @@ QT_BEGIN_NAMESPACE
  *****************************************************************************/
 
 #ifndef QT_NO_DATASTREAM
-
-
 /*!
     \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
     \relates QCursor
@@ -211,17 +194,11 @@ QT_BEGIN_NAMESPACE
 
     \sa {Serializing Qt Data Types}
 */
-
 QDataStream &operator<<(QDataStream &s, const QCursor &c)
 {
-    s << (qint16)c.shape();                        // write shape id to stream
-    if (c.shape() == Qt::BitmapCursor) {                // bitmap cursor
-        bool isPixmap = !c.pixmap().isNull();
-        s << isPixmap;
-        if (isPixmap)
-            s << c.pixmap();
-        else
-            s << *c.bitmap() << *c.mask();
+    s << (qint16)c.shape();
+    if (c.shape() == Qt::BitmapCursor) {
+        s << c.pixmap();
         s << c.hotSpot();
     }
     return s;
@@ -235,33 +212,22 @@ QDataStream &operator<<(QDataStream &s, const QCursor &c)
 
     \sa {Serializing Qt Data Types}
 */
-
 QDataStream &operator>>(QDataStream &s, QCursor &c)
 {
-    qint16 shape;
-    s >> shape;                                        // read shape id from stream
-    if (shape == Qt::BitmapCursor) {                // read bitmap cursor
-        bool isPixmap = false;
-        s >> isPixmap;
-        if (isPixmap) {
-            QPixmap pm;
-            QPoint hot;
-            s >> pm >> hot;
-            c = QCursor(pm, hot.x(), hot.y());
-        } else {
-            QBitmap bm, bmm;
-            QPoint hot;
-            s >> bm >> bmm >> hot;
-            c = QCursor(bm, bmm, hot.x(), hot.y());
-        }
+    qint16 shape = Qt::ArrowCursor;
+    s >> shape;
+    if (shape == Qt::BitmapCursor) {
+        QPixmap pm;
+        QPoint hot;
+        s >> pm >> hot;
+        c = QCursor(pm, hot.x(), hot.y());
     } else {
-        c.setShape((Qt::CursorShape)shape);                // create cursor with shape
+        c.setShape(static_cast<Qt::CursorShape>(shape));                // create cursor with shape
     }
     return s;
 }
 #endif // QT_NO_DATASTREAM
 
-
 /*!
     Constructs a custom pixmap cursor.
 
@@ -279,111 +245,65 @@ QDataStream &operator>>(QDataStream &s, QCursor &c)
 
     \sa QPixmap::QPixmap(), QPixmap::setMask()
 */
-
 QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
     : d(nullptr)
 {
-    d = QCursorData::setBitmap(QBitmap(pixmap), pixmap.mask(), hotX, hotY);
-    d->pixmap = pixmap;
+    d = QCursorData::setBitmap(pixmap, pixmap.mask(), hotX, hotY);
 }
 
-
-
 /*!
-    Constructs a custom bitmap cursor.
-
-    \a bitmap and
-    \a mask make up the bitmap.
-    \a hotX and
-    \a hotY define the cursor's hot spot.
-
-    If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
-    If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
-
-    The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
-    \list
-    \o B=1 and M=1 gives black.
-    \o B=0 and M=1 gives white.
-    \o B=0 and M=0 gives transparent.
-    \o B=1 and M=0 gives an XOR'd result under Windows, undefined
-    results on all other platforms.
-    \endlist
-
-    Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
-    draw 1-pixels in the bitmaps.
-
-    Valid cursor sizes depend on the display hardware (or the
-    underlying window system). We recommend using 32 x 32 cursors,
-    because this size is supported on all platforms. Some platforms
-    also support 16 x 16, 48 x 48, and 64 x 64 cursors.
-
-    \sa QBitmap::QBitmap(), QBitmap::setMask()
+    Constructs a cursor with the default arrow shape.
 */
-
-QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
-    : d(QCursorData::setBitmap(bitmap, mask, hotX, hotY))
+QCursor::QCursor()
+    : d(nullptr)
 {
+    setShape(Qt::ArrowCursor);
 }
 
-QCursorData *qt_cursorTable[Qt::LastCursor + 1];
-bool QCursorData::initialized = false;
+/*!
+    Constructs a cursor with the specified \a shape.
+
+    See \l Qt::CursorShape for a list of shapes.
 
-/*! \internal */
-void QCursorData::cleanup()
+    \sa setShape()
+*/
+QCursor::QCursor(Qt::CursorShape shape)
+    : d(nullptr)
 {
-    if(!QCursorData::initialized)
-        return;
-
-    for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
-        // In case someone has a static QCursor defined with this shape
-        if (!qt_cursorTable[shape]->ref.deref())
-            delete qt_cursorTable[shape];
-        qt_cursorTable[shape] = 0;
-    }
-    QCursorData::initialized = false;
+    setShape(shape);
 }
 
-/*! \internal */
-void QCursorData::initialize()
+/*!
+    Constructs a copy of the cursor \a other.
+*/
+QCursor::QCursor(const QCursor &other)
+    : d(other.d)
 {
-    if (QCursorData::initialized)
-        return;
-    for (int shape = 0; shape <= Qt::LastCursor; ++shape)
-        qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
-    QCursorData::initialized = true;
+    if (d) {
+        d->ref.ref();
+    }
 }
 
 /*!
-    Constructs a cursor with the default arrow shape.
+    Destroys the cursor.
 */
-QCursor::QCursor()
+QCursor::~QCursor()
 {
-    if (!QCursorData::initialized) {
-        if (QApplication::startingUp()) {
-            d = 0;
-            return;
-        }
-        QCursorData::initialize();
+    if (d && !d->ref.deref()) {
+        delete d;
     }
-    QCursorData *c = qt_cursorTable[0];
-    c->ref.ref();
-    d = c;
 }
 
 /*!
-    Constructs a cursor with the specified \a shape.
-
-    See \l Qt::CursorShape for a list of shapes.
-
-    \sa setShape()
+    Assigns \a other to this cursor and returns a reference to this
+    cursor.
 */
-QCursor::QCursor(Qt::CursorShape shape)
-    : d(nullptr)
+QCursor &QCursor::operator=(const QCursor &other)
 {
-    setShape(shape);
+    qAtomicAssign(d, other.d);
+    return *this;
 }
 
-
 /*!
     Returns the cursor shape identifier. The return value is one of
     the \l Qt::CursorShape enum values (cast to an int).
@@ -392,8 +312,9 @@ QCursor::QCursor(Qt::CursorShape shape)
 */
 Qt::CursorShape QCursor::shape() const
 {
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
+    if (!d) {
+        return Qt::ArrowCursor;
+    }
     return d->cshape;
 }
 
@@ -406,42 +327,13 @@ Qt::CursorShape QCursor::shape() const
 */
 void QCursor::setShape(Qt::CursorShape shape)
 {
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : 0;
-    if (!c)
-        c = qt_cursorTable[0];
-    c->ref.ref();
-    if (!d) {
-        d = c;
-    } else {
-        if (!d->ref.deref())
-            delete d;
-        d = c;
+    if (d && !d->ref.deref()) {
+        delete d;
+        d = nullptr;
+    }
+    if (shape <= Qt::LastCursor) {
+        d = new QCursorData(shape);
     }
-}
-
-/*!
-    Returns the cursor bitmap, or 0 if it is one of the standard
-    cursors.
-*/
-const QBitmap *QCursor::bitmap() const
-{
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    return d->bm;
-}
-
-/*!
-    Returns the cursor bitmap mask, or 0 if it is one of the standard
-    cursors.
-*/
-
-const QBitmap *QCursor::mask() const
-{
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    return d->bmm;
 }
 
 /*!
@@ -451,9 +343,10 @@ const QBitmap *QCursor::mask() const
 
 QPixmap QCursor::pixmap() const
 {
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    return d->pixmap;
+    if (!d) {
+        return QPixmap();
+    }
+    return d->px;
 }
 
 /*!
@@ -463,48 +356,13 @@ QPixmap QCursor::pixmap() const
 
 QPoint QCursor::hotSpot() const
 {
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
+    if (!d) {
+        return QPoint(0, 0);
+    }
     return QPoint(d->hx, d->hy);
 }
 
 /*!
-    Constructs a copy of the cursor \a other.
-*/
-
-QCursor::QCursor(const QCursor &other)
-{
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    d = other.d;
-    d->ref.ref();
-}
-
-/*!
-    Destroys the cursor.
-*/
-
-QCursor::~QCursor()
-{
-    if (d && !d->ref.deref())
-        delete d;
-}
-
-
-/*!
-    Assigns \a other to this cursor and returns a reference to this
-    cursor.
-*/
-
-QCursor &QCursor::operator=(const QCursor &other)
-{
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    qAtomicAssign(d, other.d);
-    return *this;
-}
-
-/*!
    Returns the cursor as a QVariant.
 */
 QCursor::operator QVariant() const
index 3a62103..bab968d 100644 (file)
@@ -46,7 +46,6 @@ private:
 #else // QT_NO_CURSOR
 
 class QCursorData;
-class QBitmap;
 class QPixmap;
 
 class Q_GUI_EXPORT QCursor
@@ -54,7 +53,6 @@ class Q_GUI_EXPORT QCursor
 public:
     QCursor();
     QCursor(Qt::CursorShape shape);
-    QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX=-1, int hotY=-1);
     QCursor(const QPixmap &pixmap, int hotX=-1, int hotY=-1);
     QCursor(const QCursor &cursor);
     ~QCursor();
@@ -66,8 +64,6 @@ public:
     Qt::CursorShape shape() const;
     void setShape(Qt::CursorShape newShape);
 
-    const QBitmap *bitmap() const;
-    const QBitmap *mask() const;
     QPixmap pixmap() const;
     QPoint hotSpot() const;
 
index ae91320..765c1c7 100644 (file)
@@ -36,6 +36,7 @@
 #include "QtCore/qatomic.h"
 #include "QtCore/qnamespace.h"
 #include "QtGui/qpixmap.h"
+#include "QtGui/qbitmap.h"
 
 #if defined(Q_WS_X11)
 #  include "qt_x11_p.h"
 
 QT_BEGIN_NAMESPACE
 
-class QBitmap;
 class QCursorData {
 public:
-    QCursorData(Qt::CursorShape s = Qt::ArrowCursor);
+    QCursorData(Qt::CursorShape s);
     ~QCursorData();
 
-    static void initialize();
-    static void cleanup();
-
     QAtomicInt ref;
     Qt::CursorShape cshape;
-    QBitmap  *bm, *bmm;
-    QPixmap pixmap;
-    short     hx, hy;
+    QPixmap px;
+    QBitmap bm;
+    short hx, hy;
 #if defined(Q_WS_X11)
     XColor fg, bg;
     Cursor hcurs;
-    Pixmap pm;
+    Qt::HANDLE x11px;
+    Qt::HANDLE x11bm;
+#ifndef QT_NO_XRENDER
+    Picture x11pic;
+#endif
 #endif
-    static bool initialized;
-    void update();
-    static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY);
-};
 
-extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
+    static QCursorData *setBitmap(const QPixmap &pixmap, const QBitmap &mask, int hotX, int hotY);
+};
 
 QT_END_NAMESPACE
 
index 8693378..01f2ad6 100644 (file)
 QT_BEGIN_NAMESPACE
 
 #ifndef QT_NO_CURSOR
+// values are from:
+// https://www.freedesktop.org/wiki/Specifications/cursor-spec/
+// https://tronche.com/gui/x/xlib/appendix/b/
+static const struct CursorTblData {
+    const int font;
+    const char* name;
+    const char* alternative;
+} CursorTbl[] = {
+    { XC_left_ptr, "left_ptr", "default" }, // Qt::ArrowCursor
+    { XC_center_ptr, "up_arrow", nullptr }, // Qt::UpArrowCursor
+    { XC_crosshair, "cross", "crosshair" }, // Qt::CrossCursor
+    { XC_watch, "wait", "watch" }, // Qt::WaitCursor
+    { XC_xterm, "ibeam", "text" }, // Qt::IBeamCursor
+    { XC_sb_v_double_arrow, "size_ver", "ns-resize" }, // Qt::SizeVerCursor
+    { XC_sb_h_double_arrow, "size_hor", "ew-resize" }, // Qt::SizeHorCursor
+    { XC_top_right_corner, "size_bdiag", "nwse-resize" }, // Qt::SizeBDiagCursor
+    { XC_bottom_right_corner, "size_fdiag", "nesw-resize" }, // Qt::SizeFDiagCursor
+    { XC_fleur, "size_all", nullptr }, // Qt::SizeAllCursor
+    { -1, "blank", nullptr }, // Qt::BlankCursor
+    { XC_sb_v_double_arrow, "split_v", "row-resize" }, // Qt::SplitVCursor
+    { XC_sb_h_double_arrow, "split_h", "col-resize" }, // Qt::SplitHCursor
+    { XC_hand2, "pointing_hand", "pointer" }, // Qt::PointingHandCursor
+    { XC_circle, "forbidden", "not-allowed" }, // Qt::ForbiddenCursor
+    { XC_question_arrow, "whats_this", "help" }, // Qt::WhatsThisCursor
+    { XC_watch, "left_ptr_watch", "half-busy" }, // Qt::BusyCursor
+    { -1, "openhand", "grab" }, // Qt::OpenHandCursor
+    { -1, "closedhand", "grabbing" }, // Qt::ClosedHandCursor
+    { XC_tcross, "copy", "dnd-copy" }, // Qt::DragCopyCursor
+    { XC_top_left_arrow, "move", "dnd-move" }, // Qt::DragMoveCursor
+    { XC_center_ptr, "link", "dnd-link" }, // Qt::DragLinkCursor
+};
+
+static const char x11_blank_cursor_bits[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 /*****************************************************************************
   Internal QCursorData class
  *****************************************************************************/
 
 QCursorData::QCursorData(Qt::CursorShape s)
-    : ref(1), cshape(s), bm(nullptr), bmm(nullptr), hx(0), hy(0), hcurs(0), pm(0)
+    : ref(1), cshape(s), hx(0), hy(0), hcurs(0), x11px(0), x11bm(0)
+#ifndef QT_NO_XRENDER
+    , x11pic(0)
+#endif
 {
 }
 
 QCursorData::~QCursorData()
 {
-    Display *dpy = qt_x11Data ? qt_x11Data->display : (Display*)0;
+    Display *dpy = (qt_x11Data ? qt_x11Data->display : nullptr);
 
     // Add in checking for the display too as on HP-UX
     // we seem to get a core dump as the cursor data is
     // deleted again from main() on exit...
-    if (hcurs && dpy)
+    if (hcurs && dpy) {
         XFreeCursor(dpy, hcurs);
-    if (pm && dpy)
-        XFreePixmap(dpy, pm);
-    delete bm;
-    delete bmm;
-}
-
-QCursor::QCursor(Qt::HANDLE cursor)
-{
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    d = new QCursorData(Qt::CustomCursor);
-    d->hcurs = cursor;
+    }
+#ifndef QT_NO_XRENDER
+    if (x11pic) {
+        XRenderFreePicture(dpy, x11pic);
+    }
+#endif
+    if (x11px && dpy) {
+        XFreePixmap(dpy, x11px);
+    }
+    if (x11bm && dpy) {
+        XFreePixmap(dpy, x11bm);
+    }
 }
 
-QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+QCursorData *QCursorData::setBitmap(const QPixmap &pixmap, const QBitmap &mask, int hotX, int hotY)
 {
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    if (Q_UNLIKELY(bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size())) {
+    if (Q_UNLIKELY(mask.depth() != 1 || pixmap.size() != mask.size())) {
         qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
-        QCursorData *c = qt_cursorTable[0];
-        c->ref.ref();
-        return c;
+        return nullptr;
     }
     QCursorData *d = new QCursorData(Qt::BitmapCursor);
 
-    d->bm  = new QBitmap(bitmap);
-    d->bmm = new QBitmap(mask);
-    d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
-    d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+    d->px = pixmap;
+    d->bm = mask;
+    d->hx = (hotX >= 0 ? hotX : (pixmap.width() / 2));
+    d->hy = (hotY >= 0 ? hotY : (pixmap.height() / 2));
     d->fg.red   = 0x0000;
     d->fg.green = 0x0000;
     d->fg.blue  = 0x0000;
@@ -85,14 +123,102 @@ QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask,
     return d;
 }
 
+QCursor::QCursor(Qt::HANDLE cursor)
+    : d(new QCursorData(Qt::CustomCursor))
+{
+    d->hcurs = cursor;
+}
+
 Qt::HANDLE QCursor::handle() const
 {
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    if (!d->hcurs)
-        d->update();
+    if (!d) {
+        return 0;
+    }
+
+    Display *dpy = qt_x11Data->display;
+    if (!dpy) {
+        return 0;
+    }
+
+    if (!d->hcurs) {
+        // Non-standard X11 cursors are created from bitmaps
+        if (d->cshape == Qt::BitmapCursor) {
+#ifndef QT_NO_XRENDER
+            if (!d->px.isNull() && qt_x11Data->use_xrender) {
+                d->x11px = d->px.toX11Pixmap();
+                XRenderPictFormat *format = (d->px.depth() == 1)
+                                        ? XRenderFindStandardFormat(dpy, PictStandardA1)
+                                        : XRenderFindStandardFormat(dpy, PictStandardARGB32);
+                d->x11pic = XRenderCreatePicture(dpy, d->x11px, format, 0, 0);
+                if (d->x11pic) {
+                    d->hcurs = XRenderCreateCursor(dpy, d->x11pic, d->hx, d->hy);
+                }
+                return d->hcurs;
+            }
+#endif
+            if (!d->px.isNull()) {
+                d->x11px = d->px.toX11Pixmap();
+                d->x11bm = d->px.mask().toX11Pixmap();
+                d->hcurs = XCreatePixmapCursor(dpy, d->x11px, d->x11bm, &d->fg, &d->bg, d->hx, d->hy);
+            }
+            return d->hcurs;
+        }
+
+#ifndef QT_NO_XCURSOR
+        if (!d->hcurs) {
+            d->hcurs = XcursorLibraryLoadCursor(dpy, CursorTbl[d->cshape].name);
+        }
+        if (!d->hcurs && CursorTbl[d->cshape].alternative) {
+            d->hcurs = XcursorLibraryLoadCursor(dpy, CursorTbl[d->cshape].alternative);
+        }
+        if (d->hcurs) {
+            return d->hcurs;
+        }
+#endif // QT_NO_XCURSOR
+
+        // Q cursor to X cursor
+        if (d->cshape == Qt::BlankCursor) {
+            XColor bg, fg;
+            bg.red   = 255 << 8;
+            bg.green = 255 << 8;
+            bg.blue  = 255 << 8;
+            fg.red   = 0;
+            fg.green = 0;
+            fg.blue  = 0;
+            d->x11bm = XCreateBitmapFromData(dpy, QX11Info::appRootWindow(), x11_blank_cursor_bits, 16, 16);
+            // reusing the pixmap as mask to create invisible cursor
+            d->hcurs = XCreatePixmapCursor(dpy, d->x11bm, d->x11bm, &fg, &bg, 8, 8);
+        } else {
+            d->hcurs = XCreateFontCursor(dpy, CursorTbl[d->cshape].font);
+            if (Q_UNLIKELY(!d->hcurs)) {
+                qWarning("QCursor::update: Invalid cursor shape %d", d->cshape);
+#ifndef QT_NO_XFIXES
+            } else if (qt_x11Data->use_xfixes) {
+                XFixesSetCursorName(dpy, d->hcurs, CursorTbl[d->cshape].name);
+#endif
+            }
+        }
+    }
     return d->hcurs;
 }
+
+/*! \internal
+*/
+int QCursor::x11Screen()
+{
+    Window root;
+    Window child;
+    int root_x, root_y, win_x, win_y;
+    uint buttons;
+    Display* dpy = qt_x11Data->display;
+    for (int i = 0; i < ScreenCount(dpy); ++i) {
+        if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
+                          &win_x, &win_y, &buttons)) {
+            return i;
+        }
+    }
+    return -1;
+}
 #endif // QT_NO_CURSOR
 
 QPoint QCursor::pos()
@@ -104,16 +230,17 @@ QPoint QCursor::pos()
     Display* dpy = qt_x11Data->display;
     for (int i = 0; i < ScreenCount(dpy); ++i) {
         if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
-                          &win_x, &win_y, &buttons))
-
+                          &win_x, &win_y, &buttons)) {
             return QPoint(root_x, root_y);
+        }
     }
     return QPoint();
 }
 
 void QCursor::setPos(int x, int y)
 {
-    QPoint current, target(x, y);
+    QPoint current;
+    QPoint target(x, y);
 
     // this is copied from pos(), since we need the screen number for the correct
     // root window in the XWarpPointer call
@@ -131,155 +258,19 @@ void QCursor::setPos(int x, int y)
         }
     }
 
-    if (screen >= ScreenCount(dpy))
+    if (screen >= ScreenCount(dpy)) {
         return;
+    }
 
     // Need to check, since some X servers generate null mouse move
     // events, causing looping in applications which call setPos() on
     // every mouse move event.
-    if (current == target)
+    if (current == target) {
         return;
-
-    XWarpPointer(qt_x11Data->display, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y);
-}
-
-
-/*! \internal
-*/
-#ifndef QT_NO_CURSOR
-int QCursor::x11Screen()
-{
-    Window root;
-    Window child;
-    int root_x, root_y, win_x, win_y;
-    uint buttons;
-    Display* dpy = qt_x11Data->display;
-    for (int i = 0; i < ScreenCount(dpy); ++i) {
-        if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y,
-                          &win_x, &win_y, &buttons))
-            return i;
     }
-    return -1;
-}
 
-// values are from:
-// https://www.freedesktop.org/wiki/Specifications/cursor-spec/
-// https://tronche.com/gui/x/xlib/appendix/b/
-static const struct CursorTblData {
-    const int font;
-    const char* name;
-    const char* alternative;
-} CursorTbl[] = {
-    { XC_left_ptr, "left_ptr", "default" }, // Qt::ArrowCursor
-    { XC_center_ptr, "up_arrow", nullptr }, // Qt::UpArrowCursor
-    { XC_crosshair, "cross", "crosshair" }, // Qt::CrossCursor
-    { XC_watch, "wait", "watch" }, // Qt::WaitCursor
-    { XC_xterm, "ibeam", "text" }, // Qt::IBeamCursor
-    { XC_sb_v_double_arrow, "size_ver", "ns-resize" }, // Qt::SizeVerCursor
-    { XC_sb_h_double_arrow, "size_hor", "ew-resize" }, // Qt::SizeHorCursor
-    { XC_top_right_corner, "size_bdiag", "nwse-resize" }, // Qt::SizeBDiagCursor
-    { XC_bottom_right_corner, "size_fdiag", "nesw-resize" }, // Qt::SizeFDiagCursor
-    { XC_fleur, "size_all", nullptr }, // Qt::SizeAllCursor
-    { -1, "blank", nullptr }, // Qt::BlankCursor
-    { XC_sb_v_double_arrow, "split_v", "row-resize" }, // Qt::SplitVCursor
-    { XC_sb_h_double_arrow, "split_h", "col-resize" }, // Qt::SplitHCursor
-    { XC_hand2, "pointing_hand", "pointer" }, // Qt::PointingHandCursor
-    { XC_circle, "forbidden", "not-allowed" }, // Qt::ForbiddenCursor
-    { XC_question_arrow, "whats_this", "help" }, // Qt::WhatsThisCursor
-    { XC_watch, "left_ptr_watch", "half-busy" }, // Qt::BusyCursor
-    { -1, "openhand", "grab" }, // Qt::OpenHandCursor
-    { -1, "closedhand", "grabbing" }, // Qt::ClosedHandCursor
-    { XC_tcross, "copy", "dnd-copy" }, // Qt::DragCopyCursor
-    { XC_top_left_arrow, "move", "dnd-move" }, // Qt::DragMoveCursor
-    { XC_center_ptr, "link", "dnd-link" }, // Qt::DragLinkCursor
-};
-
-static const char x11_blank_cursor_bits[] = {
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/*!
-    \internal
-
-    Creates the cursor.
-*/
-void QCursorData::update()
-{
-    if (!QCursorData::initialized)
-        QCursorData::initialize();
-    if (hcurs)
-        return;
-
-    Display *dpy = qt_x11Data->display;
-
-    // Non-standard X11 cursors are created from bitmaps
-    if (cshape == Qt::BitmapCursor) {
-#ifndef QT_NO_XRENDER
-        if (!pixmap.isNull() && qt_x11Data->use_xrender) {
-            Qt::HANDLE pxpixmap = pixmap.toX11Pixmap();
-            XRenderPictFormat *format = (pixmap.depth() == 1)
-                                    ? XRenderFindStandardFormat(dpy, PictStandardA1)
-                                    : XRenderFindStandardFormat(dpy, PictStandardARGB32);
-            Picture picture = XRenderCreatePicture(dpy, pxpixmap, format, 0, 0);
-            if (picture) {
-                hcurs = XRenderCreateCursor(dpy, picture, hx, hy);
-                XRenderFreePicture(dpy, picture);
-            }
-            if (pxpixmap) {
-                XFreePixmap(dpy, pxpixmap);
-            }
-        } else
-#endif
-        {
-            Qt::HANDLE bmpixmap = bm->toX11Pixmap();
-            Qt::HANDLE bmmpixmap = bmm->toX11Pixmap();
-            hcurs = XCreatePixmapCursor(dpy, bmpixmap, bmmpixmap, &fg, &bg, hx, hy);
-            if (bmpixmap) {
-                XFreePixmap(dpy, bmpixmap);
-            }
-            if (bmmpixmap) {
-                XFreePixmap(dpy, bmmpixmap);
-            }
-        }
-        return;
-    }
-
-#ifndef QT_NO_XCURSOR
-    if (!hcurs)
-        hcurs = XcursorLibraryLoadCursor(dpy, CursorTbl[cshape].name);
-    if (!hcurs && CursorTbl[cshape].alternative)
-        hcurs = XcursorLibraryLoadCursor(dpy, CursorTbl[cshape].alternative);
-    if (hcurs)
-        return;
-#endif // QT_NO_XCURSOR
-
-    // Q cursor to X cursor
-    if (cshape == Qt::BlankCursor) {
-        XColor bg, fg;
-        bg.red   = 255 << 8;
-        bg.green = 255 << 8;
-        bg.blue  = 255 << 8;
-        fg.red   = 0;
-        fg.green = 0;
-        fg.blue  = 0;
-        pm  = XCreateBitmapFromData(dpy, QX11Info::appRootWindow(), x11_blank_cursor_bits, 16, 16);
-        // reusing the pixmap as mask to create invisible cursor
-        hcurs = XCreatePixmapCursor(dpy, pm, pm, &fg, &bg, 8, 8);
-    } else {
-        hcurs = XCreateFontCursor(dpy, CursorTbl[cshape].font);
-        if (Q_UNLIKELY(!hcurs)) {
-            qWarning("QCursor::update: Invalid cursor shape %d", cshape);
-#ifndef QT_NO_XFIXES
-        } else if (qt_x11Data->use_xfixes) {
-            XFixesSetCursorName(dpy, hcurs, CursorTbl[cshape].name);
-#endif
-        }
-    }
+    XWarpPointer(qt_x11Data->display, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y);
 }
-#endif // QT_NO_CURSOR
 
 QT_END_NAMESPACE
 
index cc1e829..0f6064a 100644 (file)
@@ -601,9 +601,6 @@ Atom QX11Data::xdndMimeAtomForFormat(const QString &format, QVariant::Type reque
 }
 
 void QX11Data::xdndSetup() {
-#ifndef QT_NO_CURSOR
-    QCursorData::initialize();
-#endif // QT_NO_CURSOR
     qAddPostRoutine(qt_xdnd_cleanup);
 }
 
index 9786b25..b299132 100644 (file)
@@ -981,7 +981,7 @@ static QCursor qCursorData(int index)
         case 3: return QCursor(Qt::BlankCursor);
         case 4: return QCursor(Qt::BlankCursor);
         case 5: return QCursor(QPixmap(open_png), 1, 1);
-        case 6: { QPixmap pm(open_png); return QCursor(QBitmap(pm), pm.mask(), 3, 4); }
+        case 6: return QCursor(QPixmap(open_png), 3, 4);
         case 7: return QCursor(QPixmap(open_png), -1, 5);
         case 8: return QCursor(QPixmap(open_png), 5, -1);
     }
@@ -1021,12 +1021,7 @@ void tst_QDataStream::readQCursor(QDataStream *s)
 
     QVERIFY(d5.shape() == test.shape()); //## lacks operator==
     QVERIFY(d5.hotSpot() == test.hotSpot());
-    QVERIFY((d5.bitmap() != 0 && test.bitmap() != 0) || (d5.bitmap() == 0 && test.bitmap() == 0));
-    if (d5.bitmap() != 0)
-        QVERIFY(d5.bitmap()->toImage() == test.bitmap()->toImage());
-    QVERIFY((d5.mask() != 0 && test.mask() != 0) || (d5.mask() == 0 && test.mask() == 0));
-    if (d5.mask() != 0)
-        QVERIFY(d5.mask()->toImage() == test.mask()->toImage());
+    QVERIFY(d5.pixmap().toImage() == test.pixmap().toImage());
 #endif
 }