Skip to content

Fast double-taps on Shift no longer enable Caps Lock #475

Description

@AsafMah

Regression

Fast double-taps on Shift do not enable Caps Lock. This is still reproducible in v4.1.8.

The regression was introduced by ec1de5fa84fd819b93e3ba904f17445f7424f61f (feat: tune double-tap shift timing and keep llamacpp proguard), which changed KeyboardState.onPressShift() to require both an active double-tap timer and now - lastShiftPressTime > 100.

That 100 ms minimum was intended to address the single-tap Caps Lock failures reported in #186 and #188, but it rejects legitimate fast double-taps. It also does not mechanically solve duplicate press delivery: a second press event without a release can still lock Caps after 100 ms.

Deterministic reproduction

A KeyboardStateTest using the real onPressKey/onReleaseKey sequence, a fake clock, and a controllable 300 ms timer produces these pre-fix results:

  • fastDoubleTapShiftLocksCaps (50 ms between distinct taps): fails
  • ordinaryDoubleTapShiftWithinTimerLocksCaps (150 ms): passes
  • singleTapShiftStaysTemporarilyShifted: passes
  • duplicateShiftPressWithoutReleaseDoesNotLockCaps (150 ms between DOWN events, no UP): fails

Pre-fix targeted result: 5 tests, 2 failed. After the patch below, the complete KeyboardStateTest passes, including lock-then-single-tap unlock after the timer window. The broader fork gate also reports no new failures across 369 tests.

Suggested patch

A double-tap should be identified by the invariant that two presses have an intervening release boundary, while the existing TimerHandler supplies the maximum 300 ms window:

// A second tap must have a release boundary; repeated press events are not double taps.
if (!shiftKeyState.isReleasing) return
isInDoubleTapShiftKey = switchActions.isInDoubleTapShiftKeyTimeout

This replaces the SystemClock/lastShiftPressTime minimum check and removes lastShiftPressTime. It restores legitimate sub-100 ms double-taps while preserving the purpose of #186/#188: duplicate pointer-down/key-repeat delivery without a release cannot become Caps Lock.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions