Skip to content

Windows: no strobes on Caps/Num/Scroll Lock above 30 FPS - #69

Open
BrenOne wants to merge 2 commits into
mskutin:mainfrom
BrenOne:contrib/lock-keys
Open

BrenOne wants to merge 2 commits into
mskutin:mainfrom
BrenOne:contrib/lock-keys

Conversation

@BrenOne

@BrenOne BrenOne commented Nov 1, 2026

Copy link
Copy Markdown

Depends on #68 (adds 45/60 FPS); until it is merged this PR also shows its commit. Closes issue #67 point 4.

Cause

Toggling Caps/Num/Scroll Lock makes Windows send a keyboard-indicator SET_REPORT to the strip's keyboard interface (USB capture: 21 09 0200, interface 1). The controller is busy with it for ~27 ms; a frame arriving meanwhile shows white/random flashes. At 30 FPS (33 ms between frames) they never overlap, so it only happens above 30 FPS.

Fix

  • A low-level keyboard hook (on its own thread, so it is never timed out) plus a 4 ms GetAsyncKeyState poll mark a 250 ms hold on those three keys only.
  • During a hold frames are sent at least 32 ms apart (~30 FPS) instead of every tick, so lighting keeps moving; solid colours wait for the hold to end (max 1 s).
  • At 30 FPS or less nothing changes.

Validation

Windows 11, Robobloq 27" (94 LEDs), 60 FPS: holding and tapping all three lock keys, no flashes, 0 write failures. cargo fmt, cargo clippy -D warnings, tests.

Limitation

Windows hides key presses from non-elevated hooks while an elevated (administrator) window is in front, so flashes can still happen there unless DynamicLight runs elevated.

BrenOne and others added 2 commits October 30, 2026 08:02
- Frames use the controller's own format: 1-based inclusive
  (start, r, g, b, end) ranges after the 0x80 command, merged greedily to
  at most 34 ranges (3 HID reports instead of 8), as the vendor app and
  OpenRGB do. The previous 0-based ranges and trailing byte matched no
  known firmware behaviour.
- 1 ms gap between reports; a stalled hid_write (0x3E5) is retried, then
  the interface is reopened before the strip is reported lost.
- Hardware brightness 255 (0x87 takes 0-255; 100 left the strip at ~39 %).
- Read LED count and display size from the 0x82 reply and adopt them.
  On a fresh setup pick 3 or 4 edges from the kit's ~2 cm LED pitch and
  split LEDs by the display's real aspect ratio, leaving a configurable
  gap at the corners (bars wired at the corners have no LEDs there).
- Per-side LED counts and corner gap in Device setup, with a warning when
  they do not add up; the strip preview shows the real positions.
- 45 and 60 FPS (60 by default); RGB recordings stay at 30 frames/s.
- Windows: turn the strip off on shutdown, restart and sign-out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Sqdi9StAk5iH4ETYHDqEq
Toggling a lock key makes Windows send a keyboard-indicator SET_REPORT to the
strip's keyboard interface; the controller is busy with it for ~27 ms, and a
frame arriving meanwhile shows white/random flashes (seen only above 30 FPS).

A low-level keyboard hook (own thread) and a 4 ms GetAsyncKeyState poll mark
a 250 ms hold on those keys. During a hold frames are sent at least 32 ms
apart (~30 FPS) instead of every tick, and solid colours wait it out (max 1 s).
At 30 FPS or less nothing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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