mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-10 01:16:40 +02:00
On X11, hiro uses the xdg-screensaver helper tool to disable the screensaver, which detects the screensaver that is running and uses the appropriate mechanism to communicate with it. The tool's API expects an X11 window ID, but at least some screensavers ignore it, so it can be set up however. The GNOME backend *does* care about the window ID, but its expectations are not documented anywhere, so byuu spent a frustrating few days trying things at random to get it working, and failing. It turns out, GNOME does *not* require the window to be mapped, but it *does* require the window to have a name. Using XStoreName() to name the window fixes screensaver suspension for me under GNOME 3.38. Note: while XStoreName is technically deprecated, it's not going to go away while X11 is still around, and the reason it's deprecated is because it doesn't include character encoding data. We don't care — no user should ever see the window name, and it's plain ASCII so it should be fine. Fixes #102.
117 lines
3.3 KiB
C++
Executable File
117 lines
3.3 KiB
C++
Executable File
#if defined(Hiro_Application)
|
|
|
|
namespace hiro {
|
|
|
|
auto pApplication::exit() -> void {
|
|
quit();
|
|
::exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
auto pApplication::modal() -> bool {
|
|
return Application::state().modal > 0;
|
|
}
|
|
|
|
auto pApplication::run() -> void {
|
|
if(Application::state().onMain) {
|
|
while(!Application::state().quit) {
|
|
Application::doMain();
|
|
processEvents();
|
|
}
|
|
} else {
|
|
QApplication::exec();
|
|
}
|
|
}
|
|
|
|
auto pApplication::pendingEvents() -> bool {
|
|
return QApplication::hasPendingEvents();
|
|
}
|
|
|
|
auto pApplication::processEvents() -> void {
|
|
while(pendingEvents()) QApplication::processEvents();
|
|
}
|
|
|
|
auto pApplication::quit() -> void {
|
|
QApplication::quit();
|
|
qtApplication = nullptr; //note: deleting QApplication will crash libQtGui
|
|
|
|
if(state().display) {
|
|
if(state().screenSaverXDG && state().screenSaverWindow) {
|
|
//this needs to run synchronously, so that XUnmapWindow() won't happen before xdg-screensaver is finished
|
|
execute("xdg-screensaver", "resume", string{"0x", hex(state().screenSaverWindow)});
|
|
XUnmapWindow(state().display, state().screenSaverWindow);
|
|
state().screenSaverWindow = 0;
|
|
}
|
|
XCloseDisplay(state().display);
|
|
state().display = nullptr;
|
|
}
|
|
}
|
|
|
|
auto pApplication::setScreenSaver(bool screenSaver) -> void {
|
|
#if defined(DISPLAY_XORG)
|
|
if(state().screenSaverXDG && state().screenSaverWindow) {
|
|
invoke("xdg-screensaver", screenSaver ? "resume" : "suspend", string{"0x", hex(state().screenSaverWindow)});
|
|
}
|
|
#endif
|
|
}
|
|
|
|
auto pApplication::state() -> State& {
|
|
static State state;
|
|
return state;
|
|
}
|
|
|
|
//this is sadly necessary for things like determining window frame geometry
|
|
//obviously, it is used as sparingly as possible
|
|
auto pApplication::synchronize() -> void {
|
|
for(auto n : range(8)) {
|
|
#if HIRO_QT==4 && defined(DISPLAY_XORG)
|
|
QApplication::syncX();
|
|
#elif HIRO_QT==5
|
|
QApplication::sync();
|
|
#endif
|
|
Application::processEvents();
|
|
usleep(2000);
|
|
}
|
|
}
|
|
|
|
auto pApplication::initialize() -> void {
|
|
#if HIRO_QT==5 && defined(PLATFORM_BSD)
|
|
setenv("QTCOMPOSE", "/usr/local/lib/X11/locale/", 0);
|
|
#endif
|
|
|
|
#if defined(DISPLAY_XORG)
|
|
state().display = XOpenDisplay(nullptr);
|
|
state().screenSaverXDG = (bool)execute("xdg-screensaver", "--version").output.find("xdg-screensaver");
|
|
|
|
if(state().screenSaverXDG) {
|
|
auto screen = DefaultScreen(state().display);
|
|
auto rootWindow = RootWindow(state().display, screen);
|
|
XSetWindowAttributes attributes{};
|
|
attributes.background_pixel = BlackPixel(state().display, screen);
|
|
attributes.border_pixel = 0;
|
|
attributes.override_redirect = true;
|
|
state().screenSaverWindow = XCreateWindow(state().display, rootWindow,
|
|
0, 0, 1, 1, 0, DefaultDepth(state().display, screen),
|
|
InputOutput, DefaultVisual(state().display, screen),
|
|
CWBackPixel | CWBorderPixel | CWOverrideRedirect, &attributes
|
|
);
|
|
XStoreName(state().display, state().screenSaverWindow, "hiro screensaver-prevention window");
|
|
XFlush(state().display);
|
|
}
|
|
#endif
|
|
|
|
static auto name = Application::state().name ? Application::state().name : string{"hiro"};
|
|
|
|
//QApplication stores references to argc;
|
|
//and will access them after pApplication::initialize() returns
|
|
static int argc = 1;
|
|
static char* argv[] = {name.get(), nullptr};
|
|
static char** argvp = argv;
|
|
qtApplication = new QApplication(argc, argvp);
|
|
|
|
pKeyboard::initialize();
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|