Open fohrloop opened 8 months ago
Comments which are merely debugging details mode under \<details> to reduce noise
@ccrutchf I'm continuing the discussion here. I added my current understanding about the Windows sleep & lock states and the possible transitions in a diagram here. Not sure if it is perfect, but it can serve as basis for discussion.
When the SetThreadExecutionState is used with ES_SYSTEM_REQUIRED (keep.running) it is not possible to automatically get to the Sleep state which takes the upper right corner away (let's also forget manual sleep):
Result: Now the screen lock state will only be entered if there is a screen saver with password enabled. Not sure if this a problem of not.
Document well that wakepy keep.running mode only prevents suspend, and it does not guarantee that the system will lock automatically, if a screensaver with password (or a screen lock process) is not enabled.
wakepy keep.running mode prevents suspend and guarantees that system will lock the screen automatically.
wakepy keep.running mode which only prevents suspend. Add another context manager which guarantees automatic screen lock.
@ccrutchf
PowerToys sets the precedent of not worrying about locking: https://github.com/microsoft/PowerToys/blob/c406a15099584a069374ab5531e1f711c5b53315/src/modules/awake/Awake/Core/Manager.cs
I interpreted your comment as "PowerToys does not lock the screen automatically but just uses SetThreadExecutionState to prevent automatic suspend. Because PowerToys is widely used, it can be used as an example, and people are used to that behavior. In other words, perhaps wakepy should not guarantee automatic screen lock". I agree with that :)
They even have an issue about this: https://github.com/microsoft/PowerToys/issues
Search 27178.
I checked it. It says
- Set Awake to keep awake indefinitely + keep screen on.
Let's look at the state transition diagram. Since ES_SYSTEM_REQUIRED and ES_DISPLAY_REQUIRED are both on, the automatic idle timer based transitions (ScreenSaveTimeout and suspend timer) are not possible:
- Put your computer to sleep.
This means that manual transition from Working to Sleep.
- Somehow awake the computer (i.e. via mouse) but do not unlock it (keep lock screen).
Now the system gets to the lock screen. This means that the user had "Require sign-in when PC wakes up from sleep" setting enabled. Now if you look at the situation, since ES_SYSTEM_REQUIRED and ES_DISPLAY_REQUIRED are both set, there are only two ways to get out of the lock screen: (4) unlocking with password (5) putting system manually back to sleep (with power button? not sure if possible otherwise)
NB: if Keep screen on is disabled PC will go to sleep again in 2 mins.
I would like to test if this is actually what happens. Note that is "keep screen" is disabled (there is no ES_DISPLAY_REQUIRED flag), the options look like this (additional option 6):
I would guess that most likely the route (6) occurs then automatically after the ScreenSaverTimeout. Then, as it is very common to have "blank" as the Screen Saver, the laptop screen will simply turn black. But the computer is not in sleep state, as it cannot enter sleep state automatically since ES_SYSTEM_REQUIRED prevents it. So without testing myself or seeing more proof, my guess is that what is actually happening is that the system ends up in the Screen saver state with "blank" screen saver.
PC should be able to go to sleep again in 2 mins (default value for Windows 10) if it hasn't been unlocked.
^-- If automatic sleep is prevented, the system will not automatically sleep. It will not matter if the starting state is the screen lock or the working state. I don't think that PowerToys (or wakepy) should disable itself when lock screen is turned on. Otherwise, when someone just starts a long running process with keep.running mode on, and locks the screen (for security), the mode would be terminated immediately and the process would not long more than few minutes.
Then other question is that if the mode should terminate itself if the system is put manually to sleep. I think it should not. The reasoning is that if something is running before (manual) sleep, it should be running after system resumes from sleep. That is how all programs work. Maybe there are some rare use cases where that kind of behavior is beneficial, but that should not be the automatic behaviour in wakepy, I think. And providing similar user experience cross-platform would probably be quite difficult. I guess that in a potential solution one somehow listen the system when it's going to sleep/resuming from sleep.
Labeled this as a bug although not sure if this can be thought of a bug in wakepy or as a feature of the Windows operating system.
A possible solution to this should consider also other systems, which may only lock screen automatically on certain situations. For example, on KDE Plasma on Kubuntu, screenlock is started when returning from sleep, or when it's enabled with a timer and the idle timer reaches the set value. It's possible that people have this automatic screensaver timer completely disabled. What should happen then? Should wakepy at least give a warning by default? See this comment on reddit.
Background: State diagram
The current understanding of the Windows sleep & lock states diagram.
Windows may lock the screen automatically in two occasions:
This has the implication that wakepy might prevent automatic screen lock, because if Sleep is inhibited, the route (2) to lock screen is not possible. If route (1) to lock screen is also removed, Windows will never lock screen automatically.This happens when user does not a screen saver with password enabled and there is no Group Policy enforcing automatic and secure screen lock.
To think about
Should wakepy take care that the screen lock is started in the keep.running mode? Or is it the responsibility of the user to have Screen Saver enabled on Windows (and perhaps, on some other systems)?
Possible solutions
Solution option A
Solution option B
allow_disable_autolock=False
to the keep.running mode? In the returned mode, also tell if the automatic screen lock is disabled.