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