summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorTilka <tilkax@gmail.com>2024-10-12 00:31:58 +0100
committerGitHub <noreply@github.com>2024-10-12 00:31:58 +0100
commitd6e10e586af3cbe8e045babf1d7727e89a35752e (patch)
treef16f1103aa711a1b567335b55d6b4e1ac7aca56f /Source
parentf4e0a42cfc9c18593170130409d262994035931f (diff)
parent2748771cb3b8dd23ccd27392f35d0ebd04927f5a (diff)
Merge pull request #13076 from robxnano/dbus-inhibit
Linux: Use D-Bus to inhibit screensaver
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/DolphinNoGUI/PlatformX11.cpp3
-rw-r--r--Source/Core/DolphinQt/MainWindow.cpp5
-rw-r--r--Source/Core/UICommon/CMakeLists.txt7
-rw-r--r--Source/Core/UICommon/DBusUtils.cpp204
-rw-r--r--Source/Core/UICommon/DBusUtils.h11
-rw-r--r--Source/Core/UICommon/UICommon.cpp12
-rw-r--r--Source/Core/UICommon/UICommon.h6
-rw-r--r--Source/Core/UICommon/X11Utils.cpp18
-rw-r--r--Source/Core/UICommon/X11Utils.h4
9 files changed, 229 insertions, 41 deletions
diff --git a/Source/Core/DolphinNoGUI/PlatformX11.cpp b/Source/Core/DolphinNoGUI/PlatformX11.cpp
index 94a72b4c53..8fed2c8c87 100644
--- a/Source/Core/DolphinNoGUI/PlatformX11.cpp
+++ b/Source/Core/DolphinNoGUI/PlatformX11.cpp
@@ -26,6 +26,7 @@ static constexpr auto X_None = None;
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#include "UICommon/UICommon.h"
#include "UICommon/X11Utils.h"
#include "VideoCommon/Present.h"
@@ -110,7 +111,7 @@ bool PlatformX11::Init()
ProcessEvents();
if (Config::Get(Config::MAIN_DISABLE_SCREENSAVER))
- X11Utils::InhibitScreensaver(m_window, true);
+ UICommon::InhibitScreenSaver(true);
#ifdef HAVE_XRANDR
m_xrr_config = new X11Utils::XRRConfiguration(m_display, m_window);
diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp
index 19e53d5f0b..5e733b1c71 100644
--- a/Source/Core/DolphinQt/MainWindow.cpp
+++ b/Source/Core/DolphinQt/MainWindow.cpp
@@ -1682,12 +1682,7 @@ void MainWindow::UpdateScreenSaverInhibition()
m_is_screensaver_inhibited = inhibit;
-#ifdef HAVE_X11
- if (GetWindowSystemType() == WindowSystemType::X11)
- UICommon::InhibitScreenSaver(winId(), inhibit);
-#else
UICommon::InhibitScreenSaver(inhibit);
-#endif
}
bool MainWindow::eventFilter(QObject* object, QEvent* event)
diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt
index 67460ac1af..fa247514e8 100644
--- a/Source/Core/UICommon/CMakeLists.txt
+++ b/Source/Core/UICommon/CMakeLists.txt
@@ -43,6 +43,13 @@ if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_
target_link_libraries(uicommon PRIVATE bdisasm)
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)
target_sources(uicommon PRIVATE X11Utils.cpp)
target_link_libraries(uicommon PUBLIC PkgConfig::XRANDR PkgConfig::X11)
diff --git a/Source/Core/UICommon/DBusUtils.cpp b/Source/Core/UICommon/DBusUtils.cpp
new file mode 100644
index 0000000000..6f92f662c5
--- /dev/null
+++ b/Source/Core/UICommon/DBusUtils.cpp
@@ -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
diff --git a/Source/Core/UICommon/DBusUtils.h b/Source/Core/UICommon/DBusUtils.h
new file mode 100644
index 0000000000..5353efc319
--- /dev/null
+++ b/Source/Core/UICommon/DBusUtils.h
@@ -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
diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp
index d0f8345852..6fa05ef807 100644
--- a/Source/Core/UICommon/UICommon.cpp
+++ b/Source/Core/UICommon/UICommon.cpp
@@ -50,8 +50,8 @@
#include "UICommon/DiscordPresence.h"
#include "UICommon/USBUtils.h"
-#ifdef HAVE_X11
-#include "UICommon/X11Utils.h"
+#ifdef HAVE_QTDBUS
+#include "UICommon/DBusUtils.h"
#endif
#ifdef __APPLE__
@@ -480,17 +480,13 @@ bool TriggerSTMPowerEvent()
return true;
}
-#ifdef HAVE_X11
-void InhibitScreenSaver(Window win, bool inhibit)
-#else
void InhibitScreenSaver(bool inhibit)
-#endif
{
// Inhibit the screensaver. Depending on the operating system this may also
// disable low-power states and/or screen dimming.
-#ifdef HAVE_X11
- X11Utils::InhibitScreensaver(win, inhibit);
+#ifdef HAVE_QTDBUS
+ DBusUtils::InhibitScreenSaver(inhibit);
#endif
#ifdef _WIN32
diff --git a/Source/Core/UICommon/UICommon.h b/Source/Core/UICommon/UICommon.h
index f57518cf14..f23a0005c7 100644
--- a/Source/Core/UICommon/UICommon.h
+++ b/Source/Core/UICommon/UICommon.h
@@ -17,11 +17,7 @@ void Shutdown();
void InitControllers(const WindowSystemInfo& wsi);
void ShutdownControllers();
-#ifdef HAVE_X11
-void InhibitScreenSaver(unsigned long win, bool enable);
-#else
-void InhibitScreenSaver(bool enable);
-#endif
+void InhibitScreenSaver(bool inhibit);
// Calls std::locale::global, selecting a fallback locale if the
// requested locale isn't available
diff --git a/Source/Core/UICommon/X11Utils.cpp b/Source/Core/UICommon/X11Utils.cpp
index 659017ad53..219c897d9e 100644
--- a/Source/Core/UICommon/X11Utils.cpp
+++ b/Source/Core/UICommon/X11Utils.cpp
@@ -45,24 +45,6 @@ bool ToggleFullscreen(Display* dpy, Window win)
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
XRRConfiguration::XRRConfiguration(Display* _dpy, Window _win)
: dpy(_dpy), win(_win), screenResources(nullptr), outputInfo(nullptr), crtcInfo(nullptr),
diff --git a/Source/Core/UICommon/X11Utils.h b/Source/Core/UICommon/X11Utils.h
index 7a406bd641..e71fada4c3 100644
--- a/Source/Core/UICommon/X11Utils.h
+++ b/Source/Core/UICommon/X11Utils.h
@@ -20,10 +20,6 @@
namespace X11Utils
{
bool ToggleFullscreen(Display* dpy, Window win);
-Window XWindowFromHandle(void* Handle);
-Display* XDisplayFromHandle(void* Handle);
-
-void InhibitScreensaver(Window win, bool suspend);
#ifdef HAVE_XRANDR
class XRRConfiguration