Bug 479195 - Displays should be able to suspend if the session is manually locked, even when inhibited
Summary: Displays should be able to suspend if the session is manually locked, even wh...
Status: REPORTED
Alias: None
Product: plasmashell
Classification: Plasma
Component: Power management & brightness (show other bugs)
Version: 6.2.4
Platform: Arch Linux Linux
: NOR wishlist
Target Milestone: 1.0
Assignee: Plasma Bugs List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-12-30 19:15 UTC by Eevee
Modified: 2024-12-18 21:41 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eevee 2023-12-30 19:15:31 UTC
On multiple occasions I've locked my desktop for the night, gone to bed, and awoken in the morning to find that my monitors have been awake the entire time.  Even `xset dpms force suspend` doesn't actually work; my displays will suspend, but then come back on moments later.  (I prefer not to turn them completely off because that has historically confused kwin and scattered all of my windows to the four winds.)

This has always turned out to be due to some software (that I left running and forgot about) having a surprise feature of, as the frequent culprit SDL calls it, inhibiting the screen saver.  Which is very frustrating if you aren't aware that that's a freedesktop capability, let me tell you.  :)

Anyway, it seems to me that if I /manually/ lock my session, there's no reason to also prevent my displays from sleeping -- whatever might be on the screen, I can't see it anyway!

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: 
KDE Plasma Version: 5.27.8
KDE Frameworks Version: 5.110.0
Qt Version: 5.15.11
Using X.
Comment 1 Jakob Petsovits 2024-03-17 17:55:23 UTC
Okay, so I just tried out VLC (which uses the freedesktop inhibitor functionality) on Plasma 6.0.2 as well as my old 5.27 installation, X11 and Wayland. I cannot reproduce what you're mentioning. It works exactly like you're suggesting: When the desktop is unlocked and the video is playing, the screen locker does not trigger and the displays stay on; when I manually lock the screen, it turns off after the 1 minute that I used as example configuration.

I looked at the code - the KDE power management service has a section that specifically checks for whether the screen locker is active, and disables screen change inhibitions when it is active. When the inhibition disappears, the "DPMS" action kicks in to turn off the screen after the configured timeout. So from what I can tell, everything in the locking / screen turn-off department is working as it's supposed to.

Which makes me wonder whether your software is up to some other shenanigans in order to prevent sleeping. Back in the days, before the freedesktop inhibitions interface existed, it was somewhat common to block screen locking by emulating the the Shift key being pressed. On X11, there is nothing to keep apps from injecting keys that way, and I can confirm that pressing my physical Shift key will wake up the monitor also when the screen is locked.

Could you have a look if there are input events being sent by an application when this happens to you? On X11, you can use command line programs such as `evtest` / `xinput test` (for individual devices, including pointer input) or `sudo showkey` (with a longer timeout, for keyboard input from any device?) to print input events that Plasma including the screen locker would pick up on.
Comment 2 Eevee 2024-03-18 01:25:20 UTC
That's, uh, odd.

I tried the following:

- run `xinput test 9` in one terminal
- run `love` in another terminal (no game loaded, just an SDL window, so, about as small a test as I can get without building something)
- run `sleep 10; xset dpms force suspend` in a third terminal
- quickly lock the screen and sit back

My screen reliably turns off, then back on.  I don't see anything that looks like spurious keyboard input.

Poring over source code, LÖVE simply calls SDL_DisableScreenSaver(), which is implemented here for X:
https://github.com/libsdl-org/SDL/blob/12245e4c756eb964ecdf4a528c36aab6f971baf5/src/video/x11/SDL_x11events.c#L2023

If built with dbus support, which seems to be the default, then it appears to use the freedesktop interface:
https://github.com/libsdl-org/SDL/blob/main/src/core/linux/SDL_dbus.c#L428
Otherwise it falls back to XScreenSaverSuspend, which looks like it's supposed to be called on a timer.

VLC also has two implementations: one that shells out to `xdg-screensaver reset`:
https://github.com/videolan/vlc/blob/f7bb59d9f51cc10b25ff86d34a3eff744e60c46e/modules/misc/inhibit/xdg.c#L33
And one using dbus, which at a glance is at least somewhat similar to the SDL implementation:
https://github.com/videolan/vlc/blob/f7bb59d9f51cc10b25ff86d34a3eff744e60c46e/modules/misc/inhibit/dbus.c#L239

