dolphin/Source/Core/UICommon/DBusUtils.cpp
2024-09-27 21:22:57 +01:00

205 lines
6.3 KiB
C++

// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "UICommon/DBusUtils.h"
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <QHash>
#include <QObject>
#include <QString>
#include "Common/Logging/Log.h"
namespace DBusUtils
{
static bool InhibitFDO();
static bool InhibitXfce();
static bool InhibitMate();
static bool InhibitPortal();
static void Uninhibit();
static constexpr char s_app_id[] = "org.DolphinEmu.dolphin-emu";
// Cookie for the org.freedesktop.ScreenSaver interface
static uint32_t s_fdo_cookie = 0;
// Cookie for the org.xfce.ScreenSaver interface
static uint32_t s_xfce_cookie = 0;
// Cookie for the org.mate.ScreenSaver interface
static uint32_t s_mate_cookie = 0;
// Return handle for the org.freedesktop.portal.Desktop interface
static QString s_portal_handle;
// Uses D-Bus to inhibit the screensaver
// Tries various D-Bus interfaces until it finds one that works
void InhibitScreenSaver(bool inhibit)
{
if (inhibit)
{
if (s_fdo_cookie || s_xfce_cookie || s_mate_cookie || !s_portal_handle.isEmpty())
return;
if (!InhibitFDO() && !InhibitXfce() && !InhibitMate() && !InhibitPortal())
INFO_LOG_FMT(VIDEO, "Could not inhibit screensaver: No services available");
}
else
Uninhibit();
}
// Inhibits screensaver on Xfce desktop
static bool InhibitXfce()
{
QDBusInterface interface("org.xfce.ScreenSaver", "/", "org.xfce.ScreenSaver");
if (!interface.isValid())
return false;
QDBusReply<uint32_t> reply = interface.call("Inhibit", s_app_id, QObject::tr("Playing a game"));
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::Inhibit succeeded");
s_xfce_cookie = reply;
return true;
}
// Inhibits screensaver on the MATE desktop
// MATE advertises support for xdg-desktop-portal Inhibit,
// but it doesn't work as of Fedora 40
static bool InhibitMate()
{
QDBusInterface interface("org.mate.ScreenSaver", "/org/mate/ScreenSaver", "org.mate.ScreenSaver");
if (!interface.isValid())
return false;
QDBusReply<uint32_t> reply = interface.call("Inhibit", s_app_id, QObject::tr("Playing a game"));
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.mate.ScreenSaver::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.mate.ScreenSaver::Inhibit succeeded");
s_mate_cookie = reply;
return true;
}
// Inhibits screensaver on GNOME, KDE and Cinnamon
static bool InhibitFDO()
{
QDBusInterface interface("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver");
if (!interface.isValid())
return false;
QDBusReply<uint32_t> reply = interface.call("Inhibit", s_app_id, QObject::tr("Playing a game"));
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::Inhibit succeeded");
s_fdo_cookie = reply;
return true;
}
// Inhibits screensaver when sandboxed through Flatpak
// Does not work on KDE Plasma versions before 6.1.5
static bool InhibitPortal()
{
QDBusInterface interface("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop",
"org.freedesktop.portal.Inhibit");
if (!interface.isValid())
return false;
QHash<QString, QVariant> options;
options["handle_token"] = "dolphin_" + QString::number(std::rand(), 0x10);
options["reason"] = QObject::tr("Playing a game");
uint32_t flags = 9; // logout | idle
QDBusReply<QDBusObjectPath> reply = interface.call("Inhibit", "", flags, options);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.portal.Desktop::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.freedesktop.portal.Desktop::Inhibit succeeded");
s_portal_handle = reply.value().path();
return true;
}
static void Uninhibit()
{
if (s_fdo_cookie)
{
QDBusInterface interface("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver");
interface.call("UnInhibit", s_fdo_cookie);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::UnInhibit failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::UnInhibit succeeded");
}
s_fdo_cookie = 0;
}
if (s_xfce_cookie)
{
QDBusInterface interface("org.xfce.ScreenSaver", "/org/xfce/ScreenSaver",
"org.xfce.ScreenSaver");
interface.call("UnInhibit", s_xfce_cookie);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::UnInhibit failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::UnInhibit succeeded");
}
s_xfce_cookie = 0;
}
if (s_mate_cookie)
{
QDBusInterface interface("org.mate.ScreenSaver", "/", "org.mate.ScreenSaver");
interface.call("UnInhibit", s_mate_cookie);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.mate.ScreenSaver::UnInhibit failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.mate.ScreenSaver::UnInhibit succeeded");
}
s_mate_cookie = 0;
}
if (!s_portal_handle.isEmpty())
{
QDBusInterface interface("org.freedesktop.portal.Desktop", s_portal_handle,
"org.freedesktop.portal.Request");
interface.call("Close");
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.portal.Request::Close failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.freedesktop.portal.Request::Close succeeded");
}
s_portal_handle = QString();
}
}
} // namespace DBusUtils