Skip to content

Input: Unify native key queries and shared acquisition - #292

Merged
Segfaultd merged 2 commits into
developfrom
feature/unified-native-input
Sep 30, 2026
Merged

Segfaultd merged 2 commits into
developfrom
feature/unified-native-input

Conversation

@zpl-zak

@zpl-zak zpl-zak commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Multiplayer clients duplicate window key/button state and resource-owned control holds, while scripted keys and native controls use different query paths. This provides shared acquisition and ownership primitives and makes IInput the common key-query contract: input->IsKeyDown(FW_KEY_SPACE) works for every adapter, with native layout/device conversion inside the backend.

Changes

  • Standardize IInput on the existing FW_KEY_* macros and uppercase US physical letter/digit positions. Keep IsKeyDown, IsKeyUp, IsKeyPressed and IsKeyReleased as the consumer query methods. Require IsAvailable() to report fresh acquisition state and remove the public MapKey method.
  • Use one contract across OS and native device sources. There is no shared key enum, provider opt-in, alternate key-code space, compatibility switch or separate public physical-key query helper.
  • Add Win32Input for foreground-aware held queries and ordinary cursor operations, WindowInput for message-based edges, and PollingInput for frame-based edges. Games retain native cursor/control-lock policy. UI features can own a live PollingInput source when native gameplay acquisition is paused and use exactly the same query API.
  • Normalize printable physical positions; filter repeated keydown edges; retain taps shorter than a frame; aggregate both modifier sides; expose stable mouse-button indices and signed client coordinates. Focus loss discards pending presses and releases tracked window-event state for cleanup. Focus gain seeds already-held state without manufacturing presses.
  • Add a fixed physical-code-to-DirectInput mapping inside adapters, including distinct navigation/numpad and Pause/NumLock codes. It does not depend on the active keyboard layout.
  • Add KeySnapshot for sampled edge storage and acquisition recovery. Unavailable snapshots publish no active input and reseed on recovery. Convert scripted Key polling to the registered IInput source and keep its existing callback ownership and gameplay gate.
  • Use framework key macros in the shared key-name table and remove its Win32-header dependency.
  • Add counted/idempotent ResourceHolds storage so resource cleanup can release only the native holds that owner acquired.
  • Document native adapter contracts and add the standalone FrameworkInputTests target, registering the same modules in the existing framework test suite.

Validation

  • Canonical Linux FrameworkInputTests build and unit run: 12 cases passed.
  • Canonical builds\build.bat MSVC x64 Debug input unit build/run under Wine, through the repository container wrapper: 30 cases passed, one real multi-layout case skipped because English/Russian/AZERTY layouts were unavailable. The runner's aggregate total is 31 because it counts skips as passes; that case is not claimed as verified coverage.
  • Windows coverage exercises message decoding, repeat/focus transitions, modifier aggregation, stable mouse buttons, signed coordinates, the common query API and fixed DirectInput mappings. Portable coverage exercises state transitions, acquisition recovery and resource ownership.
  • The key-name translation unit passed Linux syntax checking after its Win32 dependency was removed. git diff --check passed.
  • Only unit-test executables were run. Full game integration, native Windows multi-layout input and gameplay/UI validation remain outstanding.

Integration

This changes the native virtual interface. All adapters must rebuild against these headers; there is no compatibility layer. The review commit is 689c27139ba8e0123e33cfb54f869d27f15c7001. Merge Framework first, then move the adoption pins to the resulting merged commit before release.

Adoption PR Integration status
KCDC #21 Shared window state, direct framework key bindings and resource-owned controls; review pin included.
HogwartsMP #228 Shared window state, direct voice/editor queries and resource-owned script locks; review pin included.
M2O #13 Native device queries and a separate live UI source using the same API; resource-owned script locks. Framework pin and project version intentionally pending. Its existing Framework 28 pin cannot build this adoption.
MafiaMP #160 Shared window state and direct camera queries; review pin included. Full legacy-project compatibility remains unverified.
Mafia1 Online #1 Native IInput provider and gameplay consumers; review pin included.

Native engine action-map rebinding and context priorities stay with game features. Complete chat UI replacement, relative-mouse abstractions and CEF/IME routing extraction remain separate migrations.

Summary by CodeRabbit

  • New Features
    • Added consistent keyboard and mouse input handling across supported input sources, including accurate press and release detection.
    • Keyboard input now accounts for keyboard layout differences, and left/right modifier keys are reflected in their shared modifier state.
  • Bug Fixes
    • Input interruptions, such as losing and regaining focus, no longer create spurious key transitions or disrupt keybind state.
    • Mouse position and button queries now handle window focus and invalid button indices more reliably.
  • Documentation
    • Added guidance on input availability, key codes, and input behavior.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: cfa03f8f-265f-4713-8698-c7c83ddfbddc

📥 Commits

