Skip to content

Commit baa36cb

Browse files
Copilotmichaliskon
andauthored
fix: re-arm VIDEOCONLOCK at OnLock to prevent early screen-off
Agent-Logs-Url: https://github.com/michaliskon/Turn-off-screen-on-lock/sessions/b4924dc0-60c2-4691-8608-300fcd209e65 Co-authored-by: michaliskon <49875310+michaliskon@users.noreply.github.com>
1 parent a7fbbb3 commit baa36cb

4 files changed

Lines changed: 21 additions & 16 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ Can be adjusted by editing the config file:
8484

8585
```json
8686
{
87-
"baselineTimeoutSeconds": 5,
87+
"baselineTimeoutSeconds": 1,
8888
"wakeTimeoutSeconds": 300
8989
}
9090
```
9191

9292
| Setting | Default | Description |
9393
|---|---|---|
94-
| `baselineTimeoutSeconds` | 5 | Seconds before the screen turns off after locking |
94+
| `baselineTimeoutSeconds` | 1 | Seconds before the screen turns off after locking |
9595
| `wakeTimeoutSeconds` | 300 | Seconds the screen stays on when waking to unlock |
9696

9797
Both values must be integers between 1 and 86400 (24 hours).

spec.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ In practice, it gives you both of these behaviors at the same time:
1515
The solution uses `VIDEOCONLOCK`, a controller, three runtime files, and three Scheduled Tasks.
1616

1717
Runtime logic:
18-
- unlocked: `VIDEOCONLOCK` = baseline timeout (default 5 seconds, configurable)
18+
- unlocked: `VIDEOCONLOCK` = baseline timeout (default 1 second, configurable)
1919
- locked + system enters Modern Standby: On Wake task asks the controller to promote `VIDEOCONLOCK` to wake timeout (default 300 seconds, configurable)
2020
- unlocked again: controller resets `VIDEOCONLOCK` to baseline timeout
2121

@@ -30,7 +30,7 @@ Roles:
3030

3131
## Intended behavior
3232

33-
- Unlocked: `VIDEOCONLOCK` = baseline timeout (default 5 seconds, configurable via `config.json`)
33+
- Unlocked: `VIDEOCONLOCK` = baseline timeout (default 1 second, configurable via `config.json`)
3434
- Locked + exiting Modern Standby: `VIDEOCONLOCK` promoted to wake timeout (default 300 seconds, configurable via `config.json`)
3535
- Unlocked again: `VIDEOCONLOCK` reset to baseline for the next cycle
3636

@@ -92,7 +92,7 @@ uninstaller.ps1
9292

9393
| Action | Reads | Writes | Changes VIDEOCONLOCK |
9494
|---|---|---|---|
95-
| `OnLock` | -- | `state.json` | no |
95+
| `OnLock` | `config.json` | `state.json` | yes, baseline |
9696
| `OnUnlock` | `config.json` | `state.json` | yes, baseline |
9797
| `PromoteOnWake` | `state.json`, `config.json` | -- | yes, wake (if locked) |
9898

@@ -101,7 +101,7 @@ Write directions for the three JSON files:
101101
| File | Written by | Read by |
102102
|---|---|---|
103103
| `state.json` | `OnLock`, `OnUnlock`, installer | `PromoteOnWake` |
104-
| `config.json` | installer (defaults only) | `OnUnlock`, `PromoteOnWake`, installer |
104+
| `config.json` | installer (defaults only) | `OnLock`, `OnUnlock`, `PromoteOnWake`, installer |
105105
| `baseline.json` | installer (once, on first install) | uninstaller |
106106

107107
---
@@ -138,7 +138,7 @@ Full runtime design, one complete lock/unlock cycle.
138138

139139
### 1. PC is unlocked
140140

141-
- `VIDEOCONLOCK` AC and DC: baseline timeout (default `5`)
141+
- `VIDEOCONLOCK` AC and DC: baseline timeout (default `1`)
142142
- `state.json`: `status = "unlocked"`, `generation = <latest>`, `lastActionUtc = <timestamp>`
143143

144144
The baseline is armed for the next lock event.
@@ -157,11 +157,14 @@ wscript.exe "<install-folder>\RunHidden.vbs" OnLock
157157

158158
1. Generates a new GUID for this lock cycle.
159159
2. Writes `state.json`: `status = "locked"`, `generation = <new GUID>`, `lastActionUtc = <now>`.
160-
3. Leaves `VIDEOCONLOCK` unchanged.
160+
3. Reads `config.json` for the baseline timeout.
161+
4. Sets `VIDEOCONLOCK` AC and DC to the baseline timeout. Reapplies the active power scheme.
162+
163+
Setting `VIDEOCONLOCK` at lock time forces Windows to re-arm its internal display-off countdown from the moment of lock, preventing stale idle time accumulated before the lock event from causing the screen to turn off earlier than configured.
161164

