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