1 | // Copyright (C) 2017 Erik Larsson. |
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 QWAYLANDCLIENTEXTENSION_H |
5 | #define QWAYLANDCLIENTEXTENSION_H |
6 | |
7 | #include <QtCore/QObject> |
8 | #include <QtWaylandClient/qtwaylandclientglobal.h> |
9 | |
10 | struct wl_interface; |
11 | struct wl_registry; |
12 | |
13 | QT_BEGIN_NAMESPACE |
14 | |
15 | namespace QtWaylandClient { |
16 | class QWaylandIntegration; |
17 | } |
18 | |
19 | class QWaylandClientExtensionPrivate; |
20 | class QWaylandClientExtensionTemplatePrivate; |
21 | |
22 | class Q_WAYLANDCLIENT_EXPORT QWaylandClientExtension : public QObject |
23 | { |
24 | Q_OBJECT |
25 | Q_DECLARE_PRIVATE(QWaylandClientExtension) |
26 | Q_PROPERTY(int protocolVersion READ version NOTIFY versionChanged) |
27 | Q_PROPERTY(bool active READ isActive NOTIFY activeChanged) |
28 | public: |
29 | QWaylandClientExtension(const int version); |
30 | ~QWaylandClientExtension(); |
31 | |
32 | QtWaylandClient::QWaylandIntegration *integration() const; |
33 | int version() const; |
34 | bool isActive() const; |
35 | |
36 | virtual const struct wl_interface *extensionInterface() const = 0; |
37 | virtual void bind(struct ::wl_registry *registry, int id, int version) = 0; |
38 | protected: |
39 | void setVersion(const int version); |
40 | Q_SIGNALS: |
41 | void versionChanged(); |
42 | void activeChanged(); |
43 | |
44 | protected Q_SLOTS: |
45 | void initialize(); |
46 | }; |
47 | |
48 | |
49 | template<typename T, auto destruct = nullptr> |
50 | class Q_WAYLANDCLIENT_EXPORT QWaylandClientExtensionTemplate : public QWaylandClientExtension |
51 | { |
52 | Q_DECLARE_PRIVATE(QWaylandClientExtensionTemplate) |
53 | |
54 | public: |
55 | QWaylandClientExtensionTemplate(const int ver) : QWaylandClientExtension(ver) |
56 | { |
57 | if constexpr (destruct != nullptr) { |
58 | connect(this, &QWaylandClientExtensionTemplate::activeChanged, this, [this] { |
59 | if (!isActive()) { |
60 | std::invoke(destruct, static_cast<T *>(this)); |
61 | } |
62 | }); |
63 | } |
64 | } |
65 | |
66 | ~QWaylandClientExtensionTemplate() |
67 | { |
68 | if constexpr (destruct != nullptr) { |
69 | if (isActive()) { |
70 | std::invoke(destruct, static_cast<T *>(this)); |
71 | } |
72 | } |
73 | } |
74 | |
75 | const struct wl_interface *extensionInterface() const override |
76 | { |
77 | return T::interface(); |
78 | } |
79 | |
80 | void bind(struct ::wl_registry *registry, int id, int ver) override |
81 | { |
82 | T* instance = static_cast<T *>(this); |
83 | // Make sure lowest version is used of the supplied version from the |
84 | // developer and the version specified in the protocol and also the |
85 | // compositor version. |
86 | if (this->version() > T::interface()->version) { |
87 | qWarning(msg: "Supplied protocol version to QWaylandClientExtensionTemplate is higher than the version of the protocol, using protocol version instead." ); |
88 | } |
89 | int minVersion = qMin(ver, qMin(T::interface()->version, this->version())); |
90 | setVersion(minVersion); |
91 | instance->init(registry, id, minVersion); |
92 | } |
93 | }; |
94 | |
95 | QT_END_NAMESPACE |
96 | |
97 | #endif // QWAYLANDCLIENTEXTENSION_H |
98 | |