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 | QSize size() const override; |
52 | |
53 | void updateContext(); |
54 | |
55 | static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = nullptr); |
56 | |
57 | #ifndef QT_NO_CURSOR |
58 | xcb_cursor_t xcbCursor(const QCursor &c) const |
59 | { return m_cursorHash.value(key: QXcbCursorCacheKey(c), defaultValue: xcb_cursor_t(0)); } |
60 | #endif |
61 | |
62 | private: |
63 | |
64 | #ifndef QT_NO_CURSOR |
65 | typedef QHash<QXcbCursorCacheKey, xcb_cursor_t> CursorHash; |
66 | |
67 | struct CachedCursor |
68 | { |
69 | explicit CachedCursor(xcb_connection_t *conn, xcb_cursor_t c) |
70 | : cursor(c), connection(conn) {} |
71 | ~CachedCursor() { xcb_free_cursor(c: connection, cursor); } |
72 | xcb_cursor_t cursor; |
73 | xcb_connection_t *connection; |
74 | }; |
75 | typedef QCache<QXcbCursorCacheKey, CachedCursor> BitmapCursorCache; |
76 | |
77 | xcb_cursor_t createFontCursor(int cshape); |
78 | xcb_cursor_t createBitmapCursor(QCursor *cursor); |
79 | xcb_cursor_t createNonStandardCursor(int cshape); |
80 | #endif |
81 | |
82 | QXcbScreen *m_screen; |
83 | xcb_cursor_context_t *m_cursorContext; |
84 | #ifndef QT_NO_CURSOR |
85 | CursorHash m_cursorHash; |
86 | BitmapCursorCache m_bitmapCache; |
87 | #endif |
88 | static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen, |
89 | const QByteArray &name, |
90 | const QVariant &property, |
91 | void *handle); |
92 | bool m_callbackForPropertyRegistered; |
93 | }; |
94 | |
95 | QT_END_NAMESPACE |
96 | |
97 | #endif |
98 | |