Skip to content

[Core] Options to constrain Speculative Hold: SPECULATIVE_HOLD_ONE_KEY and SPECULATIVE_HOLD_FLOW_TERM.#26099

Open
getreuer wants to merge 4 commits intoqmk:developfrom
getreuer:core/speculative_hold_flow_term
Open

[Core] Options to constrain Speculative Hold: SPECULATIVE_HOLD_ONE_KEY and SPECULATIVE_HOLD_FLOW_TERM.#26099
getreuer wants to merge 4 commits intoqmk:developfrom
getreuer:core/speculative_hold_flow_term

Conversation

@getreuer
Copy link
Copy Markdown
Contributor

To curb "flashing mods" problems, this PR implements two new options, SPECULATIVE_HOLD_ONE_KEY and SPECULATIVE_HOLD_FLOW_TERM, to constrain when Speculative Hold may apply.

Description

In some conditions, Speculative Hold will press and then release a modifier without pressing any other key while it is held, and the OS or application might react to this (aka the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution. Using DUMMY_MOD_NEUTRALIZER_KEYCODE is a good mitigation, but not a full solution.

This PR adds two options that limit when Speculative Hold may apply. Depending on the user's scenario, these may fix cases where flashing mods would confuse and break an important hotkey.

SPECULATIVE_HOLD_ONE_KEY

This option constrains Speculative Hold to one key at a time. Enable by adding in config.h:

#define SPECULATIVE_HOLD_ONE_KEY

With this option, speculation does not apply when any mods are already active. Mod combinations across multiple keys can still be made after settling. This option would fix #26061, where Speculative Hold breaks certain "mod+key" hotkeys in Blender.

SPECULATIVE_HOLD_FLOW_TERM

This option disables Speculative Hold during the flow of fast typing. Add in config.h:

#define SPECULATIVE_HOLD_FLOW_TERM 200

Speculative Hold does not apply if a key is pressed within this threshold of the previous key. The effect is similar to Flow Tap; however, SPECULATIVE_HOLD_FLOW_TERM only restricts when speculation is allowed, without affecting how the key settles. This option would fix where speculation breaks Zed editor leader key hotkeys, an example as noted in getreuer/qmk-modules#15.

Rationale

The intention with both of these options is that they yet allow speculation in isolated "mod + mouse" inputs, since that's the motivating use case for Speculative Hold. In hindsight, I wish SPECULATIVE_HOLD_ONE_KEY + SPECULATIVE_HOLD_FLOW_TERM was default behavior.

Implementation notes

  • The most interesting changes are in the speculative_key_press() function in action_tapping.c. This is where the logic lives that determines when Speculative Hold is allowed to apply.
  • SPECULATIVE_HOLD_FLOW_TERM reuses Flow Tap's tracking of the previous key time, done through ifdef'ing the needed parts.
  • There are two new tests: speculative_hold_one_key and speculative_hold_flow_term.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Keyboard (addition or update)
  • Keymap/layout (addition or update)
  • Documentation

Issues Fixed or Closed by This PR

Checklist

  • My code follows the code style of this project: C, Python
  • I have read the PR Checklist document and have made the appropriate changes.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

@github-actions github-actions bot added core documentation dd Data Driven Changes labels Mar 21, 2026
@drashna drashna requested a review from a team April 6, 2026 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core dd Data Driven Changes documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants