fix(keyboard): prevent modifier key auto-release during typing (#1386)#1387
Merged
adamshiervani merged 1 commit intodevfrom Apr 1, 2026
Merged
fix(keyboard): prevent modifier key auto-release during typing (#1386)#1387adamshiervani merged 1 commit intodevfrom
adamshiervani merged 1 commit intodevfrom
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Stale keepalive closure after RPC channel reconnection
- Added tracking of scheduleKeepAlive reference to detect and restart the keepalive timer when RPC channel reconnects, while preserving the key-repeat starvation fix.
Or push these changes by commenting:
@cursor push 3792219466
Preview (3792219466)
diff --git a/ui/src/hooks/useKeyboard.ts b/ui/src/hooks/useKeyboard.ts
--- a/ui/src/hooks/useKeyboard.ts
+++ b/ui/src/hooks/useKeyboard.ts
@@ -212,6 +212,9 @@
return { modifier: modifiers, keys };
}
+ // Track the current scheduleKeepAlive reference to detect reconnections
+ const scheduleKeepAliveRef = useRef(scheduleKeepAlive);
+
const sendKeypress = useCallback(
(key: number, press: boolean) => {
if (press) {
@@ -227,7 +230,10 @@
// interval — key-repeat events fire faster (~33ms) than the keepalive
// period (50ms), so cancel+restart would prevent the tick from ever
// firing, starving the device-side auto-release extension (issue #1386).
- if (!keepAliveTimerRef.current) {
+ // However, if scheduleKeepAlive changed (e.g., RPC reconnection), restart
+ // the timer to pick up the new closure.
+ if (!keepAliveTimerRef.current || scheduleKeepAliveRef.current !== scheduleKeepAlive) {
+ scheduleKeepAliveRef.current = scheduleKeepAlive;
scheduleKeepAlive();
}
} else {This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
Key-repeat events (fired at ~30Hz by the browser for held keys) were cancelling and restarting the keepalive interval on every keydown. Since the repeat rate (~33ms) is shorter than the keepalive period (50ms), the keepalive tick could never fire. When a second key was pressed and the modifier's repeat stopped, the modifier's 100ms auto-release timer expired with no keepalive to extend it. Fix: start the keepalive interval on first key press and leave it running undisturbed until all keys are released. Track held keys client-side via a Set to know when to start/stop the interval. Also adds six e2e tests covering: - Key-repeat simulation (rapid repeated presses without releases) - Modifier held across rapid tap burst (20 keys at 50ms spacing) - Multiple simultaneous modifiers (Ctrl+Shift+key) - Reversed release order (modifier up before non-modifier) - AltGr (AltRight) held while tapping - Modifier held while tapping 10 keys over 10 seconds Closes #1386
260484c to
6189cba
Compare
1 task
|
Issue is still present in 0.5.6 release. Bug not fixed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
keydown, but the repeat rate (~33ms) was shorter than the keepalive period (50ms), so the keepalive tick could never fire. When a second key was pressed and the modifier's repeat stopped, the modifier's 100ms auto-release timer expired with no keepalive to extend itSet<number>to know when to start/stopuseKeyboard.ts(no-floating-promises, restrict-template-expressions)Test plan
make test_e2esuite (47 tests) passesCloses #1386
Note
Medium Risk
Changes the client-side HID keepalive scheduling used to prevent device auto-release, which can affect all keyboard input timing and stuck-key behavior; adds broad e2e coverage to reduce regression risk.
Overview
Fixes a regression where held modifiers (e.g. Shift/Ctrl/Alt) could auto-release during typing by changing the keepalive logic in
useKeyboardto keep a single interval running while any keys are held, instead of cancelling/restarting it on each press.Adds client-side tracking of currently held keys and ensures the keepalive tick always uses the latest HID RPC sender across reconnects; also cleans up a few legacy RPC sends/logging to avoid floating promises. Expands
ra-all.spec.tswith several new e2e scenarios covering long holds, key-repeat, burst typing, multiple modifiers, reversed release order, and AltGr to validate modifiers are not dropped.Written by Cursor Bugbot for commit 6189cba. This will update automatically on new commits. Configure here.