microsoft / microsoft/PowerToys
[Awake] Automatically disable “Keep screen on” when the workstation is locked
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 139k
- Forks
- 8.6k
- PR merge metrics
- PR metrics pending
Description
Description of the new feature / enhancement
The Keep screen on option in PowerToys Awake prevents Windows from running certain background tasks that only execute when the display is allowed to turn off.
Additionally, when I lock my PC, I usually want the screensaver (or sleep timers) to be allowed to run.
Currently, I have to manually disable Keep screen on every time before locking the machine.
This feature request proposes an automatic behavior:
When the workstation is locked, Awake should temporarily stop requesting display‑awake state, and restore it when the user unlocks the session.
Proposed solution
Awake should listen for Windows session state changes (lock/unlock) and adjust its execution state flags accordingly:
On session lock:
Temporarily disable the Keep screen on request so Windows can start the screensaver or apply normal power management.
On session unlock:
Restore the Awake state based on the user’s configured mode (indefinite or timed awake).
This would allow Awake to keep background tasks running while still respecting user expectations when the device is locked.
Scenario when this would be used?
Why this is useful
Some Windows background tasks only run when the screen is allowed to turn off.
Users often want screensavers or sleep timers to work when the device is locked.
The current behavior forces manual toggling of Awake before locking the workstation.
The proposed behavior is fully automatic and does not change Awake’s core functionality.
Supporting information
Awake continuously calls SetThreadExecutionState with flags such as ES_DISPLAY_REQUIRED and ES_SYSTEM_REQUIRED, even when the workstation is locked.
To allow screensavers and sleep timers to run, Awake needs to handle Windows session state changes.
- Detecting workstation lock/unlock
When the app starts, it detect the state of the workstation with the native WTSQuerySessionInformation.
To get the event of the locked state changes, in C#, this can be done using SystemEvents.SessionSwitch:
public class Manager : IDisposable // <-- This is new, it should be disposable
{
private bool _disposed; // <-- This is new, it should be disposable
private static bool IsScreenLocked { get; set; }
static Manager()
{
_monitorTokenSource = new CancellationTokenSource();
_stateQueue = [];
ModuleSettings = SettingsUtils.Default;
SystemEvents.SessionSwitch += OnSessionSwitch; // <-- This is new
}
private static void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLock)
{
IsScreenLocked = true;
}
else if (e.Reason == SessionSwitchReason.SessionUnlock)
{
IsScreenLocked = false;
}
ReapplyAwakeState();
}
private static ExecutionState ComputeAwakeState(bool keepDisplayOn)
{
return keepDisplayOn
&& !IsScreenLocked // <-- This is new
? ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_CONTINUOUS
: ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS;
}
// Dispose pattern starts ----
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
SystemEvents.SessionSwitch -= OnSessionSwitch;
}
_disposed = true;
}
~Manager()
{
Dispose(false);
}
Additional notes
This change does not alter existing UI or user workflows.
It improves consistency with user expectations when locking the workstation.
It aligns Awake with typical Windows session‑aware behavior.
Tested on Windows 11.
The WtsApi tested with a small console dotnet Windows APP:
namespace ConsoleApp1;
internal class Program
{
public static async Task Main()
{
while (true)
{
Console.Write($"{DateTime.Now} Screen locked: {SessionStateDetector.IsWorkstationLocked()}{Environment.NewLine}");
await Task.Delay(1000);
}
}
}
The output while it lockwd about 10 secs:
2026. 09. 01. 19:12:14 Screen locked: False
2026. 09. 01. 19:12:15 Screen locked: False
2026. 09. 01. 19:12:16 Screen locked: False
2026. 09. 01. 19:12:17 Screen locked: False
2026. 09. 01. 19:12:18 Screen locked: True
2026. 09. 01. 19:12:19 Screen locked: True
2026. 09. 01. 19:12:20 Screen locked: True
2026. 09. 01. 19:12:21 Screen locked: True
2026. 09. 01. 19:12:22 Screen locked: True
2026. 09. 01. 19:12:23 Screen locked: True
2026. 09. 01. 19:12:24 Screen locked: True
2026. 09. 01. 19:12:25 Screen locked: True
2026. 09. 01. 19:12:26 Screen locked: True
2026. 09. 01. 19:12:27 Screen locked: True
2026. 09. 01. 19:12:28 Screen locked: True
2026. 09. 01. 19:12:29 Screen locked: True
2026. 09. 01. 19:12:30 Screen locked: True
2026. 09. 01. 19:12:31 Screen locked: True
2026. 09. 01. 19:12:32 Screen locked: True
2026. 09. 01. 19:12:33 Screen locked: True
2026. 09. 01. 19:12:34 Screen locked: False
2026. 09. 01. 19:12:35 Screen locked: False
2026. 09. 01. 19:12:36 Screen locked: False
2026. 09. 01. 19:12:37 Screen locked: False
2026. 09. 01. 19:12:38 Screen locked: False
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing Awake's SetThreadExecutionState handling and the proposed WTSQuerySessionInformation and SystemEvents.SessionSwitch entry points. Implement lock and unlock state handling so display-awake requests are removed while locked and restored according to the configured mode, then verify the behavior on Windows 11.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop, operating-systems
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100