feat(input): a Keyboard row: Auto, On or Off #2530
Open
omgitsgela wants to merge 2 commits from
omgitsgela/pr-keyboard-input into main
pull from: omgitsgela/pr-keyboard-input
merge into: MagicBeanDev:main
MagicBeanDev:main
MagicBeanDev:github/pr/2893
MagicBeanDev:github/pr/2890
MagicBeanDev:github/pr/2887
MagicBeanDev:github/pr/2878
MagicBeanDev:github/pr/2875
MagicBeanDev:github/pr/2874
MagicBeanDev:github/pr/2873
MagicBeanDev:github/pr/2871
MagicBeanDev:github/pr/2756
MagicBeanDev:github/pr/2897
MagicBeanDev:github/pr/2896
MagicBeanDev:github/pr/2718
MagicBeanDev:github/pr/2842
MagicBeanDev:github/pr/2691
MagicBeanDev:github/pr/2895
MagicBeanDev:github/pr/2743
MagicBeanDev:github/pr/2765
MagicBeanDev:github/pr/2708
MagicBeanDev:github/pr/2732
MagicBeanDev:github/pr/2755
MagicBeanDev:github/pr/2817
MagicBeanDev:github/pr/2876
MagicBeanDev:release-please--branches--main
MagicBeanDev:release-please--branches--main--release-notes
MagicBeanDev:github/pr/2778
MagicBeanDev:github/pr/2888
MagicBeanDev:github/pr/2866
MagicBeanDev:github/pr/2877
MagicBeanDev:github/pr/2800
MagicBeanDev:github/pr/2829
MagicBeanDev:github/pr/2850
MagicBeanDev:github/pr/2889
MagicBeanDev:github/pr/2882
MagicBeanDev:github/pr/2860
MagicBeanDev:github/pr/2849
MagicBeanDev:github/pr/2886
MagicBeanDev:github/pr/2794
MagicBeanDev:github/pr/2840
MagicBeanDev:github/pr/2830
MagicBeanDev:github/pr/2834
MagicBeanDev:github/pr/2719
MagicBeanDev:github/pr/2742
MagicBeanDev:github/pr/2741
MagicBeanDev:github/pr/2820
MagicBeanDev:github/pr/2771
MagicBeanDev:github/pr/2859
MagicBeanDev:github/pr/2858
MagicBeanDev:github/pr/2823
MagicBeanDev:github/pr/2757
MagicBeanDev:github/pr/2769
MagicBeanDev:github/pr/2844
MagicBeanDev:github/pr/2843
MagicBeanDev:github/pr/2673
MagicBeanDev:github/pr/2855
MagicBeanDev:github/pr/2739
MagicBeanDev:github/pr/2807
MagicBeanDev:github/pr/2851
MagicBeanDev:github/pr/2789
MagicBeanDev:github/pr/2814
MagicBeanDev:github/pr/2818
MagicBeanDev:github/pr/2774
MagicBeanDev:github/pr/2772
MagicBeanDev:github/pr/2750
MagicBeanDev:github/pr/2786
MagicBeanDev:github/pr/2785
MagicBeanDev:github/pr/2782
MagicBeanDev:github/pr/2779
MagicBeanDev:github/pr/2775
MagicBeanDev:github/pr/2706
MagicBeanDev:github/pr/2766
MagicBeanDev:github/pr/2747
MagicBeanDev:github/pr/2759
MagicBeanDev:github/pr/2745
MagicBeanDev:github/pr/2740
MagicBeanDev:github/pr/2733
MagicBeanDev:github/pr/2725
MagicBeanDev:github/pr/2727
MagicBeanDev:github/pr/2728
MagicBeanDev:github/pr/2729
MagicBeanDev:github/pr/2721
MagicBeanDev:github/pr/2722
MagicBeanDev:github/pr/2715
MagicBeanDev:github/pr/2714
MagicBeanDev:github/pr/2707
MagicBeanDev:github/pr/2703
MagicBeanDev:github/pr/2705
MagicBeanDev:github/pr/2697
MagicBeanDev:github/pr/2679
MagicBeanDev:github/pr/2676
MagicBeanDev:github/pr/2669
MagicBeanDev:docs/what-hookshot-connects-to
MagicBeanDev:fix/hdr-encode-test
MagicBeanDev:fix/main-tests
MagicBeanDev:fix/play-cache-files
MagicBeanDev:perf/game-barrier-order
MagicBeanDev:feat/heap-lazy
MagicBeanDev:feat/texture-detail
MagicBeanDev:perf/astc-opaque-bc1
MagicBeanDev:fix/fs-dir-lock
MagicBeanDev:fix/framegen-native-kept
MagicBeanDev:fix/update-no-downgrade
MagicBeanDev:port/k10-gcn-f16-mirrors
MagicBeanDev:fix/framegen-mult-cap
MagicBeanDev:chore/release-as-2.1.1
MagicBeanDev:perf/pcache-load-switch
MagicBeanDev:fix/prepare-progress-log
MagicBeanDev:fix/update-closes-stale-game
MagicBeanDev:fix/hdr-scaled-sampled
MagicBeanDev:perf/first-start-preset
MagicBeanDev:perf/zero-upload
MagicBeanDev:fix/vcore-escape-2s
MagicBeanDev:test/fake-gh-atomic
MagicBeanDev:perf/batch-idle-flush
MagicBeanDev:test/finish-stub-a
MagicBeanDev:chore/record-2.1.0
MagicBeanDev:fix/main-red-tests
MagicBeanDev:fix/test-display-startup-driver-cache
MagicBeanDev:feat/mesh-shader-mode
MagicBeanDev:fix/menu-probes-at-startup
MagicBeanDev:fix/fps-counter-classic
MagicBeanDev:fix/test-log-batch-flake
MagicBeanDev:fix/narrow-screen-hud
MagicBeanDev:ci/prereleases
MagicBeanDev:release/v2.0.15
MagicBeanDev:hotfix/v2.0.15
MagicBeanDev:fix/present-ahead-replay
MagicBeanDev:release/v2.0.13
MagicBeanDev:fix/bracket-paths-2013
MagicBeanDev:fix/hdr-overlays-2013
MagicBeanDev:fix/fps-counter-scale-2013
MagicBeanDev:fix/stick-seen-at-rest
MagicBeanDev:hotfix/menu-fits-screen
MagicBeanDev:fix/f1-always-opens-menu
MagicBeanDev:fix/ini-keep-lines
MagicBeanDev:claude/cranky-pike-7cf247
MagicBeanDev:perf/texture-answer-flat
MagicBeanDev:fix/stamp-test-modules
MagicBeanDev:fix/appimage-fonts
MagicBeanDev:fix/display-awake
MagicBeanDev:release/v2.0.12
MagicBeanDev:fix/discord-windows
MagicBeanDev:rc/v2.0.12-tests
MagicBeanDev:fix/dlss-keep-feature
MagicBeanDev:rc/v2.0.12
MagicBeanDev:button-icons
No reviewers
Labels
Clear labels
accessibility
Barrier affecting people with disabilities
autorelease: pending
autorelease: tagged
bug
Something isn't working
dependencies
Pull requests that update a dependency file
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
github_actions
Pull requests that update GitHub Actions code
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
testing wanted
wontfix
This will not be worked on
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
Milestone
Clear milestone
No items
No milestone
Assignees
Clear assignees
No assignees
1 participant
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/Hookshot!2530
Loading…
Reference in a new issue
No description provided.
Delete branch "omgitsgela/pr-keyboard-input"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Status: draft, menu-input coverage incomplete
The current PR head (
4c276b88) gates gameplay keyboard bindings only. Hardware testing found that the menu's independent keyboard path still accepts Steam-injected Escape, so this is not yet a complete fix for direct Desktop launches. A local follow-up candidate is built, but its on-device validation is pending. That follow-up is not in this PR's current code.Why
On a Steam Deck LCD in Desktop Mode, with Hookshot started outside Steam, the left stick moved Link and tilted the camera, and face/menu buttons triggered unintended actions. The initial report followed a camera-inversion change, but the saved and live keyboard/controller bindings matched: it was not a corrupted binding file.
Steam's Desktop layout emits keyboard input in addition to controller input. Hookshot's newer keyboard defaults bind arrows to camera movement and Tab/Enter to Plus. Our earlier XQueryKeymap recording measured Up arrow (keycode 111) held for 2.81 seconds while the left stick was held forward. Remapping the local camera keys to IJKL and Plus to P removed those gameplay collisions, but changing global keyboard defaults would penalize keyboard players.
The newer direct-launch capture found the same physical B press in both paths: native controller bit 1 (east face button, bound to Switch A/confirm) and an Escape key event. The native binding was correct; the independent menu keyboard reader accepted Escape and opened Hookshot's menu.
What the current PR adds
A Keyboard row on Controls, saved as
keyboard=:HOS_OPT_KEYBOARDis 54 in the current PR code. It was moved from 49 to avoid the Walk mode/speed reservation; this description previously retained the stale value.pads_read()records whether SDL/XInput controllers are connected;key()applies the selected mode. Connection state, not whether a button happens to be held, decides Auto. Mouse buttons retain their separate behavior.Current limitation: F1, Escape, arrows, Enter and Tab in Hookshot's menu are still read on a separate path outside this policy. Leaving that path unaffected was deliberate in the first version, but it permits the captured Escape collision. The help text and implementation need to be updated together before this is ready.
Hardware findings and remaining uncertainty
Follow-up candidate, not yet pushed
The local candidate shares the host's keyboard policy with menu input, preserves intentional F1/enabled-Insert access, drains suppressed queued keys, and gates keyboard direction repeats without suppressing native controller navigation. It adds a host callback and a matched host/renderer ABI change.
A regression extracting the actual menu polling code and actual host policy fails before the fix: Auto with a connected controller accepts Escape. It passes with the local change. The focused Linux run over
input,keyboard,menu,bound_keys,pad,optionandhidreports 26 passed, 0 failed, 0 skipped for that local candidate. These are not CI results for the published PR head and are not hardware acceptance.A matched executable and Vulkan renderer built successfully on the Deck. First-launch preparation is currently blocking hardware validation: the builder hashes
vk_api.hinto the shader translator stamp, so even this input-only ABI change invalidates translated-program caches. No cache checks were bypassed.Tests already in this PR
tests/test_keyboard_option.py: extracts the gameplaykey()/keyboard_counts()functions and checks 10 Auto/On/Off, controller, menu, key and mouse cases.tests/test_input_background.py: updated fixture for the keyboard policy and controller-count state.Acceptance still required
Before marking ready, verify the amended candidate on the Deck:
No universal Deck mapping or SDL2-only/SDL3-only requirement is established by the current evidence. Windows and other controllers are not hardware-tested by these Deck runs.
Thanks for the measurements, the diagnosis is convincing and the fix is small and well tested at the unit level. Two things I'd want settled before this goes in, plus a note.
Option id 49 collides with #2345 (
HOS_OPT_WALK_MODE = 49, HOS_OPT_WALK_SPEED). Main also has 48 (camera speed) now, and #2357 takes 51, #2261 takes 60. Whichever of these lands second has to renumber, and a saved id that means two things in two builds is the painful kind of bug. Worth agreeing on an id with #2345's author (50-something, or 52+).Auto changes the default for everyone with a pad plugged in, not just Steam Input users.
keyboard_counts()returns false for every key as soon aspads_read()sees one pad, even an idle one. A Windows player on keyboard and mouse with an XInput pad connected (or a Steam virtual pad, a DualSense on USB charging) loses WASD, the camera keys, Enter and so on after updating, and the only hint is a row in the Insert menu. The Deck case you measured is real, but I don't think it should cost these players their keyboard silently. Options: keep the default On and let the Deck case default to Off/Auto (e.g. only when SteamDeck/Steam Input is detected), or make Auto mean "a pad was used more recently than the keyboard's non-injected input" if that's detectable. At the least the PR description should say plainly that Auto turns the keyboard off with any pad connected. I'd leave which way to go to @NotRexed.Nit:
key()also feeds the mouse-sensitivity hotkeys (-/+) at the top of the mouse code, so those go quiet under Auto with a pad connected too. Probably fine, just worth knowing.What I checked and found fine: the mouse-button range test (
0x01..0x06minusVK_CANCEL) matches the fivemouse_vk_slotbuttons;controlledcounts SDL pads plus connected XInput slots; the Insert menu keys use their own path (vk_menu.cppkey table) so Off cannot lock you out of it;MkwVkHostis unchanged so noMKWVK_API_VERSIONbump is needed;fill_replay_tablereturnsopts.keyboard; test is a newtest_*.py, so run_all discovers it. CI: only the title check had reported when I looked (pending), so the 23 passing checks in the description are the author's local run, not confirmed by CI yet. No discussion on the PR so far, and I didn't find any other review.Collides with #2345 (
HOS_OPT_WALK_MODE = 49, HOS_OPT_WALK_SPEED); see the review body.This now conflicts with main in
gpu/vk/vk_api.h. Could you merge main into the branch (or rebase) when you get a chance? I'll take another look once it's up to date.For the id collision noted above: Walk in #2345 moved to 52/53 (
5ab213a6), so its old 49 no longer stands in this pull request's way, whichever lands first.Heads up: I merged main into this branch (merge commit
4c276b88) to clear thegpu/vk/vk_api.hconflict, so please pull before pushing. The conflict was main's newHOS_OPT_FOV = 51next toHOS_OPT_KEYBOARD = 49. I moved the Keyboard option to id 54 (49 and 50 are reserved for #2345's Walk options, #2345 and #2567 are taking 52/53, and 60 is #2261) and updated the comment ingpu/vk/vk_menu.h. The keyboard, option-id, nn_hid and vk_api tests pass locally.That settles the id collision from my earlier review. Two points are still open, and nothing else has changed since:
pad_count_nowcounts every connected pad, idle or not, so as soon as one is plugged in (or Steam presents a virtual pad) all the keyboard's bindings stop, WASD included. A keyboard and mouse player with a pad plugged in would lose their controls with no hint why. A Deck/Steam-specific default, or an Auto that only drops the keyboard while the pad is actually being used, would avoid that. This is NotRexed's call.key(), so Auto and Off gate them too.The decision stays with NotRexed. CI is still pending.
This conflicts with main again, in
host/nn_hid.c(main has changed that file since our merge; the rest merges cleanly). Could you merge main into the branch, pulling our merge commit first so the history stays simple?A correction to my last review: I wrote that the default for Auto was someone else's call. That was wrong. Whether Auto should be the default, given it drops every keyboard binding once any pad is connected (idle or not), is an open maintainer question, and we will follow up on it here. I am not deciding it in this comment.