citra_qt: Prevent OS sleep on Linux when a game is running (#6249)

This commit is contained in:
Tobias 2023-03-23 19:37:10 +01:00 committed by GitHub
parent 343717e683
commit 54385a54eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 2 deletions

View file

@ -211,6 +211,10 @@ if (ENABLE_QT)
find_package(Qt5 REQUIRED COMPONENTS Widgets Multimedia Concurrent ${QT_PREFIX_HINT})
if (UNIX AND NOT APPLE)
find_package(Qt5 REQUIRED COMPONENTS DBus ${QT_PREFIX_HINT})
endif()
if (ENABLE_QT_TRANSLATION)
find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
endif()

View file

@ -269,6 +269,10 @@ target_link_libraries(citra-qt PRIVATE audio_core common core input_common netwo
target_link_libraries(citra-qt PRIVATE Boost::boost glad nihstro-headers Qt5::Widgets Qt5::Multimedia Qt5::Concurrent)
target_link_libraries(citra-qt PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
if (UNIX AND NOT APPLE)
target_link_libraries(citra-qt PRIVATE Qt5::DBus)
endif()
target_compile_definitions(citra-qt PRIVATE
# Use QStringBuilder for string concatenation to reduce
# the overall number of temporary strings created.

View file

@ -24,6 +24,11 @@
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef __unix__
#include <QVariant>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QtDBus>
#endif
#include "citra_qt/aboutdialog.h"
#include "citra_qt/applets/mii_selector.h"
#include "citra_qt/applets/swkbd.h"
@ -945,16 +950,72 @@ void GMainWindow::OnOpenUpdater() {
updater->LaunchUI();
}
#if defined(__unix__) && !defined(__APPLE__)
static std::optional<QDBusObjectPath> 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(QStringLiteral("org.freedesktop.portal.Desktop"),
QStringLiteral("/org/freedesktop/portal/desktop"),
QStringLiteral("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 Citra needs to prevent the
//: computer from sleeping
options.insert(QString::fromLatin1("reason"),
QCoreApplication::translate("GMainWindow", "Citra is running a game"));
// 0x4: Suspend lock; 0x8: Idle lock
QDBusReply<QDBusObjectPath> 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(const 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 // __unix__
void GMainWindow::PreventOSSleep() {
#ifdef _WIN32
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
#endif
#elif defined(HAVE_SDL2)
SDL_DisableScreenSaver();
#ifdef __unix__
auto reply = HoldWakeLockLinux(winId());
if (reply) {
wake_lock = std::move(reply.value());
}
#endif // __unix__
#endif // _WIN32
}
void GMainWindow::AllowOSSleep() {
#ifdef _WIN32
SetThreadExecutionState(ES_CONTINUOUS);
#endif
#elif defined(HAVE_SDL2)
SDL_EnableScreenSaver();
#ifdef __unix__
if (!wake_lock.path().isEmpty()) {
ReleaseWakeLockLinux(wake_lock);
}
#endif // __unix__
#endif // _WIN32
}
bool GMainWindow::LoadROM(const QString& filename) {

View file

@ -16,6 +16,10 @@
#include "core/hle/service/am/am.h"
#include "core/savestate.h"
#ifdef __unix__
#include <QDBusObjectPath>
#endif
class AboutDialog;
class Config;
class ClickableLabel;
@ -329,6 +333,10 @@ private:
HotkeyRegistry hotkey_registry;
#ifdef __unix__
QDBusObjectPath wake_lock{};
#endif
protected:
void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;