1// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
2// SPDX-FileCopyrightText: 2025 Harald Sitter <sitter@kde.org>
3
4#include "ksysteminhibitor.h"
5
6#include <QDBusConnection>
7#include <QDBusMessage>
8#include <QDBusPendingCall>
9#include <QDBusPendingReply>
10#include <private/qdesktopunixservices_p.h>
11#include <private/qguiapplication_p.h>
12#include <qpa/qplatformintegration.h>
13
14#include "kguiaddons_debug.h"
15
16using namespace Qt::StringLiterals;
17
18namespace
19{
20void release(const QDBusObjectPath &path)
21{
22 QDBusMessage message = QDBusMessage::createMethodCall(destination: u"org.freedesktop.portal.Desktop"_s, path: path.path(), interface: u"org.freedesktop.portal.Request"_s, method: u"Close"_s);
23 QDBusConnection::sessionBus().asyncCall(message);
24};
25} // namespace
26
27class KSystemInhibitorPrivate
28{
29public:
30 std::optional<QDBusObjectPath> m_inhibition;
31};
32
33KSystemInhibitor::KSystemInhibitor(const QString &reason, Types types, QWindow *window, QObject *parent)
34 : QObject(parent)
35 , d(std::make_unique<KSystemInhibitorPrivate>())
36{
37 QDBusMessage message = QDBusMessage::createMethodCall(destination: u"org.freedesktop.portal.Desktop"_s,
38 path: u"/org/freedesktop/portal/desktop"_s,
39 interface: u"org.freedesktop.portal.Inhibit"_s,
40 method: u"Inhibit"_s);
41
42 const QString windowIdentifier = [window] {
43 if (window) {
44 auto services = QGuiApplicationPrivate::platformIntegration()->services();
45 if (auto unixServices = dynamic_cast<QDesktopUnixServices *>(services)) {
46 return unixServices->portalWindowIdentifier(window);
47 }
48 }
49 return QString();
50 }();
51 message << windowIdentifier << static_cast<unsigned>(types.toInt()) << QVariantMap({{QLatin1String("reason"), reason}});
52
53 auto watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(message), qApp);
54 QObject::connect(sender: watcher,
55 signal: &QDBusPendingCallWatcher::finished,
56 qApp,
57 slot: [that = QPointer(this) /* we bind to the lifetime of qApp, guard this!*/](QDBusPendingCallWatcher *watcher) {
58 watcher->deleteLater();
59 QDBusPendingReply<QDBusObjectPath> reply = *watcher;
60 if (reply.isError()) {
61 qCWarning(KGUIADDONS_LOG) << "KSystemInhibitor Error: " << reply.error().message();
62 } else if (that) {
63 that->d->m_inhibition.emplace(args: reply.value());
64 } else { // KSystemInhibitor got deleted before we could store the inhibition, release it immediately.
65 release(path: reply.value());
66 }
67 });
68}
69
70KSystemInhibitor::~KSystemInhibitor()
71{
72 if (d->m_inhibition.has_value()) {
73 release(path: d->m_inhibition.value());
74 }
75}
76
77#include "moc_ksysteminhibitor.cpp"
78

source code of kguiaddons/src/util/ksysteminhibitor_dbus.cpp