#Facilitate Tap Hold Key with hold until tap/hold can be decided

9 messages · Page 1 of 1 (latest)

atomic valley
#

Hi, I have a key called K setup with tap hold functionality to be Control on hold and Space on tap.
Using tap hold configuration (see HOLD_ON_OTHER_KEY_PRESS) I managed to make it that the sequence: Press K, Press C, Release K, Release C will generate a Control C after C press.
I am interested to change the behavior before either another key (here C) is pressed or a timer finishes to classify it as a hold.

On my motivation, in my text editor holding Control and using the Left-mouse-button has special meaning, but using the current setup i have to wait for the timer to register Control.
This could be solved either by connecting the mouse to the keyboard to give Left-mouse-button the same behavior as C (I do not think this is a great idea)
or by sending the computer the held-event while the keyboard is unsure which of hold or tap is appropriate and releasing before the tap event is sent.

I am not familiar with the code generating actions to find the place where such behavior could be inserted. The issue is that I am unsure if there is yet an action created on K press, which's meaning can be changed.
If there was, then (ignoring modifiers already being held beforehand) sending Control press on K press, and sending Control release on quick Release K before sending Space tap should work nicely.

If similar behavior was discussed elsewhere, please point me to it since i could not find it.

#

Diagram on current behavior, modified from tap_hold

                                Tapping term
  +-------------------------------|--------+
  | +-----------------+           |        |
  | | CTL_T(KC_SPACE) |           |        |
  | +-----------------+           |        |
  |       +------------------+    |        |
  |       | KC_C             |    |        |
  |       +------------------+    |        |
  +-------|-----------------------|--------+
          |
        Send CTL(C)


                        Tapping Term
  +-----------------------|--------+
  | +---------------------|--+     |
  | | CTL_T(KC_SPACE)     |  |     |
  | +---------------------|--+     |
  +-----------------------|--------+
                          |
                        Send SPACE                    

Diagram on desired behavior

                                Tapping term
  +-------------------------------|--------+
  | +-----------------+           |        |
  | | CTL_T(KC_SPACE) |           |        |
  | +-----------------+           |        |
  | |     +------------------+    |        |
  | |     | KC_C             |    |        |
  | |     +------------------+    |        |
  +-|-----|-----------------------|--------+
    |     |
    |   Send CTL(C)
    |
   Send CTL

                        Tapping Term
  +-----------------------|--------+
  | +---------------------|--+     |
  | | CTL_T(KC_SPACE)     |  |     |
  | +---------------------|--+     |
  +-|---------------------|--------+
    |                     |
    Send CTL              Release CLT, Send SPACE
oak cove
# atomic valley Diagram on current behavior, modified from [tap_hold](https://docs.qmk.fm/tap_ho...

The core tapping code can't do what you want, because it delays events until enough information is available to distinguish a tap from a hold.

The Space Cadet feature can register the modifier without any delay, but you would need to hijack some predefined keycode like SC_LCPO and redefine the tap keycode for it. Also the interrupt behavior for that feature is hardcoded to the equivalent of HOLD_ON_OTHER_KEY_PRESS, and there might be other subtle differences.

A more general option is Tap Dance, but you would need to implement the desired behavior using custom on_each_tap and on_each_release functions (the on_dance_finished function is called only after the tap dance had been completed).

finite marsh
#

You could make the hold key register the mod on keydown using the preprocess_record function

#

then make other unrelated keys remove the modifier to make it not interfere with anything else

#

something along the lines of

bool lctl_on = false;

bool pre_process_record_user(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        case CTL_T(KC_SPC):
            if (record->event.pressed) {
                register_mods(MOD_BIT(KC_LCTL));
                lctl_on = true;
            }
            return true;
    }
    if (keycode != KC_C && lctl_on) {
        unregister_mods(MOD_BIT(KC_LCTL));
    }
    return true;
}


bool process_record_user(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        case CTL_T(KC_SPC):
            if (!record->tap.count && !record->event.pressed) {
                unregister_mods(MOD_BIT(KC_LCTL));
            }
            if (record->tap.count && record->event.pressed) {
                if (lctl_on) {
                    unregister_mods(MOD_BIT(KC_LCTL));
                }
                tap_code(KC_SPC);
            }
            lctl_on = false;
            return false
    }
    ...
}
atomic valley
#

Thanks for the suggestions!
Space cadet seems nice, but ideally i want to do this for space and control.
Tap dance seems to have all the functionality to get the events, but i haven't used the feature yet so i will first read the documentation.
I wasnt aware of pre_process_record_user but it seems likely to work. Maybe less setup compared to tap-dance? Will read its docs, too.

What is this supposed to do?

        unregister_mods(MOD_BIT(KC_LCTL));
    }```
It seems to limit it to only ctl + C, but then I'd expect `lctl_on=false;`; but maybe it doesnt change the behavior.
#

I mean I want to do it for shift and control.