Skip to content

refactor: expose hook HID runtime state#139

Merged
hieshima merged 2 commits intoTomBadash:masterfrom
hieshima:refactor/hid-runtime-state-surface
May 5, 2026
Merged

refactor: expose hook HID runtime state#139
hieshima merged 2 commits intoTomBadash:masterfrom
hieshima:refactor/hid-runtime-state-surface

Conversation

@hieshima
Copy link
Copy Markdown
Collaborator

Why

Follow-up to #120 and #82.

#120 split the platform hook implementations behind a shared import surface, but intentionally kept the runtime semantics unchanged. After that split, Engine still infers HID++ readiness by directly peeking at the private hook._hid_gesture handle.

That private access is fragile because Mouser now has multiple readiness concepts:

  • input readiness: the OS/input path is available for button remapping and device identity
  • HID++ readiness: device features such as DPI, Smart Shift, battery, and saved-settings replay are available

Linux makes this split explicit: evdev can be ready while HID++ is not, or HID++ can reconnect before evdev has grabbed the input device. This PR adds a small runtime state surface so those meanings are separated and testable.

Related work

Follow-up to:

Related runtime issues:

Nearby open/merged work this does not solve directly:

What changed

  • Added HidRuntimeState with:
    • input_ready
    • hid_ready
    • connected_device
  • Added hid_runtime_state to the hook contract.
  • Implemented the runtime state projection in the shared Base hook.
  • Added a Linux-specific projection that preserves the existing evdev/HID split:
    • evdev-only connected remains input_ready=True, hid_ready=False
    • HID++ reconnect before evdev remains input_ready=False, hid_ready=True
  • Updated Engine’s read-only projections to prefer hid_runtime_state:
    • device_connected
    • connected_device
    • hid_features_ready
    • immediate connection callback state
  • Kept the old _hid_gesture fallback for existing test doubles and compatibility during the migration.

Scope

This is behavior-preserving infrastructure.

It does not change:

  • saved-settings replay timing
  • battery polling
  • DPI or Smart Shift write paths
  • HID++ reconnect behavior
  • Backend/QML state flow
  • config schema or migrations

_hid_gesture is still retained for operation paths. The next runtime cleanup step can move Engine replay/poll/setter consumers onto this state surface and add a generation token for stale result handling.

Tests

uv run --with-requirements requirements.txt python -m unittest tests.test_mouse_hook_contract tests.test_mouse_hook
uv run --with-requirements requirements.txt python -m unittest tests.test_engine tests.test_backend tests.test_smart_shift
uv run --with-requirements requirements.txt python -m unittest discover -s tests

Full result on macOS:

Ran 269 tests in 23.202s
OK

@hieshima hieshima merged commit 5216073 into TomBadash:master May 5, 2026
1 check passed
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