So I have no idea what's going on here.  Both applications seem to do the correct thing: try DBus, and if that doesn't work, fall back to an X interface.  If KDE's power management works as you describe then I'd expect both approaches to have the same results?
Comment 3 Jakob Petsovits 2024-03-18 02:42:50 UTC
Hm. I see that SDL has a fallback called SDL_DBus_ScreensaverTickle(), which calls org.freedesktop.ScreenSaver with SimulateUserActivity. If for some reason this gets called, it would do the same thing as a real or emulated key press.

Could you have a look with `dbus-monitor` to observe what actually gets called by your program?
Comment 4 Eevee 2024-03-18 20:13:38 UTC
Same procedure but with dbus-monitor running, and the only mentions of org.freedesktop.ScreenSaver are:

# starting love
method call time=1710791833.031274 sender=:1.9319 -> destination=org.freedesktop.ScreenSaver serial=6 path=/org/freedesktop/ScreenSaver; interface=org.freedesktop.ScreenSaver; member=Inhibit
   string "My SDL application"
   string "Playing a game"
method call time=1710791833.031619 sender=:1.12 -> destination=org.kde.Solid.PowerManagement.PolicyAgent serial=366224 path=/org/kde/Solid/PowerManagement/PolicyAgent; interface=org.kde.Solid.PowerManagement.PolicyAgent; member=AddInhibition
   uint32 4
   string "My SDL application"
   string "Playing a game"
...
# locking
signal time=1710791840.483870 sender=:1.14 -> destination=(null destination) serial=39716 path=/component/ksmserver; interface=org.kde.kglobalaccel.Component; member=globalShortcutPressed
   string "ksmserver"
   string "Lock Session"
   int64 243112269
signal time=1710791840.484068 sender=:1.12 -> destination=(null destination) serial=366228 path=/ScreenSaver; interface=org.kde.screensaver; member=AboutToLock
signal time=1710791840.484073 sender=:1.12 -> destination=(null destination) serial=366229 path=/org/freedesktop/ScreenSaver; interface=org.kde.screensaver; member=AboutToLock
signal time=1710791840.573955 sender=:1.14 -> destination=(null destination) serial=39717 path=/component/ksmserver; interface=org.kde.kglobalaccel.Component; member=globalShortcutReleased
   string "ksmserver"
   string "Lock Session"
   int64 243112269
...
# locking finished...?
signal time=1710791842.146249 sender=:1.12 -> destination=(null destination) serial=366230 path=/ScreenSaver; interface=org.freedesktop.ScreenSaver; member=ActiveChanged
   boolean true
signal time=1710791842.146273 sender=:1.12 -> destination=(null destination) serial=366231 path=/org/freedesktop/ScreenSaver; interface=org.freedesktop.ScreenSaver; member=ActiveChanged
   boolean true
method call time=1710791842.146277 sender=:1.12 -> destination=org.kde.kglobalaccel serial=366232 path=/kglobalaccel; interface=org.kde.KGlobalAccel; member=allComponents
signal time=1710791842.146536 sender=:1.24 -> destination=(null destination) serial=468463 path=/org/freedesktop/PowerManagement/Inhibit; interface=org.freedesktop.PowerManagement.Inhibit; member=HasInhibitChanged
   boolean true
signal time=1710791842.146545 sender=:1.24 -> destination=(null destination) serial=468464 path=/org/freedesktop/PowerManagement; interface=org.freedesktop.PowerManagement.Inhibit; member=HasInhibitChanged
   boolean true
...
# ???
signal time=1710791870.577083 sender=:1.12 -> destination=(null destination) serial=366245 path=/ScreenSaver; interface=org.freedesktop.ScreenSaver; member=ActiveChanged
   boolean false
signal time=1710791870.577304 sender=:1.12 -> destination=(null destination) serial=366246 path=/org/freedesktop/ScreenSaver; interface=org.freedesktop.ScreenSaver; member=ActiveChanged
   boolean false
signal time=1710791870.578015 sender=:1.24 -> destination=(null destination) serial=468465 path=/org/freedesktop/PowerManagement/Inhibit; interface=org.freedesktop.PowerManagement.Inhibit; member=HasInhibitChanged
   boolean true
signal time=1710791870.578030 sender=:1.24 -> destination=(null destination) serial=468466 path=/org/freedesktop/PowerManagement; interface=org.freedesktop.PowerManagement.Inhibit; member=HasInhibitChanged
   boolean true

as well as a couple calls to org.freedesktop.DBus that look like uninteresting interface inspection.  Still seems like SDL is doing the right thing.  Not sure what the last block of stuff is about, a conspicuous 30 seconds after my last input (pressing super+L).

And the same steps without running `love` do leave my monitors asleep.