microsoft / microsoft/PowerToys
Awake: keep the system awake with the display off on Modern Standby (S0), including when locked
- Dominant language
- C
- Stars
- 139k
- Forks
- 8.6k
- PR merge metrics
- PR metrics pending
Description
### Description of the new feature / enhancement
**The ask, in one line:** let PowerToys Awake keep a modern laptop awake *with the screen off* — and, ideally, while it's locked — by moving from the legacy Windows power API to the modern one.
**The pain.** Awake exists to keep a machine running while you step away. On today's laptops it can't quite deliver:
- **Keep awake** on, **Keep screen on** *off* → the machine still sleeps a few minutes after the display goes dark.
- Whatever Awake is holding also **stops the moment you lock the PC** — confirmed in Microsoft's own docs (*Lock screen behavior*, cited below).
So the most common reason anyone runs Awake — *"let the screen sleep, but keep my download, build, server, or remote session alive while I'm away"* — is exactly what fails.
**This is a Modern Standby problem, not a CPU one.** On an older **S3-sleep** laptop or a desktop, today's API holds the system awake with the display off just fine. The failure is specific to **Modern Standby (S0 Low Power Idle)** — now standard on most new laptops, **x64 and ARM alike**, with S3 disabled in firmware. (The lock-screen limitation is separate and applies on any machine.)
This keeps getting reported and closed as a "Windows / Feedback Hub" problem (#44458 → #44286, also #36864), but it is fixable inside Awake. Closing #44286 to the Feedback Hub was a mis-diagnosis: the behavior is set by Awake's choice of power API, not by Windows — switching to `PowerSetRequest` resolves it with no OS-side change. The closest open request, #39287 ("Turn Off Screen While Keeping System Awake"), asks for the behavior without pinning down why today's display-off mode fails.
One more wrinkle: the only reliable hold available today is to also enable **Keep screen on**, which keeps the panel lit *and*, per Awake's README, sets `ES_DISPLAY_REQUIRED` — blocking SSD TRIM and other idle maintenance (#44134). So the current escape hatch trades one problem for two.
**Root cause.** Awake's only power mechanism is the legacy Win32 **`SetThreadExecutionState`** — the docs describe it as spawning "background threads that tell Windows that they require a specific state of the machine." Verified against current `main`:
- `src/modules/awake/Awake/Core/Native/Bridge.cs` — P/Invokes `SetThreadExecutionState` (and imports `Powrprof.dll` only for `GetPwrCapabilities`). No `PowerSetRequest` / `PowerCreateRequest` in the module — or anywhere in the repo.
- `src/modules/awake/Awake/Core/Manager.cs` (`ComputeAwakeState`) — composes `ExecutionState.ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_CONTINUOUS` (display on) or `ES_SYSTEM_REQUIRED | ES_CONTINUOUS` (display off).
- `src/modules/awake/README.md` — "The module uses the Win32 `SetThreadExecutionState()` API."
That produces two distinct gaps:
| Gap | When it bites | Why |
| --- | --- | --- |
| **1. Won't hold with the screen off** | Modern Standby (S0) only | `ES_SYSTEM_REQUIRED` only resets the idle timer; on S0 with the display off it doesn't keep the system out of connected standby. It never sets `PowerRequestExecutionRequired` (Windows 8+), the documented request for keeping work running across Modern Standby — and on **AC power** those requests aren't auto-terminated. |
| **2. Won't hold while locked** | Any machine | Awake is a user-session app, so it can't survive the lock screen's separate security context — Microsoft's docs: *"user-mode applications like PowerToys Awake can't maintain their power requests"* — or sign-out (#29673). |
**Scope — this is a plugged-in (AC) feature.** On DC/battery, Modern Standby terminates system/execution power requests 5 minutes after the sleep timeout (per the [`PowerSetRequest` remarks](https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-powersetrequest#remarks)), so keep-awake can't hold on battery regardless of the API — which is exactly why the AC-aware mode (below) releases on DC. A plugged-in remote-access host is the intended scenario.
**Proposed enhancement.**
1. **Switch the keep-awake path to the modern API** — `PowerCreateRequest` + `PowerSetRequest` with `PowerRequestSystemRequired` (and `PowerRequestExecutionRequired` when the intent is to keep a process running). Fixes Gap 1; shows up correctly in `powercfg /requests` under SYSTEM (and EXECUTION). Resolves #44458 / #44286 / #36864.
2. **Optional — a "stay active when locked / signed out" mode** (a Windows service or SYSTEM scheduled task) for Gap 2, so the hold survives the lock screen. Microsoft's current answer — "modify your Windows power plan settings directly" — can't give you display-off-while-awake.
3. **Optional — AC-aware mode** — hold only on AC, release on battery, so it can't silently drain a laptop.
### Scenario when this would be used?
Keeping a plugged-in laptop doing real work while the user is away and the screen is off: long downloads or builds, a local server, a backup, or — increasingly — a remote-access / agent session (RDP, SSH, or an AI coding agent) that has to stay reachable. On Modern Standby hardware that's exactly where Awake falls short today: the user wants the **display to sleep** (save the panel, save power) but the **machine to stay awake and reachable, including while locked**. As S3 disappears and Modern Standby becomes universal on new laptops, this gets more common, not less.
### Supporting information
**Source (current `main`):**
- `src/modules/awake/Awake/Core/Native/Bridge.cs` — only `SetThreadExecutionState` (kernel32) + `GetPwrCapabilities` (Powrprof); no `PowerSetRequest` / `PowerCreateRequest`.
- `src/modules/awake/Awake/Core/Manager.cs` — `ComputeAwakeState` / `SetAwakeState`.
- `src/modules/awake/README.md` — "uses the Win32 `SetThreadExecutionState()` API"; plus the `ES_DISPLAY_REQUIRED` → blocked-TRIM note.
**Docs:**
- PowerToys Awake — **"Lock screen behavior"** (the locked-screen limitation, in Microsoft's own words): https://learn.microsoft.com/windows/powertoys/awake
- `SetThreadExecutionState` (resets idle timers only): https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate
- `PowerSetRequest` / `PowerRequestExecutionRequired` (overrides Process Lifetime Management; AC vs DC termination): https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-powersetrequest
- Modern Standby (S0 Low Power Idle): https://learn.microsoft.com/windows-hardware/design/device-experiences/modern-standby
**Related issues:** #44458, #44286, #36864, #39287, #29673, #15616, #34479, #44134.
**Happy to contribute.** I have a working reference implementation of this approach — a SYSTEM-level holder using `PowerSetRequest` with `PowerRequestExecutionRequired`, AC-aware, verified via `powercfg /requests` showing SYSTEM + EXECUTION on a Modern Standby machine (Surface Laptop 7, Windows 11 ARM64 — though the gap is Modern-Standby-wide, not ARM-specific). I'd be glad to put up a PR for the Awake module if the team is open to it.
Contributor guide
Research direction
Start with src/modules/awake/Awake/Core/Native/Bridge.cs and src/modules/awake/Awake/Core/Manager.cs, focusing on the existing power API and ComputeAwakeState/SetAwakeState flow. Read src/modules/awake/README.md and the linked Windows API documentation, then use powercfg /requests to verify the agreed behavior for display-off Modern Standby and any locked or AC-aware scope.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop, operating-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100