Merge pull request #13076 from robxnano/dbus-inhibit
Linux: Use D-Bus to inhibit screensaver
This commit is contained in:
commit
d6e10e586a
|
@ -26,6 +26,7 @@ static constexpr auto X_None = None;
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
#include "UICommon/UICommon.h"
|
||||||
#include "UICommon/X11Utils.h"
|
#include "UICommon/X11Utils.h"
|
||||||
#include "VideoCommon/Present.h"
|
#include "VideoCommon/Present.h"
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ bool PlatformX11::Init()
|
||||||
ProcessEvents();
|
ProcessEvents();
|
||||||
|
|
||||||
if (Config::Get(Config::MAIN_DISABLE_SCREENSAVER))
|
if (Config::Get(Config::MAIN_DISABLE_SCREENSAVER))
|
||||||
X11Utils::InhibitScreensaver(m_window, true);
|
UICommon::InhibitScreenSaver(true);
|
||||||
|
|
||||||
#ifdef HAVE_XRANDR
|
#ifdef HAVE_XRANDR
|
||||||
m_xrr_config = new X11Utils::XRRConfiguration(m_display, m_window);
|
m_xrr_config = new X11Utils::XRRConfiguration(m_display, m_window);
|
||||||
|
|
|
@ -1682,12 +1682,7 @@ void MainWindow::UpdateScreenSaverInhibition()
|
||||||
|
|
||||||
m_is_screensaver_inhibited = inhibit;
|
m_is_screensaver_inhibited = inhibit;
|
||||||
|
|
||||||
#ifdef HAVE_X11
|
|
||||||
if (GetWindowSystemType() == WindowSystemType::X11)
|
|
||||||
UICommon::InhibitScreenSaver(winId(), inhibit);
|
|
||||||
#else
|
|
||||||
UICommon::InhibitScreenSaver(inhibit);
|
UICommon::InhibitScreenSaver(inhibit);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::eventFilter(QObject* object, QEvent* event)
|
bool MainWindow::eventFilter(QObject* object, QEvent* event)
|
||||||
|
|
|
@ -43,6 +43,13 @@ if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_
|
||||||
target_link_libraries(uicommon PRIVATE bdisasm)
|
target_link_libraries(uicommon PRIVATE bdisasm)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(UNIX AND NOT APPLE AND NOT ANDROID AND ENABLE_QT)
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS DBus)
|
||||||
|
target_sources(uicommon PRIVATE DBusUtils.cpp)
|
||||||
|
target_compile_definitions(uicommon PRIVATE -DHAVE_QTDBUS=1)
|
||||||
|
target_link_libraries(uicommon PUBLIC Qt6::DBus)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(X11_FOUND)
|
if(X11_FOUND)
|
||||||
target_sources(uicommon PRIVATE X11Utils.cpp)
|
target_sources(uicommon PRIVATE X11Utils.cpp)
|
||||||
target_link_libraries(uicommon PUBLIC PkgConfig::XRANDR PkgConfig::X11)
|
target_link_libraries(uicommon PUBLIC PkgConfig::XRANDR PkgConfig::X11)
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
// 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
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2024 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace DBusUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
void InhibitScreenSaver(bool inhibit);
|
||||||
|
|
||||||
|
} // namespace DBusUtils
|
|
@ -50,8 +50,8 @@
|
||||||
#include "UICommon/DiscordPresence.h"
|
#include "UICommon/DiscordPresence.h"
|
||||||
#include "UICommon/USBUtils.h"
|
#include "UICommon/USBUtils.h"
|
||||||
|
|
||||||
#ifdef HAVE_X11
|
#ifdef HAVE_QTDBUS
|
||||||
#include "UICommon/X11Utils.h"
|
#include "UICommon/DBusUtils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
@ -480,17 +480,13 @@ bool TriggerSTMPowerEvent()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_X11
|
|
||||||
void InhibitScreenSaver(Window win, bool inhibit)
|
|
||||||
#else
|
|
||||||
void InhibitScreenSaver(bool inhibit)
|
void InhibitScreenSaver(bool inhibit)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
// Inhibit the screensaver. Depending on the operating system this may also
|
// Inhibit the screensaver. Depending on the operating system this may also
|
||||||
// disable low-power states and/or screen dimming.
|
// disable low-power states and/or screen dimming.
|
||||||
|
|
||||||
#ifdef HAVE_X11
|
#ifdef HAVE_QTDBUS
|
||||||
X11Utils::InhibitScreensaver(win, inhibit);
|
DBusUtils::InhibitScreenSaver(inhibit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -17,11 +17,7 @@ void Shutdown();
|
||||||
void InitControllers(const WindowSystemInfo& wsi);
|
void InitControllers(const WindowSystemInfo& wsi);
|
||||||
void ShutdownControllers();
|
void ShutdownControllers();
|
||||||
|
|
||||||
#ifdef HAVE_X11
|
void InhibitScreenSaver(bool inhibit);
|
||||||
void InhibitScreenSaver(unsigned long win, bool enable);
|
|
||||||
#else
|
|
||||||
void InhibitScreenSaver(bool enable);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Calls std::locale::global, selecting a fallback locale if the
|
// Calls std::locale::global, selecting a fallback locale if the
|
||||||
// requested locale isn't available
|
// requested locale isn't available
|
||||||
|
|
|
@ -45,24 +45,6 @@ bool ToggleFullscreen(Display* dpy, Window win)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InhibitScreensaver(Window win, bool suspend)
|
|
||||||
{
|
|
||||||
char id[11];
|
|
||||||
snprintf(id, sizeof(id), "0x%lx", win);
|
|
||||||
|
|
||||||
// Call xdg-screensaver
|
|
||||||
char* argv[4] = {(char*)"xdg-screensaver", (char*)(suspend ? "suspend" : "resume"), id, nullptr};
|
|
||||||
pid_t pid;
|
|
||||||
if (!posix_spawnp(&pid, "xdg-screensaver", nullptr, nullptr, argv, environ))
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
while (waitpid(pid, &status, 0) == -1)
|
|
||||||
;
|
|
||||||
|
|
||||||
INFO_LOG_FMT(VIDEO, "Started xdg-screensaver (PID = {})", pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_XRANDR
|
#ifdef HAVE_XRANDR
|
||||||
XRRConfiguration::XRRConfiguration(Display* _dpy, Window _win)
|
XRRConfiguration::XRRConfiguration(Display* _dpy, Window _win)
|
||||||
: dpy(_dpy), win(_win), screenResources(nullptr), outputInfo(nullptr), crtcInfo(nullptr),
|
: dpy(_dpy), win(_win), screenResources(nullptr), outputInfo(nullptr), crtcInfo(nullptr),
|
||||||
|
|
|
@ -20,10 +20,6 @@
|
||||||
namespace X11Utils
|
namespace X11Utils
|
||||||
{
|
{
|
||||||
bool ToggleFullscreen(Display* dpy, Window win);
|
bool ToggleFullscreen(Display* dpy, Window win);
|
||||||
Window XWindowFromHandle(void* Handle);
|
|
||||||
Display* XDisplayFromHandle(void* Handle);
|
|
||||||
|
|
||||||
void InhibitScreensaver(Window win, bool suspend);
|
|
||||||
|
|
||||||
#ifdef HAVE_XRANDR
|
#ifdef HAVE_XRANDR
|
||||||
class XRRConfiguration
|
class XRRConfiguration
|
||||||
|
|
Loading…
Reference in New Issue