Skip to content

fix(input): run low-level hooks on a dedicated thread; use hook-time cursor - #75

Open
DysektAI wants to merge 2 commits into
masterfrom
fix/input-hook-thread
Open

DysektAI wants to merge 2 commits into
masterfrom
fix/input-hook-thread

Conversation

@DysektAI

Copy link
Copy Markdown
Member

Why

  • The WH_MOUSE_LL/WH_KEYBOARD_LL hooks were installed on the WPF UI thread. Low-level hooks run on the installing thread, so every system-wide mouse event (including in-game movement) waited behind UI work: WebView layout, the content-fit animation, a synchronous engine rebuild from a game-mode switch. That is a plausible source of the reported random hitches.
  • Windows silently removes a hook that exceeds LowLevelHooksTimeout; hotkeys then stop until restart, which users would describe as inconsistent scanning.
  • Handlers read the cursor later on the thread pool, so a busy pool could centre the capture on a moved cursor.

What

  • UserActivityHelper.Start installs both hooks on an AboveNormal background thread with its own message loop (queue created before startup completes); Stop() posts WM_QUIT and joins (2 s cap); the thread unhooks on exit. Startup failures still throw to the caller with the original rollback.
  • KeyUpEventArgs/KeyDownEventArgs carry CursorPosition captured in the hook (MSLLHOOKSTRUCT.pt for mouse, GetCursorPos for keyboard); HotkeyManager scans at that point.
  • HotkeySelector marshals hook callbacks onto the Blazor renderer (it mutated component state from the hook).

Validation

  • Release build with debug logging: injected Shift down/up reached the new hook thread (logged with LLKHF_INJECTED); app shut down cleanly (exit 0).
  • Debug and Release build; dotnet test 408/408; verify.ps1 -Mode Ui 2/2; CodeRabbit: no findings.

Not proven

  • ⚠️ Hitch reduction in game is not measured: needs a manual session (rapid clicking while the main window re-lays out) comparing hook.dispatch stage times in Log.txt before/after.
  • ⚠️ Hotkey recording in Settings should get a manual check (record Shift+Click, Escape cancels).

https://claude.ai/code/session_01QFKiA2aswHyp8SnpraLxE2

…cursor

The WH_MOUSE_LL/WH_KEYBOARD_LL hooks were installed from the WPF UI
thread, so every mouse event on the system (including in-game movement)
waited behind UI work such as WebView layout or a synchronous engine
rebuild, and Windows can silently drop a hook that misses
LowLevelHooksTimeout (hotkeys then stop until restart).

- Install the hooks on an AboveNormal background thread with its own
  message loop; Stop posts WM_QUIT and the thread unhooks on exit.
- Capture the cursor position in the hook (MSLLHOOKSTRUCT.pt for mouse,
  GetCursorPos for keyboard) and scan at that point instead of reading
  the cursor later on the thread pool.
- HotkeySelector now marshals hook callbacks onto the renderer.

Verified on a Release build: injected Shift key events reach the hook
thread (debug log), shutdown joins it cleanly (exit 0), UI smoke passes.

Claude-Session: https://claude.ai/code/session_01QFKiA2aswHyp8SnpraLxE2
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Next included review available in 37 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 68 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Essentials
  • Run ID: e82a9551-e91f-488b-a8b0-b0ffa13caecf
📥 Commits

Reviewing files that changed from the base of the PR and between c15eda6 and 12d2868.

📒 Files selected for processing: 3
  • src/App/Components/HotkeySelector.razor
  • src/App/HotkeyManager.cs
  • src/App/UserActivityHelper.cs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

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