Skip to content

fix(input): accept Windows keys sent without a scan code - #331

Open
devin-ai-integration[bot] wants to merge 4 commits into
devfrom
devin/1791432794-zero-scan-keys
Open

devin-ai-integration[bot] wants to merge 4 commits into
devfrom
devin/1791432794-zero-scan-keys

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

What changed and why

On some Windows input paths (BrailleNote Evolve, ChatGPT computer use) menus arrow fine but Enter does nothing. The shipped SDL2 (2.32.10, vendor/sdl2) drops WM_KEYDOWN/WM_KEYUP whose lParam scan code is 0, except the four arrows, which have a VK fallback. So virtual-key-only Enter/Space/Escape/letters never become SDL events. Unicode-injected keys (VK_PACKET + WM_CHAR) never produce an SDL KeyDown either.

New app/win_keys.rs subclasses the SDL window right after creation (skipped under the dummy driver):

  • Zero-scan key messages get their scan code (and extended bit) filled from MapVirtualKeyW(vk, MAPVK_VK_TO_VSC_EX) before SDL sees them. Any extended bit the sender set is kept.
  • When a VK_PACKET key-down is followed by WM_CHAR, the subclass sends SDL a key-down built from VkKeyScanW just before the character, then a matching key-up when the packet key is released. The menu then gets a real Key::Return/Space/letter with its text.

Physical keyboards and screen-reader input already carry scan codes, so they pass through untouched.

What players or maintainers will notice

Enter, Space, keypad Enter, Escape and first-letter jumps now work from devices and tools that send keys without scan codes or as Unicode characters.

Tests and checks run

  • cargo fmt, cargo clippy -p freight-fate --all-targets -- -D warnings
  • 7 new unit tests for the lParam math in win_keys
  • cargo test -p ff-core -p freight-fate: 3074 passed, 0 failed. --break-battery: 47/47 clean. Both ran before a timing-only move of the hook call; fmt, clippy, the unit tests and the build were re-run after it.
  • Real Windows desktop run of the debug build with an isolated profile, sending input with SendInput/PostMessage and checking the speech transcript.
    • Before the fix: zero-scan Return, Space, keypad Enter, Escape and letters did nothing, and so did Unicode CR and Space. Zero-scan arrows still moved.
    • After the fix: each of these input forms gave exactly one response: zero-scan arrows, letters, Return, Space, keypad Enter and Escape; normal and scan-only Return; posted WM_KEYDOWN; Unicode CR, LF and Space. Unicode letters typed into driver-name entry.
    • A bare posted WM_CHAR CR (no key-down) is still ignored. That is intended.
    • Ordinary computer-tool Down and Return were unchanged.

Not tested on a real BrailleNote Evolve.

Accessibility impact

Restores menu selection for braille notetakers and automation/computer-use tools on Windows. Keyboard and screen-reader paths that already worked are unchanged (checked through the transcript, as above).

Changelog

  • I added a player-facing bullet under ## Unreleased in CHANGELOG.md, written in plain player language and matching the style of the existing entries.
  • This change is not player-facing, and every commit message in this PR includes [skip changelog].

Link to Devin session: https://app.devin.ai/sessions/4fea8f0471354515a76ff07b5fd21a00
Open in Devin Desktop: https://app.devin.ai/desktop/session/4fea8f0471354515a76ff07b5fd21a00?variant=devin
Requested by: @Orinks

devin-ai-integration Bot and others added 2 commits October 8, 2026 04:42
Co-Authored-By: Joshua Tubbs <orin8722@gmail.com>
Co-Authored-By: Joshua Tubbs <orin8722@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

…scan-keys

Co-Authored-By: Joshua Tubbs <orin8722@gmail.com>

# Conflicts:
#	CHANGELOG.md
…scan-keys

Co-Authored-By: Joshua Tubbs <orin8722@gmail.com>

# Conflicts:
#	CHANGELOG.md
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Tested the real Windows game window: dev 4d3d079b (before) and this PR (56c0fe9c, after), each on a fresh isolated profile, with results read from the speech transcript.

  • Before: zero-scan arrows moved. Return, Space and keypad Enter sent without a scan code gave no response, and neither did Unicode CR or Space.
  • After:
    • Each of those, plus Unicode LF, opened New career's name entry exactly once.
    • Zero-scan Escape and first-letter jumps worked.
    • Unicode letters plus a zero-scan Space typed exactly ab cd.
    • Six repeated zero-scan Down presses moved six rows and stopped on release.
  • Regression: normal computer-use navigation, typing a driver name, confirming and going back all behaved as before. So did scan-coded and scan-only Return.

The plain computer-use tool's Return already worked on dev here, so only explicit zero-scan and Unicode input reproduced the bug. Not tested on a real BrailleNote Evolve.

Before screenshot. A black Freight Fate window sits above a transcript viewer titled "BEFORE, dev 4d3d079b". Zero-scan Down and Up each speak one menu row (Achievements 2 of 8, then New career 1 of 8). Zero-scan Return, zero-scan Space, zero-scan keypad Enter, Unicode CR and Unicode Space each show 0 transcript lines.

After screenshot. Transcript viewer titled "AFTER, PR 331 / 56c0fe9c". Repeated Down speaks six rows, from Achievements 2 of 8 to Report a problem 7 of 8. Releasing Down gives 0 more lines. Scan Home returns to New career 1 of 8. Zero-scan Return gives one line: "New career. Type your driver name, then Enter..."

Written by Devin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant