File indexing completed on 2024-12-22 05:09:19
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #ifndef WAYLAND_CONNECTION_THREAD_H 0007 #define WAYLAND_CONNECTION_THREAD_H 0008 0009 #include <QList> 0010 #include <QObject> 0011 0012 #include "KWayland/Client/kwaylandclient_export.h" 0013 0014 struct wl_display; 0015 0016 namespace KWayland 0017 { 0018 /** 0019 * @short KWayland Client. 0020 * 0021 * This namespace groups all classes related to the Client module. 0022 * 0023 * The main entry point into the KWayland::Client API is the ConnectionThread class. 0024 * It allows to create a Wayland client connection either in a native way or wrap a 0025 * connection created by the QtWayland QPA plugin. 0026 * 0027 * KWayland::Client provides one the one hand a low-level API to interact with the 0028 * Wayland API, on the other hand an easy to use convenience API. Each class directly 0029 * relates to a low-level Wayland type and allows direct casting into the type. 0030 * 0031 * On the convenience side KWayland::Client allows easy creation of objects, signals 0032 * emitted for Wayland events and easy conversion from Qt to Wayland types. 0033 * 0034 * Once one has a ConnectionThread created, it's possible to setup a Registry to 0035 * get a listing of all registered globals. For each global the Registry provides a convenience 0036 * method to create the resource. 0037 * 0038 * @see ConnectionThread 0039 * @see Registry 0040 **/ 0041 namespace Client 0042 { 0043 /** 0044 * @short Creates and manages the connection to a Wayland server. 0045 * 0046 * The purpose of this class is to create the connection to a Wayland server 0047 * and to manage it. As the name suggests it's intended to move instances of 0048 * this class into a dedicated thread. This also means that this class doesn't 0049 * inherit QThread. In order to use it in a threaded way one needs to create a 0050 * QThread and move the object there: 0051 * 0052 * @code 0053 * ConnectionThread *connection = new ConnectionThread; 0054 * QThread *thread = new QThread; 0055 * connection->moveToThread(thread); 0056 * thread->start(); 0057 * @endcode 0058 * 0059 * To finalize the initialization of the connection one needs to call @link ::initConnection @endlink. 0060 * This starts an asynchronous connection initialization. In case the initialization 0061 * succeeds the signal @link ::connected @endlink will be emitted, otherwise @link ::failed @endlink will 0062 * be emitted: 0063 * 0064 * @code 0065 * connect(connection, &ConnectionThread::connected, [connection] { 0066 * qDebug() << "Successfully connected to Wayland server at socket:" << connection->socketName(); 0067 * }); 0068 * connect(connection, &ConnectionThread::failed, [connection] { 0069 * qDebug() << "Failed to connect to Wayland server at socket:" << connection->socketName(); 0070 * }); 0071 * connection->initConnection(); 0072 * @endcode 0073 * 0074 * This class is also responsible for dispatching events. Whenever new data is available on 0075 * the Wayland socket, it will be dispatched and the signal @link ::eventsRead @endlink is emitted. 0076 * This allows further event queues in other threads to also dispatch their events. 0077 * 0078 * Furthermore this class flushes the Wayland connection whenever the QAbstractEventDispatcher 0079 * is about to block. 0080 * 0081 * To disconnect the connection to the Wayland server one should delete the instance of this 0082 * class and quit the dedicated thread: 0083 * 0084 * @code 0085 * connection->deleteLater(); 0086 * thread->quit(); 0087 * thread->wait(); 0088 * @endcode 0089 * 0090 * In addition the ConnectionThread provides integration with QtWayland QPA plugin. For that 0091 * it provides a static factory method: 0092 * 0093 * @code 0094 * auto connection = ConnectionThread::fromApplication(); 0095 * @endcode 0096 * 0097 * The semantics of the ConnectionThread are slightly changed if it's integrated with QtWayland. 0098 * The ConnectionThread does not hold the connection, does not emit connected or released signals 0099 * (one can safely assume that the connection is valid when integrating with the Qt application), 0100 * does not dispatch events. Given that the use case of the ConnectionThread is rather limited to 0101 * a convenient API around wl_display to allow easily setup an own Registry in a QtWayland powered 0102 * application. Also moving the ConnectionThread to a different thread is not necessarily recommended 0103 * in that case as QtWayland holds it's connection in an own thread anyway. 0104 * 0105 **/ 0106 class KWAYLANDCLIENT_EXPORT ConnectionThread : public QObject 0107 { 0108 Q_OBJECT 0109 public: 0110 explicit ConnectionThread(QObject *parent = nullptr); 0111 ~ConnectionThread() override; 0112 0113 /** 0114 * Creates a ConnectionThread for the used QGuiApplication. 0115 * This is an integration feature for QtWayland. On non-wayland platforms this method returns 0116 * @c nullptr. 0117 * 0118 * The returned ConnectionThread will be fully setup, which means it manages a wl_display. 0119 * There is no need to initConnection and the connected or failed signals won't be emitted. 0120 * When the created ConnectionThread gets destroyed the managed wl_display won't be disconnected 0121 * as that's managed by Qt. 0122 * 0123 * The returned ConnectionThread is not able to detect (protocol) error. The signal 0124 * {@link errorOccurred} won't be emitted, {@link hasError} will return @c false, even if the 0125 * actual connection held by QtWayland is on error. The behavior of QtWayland is to exit the 0126 * application on error. 0127 * 0128 * @since 5.4 0129 **/ 0130 static ConnectionThread *fromApplication(QObject *parent = nullptr); 0131 0132 /** 0133 * The display this ConnectionThread is connected to. 0134 * As long as there is no connection this method returns @c null. 0135 * @see initConnection 0136 **/ 0137 wl_display *display(); 0138 /** 0139 * @returns the name of the socket it connects to. 0140 **/ 0141 QString socketName() const; 0142 /** 0143 * Sets the @p socketName to connect to. 0144 * Only applies if called before calling initConnection. 0145 * The default socket name is derived from environment variable WAYLAND_DISPLAY 0146 * and if not set is hard coded to "wayland-0". 0147 * 0148 * The socket name will be ignored if a file descriptor has been set through @link setSocketFd @endlink. 0149 * 0150 * @see setSocketFd 0151 **/ 0152 void setSocketName(const QString &socketName); 0153 /** 0154 * Sets the socket @p fd to connect to. 0155 * Only applies if called before calling initConnection. 0156 * If this method is invoked, the connection will be created on the file descriptor 0157 * and not on the socket name passed through @link setSocketName @endlink or through the 0158 * default environment variable WAYLAND_DISPLAY. 0159 * @see setSocketName 0160 **/ 0161 void setSocketFd(int fd); 0162 0163 /** 0164 * Trigger a blocking roundtrip to the Wayland server. Ensures that all events are processed 0165 * before returning to the event loop. 0166 * 0167 * @since 5.4 0168 **/ 0169 void roundtrip(); 0170 0171 /** 0172 * @returns whether the Wayland connection experienced an error 0173 * @see errorCode 0174 * @see errorOccurred 0175 * @since 5.23 0176 **/ 0177 bool hasError() const; 0178 0179 /** 0180 * @returns the error code of the last occurred error or @c 0 if the connection doesn't have an error 0181 * @see hasError 0182 * @see errorOccurred 0183 * @since 5.23 0184 **/ 0185 int errorCode() const; 0186 0187 /** 0188 * @returns all connections created in this application 0189 * @since 5.37 0190 **/ 0191 static QList<ConnectionThread *> connections(); 0192 0193 public Q_SLOTS: 0194 /** 0195 * Initializes the connection in an asynchronous way. 0196 * In case the connection gets established the signal @link ::connected @endlink will be 0197 * emitted, on failure the signal @link ::failed @endlink will be emitted. 0198 * 0199 * @see connected 0200 * @see failed 0201 **/ 0202 void initConnection(); 0203 0204 /** 0205 * Explicitly flush the Wayland display. 0206 * @since 5.3 0207 **/ 0208 void flush(); 0209 0210 Q_SIGNALS: 0211 /** 0212 * Emitted once a connection to a Wayland server is established. 0213 * Normally emitted after invoking initConnection(), but might also be 0214 * emitted after re-connecting to another server. 0215 **/ 0216 void connected(); 0217 /** 0218 * Emitted if connecting to a Wayland server failed. 0219 **/ 0220 void failed(); 0221 /** 0222 * Emitted whenever new events are ready to be read. 0223 **/ 0224 void eventsRead(); 0225 /** 0226 * Emitted if the Wayland server connection dies. 0227 * If the socket reappears, it is tried to reconnect. 0228 **/ 0229 void connectionDied(); 0230 /** 0231 * The Wayland connection experienced a fatal error. 0232 * The ConnectionThread is no longer valid, no requests may be sent. 0233 * This has the same effects as {@link connectionDied}. 0234 * 0235 * @see hasError 0236 * @see errorCode 0237 * @since 5.23 0238 **/ 0239 void errorOccurred(); 0240 0241 protected: 0242 /* 0243 * Creates a connection thread from an existing wl_display object 0244 * @see ConnectionThread::fromApplication 0245 */ 0246 explicit ConnectionThread(wl_display *display, QObject *parent); 0247 0248 private Q_SLOTS: 0249 /** 0250 * @internal 0251 **/ 0252 void doInitConnection(); 0253 0254 private: 0255 class Private; 0256 QScopedPointer<Private> d; 0257 }; 0258 } 0259 } 0260 0261 #endif