Add option for preventing display sleep (#5783)

Adds support for preventing the display from sleeping while a game is
running. Supports Windows, Linux (with the org.freedesktop.ScreenSaver
D-Bus service), and macOS.
This commit is contained in:
Alex James 2019-10-12 07:40:47 -05:00 committed by Ivan
parent 07022fd3b6
commit 3ad743ecaa
11 changed files with 118 additions and 16 deletions

View File

@ -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

View File

@ -2,10 +2,6 @@
#include "PadHandler.h"
#include "pad_thread.h"
#ifdef _WIN32
#include <Windows.h>
#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
}
}

View File

@ -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<named_thread<ppu_thread>>(on_select);
idm::select<named_thread<spu_thread>>(on_select);
if (g_cfg.misc.prevent_display_sleep)
{
disable_display_sleep();
}
}
bool Emulator::Pause()
@ -1682,6 +1689,12 @@ bool Emulator::Pause()
idm::select<named_thread<ppu_thread>>(on_select);
idm::select<named_thread<spu_thread>>(on_select);
if (g_cfg.misc.prevent_display_sleep)
{
enable_display_sleep();
}
return true;
}
@ -1747,6 +1760,11 @@ void Emulator::Resume()
idm::select<named_thread<ppu_thread>>(on_select);
idm::select<named_thread<spu_thread>>(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

View File

@ -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 };

View File

@ -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.",

View File

@ -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 <windows.h>
#elif defined(__APPLE__)
#include <IOKit/pwr_mgt/IOPMLib.h>
static IOPMAssertionID s_pm_assertion = kIOPMNullAssertionID;
#elif defined(HAVE_QTDBUS)
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusMessage>
#include <QDBusReply>
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<u32> reply = interface.call("Inhibit", "rpcs3", "Game running");
if (reply.isValid())
{
s_dbus_cookie = reply.value();
}
#endif
}

View File

@ -0,0 +1,5 @@
#pragma once
bool display_sleep_control_supported();
void enable_display_sleep();
void disable_display_sleep();

View File

@ -332,6 +332,7 @@
<ItemGroup>
<ClCompile Include="basic_keyboard_handler.cpp" />
<ClCompile Include="basic_mouse_handler.cpp" />
<ClCompile Include="display_sleep_control.cpp" />
<ClCompile Include="ds3_pad_handler.cpp" />
<ClCompile Include="ds4_pad_handler.cpp" />
<ClCompile Include="evdev_joystick_handler.cpp" />
@ -1207,6 +1208,7 @@
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
</CustomBuild>
<ClInclude Include="display_sleep_control.h" />
<ClInclude Include="ds3_pad_handler.h" />
<ClInclude Include="ds4_pad_handler.h" />
<ClInclude Include="evdev_joystick_handler.h" />

View File

@ -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"}},

View File

@ -15,6 +15,7 @@
#include <QTimer>
#include <QScreen>
#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<gui_settings> 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());

View File

@ -1899,6 +1899,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="preventDisplaySleep">
<property name="text">
<string>Prevent display sleep while running games</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showFPSInTitle">
<property name="text">