Changeset View
Changeset View
Standalone View
Standalone View
src/gui/kprocessrunner.cpp
Show All 24 Lines | |||||
25 | 25 | | |||
26 | #include "desktopexecparser.h" | 26 | #include "desktopexecparser.h" | ||
27 | #include "krecentdocument.h" | 27 | #include "krecentdocument.h" | ||
28 | #include <KDesktopFile> | 28 | #include <KDesktopFile> | ||
29 | #include <KLocalizedString> | 29 | #include <KLocalizedString> | ||
30 | #include <KWindowSystem> | 30 | #include <KWindowSystem> | ||
31 | 31 | | |||
32 | #include <QDBusConnection> | 32 | #include <QDBusConnection> | ||
33 | #include <QDBusConnectionInterface> | ||||
33 | #include <QDBusInterface> | 34 | #include <QDBusInterface> | ||
35 | #include <QDBusMetaType> | ||||
36 | #include <QDBusPendingCallWatcher> | ||||
34 | #include <QDBusReply> | 37 | #include <QDBusReply> | ||
35 | #include <QFileInfo> | 38 | #include <QFileInfo> | ||
36 | #include <QGuiApplication> | 39 | #include <QGuiApplication> | ||
37 | #include <QStandardPaths> | 40 | #include <QStandardPaths> | ||
41 | #include <QUuid> | ||||
42 | | ||||
43 | #include <mutex> | ||||
dfaure: unused? std::call_once and std::once_flag come from <mutex> | |||||
38 | 44 | | |||
39 | static int s_instanceCount = 0; // for the unittest | 45 | static int s_instanceCount = 0; // for the unittest | ||
40 | 46 | | |||
41 | KProcessRunner::KProcessRunner(const KService::Ptr &service, const QList<QUrl> &urls, | 47 | KProcessRunner::KProcessRunner(const KService::Ptr &service, const QList<QUrl> &urls, | ||
42 | KIO::ApplicationLauncherJob::RunFlags flags, const QString &suggestedFileName, const QByteArray &asn) | 48 | KIO::ApplicationLauncherJob::RunFlags flags, const QString &suggestedFileName, const QByteArray &asn) | ||
43 | : m_process{new KProcess}, | 49 | : m_process{new KProcess}, | ||
44 | m_executable(KIO::DesktopExecParser::executablePath(service->exec())) | 50 | m_executable(KIO::DesktopExecParser::executablePath(service->exec())) | ||
45 | { | 51 | { | ||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Line(s) | 148 | if (startup_notify) { | |||
172 | KStartupInfo::sendStartup(m_startupId, data); | 178 | KStartupInfo::sendStartup(m_startupId, data); | ||
173 | } | 179 | } | ||
174 | } | 180 | } | ||
175 | #else | 181 | #else | ||
176 | Q_UNUSED(bin); | 182 | Q_UNUSED(bin); | ||
177 | Q_UNUSED(userVisibleName); | 183 | Q_UNUSED(userVisibleName); | ||
178 | Q_UNUSED(iconName); | 184 | Q_UNUSED(iconName); | ||
179 | #endif | 185 | #endif | ||
186 | if (service) { | ||||
187 | m_scopeId = service->desktopEntryName(); | ||||
188 | } | ||||
189 | if (m_scopeId.isEmpty()) { | ||||
190 | m_scopeId = m_executable; | ||||
191 | } | ||||
180 | startProcess(); | 192 | startProcess(); | ||
181 | } | 193 | } | ||
182 | 194 | | |||
183 | void KProcessRunner::startProcess() | 195 | void KProcessRunner::startProcess() | ||
184 | { | 196 | { | ||
185 | connect(m_process.get(), QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished), | 197 | connect(m_process.get(), QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished), | ||
186 | this, &KProcessRunner::slotProcessExited); | 198 | this, &KProcessRunner::slotProcessExited); | ||
187 | connect(m_process.get(), &QProcess::started, | 199 | connect(m_process.get(), &QProcess::started, | ||
Show All 16 Lines | 213 | { | |||
204 | // So the emit does nothing, this is really just for debugging. | 216 | // So the emit does nothing, this is really just for debugging. | ||
205 | qCDebug(KIO_GUI) << m_executable << "error=" << errorCode << m_process->errorString(); | 217 | qCDebug(KIO_GUI) << m_executable << "error=" << errorCode << m_process->errorString(); | ||
206 | Q_EMIT error(m_process->errorString()); | 218 | Q_EMIT error(m_process->errorString()); | ||
207 | } | 219 | } | ||
208 | 220 | | |||
209 | void KProcessRunner::slotProcessStarted() | 221 | void KProcessRunner::slotProcessStarted() | ||
210 | { | 222 | { | ||
211 | m_pid = m_process->processId(); | 223 | m_pid = m_process->processId(); | ||
224 | registerCGroup(); | ||||
212 | 225 | | |||
213 | #if HAVE_X11 | 226 | #if HAVE_X11 | ||
214 | if (!m_startupId.isNull() && m_pid) { | 227 | if (!m_startupId.isNull() && m_pid) { | ||
215 | KStartupInfoData data; | 228 | KStartupInfoData data; | ||
216 | data.addPid(m_pid); | 229 | data.addPid(m_pid); | ||
217 | KStartupInfo::sendChange(m_startupId, data); | 230 | KStartupInfo::sendChange(m_startupId, data); | ||
218 | KStartupInfo::resetStartupEnv(); | 231 | KStartupInfo::resetStartupEnv(); | ||
219 | } | 232 | } | ||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Line(s) | |||||
261 | 274 | | |||
262 | void KProcessRunner::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) | 275 | void KProcessRunner::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) | ||
263 | { | 276 | { | ||
264 | qCDebug(KIO_GUI) << m_executable << "exitCode=" << exitCode << "exitStatus=" << exitStatus; | 277 | qCDebug(KIO_GUI) << m_executable << "exitCode=" << exitCode << "exitStatus=" << exitStatus; | ||
265 | terminateStartupNotification(); | 278 | terminateStartupNotification(); | ||
266 | deleteLater(); | 279 | deleteLater(); | ||
267 | } | 280 | } | ||
268 | 281 | | |||
282 | void KProcessRunner::registerCGroup() | ||||
283 | { | ||||
284 | #ifdef Q_OS_LINUX | ||||
285 | if (!qEnvironmentVariableIsSet("KDE_APPLICATIONS_AS_SCOPE")) { | ||||
286 | return; | ||||
287 | } | ||||
288 | if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.freedesktop.systemd1"))) { | ||||
289 | return; | ||||
290 | } | ||||
291 | | ||||
292 | typedef QPair<QString, QDBusVariant> NamedVariant; | ||||
293 | typedef QList<NamedVariant> NamedVariantList; | ||||
294 | | ||||
295 | static std::once_flag dbusTypesRegistered; | ||||
296 | std::call_once(dbusTypesRegistered, []() { | ||||
297 | qDBusRegisterMetaType<NamedVariant>(); | ||||
298 | qDBusRegisterMetaType<NamedVariantList>(); | ||||
299 | qDBusRegisterMetaType<QPair<QString, NamedVariantList>>(); | ||||
The code in this method should be in some #ifdef UNIX and not MAC, right? dfaure: The code in this method should be in some #ifdef UNIX and not MAC, right?
Pretty pointless to… | |||||
300 | qDBusRegisterMetaType<QList<QPair<QString, NamedVariantList>>>(); | ||||
301 | }); | ||||
302 | | ||||
303 | QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), | ||||
304 | QStringLiteral("/org/freedesktop/systemd1"), | ||||
305 | QStringLiteral("org.freedesktop.systemd1.Manager"), | ||||
306 | QStringLiteral("StartTransientUnit")); | ||||
307 | | ||||
308 | const QString name = QStringLiteral("apps-%1-%2.scope").arg(m_scopeId, QUuid::createUuid().toString(QUuid::Id128)); | ||||
dfaure: (this is what made me think about Windows, where pid is a 64bit value).
| |||||
309 | // mode defines what to do in the case of a name conflict, in this case, just do nothing | ||||
310 | const QString mode = QStringLiteral("fail"); | ||||
311 | | ||||
312 | const QList<uint> pidList = {static_cast<quint32>(m_process->pid())}; | ||||
dfaure: const | |||||
313 | | ||||
314 | NamedVariantList properties = {NamedVariant({QStringLiteral("PIDs"), QDBusVariant(QVariant::fromValue(pidList))})}; | ||||
315 | | ||||
And then? if we don't care about the async reply, maybe you should remove the left part of the equal sign? dfaure: And then? if we don't care about the async reply, maybe you should remove the left part of the… | |||||
316 | QList<QPair<QString, NamedVariantList>> aux; | ||||
317 | | ||||
318 | message.setArguments({name, mode, QVariant::fromValue(properties), QVariant::fromValue(aux)}); | ||||
319 | QDBusPendingCall reply = QDBusConnection::sessionBus().asyncCall(message); | ||||
320 | | ||||
321 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); | ||||
322 | | ||||
323 | QObject::connect(watcher, &QDBusPendingCallWatcher::finished, qApp, [=]() { | ||||
324 | watcher->deleteLater(); | ||||
325 | if (reply.isError()) { | ||||
326 | qCWarning(KIO_GUI) << "Failed to register new cgroup:" << name; | ||||
327 | } else { | ||||
328 | qCDebug(KIO_GUI) << "Successfully registered new cgroup:" << name; | ||||
329 | } | ||||
330 | }); | ||||
331 | | ||||
332 | #endif | ||||
333 | } | ||||
334 | | ||||
335 | | ||||
269 | // This code is also used in klauncher (and KRun). | 336 | // This code is also used in klauncher (and KRun). | ||
270 | bool KIOGuiPrivate::checkStartupNotify(const KService *service, bool *silent_arg, QByteArray *wmclass_arg) | 337 | bool KIOGuiPrivate::checkStartupNotify(const KService *service, bool *silent_arg, QByteArray *wmclass_arg) | ||
271 | { | 338 | { | ||
272 | bool silent = false; | 339 | bool silent = false; | ||
273 | QByteArray wmclass; | 340 | QByteArray wmclass; | ||
274 | if (service && service->property(QStringLiteral("StartupNotify")).isValid()) { | 341 | if (service && service->property(QStringLiteral("StartupNotify")).isValid()) { | ||
275 | silent = !service->property(QStringLiteral("StartupNotify")).toBool(); | 342 | silent = !service->property(QStringLiteral("StartupNotify")).toBool(); | ||
276 | wmclass = service->property(QStringLiteral("StartupWMClass")).toString().toLatin1(); | 343 | wmclass = service->property(QStringLiteral("StartupWMClass")).toString().toLatin1(); | ||
Show All 31 Lines |
unused? std::call_once and std::once_flag come from <mutex>