diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index f50c5ef531..0c5baa6a3b 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -38,6 +38,7 @@ add_subdirectory(rpcs3qt) set(RPCS3_SRC basic_keyboard_handler.cpp basic_mouse_handler.cpp + display_sleep_control.cpp ds3_pad_handler.cpp ds4_pad_handler.cpp evdev_joystick_handler.cpp diff --git a/rpcs3/Emu/Io/PadHandler.cpp b/rpcs3/Emu/Io/PadHandler.cpp index 2561e570b2..9abae1a2d9 100644 --- a/rpcs3/Emu/Io/PadHandler.cpp +++ b/rpcs3/Emu/Io/PadHandler.cpp @@ -2,10 +2,6 @@ #include "PadHandler.h" #include "pad_thread.h" -#ifdef _WIN32 -#include -#endif - cfg_input g_cfg_input; PadHandlerBase::PadHandlerBase(pad_handler type) : m_type(type) @@ -621,16 +617,5 @@ void PadHandlerBase::ThreadProc() get_mapping(device, pad); get_extended_info(device, pad); apply_pad_data(device, pad); - -#ifdef _WIN32 - for (const auto& btn : pad->m_buttons) - { - if (pad->m_buttons[i].m_pressed) - { - SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); - break; - } - } -#endif } } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 913d84056b..fe6bb41c61 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -40,6 +40,8 @@ #include "Utilities/JIT.h" +#include "display_sleep_control.h" + #if defined(_WIN32) || defined(HAVE_VULKAN) #include "Emu/RSX/VK/VulkanAPI.h" #endif @@ -1655,6 +1657,11 @@ void Emulator::Run() idm::select>(on_select); idm::select>(on_select); + + if (g_cfg.misc.prevent_display_sleep) + { + disable_display_sleep(); + } } bool Emulator::Pause() @@ -1682,6 +1689,12 @@ bool Emulator::Pause() idm::select>(on_select); idm::select>(on_select); + + if (g_cfg.misc.prevent_display_sleep) + { + enable_display_sleep(); + } + return true; } @@ -1747,6 +1760,11 @@ void Emulator::Resume() idm::select>(on_select); idm::select>(on_select); GetCallbacks().on_resume(); + + if (g_cfg.misc.prevent_display_sleep) + { + disable_display_sleep(); + } } void Emulator::Stop(bool restart) @@ -1818,6 +1836,11 @@ void Emulator::Stop(bool restart) klic.clear(); m_force_boot = false; + + if (g_cfg.misc.prevent_display_sleep) + { + enable_display_sleep(); + } } std::string cfg_root::node_vfs::get(const cfg::string& _cfg, const char* _def) const diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 2548f021c3..27ea007793 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -612,6 +612,7 @@ struct cfg_root : cfg::node cfg::_bool autostart{this, "Automatically start games after boot", true}; cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"}; cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" }; + cfg::_bool prevent_display_sleep{ this, "Prevent display sleep while running games", true}; cfg::_bool show_fps_in_title{ this, "Show FPS counter in window title", true}; cfg::_bool show_trophy_popups{ this, "Show trophy popups", true}; cfg::_bool show_shader_compilation_hint{ this, "Show shader compilation hint", true }; diff --git a/rpcs3/Json/tooltips.json b/rpcs3/Json/tooltips.json index 9ce55193f6..3288fc94c1 100644 --- a/rpcs3/Json/tooltips.json +++ b/rpcs3/Json/tooltips.json @@ -80,6 +80,7 @@ "exitOnStop": "Automatically close RPCS3 when closing a game, or when a game closes itself.", "alwaysStart": "Leave this enabled unless you are a developer.", "startGameFullscreen": "Automatically puts the game window in fullscreen.\nDouble click on the game window or press alt+enter to toggle fullscreen and windowed mode.", + "preventDisplaySleep": "Prevent the display from sleeping while a game is running.\nThis requires the org.freedesktop.ScreenSaver D-Bus service on Linux.\nThis option will be disabled if the current platform does not support display sleep control.", "showFPSInTitle": "Shows the frame rate in the game window title. May cause buggy or outdated recording software to not notice RPCS3.", "gs_resizeOnBoot": "Automatically resizes the game window on boot.\nThis does not change the internal game resolution.", "showTrophyPopups": "Show trophy pop-ups when a trophy is unlocked.", diff --git a/rpcs3/display_sleep_control.cpp b/rpcs3/display_sleep_control.cpp new file mode 100644 index 0000000000..644ea42c28 --- /dev/null +++ b/rpcs3/display_sleep_control.cpp @@ -0,0 +1,70 @@ +#include "display_sleep_control.h" + +#include "Emu/System.h" +#include "Utilities/Log.h" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +#elif defined(__APPLE__) +#include + +static IOPMAssertionID s_pm_assertion = kIOPMNullAssertionID; + +#elif defined(HAVE_QTDBUS) +#include +#include +#include +#include + +static u32 s_dbus_cookie = 0; +#endif + +bool display_sleep_control_supported() +{ +#if defined(_WIN32) || defined(__APPLE__) + return true; +#elif defined(HAVE_QTDBUS) + QDBusInterface interface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", QDBusConnection::sessionBus()); + return interface.isValid(); +#else + return false; +#endif +} + +void enable_display_sleep() +{ +#ifdef _WIN32 + SetThreadExecutionState(ES_CONTINUOUS); +#elif defined(__APPLE__) + if (s_pm_assertion != kIOPMNullAssertionID) + { + IOPMAssertionRelease(s_pm_assertion); + s_pm_assertion = kIOPMNullAssertionID; + } +#elif defined(HAVE_QTDBUS) + if (s_dbus_cookie != 0) + { + QDBusInterface interface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", QDBusConnection::sessionBus()); + interface.call("UnInhibit", s_dbus_cookie); + s_dbus_cookie = 0; + } +#endif +} + +void disable_display_sleep() +{ +#ifdef _WIN32 + SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); +#elif defined(__APPLE__) + IOPMAssertionCreateWithName(kIOPMAssertionTypePreventUserIdleDisplaySleep, kIOPMAssertionLevelOn, CFSTR("Game running"), &s_pm_assertion); +#elif defined(HAVE_QTDBUS) + QDBusInterface interface("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver", QDBusConnection::sessionBus()); + QDBusReply reply = interface.call("Inhibit", "rpcs3", "Game running"); + if (reply.isValid()) + { + s_dbus_cookie = reply.value(); + } +#endif +} diff --git a/rpcs3/display_sleep_control.h b/rpcs3/display_sleep_control.h new file mode 100644 index 0000000000..dc16d0cc4f --- /dev/null +++ b/rpcs3/display_sleep_control.h @@ -0,0 +1,5 @@ +#pragma once + +bool display_sleep_control_supported(); +void enable_display_sleep(); +void disable_display_sleep(); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index a2cad4c9ed..1375ffb6e1 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -332,6 +332,7 @@ + @@ -1207,6 +1208,7 @@ $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + @@ -2110,4 +2112,4 @@ - \ No newline at end of file + diff --git a/rpcs3/rpcs3qt/emu_settings.h b/rpcs3/rpcs3qt/emu_settings.h index c8ee08b3ab..7b1f042cd0 100644 --- a/rpcs3/rpcs3qt/emu_settings.h +++ b/rpcs3/rpcs3qt/emu_settings.h @@ -127,6 +127,7 @@ public: ExitRPCS3OnFinish, StartOnBoot, StartGameFullscreen, + PreventDisplaySleep, ShowFPSInTitle, ShowTrophyPopups, ShowWelcomeScreen, @@ -358,6 +359,7 @@ private: { ExitRPCS3OnFinish, { "Miscellaneous", "Exit RPCS3 when process finishes" }}, { StartOnBoot, { "Miscellaneous", "Automatically start games after boot" }}, { StartGameFullscreen, { "Miscellaneous", "Start games in fullscreen mode"}}, + { PreventDisplaySleep, { "Miscellaneous", "Prevent display sleep while running games"}}, { ShowFPSInTitle, { "Miscellaneous", "Show FPS counter in window title"}}, { ShowTrophyPopups, { "Miscellaneous", "Show trophy popups"}}, { ShowWelcomeScreen, { "Miscellaneous", "Show Welcome Screen"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 1fa7a1e46a..7f2e2f95f8 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -15,6 +15,7 @@ #include #include +#include "display_sleep_control.h" #include "qt_utils.h" #include "settings_dialog.h" #include "ui_settings_dialog.h" @@ -1142,6 +1143,10 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: xemu_settings->EnhanceCheckBox(ui->startGameFullscreen, emu_settings::StartGameFullscreen); SubscribeTooltip(ui->startGameFullscreen, json_emu_misc["startGameFullscreen"].toString()); + xemu_settings->EnhanceCheckBox(ui->preventDisplaySleep, emu_settings::PreventDisplaySleep); + SubscribeTooltip(ui->preventDisplaySleep, json_emu_misc["preventDisplaySleep"].toString()); + ui->preventDisplaySleep->setEnabled(display_sleep_control_supported()); + xemu_settings->EnhanceCheckBox(ui->showFPSInTitle, emu_settings::ShowFPSInTitle); SubscribeTooltip(ui->showFPSInTitle, json_emu_misc["showFPSInTitle"].toString()); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index fd31461cf3..1067dbf4ee 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -1899,6 +1899,13 @@ + + + + Prevent display sleep while running games + + +