Option to suspend the X11 screensaver when running

On Linux, when not running under Wayland and the app was built with XSS
(X ScreenSaver) support, optionally suspend the X11 screensaver when a
ROM is loaded and not paused.

Add a "Suspend ScreenSaver" checkbox in UI Settings bound to an option
to enable this feature, visible only under X11.

Defaults to off, as there is already a call to suspend the screensaver
on joystick input, which may be sufficient for the user.

TODO: Add necessary support for other platforms.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
This commit is contained in:
multiSnow Liu 2023-03-17 13:15:21 +08:00 committed by Rafael Kitover
parent df81959825
commit d3f8cc1714
No known key found for this signature in database
GPG Key ID: 08AB596679D86240
10 changed files with 283 additions and 220 deletions

File diff suppressed because it is too large Load Diff

View File

@ -82,11 +82,12 @@ if(NOT WIN32 AND NOT APPLE)
if(X11_X11_LIB)
include_directories(${X11_INCLUDE_DIR})
list(APPEND VBAM_LIBS ${X11_X11_LIB})
endif()
add_definitions(-DHAVE_X11)
if(X11_Xscreensaver_LIB)
list(APPEND VBAM_LIBS ${X11_Xscreensaver_LIB})
add_definitions(-DHAVE_XSS)
endif()
endif()
find_library(EGL_LIBRARY EGL)

View File

@ -311,6 +311,7 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kUIAllowKeyboardBackgroundInput, &g_owned_opts.allow_keyboard_background_input),
Option(OptionID::kUIAllowJoystickBackgroundInput, &g_owned_opts.allow_joystick_background_input),
Option(OptionID::kUIHideMenuBar, &gopts.hide_menu_bar),
Option(OptionID::kUISuspendScreenSaver, &gopts.suspend_screensaver),
/// Sound
Option(OptionID::kSoundAudioAPI, &gopts.audio_api),
@ -538,6 +539,7 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
"AllowJoystickBackgroundInput",
_("Capture joy events while on background")},
OptionData{"ui/hideMenuBar", "", _("Hide menu bar when mouse is inactive")},
OptionData{"ui/suspendScreenSaver", "", _("Suspend screensaver when game is running")},
/// Sound
OptionData{"Sound/AudioAPI", "",

View File

@ -115,6 +115,7 @@ enum class OptionID {
kUIAllowKeyboardBackgroundInput,
kUIAllowJoystickBackgroundInput,
kUIHideMenuBar,
kUISuspendScreenSaver,
/// Sound
kSoundAudioAPI,

View File

@ -119,6 +119,7 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
/*kUIAllowKeyboardBackgroundInput*/ Option::Type::kBool,
/*kUIAllowJoystickBackgroundInput*/ Option::Type::kBool,
/*kUIHideMenuBar*/ Option::Type::kBool,
/*kUISuspendScreenSaver*/ Option::Type::kBool,
/// Sound
/*kSoundAudioAPI*/ Option::Type::kAudioApi,

View File

@ -3188,6 +3188,16 @@ bool MainFrame::BindControls()
d = LoadXRCDialog("UIConfig");
{ getcbb("HideMenuBar", gopts.hide_menu_bar); }
{
getcbb("SuspendScreenSaver", gopts.suspend_screensaver);
// TODO: change preprocessor directive to fit other platforms
#if !defined(HAVE_XSS)
cb->Hide();
#else
if (wxGetApp().UsingWayland())
cb->Hide();
#endif // !HAVE_XSS
}
wxFilePickerCtrl* fp;
#define getfp(n, o, l) \
do { \

View File

@ -100,6 +100,7 @@ extern struct opts_t {
/// UI Config
bool hide_menu_bar = true;
bool suspend_screensaver = false;
/// wxWindows
// wxWidgets-generated options (opaque)

View File

@ -413,6 +413,8 @@ void GameArea::LoadGame(const wxString& name)
#endif
#endif
SuspendScreenSaver();
// probably only need to do this for GB carts
if (coreOptions.winGbPrinterEnabled)
gbSerialFunction = gbPrinterSend;
@ -624,6 +626,7 @@ void GameArea::UnloadGame(bool destruct)
cheatsDeleteAll(false);
}
UnsuspendScreenSaver();
emulating = false;
loaded = IMAGE_UNKNOWN;
emusys = NULL;
@ -1029,6 +1032,7 @@ void GameArea::Pause()
#endif
paused = was_paused = true;
UnsuspendScreenSaver();
// when the game is paused like this, we should not allow any
// input to remain pressed, because they could be released
@ -1047,6 +1051,7 @@ void GameArea::Resume()
return;
paused = false;
SuspendScreenSaver();
SetExtraStyle(GetExtraStyle() | wxWS_EX_PROCESS_IDLE);
if (loaded != IMAGE_UNKNOWN)
@ -1210,6 +1215,7 @@ void GameArea::OnIdle(wxIdleEvent& event)
if (!emulating) {
emulating = true;
SuspendScreenSaver();
UnloadGame();
}
@ -1338,7 +1344,7 @@ static Display* GetX11Display()
{
return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(wxGetApp().frame->GetHandle()));
}
#endif
#endif // __WXGTK__
void GameArea::OnKeyDown(wxKeyEvent& ev)
{
@ -1380,7 +1386,7 @@ void GameArea::OnSDLJoy(wxJoyEvent& ev)
// tell Linux to turn off the screensaver/screen-blank if joystick button was pressed
// this shouldn't be necessary of course
#if defined(__WXGTK__) && defined(HAVE_XSS)
#if defined(__WXGTK__) && defined(HAVE_X11) && !defined(HAVE_XSS)
if (!wxGetApp().UsingWayland()) {
auto display = GetX11Display();
XResetScreenSaver(display);
@ -2638,3 +2644,27 @@ void GameArea::OnGBBorderChanged(config::Option* option) {
}
}
}
void GameArea::SuspendScreenSaver() {
#ifdef HAVE_XSS
if (xscreensaver_suspended || !gopts.suspend_screensaver)
return;
// suspend screensaver
if (emulating && !wxGetApp().UsingWayland()) {
auto display = GetX11Display();
XScreenSaverSuspend(display, true);
xscreensaver_suspended = true;
}
#endif // HAVE_XSS
}
void GameArea::UnsuspendScreenSaver() {
#ifdef HAVE_XSS
// unsuspend screensaver
if (xscreensaver_suspended) {
auto display = GetX11Display();
XScreenSaverSuspend(display, false);
xscreensaver_suspended = false;
}
#endif // HAVE_XSS
}

View File

@ -606,10 +606,12 @@ public:
void HideMenuBar();
void ShowMenuBar();
void OnGBBorderChanged(config::Option* option);
void SuspendScreenSaver();
void UnsuspendScreenSaver();
protected:
void MouseEvent(wxMouseEvent&);
bool pointer_blanked, menu_bar_hidden = false;
bool pointer_blanked, menu_bar_hidden, xscreensaver_suspended = false;
uint32_t mouse_active_time;
wxPoint mouse_last_pos;
#ifdef __WXMSW__

View File

@ -11,6 +11,13 @@
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxCheckBox" name="SuspendScreenSaver">
<label>Suspend ScreenSaver</label>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="sizeritem">
<flag>wxALL|wxEXPAND</flag>
<border>5</border>