| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]> |
| 3 | |
| 4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
| 5 | */ |
| 6 | #ifndef WAYLAND_EVENT_QUEUE_H |
| 7 | #define WAYLAND_EVENT_QUEUE_H |
| 8 | |
| 9 | #include <QObject> |
| 10 | |
| 11 | #include "KWayland/Client/kwaylandclient_export.h" |
| 12 | |
| 13 | struct wl_display; |
| 14 | struct wl_proxy; |
| 15 | struct wl_event_queue; |
| 16 | |
| 17 | namespace KWayland |
| 18 | { |
| 19 | namespace Client |
| 20 | { |
| 21 | class ConnectionThread; |
| 22 | |
| 23 | /** |
| 24 | * @short Wrapper class for wl_event_queue interface. |
| 25 | * |
| 26 | * The EventQueue is needed if a different thread is used for the connection. |
| 27 | * If the interface wrappers are held in a different thread than the connection thread |
| 28 | * an EventQueue is needed for the thread which holds the interface wrappers. A common |
| 29 | * example is a dedicated connection thread while the interface wrappers are created |
| 30 | * in the main thread. |
| 31 | * |
| 32 | * All interface wrappers are set up to support the EventQueue in the most convenient |
| 33 | * way. The EventQueue needs only to be passed to the Registry. The EventQueue will then |
| 34 | * be passed to all created wrappers through the tree. |
| 35 | * |
| 36 | * @code |
| 37 | * ConnectionThread connection; |
| 38 | * EventQueue queue; |
| 39 | * Registry registry; |
| 40 | * |
| 41 | * connect(&connection, &ConnectionThread::connected, this, [&] { |
| 42 | * queue.setup(&connection); |
| 43 | * registry.setEventQueue(&queue); |
| 44 | * registry.setup(&connection); |
| 45 | * registry.create(); |
| 46 | * }); |
| 47 | * |
| 48 | * connection.initConnection(); |
| 49 | * @endcode |
| 50 | * |
| 51 | * The EventQueue can be used as a drop-in replacement for any wl_event_queue |
| 52 | * pointer as it provides matching cast operators. |
| 53 | **/ |
| 54 | class KWAYLANDCLIENT_EXPORT EventQueue : public QObject |
| 55 | { |
| 56 | Q_OBJECT |
| 57 | public: |
| 58 | explicit EventQueue(QObject *parent = nullptr); |
| 59 | ~EventQueue() override; |
| 60 | |
| 61 | /** |
| 62 | * Creates the event queue for the @p display. |
| 63 | * |
| 64 | * Note: this will not automatically setup the dispatcher. |
| 65 | * When using this method one needs to ensure that dispatch |
| 66 | * gets invoked whenever new events need to be dispatched. |
| 67 | * @see dispatch |
| 68 | **/ |
| 69 | void setup(wl_display *display); |
| 70 | /** |
| 71 | * Creates the event queue for the @p connection. |
| 72 | * |
| 73 | * This method also connects the eventsRead signal of the ConnectionThread |
| 74 | * to the dispatch method. Events will be automatically dispatched without |
| 75 | * the need to call dispatch manually. |
| 76 | * @see dispatch |
| 77 | **/ |
| 78 | void setup(ConnectionThread *connection); |
| 79 | |
| 80 | /** |
| 81 | * @returns @c true if EventQueue is setup. |
| 82 | **/ |
| 83 | bool isValid(); |
| 84 | /** |
| 85 | * Releases the wl_event_queue interface. |
| 86 | * After the interface has been released the EventQueue instance is no |
| 87 | * longer valid and can be setup with another wl_event_queue interface. |
| 88 | **/ |
| 89 | void release(); |
| 90 | /** |
| 91 | * Destroys the data held by this EventQueue. |
| 92 | * This method is supposed to be used when the connection to the Wayland |
| 93 | * server goes away. If the connection is not valid anymore, it's not |
| 94 | * possible to call release anymore as that calls into the Wayland |
| 95 | * connection and the call would fail. This method cleans up the data, so |
| 96 | * that the instance can be deleted or set up to a new wl_event_queue interface |
| 97 | * once there is a new connection available. |
| 98 | * |
| 99 | * @see release |
| 100 | **/ |
| 101 | void destroy(); |
| 102 | |
| 103 | /** |
| 104 | * Adds the @p proxy to the EventQueue. |
| 105 | **/ |
| 106 | void addProxy(wl_proxy *proxy); |
| 107 | /** |
| 108 | * Adds the @p proxy of type wl_interface (e.g. wl_compositor) to the EventQueue. |
| 109 | **/ |
| 110 | template<typename wl_interface> |
| 111 | void addProxy(wl_interface *proxy); |
| 112 | /** |
| 113 | * Adds the @p proxy wrapper class of type T referencing the wl_interface to the EventQueue. |
| 114 | **/ |
| 115 | template<typename wl_interface, typename T> |
| 116 | void addProxy(T *proxy); |
| 117 | |
| 118 | operator wl_event_queue *(); |
| 119 | operator wl_event_queue *() const; |
| 120 | |
| 121 | public Q_SLOTS: |
| 122 | /** |
| 123 | * Dispatches all pending events on the EventQueue. |
| 124 | **/ |
| 125 | void dispatch(); |
| 126 | |
| 127 | private: |
| 128 | class Private; |
| 129 | QScopedPointer<Private> d; |
| 130 | }; |
| 131 | |
| 132 | template<typename wl_interface> |
| 133 | inline void EventQueue::addProxy(wl_interface *proxy) |
| 134 | { |
| 135 | addProxy(proxy: reinterpret_cast<wl_proxy *>(proxy)); |
| 136 | } |
| 137 | |
| 138 | template<typename wl_interface, typename T> |
| 139 | inline void EventQueue::addProxy(T *proxy) |
| 140 | { |
| 141 | addProxy(proxy: reinterpret_cast<wl_proxy *>((wl_interface *)*(proxy))); |
| 142 | } |
| 143 | |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | #endif |
| 148 | |