WIP: fix(hid): HOS_INPUT_SCRIPT_BACKGROUND no longer lets the player's keyboard into a test run #319

Draft
d4nkn3ss wants to merge 1 commit from d4nkn3ss/Longshot:fix/input-script-background into main
Contributor

Why

A test run started with HOS_INPUT_SCRIPT_BACKGROUND=1 takes the keyboard of whoever is using the PC, even when its window is behind another one. Typing in another window, even in a chat, moves Link, makes him jump, and Enter pauses the game, which spoils the run.

What changed

  • hid: read_input() in host/nn_hid.c keeps the focus gate with HOS_INPUT_SCRIPT_BACKGROUND set. Scripted presses (HOS_INPUT_SCRIPT, HOS_INPUT_LIVE) and the control bridge's are added by scripted_input() and hos_control_input() before the gate, so they already count with the window behind; the existing script-background case shows it. Skipping the gate let through only the player's devices: the keyboard (GetAsyncKeyState sees every key, whatever window is in front, so headless runs too) and the mouse. The switch is now only said in the log, as no longer needed.
  • tests: tests/test_input_background.py gets a case, script-background-switch: the window behind, HOS_INPUT_SCRIPT_BACKGROUND=1, a bound key held. It fails on main (FAIL:125 G64(address + 8) == buttons: the key's X reaches the game) and passes here.
  • docs: the switch's row in docs/development.md; two rows in docs/tested-configurations.md.

Flags and settings

Flag What it does Default now Recommendation Helps on Doesn't help on Untested on
HOS_INPUT_SCRIPT_BACKGROUND (changed) Only a log line saying it is no longer needed; it used to let the player's keyboard and mouse reach a game behind another window Unset (no effect either way now) Can be removed from scripts Any test run on a PC someone is using - Linux (the keyboard there comes through SDL, not GetAsyncKeyState)

Measurements

main: dc390e59 (2026-11-14); the A/B ran on 514591a3's code; the old build ran is fbd42024, whose host/nn_hid.c is the same as 514591a3
this PR: fix/input-script-background @ d6b5679f, rebased onto main dc390e59. Since the A/B, main changed host/nn_hid.c (the Walk key, #66); this PR's lines are unchanged and tests/test_input_background.py (all cases) and tests/test_keys_player_input.py pass on d6b5679f. The game ran in the A/B is 3fb77017.
Hardware: RTX 3080 10 GB, NVIDIA 621.14, i9-12900K, 64 GB, Windows 11 Pro 26300
Scene: the test save, in play, a window that never takes focus (scripts/run-vk.ps1 -Window), default settings
Method: one run each. The script presses A into the save, then stops; the user presses Enter twice in other windows, holds W, and types in a chat window. Counted: the control: state play -> menu lines in longshot_log.txt, and what the user saw.
How to reproduce: scripts/run-vk.ps1 -Window -Env "HOS_INPUT_SCRIPT_BACKGROUND=1;HOS_INPUT_LIVE=<file>;HOS_SKIP_OPENING=1", append 0:A lines to the file until in play, then click into another window and press Enter.

main @ fbd42024 (nn_hid.c as 514591a3) this PR @ 3fb77017
pauses from Enter pressed in other windows 3 0
Link moved while the user typed elsewhere yes (walked, jumped) no
main @ fbd42024:
hid: scripted input runs with the game in the background (HOS_INPUT_SCRIPT_BACKGROUND)
hid: game window not in front (foreground window: process 0, class "")
control: state play -> menu at frame 5731 (146.4 draws a frame)
control: state menu -> play at frame 6101 (545.4 draws a frame)
control: state play -> menu at frame 6217 (146.3 draws a frame)
control: state menu -> play at frame 6300 (636.9 draws a frame)
control: state play -> menu at frame 6398 (146.0 draws a frame)
control: state menu -> play at frame 6437 (722.6 draws a frame)

this PR @ 3fb77017:
hid: HOS_INPUT_SCRIPT_BACKGROUND is no longer needed: scripted and control-bridge presses count with the game's window behind another one, and the player's keyboard and mouse stay out
(no state play -> menu line)

Testing

Tested: python -I -B tests/run_all.py on Windows: 497 passed, 3 failed, 33 skipped. The 3 failed on main 514591a3 too: test_check_third_party.py (#80), test_menu_i18n.py (fixed on main by #273, passes after the rebase), test_release.py (#119). After the rebases onto e4b5b4d4 and ba700f58, test_input_background.py passes again. Of the 17 tests that read host/nn_hid.c, 16 pass on 96f3047d (the same nn_hid.c as e5b4789e); test_pad_layout.py fails on main ba700f58 too since #137 (fixed by #331). Every test that reads host/nn_hid.c (17, all pass). In the game, on the PC above: the A/B above, with the user at the keyboard. On this PR the script's presses still drove the game into play with the window behind.

Not tested:

  • Linux: the keyboard there comes from SDL, read through the same read_input() gate, so it should behave the same. I didn't run it.
  • A pad in the background with the switch set: it now follows HOS_INPUT_BACKGROUND and the menu's "Controller in background" row, as without the switch (the pads-env and pads-menu cases).

Needs other testers: None.

Screenshots

Nothing on screen

Risk and rollback

A script that counted on the switch to let a person's keyboard or mouse into a game behind another window loses that. None in this repository sets it. Reverting the commit is enough.

Reviewer notes

The window counts as in front while a tool window or overlay is in front (the taskbar, a notification) if the game was the last normal window in front: game_in_front(). So a test window someone clicked into still takes their keys after they click the taskbar; that is the player's case and unchanged here.

Issues

See #389 on Hookshot (the issue that added the switch).

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. One run each: a behaviour check with the user at the keyboard; the game-free case covers it each run.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Flags noted, and the switch reference updated (docs/development.md, the README).
  • A row in docs/tested-configurations.md for each measured run.
  • A game-free test added for the fix, failing on main and passing here.
  • Docs updated.

🤖 Generated with Claude Code

## Why A test run started with `HOS_INPUT_SCRIPT_BACKGROUND=1` takes the keyboard of whoever is using the PC, even when its window is behind another one. Typing in another window, even in a chat, moves Link, makes him jump, and Enter pauses the game, which spoils the run. ## What changed - hid: `read_input()` in `host/nn_hid.c` keeps the focus gate with `HOS_INPUT_SCRIPT_BACKGROUND` set. Scripted presses (`HOS_INPUT_SCRIPT`, `HOS_INPUT_LIVE`) and the control bridge's are added by `scripted_input()` and `hos_control_input()` before the gate, so they already count with the window behind; the existing `script-background` case shows it. Skipping the gate let through only the player's devices: the keyboard (`GetAsyncKeyState` sees every key, whatever window is in front, so headless runs too) and the mouse. The switch is now only said in the log, as no longer needed. - tests: `tests/test_input_background.py` gets a case, `script-background-switch`: the window behind, `HOS_INPUT_SCRIPT_BACKGROUND=1`, a bound key held. It fails on main (`FAIL:125 G64(address + 8) == buttons`: the key's X reaches the game) and passes here. - docs: the switch's row in `docs/development.md`; two rows in `docs/tested-configurations.md`. ## Flags and settings | Flag | What it does | Default now | Recommendation | Helps on | Doesn't help on | Untested on | |---|---|---|---|---|---|---| | `HOS_INPUT_SCRIPT_BACKGROUND` (changed) | Only a log line saying it is no longer needed; it used to let the player's keyboard and mouse reach a game behind another window | Unset (no effect either way now) | Can be removed from scripts | Any test run on a PC someone is using | - | Linux (the keyboard there comes through SDL, not `GetAsyncKeyState`) | ## Measurements main: dc390e59 (2026-11-14); the A/B ran on 514591a3's code; the old build ran is fbd42024, whose `host/nn_hid.c` is the same as 514591a3 this PR: fix/input-script-background @ d6b5679f, rebased onto main dc390e59. Since the A/B, main changed `host/nn_hid.c` (the Walk key, #66); this PR's lines are unchanged and `tests/test_input_background.py` (all cases) and `tests/test_keys_player_input.py` pass on d6b5679f. The game ran in the A/B is 3fb77017. Hardware: RTX 3080 10 GB, NVIDIA 621.14, i9-12900K, 64 GB, Windows 11 Pro 26300 Scene: the test save, in play, a window that never takes focus (`scripts/run-vk.ps1 -Window`), default settings Method: one run each. The script presses A into the save, then stops; the user presses Enter twice in other windows, holds W, and types in a chat window. Counted: the `control: state play -> menu` lines in `longshot_log.txt`, and what the user saw. How to reproduce: `scripts/run-vk.ps1 -Window -Env "HOS_INPUT_SCRIPT_BACKGROUND=1;HOS_INPUT_LIVE=<file>;HOS_SKIP_OPENING=1"`, append `0:A` lines to the file until in play, then click into another window and press Enter. | | main @ fbd42024 (`nn_hid.c` as 514591a3) | this PR @ 3fb77017 | |---|---|---| | pauses from Enter pressed in other windows | 3 | 0 | | Link moved while the user typed elsewhere | yes (walked, jumped) | no | ``` main @ fbd42024: hid: scripted input runs with the game in the background (HOS_INPUT_SCRIPT_BACKGROUND) hid: game window not in front (foreground window: process 0, class "") control: state play -> menu at frame 5731 (146.4 draws a frame) control: state menu -> play at frame 6101 (545.4 draws a frame) control: state play -> menu at frame 6217 (146.3 draws a frame) control: state menu -> play at frame 6300 (636.9 draws a frame) control: state play -> menu at frame 6398 (146.0 draws a frame) control: state menu -> play at frame 6437 (722.6 draws a frame) this PR @ 3fb77017: hid: HOS_INPUT_SCRIPT_BACKGROUND is no longer needed: scripted and control-bridge presses count with the game's window behind another one, and the player's keyboard and mouse stay out (no state play -> menu line) ``` ## Testing **Tested:** `python -I -B tests/run_all.py` on Windows: 497 passed, 3 failed, 33 skipped. The 3 failed on main 514591a3 too: `test_check_third_party.py` (#80), `test_menu_i18n.py` (fixed on main by #273, passes after the rebase), `test_release.py` (#119). After the rebases onto e4b5b4d4 and ba700f58, `test_input_background.py` passes again. Of the 17 tests that read `host/nn_hid.c`, 16 pass on 96f3047d (the same nn_hid.c as e5b4789e); `test_pad_layout.py` fails on main ba700f58 too since #137 (fixed by #331). Every test that reads `host/nn_hid.c` (17, all pass). In the game, on the PC above: the A/B above, with the user at the keyboard. On this PR the script's presses still drove the game into play with the window behind. **Not tested:** - Linux: the keyboard there comes from SDL, read through the same `read_input()` gate, so it should behave the same. I didn't run it. - A pad in the background with the switch set: it now follows `HOS_INPUT_BACKGROUND` and the menu's "Controller in background" row, as without the switch (the `pads-env` and `pads-menu` cases). **Needs other testers:** None. ## Screenshots Nothing on screen ## Risk and rollback A script that counted on the switch to let a person's keyboard or mouse into a game behind another window loses that. None in this repository sets it. Reverting the commit is enough. ## Reviewer notes The window counts as in front while a tool window or overlay is in front (the taskbar, a notification) if the game was the last normal window in front: `game_in_front()`. So a test window someone clicked into still takes their keys after they click the taskbar; that is the player's case and unchanged here. ## Issues See #389 on Hookshot (the issue that added the switch). ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [ ] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. One run each: a behaviour check with the user at the keyboard; the game-free case covers it each run. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Flags noted, and the switch reference updated (docs/development.md, the README). - [x] A row in `docs/tested-configurations.md` for each measured run. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
d4nkn3ss force-pushed fix/input-script-background from 2a8f331532
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 38f9d90fb6
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 11s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
2026-11-14 00:44:29 +00:00
Compare
d4nkn3ss force-pushed fix/input-script-background from 38f9d90fb6
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 11s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 96f3047d72
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
2026-11-14 01:04:05 +00:00
Compare
d4nkn3ss force-pushed fix/input-script-background from 96f3047d72
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 3s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 0268a234ca
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 7s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
2026-11-14 01:24:16 +00:00
Compare
d4nkn3ss force-pushed fix/input-script-background from 0268a234ca
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 7s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 5dee9c7b54
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 6s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
2026-11-14 02:04:37 +00:00
Compare
d4nkn3ss force-pushed fix/input-script-background from 5dee9c7b54
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 6s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
to e5b4789ef4
Some checks failed
PR description / Description follows the template (pull_request_target) Has been cancelled
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
2026-11-14 02:24:13 +00:00
Compare
d4nkn3ss force-pushed fix/input-script-background from e5b4789ef4
Some checks failed
PR description / Description follows the template (pull_request_target) Has been cancelled
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
to d6b5679f4a
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 28s
2026-11-14 15:48:57 +00:00
Compare
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 28s
This pull request is marked as a work in progress.
Some workflows are waiting to be reviewed.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/input-script-background:d4nkn3ss-fix/input-script-background'
git switch 'd4nkn3ss-fix/input-script-background'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!319
No description provided.