From fa7abafa5f2a3d066ac74193b494f162302e9590 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Tue, 21 Dec 2021 02:47:24 -0700 Subject: [PATCH] main: fix wake lock in Flatpak ... ... by using the XDP system --- CMakeLists.txt | 2 +- src/yuzu/CMakeLists.txt | 3 +++ src/yuzu/main.cpp | 51 +++++++++++++++++++++++++++++++++++++++++ src/yuzu/main.h | 9 ++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d9056aa3c..d1ad55c9cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,7 +249,7 @@ if(ENABLE_QT) # Check for system Qt on Linux, fallback to bundled Qt if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if (NOT YUZU_USE_BUNDLED_QT) - find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets) + find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus) endif() if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT) # Check for dependencies, then enable bundled Qt download diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 732e8c276c..30902101df 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -251,6 +251,9 @@ target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) if (NOT WIN32) target_include_directories(yuzu PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) endif() +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + target_link_libraries(yuzu PRIVATE Qt5::DBus) +endif() target_compile_definitions(yuzu PRIVATE # Use QStringBuilder for string concatenation to reduce diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a7271e075c..975f6dd111 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1236,11 +1236,57 @@ void GMainWindow::OnDisplayTitleBars(bool show) { } } +#ifdef __linux__ +static std::optional HoldWakeLockLinux(u32 window_id = 0) { + if (!QDBusConnection::sessionBus().isConnected()) { + return {}; + } + // reference: https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.Inhibit + QDBusInterface xdp(QString::fromLatin1("org.freedesktop.portal.Desktop"), + QString::fromLatin1("/org/freedesktop/portal/desktop"), + QString::fromLatin1("org.freedesktop.portal.Inhibit")); + if (!xdp.isValid()) { + LOG_WARNING(Frontend, "Couldn't connect to XDP D-Bus endpoint"); + return {}; + } + QVariantMap options = {}; + //: TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the computer from sleeping + options.insert(QString::fromLatin1("reason"), + QCoreApplication::translate("GMainWindow", "yuzu is emulating a game")); + // 0x4: Suspend lock; 0x8: Idle lock + QDBusReply reply = + xdp.call(QString::fromLatin1("Inhibit"), + QString::fromLatin1("x11:") + QString::number(window_id, 16), 12U, options); + + if (reply.isValid()) { + return reply.value(); + } + LOG_WARNING(Frontend, "Couldn't read Inhibit reply from XDP: {}", + reply.error().message().toStdString()); + return {}; +} + +static void ReleaseWakeLockLinux(QDBusObjectPath lock) { + if (!QDBusConnection::sessionBus().isConnected()) { + return; + } + QDBusInterface unlocker(QString::fromLatin1("org.freedesktop.portal.Desktop"), lock.path(), + QString::fromLatin1("org.freedesktop.portal.Request")); + unlocker.call(QString::fromLatin1("Close")); +} +#endif // __linux__ + void GMainWindow::PreventOSSleep() { #ifdef _WIN32 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); #elif defined(HAVE_SDL2) SDL_DisableScreenSaver(); +#ifdef __linux__ + auto reply = HoldWakeLockLinux(winId()); + if (reply) { + wake_lock = std::move(reply.value()); + } +#endif #endif } @@ -1249,6 +1295,11 @@ void GMainWindow::AllowOSSleep() { SetThreadExecutionState(ES_CONTINUOUS); #elif defined(HAVE_SDL2) SDL_EnableScreenSaver(); +#ifdef __linux__ + if (!wake_lock.path().isEmpty()) { + ReleaseWakeLockLinux(wake_lock); + } +#endif #endif } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 0fd41ed4f6..7870bb9636 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -17,6 +17,12 @@ #include "yuzu/compatibility_list.h" #include "yuzu/hotkeys.h" +#ifdef __linux__ +#include +#include +#include +#endif + class Config; class EmuThread; class GameList; @@ -394,6 +400,9 @@ private: // Applets QtSoftwareKeyboardDialog* software_keyboard = nullptr; +#ifdef __linux__ + QDBusObjectPath wake_lock{}; +#endif protected: void dropEvent(QDropEvent* event) override;