162165
### 4. Display turns off
163166

164-
`VIDEOCONLOCK` is still at the baseline (default 5 seconds), so Windows turns the display off shortly after lock.
167+
Windows turns the display off after the baseline timeout (default 1 second) has elapsed since the lock event.
165168

166169
### 5. System enters Modern Standby
167170

@@ -257,7 +260,7 @@ All three share the same principal and settings listed here. Per-task sections b
257260

258261
#### Purpose
259262

260-
Marks the start of a new lock cycle. Updates `state.json` with a fresh generation ID and `locked` status. Leaves `VIDEOCONLOCK` untouched.
263+
Marks the start of a new lock cycle. Updates `state.json` with a fresh generation ID and `locked` status. Re-applies `VIDEOCONLOCK` to the baseline timeout to re-arm Windows's display-off countdown from the moment of lock.
261264

262265
#### Trigger
263266

@@ -400,7 +403,7 @@ It bridges the gap between the GitHub Release and `installer.ps1`.
400403
Parse the hex values after "Current AC Power Setting Index" and "Current DC Power Setting Index", convert to decimal, and write `baseline.json`. If a valid `baseline.json` already exists, preserve it so the true originals are never lost on re-install.
401404

402405
7. **Create or preserve `config.json`**
403-
If missing or malformed, create with defaults (`baselineTimeoutSeconds = 5`, `wakeTimeoutSeconds = 300`). If valid, preserve it. Read the effective baseline timeout for the next step.
406+
If missing or malformed, create with defaults (`baselineTimeoutSeconds = 1`, `wakeTimeoutSeconds = 300`). If valid, preserve it. Read the effective baseline timeout for the next step.
404407

405408
8. **Apply the baseline `VIDEOCONLOCK` setting**
406409
Log the applied value. If the value came from an existing `config.json`, indicate that in the message.
@@ -577,14 +580,14 @@ The controller reads `%LOCALAPPDATA%\Turn-off-screen-on-lock\config.json` on eac
577580

578581
```json
579582
{
580-
"baselineTimeoutSeconds": 5,
583+
"baselineTimeoutSeconds": 1,
581584
"wakeTimeoutSeconds": 300
582585
}
583586
```
584587

585588
| Field | Type | Range | Default | Description |
586589
|---|---|---|---|---|
587-
| `baselineTimeoutSeconds` | integer | 1–86400 | 5 | Seconds before the screen turns off after locking. Also the value restored on unlock. |
590+
| `baselineTimeoutSeconds` | integer | 1–86400 | 1 | Seconds before the screen turns off after locking. Also the value restored on unlock. |
588591
| `wakeTimeoutSeconds` | integer | 1–86400 | 300 | Seconds the screen stays on when waking from Modern Standby to unlock. |
589592

590593
Loading rules:
@@ -605,7 +608,7 @@ Loading rules:
605608
powercfg /q SCHEME_CURRENT SUB_VIDEO VIDEOCONLOCK | findstr /i "Current AC Current DC"
606609
```
607610

608-
- Unlocked: baseline (default `0x00000005` = 5 seconds).
611+
- Unlocked: baseline (default `0x00000001` = 1 second).
609612
- After promotion during a locked cycle: wake timeout (default `0x0000012c` = 300 seconds).
610613

611614
### Check the tasks

src/LockTimeoutController.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function Get-State {
3737
}
3838

3939
function Get-Config {
40-
$DefaultBaseline = 5
40+
$DefaultBaseline = 1
4141
$DefaultWake = 300
4242
$ConfigPath = Join-Path $DataDir 'config.json'
4343

@@ -123,6 +123,8 @@ try {
123123
'OnLock' {
124124
$newGeneration = [guid]::NewGuid().Guid
125125
Save-State -State (New-State -Status 'locked' -GenerationValue $newGeneration)
126+
$config = Get-Config
127+
Set-VideoConLock -Seconds $config.baselineTimeoutSeconds
126128
}
127129

128130
'OnUnlock' {

src/installer.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ try {
298298
$baseline | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $BaselinePath -Encoding UTF8
299299
}
300300

301-
$DefaultBaseline = 5
301+
$DefaultBaseline = 1
302302
$DefaultWake = 300
303303

304304
$ConfigPath = Join-Path $DataDir 'config.json'

0 commit comments

Comments
 (0)