File indexing completed on 2024-04-21 03:53:54
0001 /* 0002 This file is part of libkdbusaddons 0003 0004 SPDX-FileCopyrightText: 2011 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2011 Kevin Ottens <ervin@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0008 */ 0009 0010 #ifndef KDBUSSERVICE_H 0011 #define KDBUSSERVICE_H 0012 0013 #include <QObject> 0014 #include <QUrl> 0015 #include <memory> 0016 0017 #include <kdbusaddons_export.h> 0018 0019 class KDBusServicePrivate; 0020 0021 /** 0022 * @class KDBusService kdbusservice.h <KDBusService> 0023 * 0024 * KDBusService takes care of registering the current process with D-Bus. 0025 * 0026 * This registers the application at a predictable location on D-Bus, registers 0027 * the QCoreApplication (or subclass) object at /MainApplication, and 0028 * assists in implementing the application side of D-Bus activation from 0029 * the <a 0030 * href="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html">Desktop 0031 * Entry Specification</a>. 0032 * 0033 * An application can either work in Multiple mode or Unique mode. 0034 * 0035 * In Multiple mode, the application can be launched many times. The service 0036 * name in the D-Bus registration will contain the PID to distinguish the 0037 * various instances; for example: <tt>org.kde.konqueror-12345</tt>. 0038 * 0039 * In Unique mode, only one instance of this application can ever run. 0040 * The first instance of the application registers with D-Bus without the PID, 0041 * and any attempt to run the application again will cause the 0042 * activateRequested() signal to be emitted in the already-running instance; the 0043 * duplicate instance will then quit. The exit value can be set by the already 0044 * running instance with setExitValue(), the default value is @c 0. 0045 * 0046 * Unique-mode applications should usually delay parsing command-line arguments 0047 * until after creating a KDBusService object; that way they know they are the 0048 * original instance of the application. 0049 * 0050 * Applications that set the D-Bus activation entry (DBusActivatable=true) in 0051 * their desktop files will use Unique mode and connect to the signals emitted 0052 * by this class. 0053 * Note that the D-Bus interface is exported for Multiple-mode applications as 0054 * well, so it also makes sense for such applications to connect to the signals 0055 * emitted by this class. 0056 * 0057 * @note In order to avoid a race, the application should export its objects to 0058 * D-Bus before allowing the event loop to run (for example, by calling 0059 * QCoreApplication::exec()). Otherwise, the application will appear on the bus 0060 * before its objects are accessible via D-Bus, which could be a problem for 0061 * other applications or scripts which start the application in order to talk 0062 * D-Bus to it immediately. 0063 * 0064 * Example usage: 0065 * 0066 * @code 0067 QApplication app(argc, argv); 0068 app.setApplicationName("kuiserver"); 0069 app.setOrganizationDomain("kde.org"); 0070 // Create your D-Bus objects here 0071 // ... 0072 KDBusService service(KDBusService::Unique); 0073 // If this point is reached, this is the only running instance 0074 // i.e. org.kde.kuiserver has been registered 0075 return app.exec(); 0076 * @endcode 0077 * 0078 * @since 5.0 0079 */ 0080 class KDBUSADDONS_EXPORT KDBusService : public QObject 0081 { 0082 Q_OBJECT 0083 0084 public: 0085 /** 0086 * Options to control the behaviour of KDBusService 0087 * @see StartupOptions 0088 */ 0089 enum StartupOption { 0090 /** 0091 * Indicates that only one instance of this application should ever exist. 0092 * 0093 * Cannot be combined with @c Multiple. 0094 */ 0095 Unique = 1, 0096 /** 0097 * Indicates that multiple instances of the application may exist. 0098 * 0099 * Cannot be combined with @c Unique. This is the default. 0100 */ 0101 Multiple = 2, 0102 /** Indicates that the application should not exit if it failed to 0103 * register with D-Bus. 0104 * 0105 * If not set, KDBusService will quit the application if it failed to 0106 * register the service with D-Bus or a @c Unique instance can not be 0107 * activated. A @c Multiple instance will exit with error code @c 1. 0108 * The exit value of a @c Unique instance can be set from the running 0109 * instance with setExitValue(), the default value is @c 0. 0110 */ 0111 NoExitOnFailure = 4, 0112 /** 0113 * Indicates that if there's already a unique service running, to be quit and replaced 0114 * with our own. 0115 * 0116 * If exported, it will try first quitting the service calling @c org.qtproject.Qt.QCoreApplication.quit, 0117 * which is exported by KDBusService by default. 0118 * 0119 * @since 5.65 0120 */ 0121 Replace = 8 0122 }; 0123 Q_ENUM(StartupOption) 0124 0125 /** 0126 * Stores a combination of #StartupOption values. 0127 */ 0128 Q_DECLARE_FLAGS(StartupOptions, StartupOption) 0129 Q_FLAG(StartupOptions) 0130 0131 /** 0132 * Tries to register the current process to D-Bus at an address based on the 0133 * application name and organization domain. 0134 * 0135 * The D-Bus service name is the reversed organization domain, followed by 0136 * the application name. If @p options includes the @c Multiple flag, the 0137 * application PID will be appended. For example, 0138 * @code 0139 * app.setApplicationName("kuiserver"); 0140 * app.setOrganizationDomain("kde.org"); 0141 * @endcode 0142 * will make KDBusService register as @c org.kde.kuiserver in @c Unique 0143 * mode, and @c org.kde.kuiserver-1234 (if the process has PID @c 1234) in 0144 * @c Multiple mode. 0145 */ 0146 explicit KDBusService(StartupOptions options = Multiple, QObject *parent = nullptr); 0147 0148 /** 0149 * Destroys this object (but does not unregister the application). 0150 * 0151 * Deleting this object before unregister() is called (either manually or 0152 * because QCoreApplication::aboutToQuit() was emitted) could confuse 0153 * clients, who will see the service on the bus but will be unable to use 0154 * the activation methods. 0155 */ 0156 ~KDBusService() override; 0157 0158 /** 0159 * Returns true if the D-Bus registration succeeded. 0160 * 0161 * Note that this is only useful when specifying the option NoExitOnFailure. 0162 * Otherwise, the simple fact that this process is still running indicates 0163 * that the registration succeeded. 0164 */ 0165 bool isRegistered() const; 0166 0167 /** 0168 * Returns the name of the D-Bus service registered by this class. 0169 * Mostly useful when using the option Multiple. 0170 * @since 5.33 0171 */ 0172 QString serviceName() const; 0173 0174 /** 0175 * Returns the error message from the D-Bus registration if it failed. 0176 * 0177 * Note that this is only useful when specifying the option NoExitOnFailure. 0178 * Otherwise the process has quit by the time you can get a chance to call this. 0179 */ 0180 QString errorMessage() const; 0181 0182 /** 0183 * Sets the exit value to be used for a duplicate instance. 0184 * 0185 * If this is a @c Unique application, a slot connected to 0186 * activateRequested() can use this to specify a non-zero exit value for the 0187 * duplicate instance. This would typically be done if invalid command-line 0188 * arguments are passed. 0189 * 0190 * Note that this will only work if the signal-slot connection type is 0191 * Qt::DirectConnection. 0192 * 0193 * @param value The exit value for the duplicate instance. 0194 */ 0195 void setExitValue(int value); 0196 0197 Q_SIGNALS: 0198 /** 0199 * Signals that the application is to be activated. 0200 * 0201 * If this is a @c Unique application, when KDBusService is constructed in 0202 * subsequent instances of the application (ie: when the executable is run 0203 * when an instance is already running), it will cause this signal to be 0204 * emitted in the already-running instance (with the arguments passed to the 0205 * duplicate instance), and the duplicate instance will then exit. 0206 * 0207 * If this application's desktop file indicates that it supports D-Bus 0208 * activation (DBusActivatable=true), a command launcher may also call the Activate() 0209 * D-Bus method to trigger this signal. In this case, @p args will be empty. 0210 * 0211 * In single-window applications, the connected signal should typically 0212 * raise the window. 0213 * 0214 * @param arguments The arguments the executable was called with, starting with the executable file name. 0215 * See QCoreApplication::arguments(). 0216 * This can also be empty. 0217 * 0218 * A typical implementation of the signal handler would be: 0219 * @code 0220 * if (!arguments.isEmpty()) { 0221 * commandLineParser->parse(arguments); // same QCommandLineParser instance as the one used in main() 0222 * handleCmdLine(workingDirectory); // shared method with main(), which uses commandLineParser to handle options and positional arguments 0223 * } 0224 * @endcode 0225 * 0226 * For GUI applications, the handler also needs to deal with any platform-specific startup ids 0227 * and make sure the mainwindow is shown as well as request its activation from the window manager. 0228 * For X11, KDBusService makes the id for the Startup Notification protocol available 0229 * from QX11Info::nextStartupId(), if there is one. 0230 * For Wayland, KDBusService provides the token for the XDG Activation protocol in the 0231 * "XDG_ACTIVATION_TOKEN" environment variable and unsets it again after the signal, if there is one. 0232 * The util method @c KWindowSystem::updateStartupId(QWindow *window) (since KF 5.91) takes care of that. 0233 * A typical implementation in the signal handler would be: 0234 * @code 0235 * mainWindow->show(); 0236 * KWindowSystem::updateStartupId(mainWindow->windowHandle()); 0237 * mainWindow->raise(); 0238 * KWindowSystem::activateWindow(mainWindow->windowHandle()); 0239 * @endcode 0240 * 0241 * If you're using the builtin handling of @c --help and @c --version in QCommandLineParser, 0242 * you should call parser.process(arguments) before creating the KDBusService instance, 0243 * since parse() doesn't handle those (and exiting the already-running instance would be wrong anyway). 0244 * 0245 * @see setExitValue() 0246 */ 0247 void activateRequested(const QStringList &arguments, const QString &workingDirectory); 0248 0249 /** 0250 * Signals that one or more files should be opened in the application. 0251 * 0252 * This signal is emitted to request handling of the respective method of the D-Bus activation. 0253 * For GUI applications, the signal handler also needs to deal with any platform-specific startup ids 0254 * and make sure the mainwindow is shown as well as request its activation from the window manager. 0255 * See documentation of activateRequested(const QStringList &arguments, const QString &) 0256 * for details. 0257 * 0258 * @param uris The URLs of the files to open. 0259 */ 0260 void openRequested(const QList<QUrl> &uris); 0261 0262 /** 0263 * Signals that an application action should be triggered. 0264 * 0265 * This signal is emitted to request handling of the respective method of the D-Bus activation. 0266 * For GUI applications, the signal handler also needs to deal with any platform-specific startup ids 0267 * and make sure the mainwindow is shown as well as request its activation from the window manager. 0268 * See documentation of activateRequested(const QStringList &arguments, const QString &) 0269 * for details. 0270 * 0271 * See the desktop entry specification for more information about action activation. 0272 */ 0273 void activateActionRequested(const QString &actionName, const QVariant ¶meter); 0274 0275 public Q_SLOTS: 0276 /** 0277 * Unregister from D-Bus. 0278 * 0279 * This is called automatically when the application is about to quit, to 0280 * make sure it doesn't keep receiving calls to its D-Bus interface while it 0281 * is doing final cleanups. 0282 */ 0283 void unregister(); 0284 0285 private: 0286 // fdo.Application spec 0287 KDBUSADDONS_NO_EXPORT void Activate(const QVariantMap &platform_data); 0288 KDBUSADDONS_NO_EXPORT void Open(const QStringList &uris, const QVariantMap &platform_data); 0289 KDBUSADDONS_NO_EXPORT void ActivateAction(const QString &action_name, const QVariantList &maybeParameter, const QVariantMap &platform_data); 0290 friend class KDBusServiceAdaptor; 0291 0292 // org.kde.KDBusService 0293 KDBUSADDONS_NO_EXPORT int CommandLine(const QStringList &arguments, const QString &workingDirectory, const QVariantMap &platform_data); 0294 friend class KDBusServiceExtensionsAdaptor; 0295 0296 private: 0297 std::unique_ptr<KDBusServicePrivate> const d; 0298 }; 0299 0300 Q_DECLARE_OPERATORS_FOR_FLAGS(KDBusService::StartupOptions) 0301 0302 #endif /* KDBUSSERVICE_H */