File indexing completed on 2024-04-21 16:17:32

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Daniel Vratil <dvratil@redhat.com>
0003  * SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.1-or-later
0006  *
0007  */
0008 
0009 /**
0010  * WARNING: This header is *not* part of public API and is subject to change.
0011  * There are not guarantees or API or ABI stability or compatibility between
0012  * releases
0013  */
0014 
0015 #ifndef KSCREEN_BACKENDMANAGER_H
0016 #define KSCREEN_BACKENDMANAGER_H
0017 
0018 #include <QDBusServiceWatcher>
0019 #include <QEventLoop>
0020 #include <QFileInfoList>
0021 #include <QObject>
0022 #include <QPluginLoader>
0023 #include <QProcess>
0024 #include <QTimer>
0025 
0026 #include "kscreen_export.h"
0027 #include "types.h"
0028 
0029 class QDBusPendingCallWatcher;
0030 class OrgKdeKscreenBackendInterface;
0031 
0032 namespace KScreen
0033 {
0034 class AbstractBackend;
0035 
0036 class KSCREEN_EXPORT BackendManager : public QObject
0037 {
0038     Q_OBJECT
0039 
0040 public:
0041     enum Method {
0042         InProcess,
0043         OutOfProcess,
0044     };
0045 
0046     static BackendManager *instance();
0047     ~BackendManager() override;
0048 
0049     KScreen::ConfigPtr config() const;
0050     void setConfig(KScreen::ConfigPtr c);
0051 
0052     /** Choose which backend to use
0053      *
0054      * This method uses a couple of heuristics to pick the backend to be loaded:
0055      * - If the @p backend argument is specified and not empty it's used to filter the
0056      *   available backend list
0057      * - If specified, the KSCREEN_BACKEND env var is considered (case insensitive)
0058      * - Otherwise, the wayland backend is picked when the runtime platform is Wayland
0059      *   (we assume kwin in this case
0060      * - Otherwise, if the runtime platform is X11, the XRandR backend is picked
0061      * - If neither is the case, we fall back to the QScreen backend, since that is the
0062      *   most generally applicable and may work on platforms not explicitly supported
0063      *
0064      * @return the backend plugin to load
0065      * @since 5.7
0066      */
0067     static QFileInfo preferredBackend(const QString &backend = QString());
0068 
0069     /** List installed backends
0070      * @return a list of installed backend plugins
0071      * @since 5.7
0072      */
0073     static QFileInfoList listBackends();
0074 
0075     /** Set arguments map which a backend may use on initialization.
0076      *
0077      * Calling this method after a backend has been initialized will have no effect.
0078      * Arguments map will NOT be automatically cleared on backend shutdown; which
0079      * makes possible setting arguments before restarting backend in tests.
0080      *
0081      * @param map of arbitrary arguments for backends; each backend is free to interpret
0082      * them as it sees fit.
0083      * @since 5.27
0084      */
0085     void setBackendArgs(const QVariantMap &arguments);
0086 
0087     /** Get arguments map which a backend may use on initialization.
0088      *
0089      * @return map of arbitrary arguments for backends.
0090      * @since 5.27
0091      */
0092     QVariantMap getBackendArgs();
0093 
0094     /** Encapsulates the plugin loading logic.
0095      *
0096      * @param loader a pointer to the QPluginLoader, the caller is
0097      * responsible for its memory management.
0098      * @param name name of the backend plugin
0099      * @param arguments arguments, used for unit tests
0100      * @return a pointer to the backend loaded from the plugin
0101      * @since 5.6
0102      */
0103     static KScreen::AbstractBackend *loadBackendPlugin(QPluginLoader *loader, const QString &name, const QVariantMap &arguments);
0104 
0105     KScreen::AbstractBackend *loadBackendInProcess(const QString &name);
0106 
0107     BackendManager::Method method() const;
0108     void setMethod(BackendManager::Method m);
0109 
0110     // For out-of-process operation
0111     void requestBackend();
0112     void shutdownBackend();
0113 
0114 Q_SIGNALS:
0115     void backendReady(OrgKdeKscreenBackendInterface *backend);
0116 
0117 private Q_SLOTS:
0118     void emitBackendReady();
0119 
0120     void startBackend(const QString &backend = QString(), const QVariantMap &arguments = QVariantMap());
0121     void onBackendRequestDone(QDBusPendingCallWatcher *watcher);
0122 
0123     void backendServiceUnregistered(const QString &serviceName);
0124 
0125 private:
0126     friend class SetInProcessOperation;
0127     friend class InProcessConfigOperationPrivate;
0128     friend class SetConfigOperation;
0129     friend class SetConfigOperationPrivate;
0130 
0131     explicit BackendManager();
0132     static BackendManager *sInstance;
0133 
0134     void initMethod();
0135 
0136     // For out-of-process operation
0137     void invalidateInterface();
0138     void backendServiceReady();
0139 
0140     static const int sMaxCrashCount;
0141     OrgKdeKscreenBackendInterface *mInterface;
0142     int mCrashCount;
0143 
0144     QString mBackendService;
0145     QDBusServiceWatcher mServiceWatcher;
0146     KScreen::ConfigPtr mConfig;
0147     QVariantMap mBackendArguments;
0148     QTimer mResetCrashCountTimer;
0149     bool mShuttingDown;
0150     int mRequestsCounter;
0151     QEventLoop mShutdownLoop;
0152 
0153     // For in-process operation
0154     QPluginLoader *mLoader;
0155     KScreen::AbstractBackend *mInProcessBackend;
0156 
0157     Method mMethod;
0158 };
0159 
0160 }
0161 
0162 #endif // KSCREEN_BACKENDMANAGER_H