Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Implement ZMK's require-prior-idle-ms in QMK #24262

Open
1 of 4 tasks
amarakon opened this issue Aug 10, 2024 · 3 comments
Open
1 of 4 tasks

[Feature Request] Implement ZMK's require-prior-idle-ms in QMK #24262

amarakon opened this issue Aug 10, 2024 · 3 comments

Comments

@amarakon
Copy link

amarakon commented Aug 10, 2024

Feature Request Type

  • Core functionality
  • Add-on hardware support (eg. audio, RGB, OLED screen, etc.)
  • Alteration (enhancement/optimization) of existing feature(s)
  • New behavior

Description

ZMK has the configuration option require-prior-idle-ms for tap-hold keys. It effectively makes all tap-hold keys resolve as tapped when typing quickly. Aside from decreasing the possibility of accidentally triggering modifiers, it has the added benefit of eliminating the delay when typing quickly.

I did find a pull request on Manna Harbour's fork of the QMK firmware, but it's from two years ago and I can't merge it into my clone of this repository without a lot of merge conflicts. There's also the achordion userspace library, but it can't get rid of the delay; it can only prevent modifiers from being triggered.

@filterpaper
Copy link
Contributor

filterpaper commented Aug 21, 2024

It is a non-trivial request to implement this into QMK's core action tapping code. But you can easily do so in your user keymap code using the pre_process_record_user function with something like:

// Decision macro for mod-tap keys to override
#define IS_HOMEROW_MOD_TAP(kc) (              \
    IS_QK_MOD_TAP(kc)                      && \
    QK_MOD_TAP_GET_TAP_KEYCODE(kc) >= KC_A && \
    QK_MOD_TAP_GET_TAP_KEYCODE(kc) <= KC_Z    )

// Decision macro for preceding trigger key and typing interval
#define IS_TYPING(k) ( \
    ((uint8_t)(k) <= KC_Z || (uint8_t)(k) == KC_SPC) && \
    (last_input_activity_elapsed() < QUICK_TAP_TERM)    )

bool pre_process_record_user(uint16_t keycode, keyrecord_t *record) {
    static bool     is_pressed[UINT8_MAX];
    static uint16_t prev_keycode;
    const  uint16_t tap_keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode);

    if (record->event.pressed) {
        // Press the tap keycode if the tap-hold key follows the previous key swiftly
        if (IS_HOMEROW_MOD_TAP(keycode) && IS_TYPING(prev_keycode)) {
            is_pressed[tap_keycode] = true;
            record->keycode         = tap_keycode;
        }
        // Cache the keycode for subsequent tap decision
        prev_keycode = keycode;
    }

    // Release the tap keycode if pressed
    else if (is_pressed[tap_keycode]) {
        is_pressed[tap_keycode] = false;
        record->keycode         = tap_keycode;
    }

    return true;
}

The preprocessor macros can be adjusted to your preference. Unlike ZMK, you can choose the preceding keycode that will trigger the feature. It uses the keycode container in the keyrecord_t. If you don't have COMBO_ENABLE, enable REPEAT_KEY_ENABLE.

@amarakon
Copy link
Author

amarakon commented Aug 21, 2024

First, thanks a lot for the code. I tested it and it works for home row mods. However, I also like to use my spacebar as a mod-tap key. This is how I set up my mod-taps:

  • spacebar: mod-tap for gui
  • s and l: mod-tap for alt
  • d and k: mod-tap for shift
  • f and j: mod-tap for control

I changed the IS_HOMEROW_MOD_TAP macro to the following:

#define IS_HOMEROW_MOD_TAP(kc) ( \
    IS_QK_MOD_TAP(kc) && \
    ((QK_MOD_TAP_GET_TAP_KEYCODE(kc) >= KC_A && \
      QK_MOD_TAP_GET_TAP_KEYCODE(kc) <= KC_Z) || \
      QK_MOD_TAP_GET_TAP_KEYCODE(kc) == KC_SPC))

This makes it so that KC_SPC can also be considered a mod-tap key. It works for the most part, but sometimes it won't work and there'll be an unexpected delay when pressing space during a typing streak, as if I was using standard mod-taps.

I attached a video. I used keyd to monitor my keystrokes. Notice how there's a delay when typing the space right before the word The. Also notice how the difference in time between space down and f down is one millisecond. This probably means that the space is delayed until the F key is pressed. By the way, I'm using the Colemak layout so I press the F key to type the letter T.

untitled.mp4

Edit: I forgot to mention that my QUICK_TAP_TERM is defined as 200.

@amarakon
Copy link
Author

I just realized that the reason I was experiencing that issue was because I also had a key-remapping daemon running which does the same thing. I was using it as a temporary solution for this problem and forgot to turn it off when I re-flashed my firmware. I'll still keep this issue open because I'd like to see this get implemented as a core QMK feature.

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

No branches or pull requests

2 participants