Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BizHawk does not inhibit display or system sleep while running #3644

Closed
koitsu opened this issue Apr 23, 2023 · 14 comments
Closed

BizHawk does not inhibit display or system sleep while running #3644

koitsu opened this issue Apr 23, 2023 · 14 comments
Labels
App: EmuHawk Relating to EmuHawk frontend Enhancement For feature requests or possible improvements Repro: Fixed/added in 2.10 dev
Milestone

Comments

@koitsu
Copy link

koitsu commented Apr 23, 2023

Summary

BizHawk does not inhibit display or system sleep while running. This is a common problem that plagues even AAA-gaming-industry titles, so don't feel bad.

Repro

Demonstrating lack of display sleep inhibition:

  1. Enable display sleep in Windows. In Windows 10: System -> Power and Sleep -> Screen -> When plugged in, turn off after: N minutes (example: 2 minutes)
  2. Launch BizHawk + load/run a game
  3. Wait 2 minutes
  4. Display will go into sleep mode

Solutions

There's 3 main methodologies you can use. I am not familiar with BizHawk's code so I don't know which is easiest to implement.

It's important to give this feature a GUI setting/toggle somewhere (probably under Config -> Customize -> General or Advanced), and the feature default to disabled (since that's how BizHawk has been behaving all this time).

Newer method (supported by Windows 7 onward)

Leverage the Windows Power Management API, specifically functions PowerCreateRequest() and PowerSetRequest() for a RequestType of PowerRequestDisplayRequired (inhibit display sleep) or PowerRequestSystemRequired (inhibit system sleep).

You can verify things are inhibited by launching a Command Prompt as Administrator and using powercfg.exe /requests. You should see the BizHawk process listed under DISPLAY, with the line "Video Wake Lock" under it. (For PowerRequestSystemRequired, it would be under SYSTEM).

If you want to see how this manifests today, run Chrome and watch a video somewhere (YouTube, Twitch, etc.): you'll find chrome.exe listed under DISPLAY and SYSTEM (thus, inhibiting display and system sleep).

Older method 1 (supported by Windows XP onward)

Use SetThreadExecutionState(). This is described at the end of the nesdev forum thread mentioned below.

Older method 2 (supported by Windows 2000 onward)

In your main window handler, add support for handling the WM_SYSCOMMAND message to detect SC_SCREENSAVE or SC_MONITORPOWER messages:

case WM_SYSCOMMAND:
    if (running && (((wParam & 0xFFF0) == SC_SCREENSAVE) || ((wParam & 0xFFF0) == SC_MONITORPOWER)))
        return 0;
    // otherwise, proceed to DefWindowProc

You cannot verify this method using powercfg.exe /requests, given that window message handlers do not "register" with the Power Management API, but it (obviously) does work.

I forget how to inhibit system sleep using this method.

SDL2 and/or Linux

There is discussion of how to implement this functionality in SDL2 and/or Linux in a nesdev forum thread I started nearly 10 years ago.

Important note

Please DO NOT implement a solution by changing system settings (Windows power profiles). I've lectured several emulator authors about this in the past. It is not the right solution and is extremely inappropriate to do, plus creates numerous problems in the case of an application crash or force-kill.

Host environment

  • BizHawk 2.9; Win10 Pro 22H2 (19045.2728); x64; Intel CPU, NVIDIA GPU
@YoshiRulz YoshiRulz added Enhancement For feature requests or possible improvements App: EmuHawk Relating to EmuHawk frontend labels Apr 23, 2023
@YoshiRulz YoshiRulz added this to the 👾 < 🦅 milestone Apr 23, 2023
@CasualPokePlayer
Copy link
Member

CasualPokePlayer commented Apr 23, 2023

To be clear, we do not support Windows XP and below at all (and Windows 7-8.1 is ""unsupported""), so the older solutions wouldn't really be applicable to us.

On Linux usage, going off SDL's source, it seems XScreenSaverSuspend/XResetScreenSaver or (if wayland is ever supported) zwp_idle_inhibit_manager_v1_create_inhibitor/zwp_idle_inhibitor_v1_destroy is the "correct" API to use. Although in that forum post, Near seems to note that XScreenSaverSuspend "does not work" (odd then that SDL would use it?), I suppose then they might have not checked if that extension was available (I would guess it wasn't), or maybe it was just bugged for them.

@nattthebear

This comment was marked as outdated.

@YoshiRulz

This comment was marked as outdated.

@nattthebear

This comment was marked as outdated.

@koitsu

This comment was marked as outdated.

@koitsu

This comment was marked as outdated.

@nattthebear nattthebear closed this as not planned Won't fix, can't repro, duplicate, stale May 24, 2023
@CasualPokePlayer
Copy link
Member

CasualPokePlayer commented Nov 26, 2023

To be clear, this (I guess unintentionally) is now implemented in practice with SDL2 now (or well, since 78f5e75) being used for the OpenGL and D3D9 display methods, as on SDL video init, SDL will disable the screensaver by default.

This probably should be adjusted in the future so we have some setting to un-disable the screensaver / give user control over this.

EDIT: There's apparently also already code in BizHawk (present since 2011?) which appears to be intended to suppress the screensaver: https://github.com/TASEmulators/BizHawk/blob/20defc890bf4a257a057acd8f997ca81d3a3da11/src/BizHawk.Client.EmuHawk/ScreenSaver.cs

Although it's Windows only and I don't know if it actually works (the fact that this issue exists probably indicates that it doesn't even work).

@YoshiRulz
Copy link
Member

YoshiRulz commented Nov 26, 2023

SDL has an implementation for Linux but it doesn't seem to be working. (edit: This is in Plasma X11.)
Firefox will trigger what KDE Plasma calls "Presentation Mode" when playing video (there's an additional global sleep toggle which seems to serve the same purpose, not sure what the deal is there), but EmuHawk dev builds do not.

@CasualPokePlayer
Copy link
Member

I suspect Linux might not work for all cases or maybe just requires some extra package (likely would need the libxss1 package installed)

@YoshiRulz
Copy link
Member

It is "installed" (there's a libXScrnSaver in SDL2's closure which provides libXss.so.1.0.0). It's definitely not inhibiting sleep. I'll add this to #1430.

@CasualPokePlayer
Copy link
Member

Not sure what you're talking about "closure", it's just calling a function pointer it gets from dlopen'ing that .so, and it doesn't do that if it's not available.

@YoshiRulz
Copy link
Member

It's Nix jargon, referring to the set of rundeps including transitive deps.

@nattthebear
Copy link
Contributor

I guess unintentionally

I never had a particularly strong opinion about this one way or the other. There was only one person advocating for, and in all of their posts they never gave a single reason why this should be done, only how. It didn't seem that useful to me, and in the absence of any other advocates, I just closed it.

@CasualPokePlayer
Copy link
Member

CasualPokePlayer commented Nov 27, 2023

fwiw, the fact we already had code to do this (but it seemed to just be broken) seems to mean SDL has fixed what was supposed to be happening (well, at least for Windows, Linux has seemingly gone from unimplemented to some broken implementation?).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
App: EmuHawk Relating to EmuHawk frontend Enhancement For feature requests or possible improvements Repro: Fixed/added in 2.10 dev
Projects
None yet
Development

No branches or pull requests

4 participants