1// Copyright (C) 2022 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#pragma once
5
6#include <qpa/qplatformcursor.h>
7#include "qxcbscreen.h"
8#include <xcb/xcb_cursor.h>
9
10#include <QtCore/QCache>
11
12QT_BEGIN_NAMESPACE
13
14#ifndef QT_NO_CURSOR
15
16struct QXcbCursorCacheKey
17{
18 explicit QXcbCursorCacheKey(const QCursor &c);
19 explicit QXcbCursorCacheKey(Qt::CursorShape s) : shape(s), bitmapCacheKey(0), maskCacheKey(0) {}
20 QXcbCursorCacheKey() : shape(Qt::CustomCursor), bitmapCacheKey(0), maskCacheKey(0) {}
21
22 Qt::CursorShape shape;
23 qint64 bitmapCacheKey;
24 qint64 maskCacheKey;
25 union {
26 qint64 hashKey;
27 struct {
28 qint32 x;
29 qint32 y;
30 };
31 } hotspotCacheKey;
32};
33
34inline bool operator==(const QXcbCursorCacheKey &k1, const QXcbCursorCacheKey &k2)
35{
36 return k1.shape == k2.shape &&
37 k1.bitmapCacheKey == k2.bitmapCacheKey &&
38 k1.maskCacheKey == k2.maskCacheKey &&
39 k1.hotspotCacheKey.hashKey == k2.hotspotCacheKey.hashKey;
40}
41
42inline size_t qHash(const QXcbCursorCacheKey &k, size_t seed) noexcept
43{
44 return (size_t(k.shape) + size_t(k.bitmapCacheKey) + size_t(k.maskCacheKey)) ^ seed;
45}
46
47#endif // !QT_NO_CURSOR
48
49class QXcbCursor : public QXcbObject, public QPlatformCursor
50{
51public:
52 QXcbCursor(QXcbConnection *conn, QXcbScreen *screen);
53 ~QXcbCursor();
54#ifndef QT_NO_CURSOR
55 void changeCursor(QCursor *cursor, QWindow *window) override;
56#endif
57 QPoint pos() const override;
58 void setPos(const QPoint &pos) override;
59
60 QSize size() const override;
61
62 void updateContext();
63
64 static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = nullptr);
65
66#ifndef QT_NO_CURSOR
67 xcb_cursor_t xcbCursor(const QCursor &c) const
68 { return m_cursorHash.value(key: QXcbCursorCacheKey(c), defaultValue: xcb_cursor_t(0)); }
69#endif
70
71private:
72
73#ifndef QT_NO_CURSOR
74 typedef QHash<QXcbCursorCacheKey, xcb_cursor_t> CursorHash;
75
76 struct CachedCursor
77 {
78 explicit CachedCursor(xcb_connection_t *conn, xcb_cursor_t c)
79 : cursor(c), connection(conn) {}
80 ~CachedCursor() { xcb_free_cursor(c: connection, cursor); }
81 xcb_cursor_t cursor;
82 xcb_connection_t *connection;
83 };
84 typedef QCache<QXcbCursorCacheKey, CachedCursor> BitmapCursorCache;
85
86 xcb_cursor_t createFontCursor(int cshape);
87 xcb_cursor_t createBitmapCursor(QCursor *cursor);
88 xcb_cursor_t createNonStandardCursor(int cshape);
89#endif
90
91 QXcbScreen *m_screen;
92 xcb_cursor_context_t *m_cursorContext;
93#ifndef QT_NO_CURSOR
94 CursorHash m_cursorHash;
95 BitmapCursorCache m_bitmapCache;
96#endif
97 static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen,
98 const QByteArray &name,
99 const QVariant &property,
100 void *handle);
101 bool m_callbackForPropertyRegistered;
102};
103
104QT_END_NAMESPACE
105

source code of qtbase/src/plugins/platforms/xcb/qxcbcursor.h