Reviewing files that changed from the base of the PR and between 263476c and 689c271.

📒 Files selected for processing (18)
  • code/framework/src/input/button_state.h
  • code/framework/src/input/detail/win32_keys.h
  • code/framework/src/input/input.h
  • code/framework/src/input/physical_keys.h
  • code/framework/src/input/polling_input.h
  • code/framework/src/input/win32_input.h
  • code/framework/src/input/window_input.h
  • code/framework/src/integrations/client/scripting/builtins/keybinds.cpp
  • code/framework/src/integrations/client/scripting/builtins/keybinds.h
  • code/framework/src/utils/key_names.cpp
  • code/framework/src/utils/key_names.h
  • code/tests/framework_ut.cpp
  • code/tests/input_ut.cpp
  • code/tests/modules/input_state_ut.h
  • code/tests/modules/physical_keys_ut.h
  • code/tests/modules/polling_input_ut.h
  • code/tests/modules/window_input_ut.h
  • docs/native_input.md

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

The changes add reusable input state and resource-hold tracking, a Win32 message-based input implementation, and physical-key query helpers. They also update script keybinds, register input tests, and add native input documentation.

Changes

Input support

Layer / File(s) Summary
Input state and resource holds
code/framework/src/input/button_state.h, code/framework/src/input/resource_holds.h, code/tests/modules/input_state_ut.h
ButtonState and KeySnapshot track key or button state and edges. ResourceHolds tracks counted holds by owner. Tests cover state transitions, resynchronization, and hold operations.
Native input and physical-key handling
code/framework/src/input/input.h, code/framework/src/input/window_input.h, code/framework/src/input/physical_key_state.h, code/tests/modules/window_input_ut.h, code/tests/framework_ut.cpp
IInput declares key-code spaces. WindowInput processes Win32 keyboard and mouse messages. PhysicalKeyState queries supported providers or foreground asynchronous key state. Windows tests cover message handling and key queries.
Physical-key integration and test setup
code/framework/src/integrations/client/scripting/builtins/keybinds.cpp, code/tests/CMakeLists.txt, code/tests/framework_ut.cpp, code/tests/input_ut.cpp, docs/native_input.md
Script keybinds use PhysicalKeyState. The test executable and runner register input tests. The documentation describes native input integration and test commands.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Win32Message
  participant WindowInput
  participant ButtonState
  Win32Message->>WindowInput: ProcessEvent keyboard or mouse message
  WindowInput->>ButtonState: Set key and button state
  WindowInput->>ButtonState: Clear edges during Update
Loading

Merge Risk: ⚪ Minimal · up to 689c2

The shared input changes have no established merge-blocking issue. Real Windows layout and gameplay validation remain outstanding, but do not currently demonstrate a regression. Adopters must rebuild against the changed native interface.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 689c2

The inspected paths preserve foreground-input restrictions, gameplay gating and resource-owned callbacks. No introduced security vulnerability was established. Downstream window routing, threading and native cleanup integration remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The inspected input-to-script path operates within the client process: it exposes bounded key-state queries and dispatches existing resource-owned callbacks. Its effective background-input scope remains restricted by the checked adapters' foreground-process controls; this conclusion does not establish equivalent controls in uninspected downstream adapters.

Trust Boundaries and Controls

  • observed — Foreground availability and gameplay permission remain separate controls. Win32 key reads require the current process to own the foreground window. Key.isDown and callback edge publication retain the host gameplay gate; resource cleanup still removes only matching resource handlers, and shutdown preserves the host gate.

Resilience and Maintainability Implications

  • observed — ResourceHolds supports owner-specific counted release, one-time bulk removal, idempotent set-style ownership and forced ledger clearing. Source tests exercise repeated cleanup and preservation of another owner's holds. These guarantees concern the ledger only; native release failures and recovery are delegated to lifecycle adapters.

Hardening Proposals

  • proposed — For downstream adoption, make the caller contract explicit: bind message forwarding to the intended window, serialize event mutation and queries, derive hold owners from trusted resource identity, and retain recoverable accounting until native cleanup succeeds. This is an integration proposal, not an observed production vulnerability.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.20% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 82 functions across 19 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: unifying native key queries and shared input acquisition across the input system.
Full details: Docstring Coverage

Explanation

Docstring coverage is 12.20% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 82 functions across 19 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit taps a key with care
A press edge hops into the air
The mouse buttons settle into place
Held resources keep their trace
Then tests greet input, ears aglow

Comment @coderabbitai help to get the list of available commands.

@zpl-zak zpl-zak changed the title Input: Share native event state, physical polling and holds Input: Unify native key queries and shared acquisition Sep 30, 2026
@Segfaultd
Segfaultd merged commit dfd7dad into develop Sep 30, 2026
5 checks passed
@Segfaultd
Segfaultd deleted the feature/unified-native-input branch September 30, 2026 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants