diff --git a/docs/ChangeLog/20200530/PR8348.md b/docs/ChangeLog/20200530/PR8348.md new file mode 100644 index 000000000000..d6a740d302d6 --- /dev/null +++ b/docs/ChangeLog/20200530/PR8348.md @@ -0,0 +1,9 @@ +# Unify Tap Hold functions and documentation + +Updates all of the per key tap-hold functions to pass the `keyrecord_t` structure, and include documentation changes. + +Any remaining versions or code outside of the main repo will need to be converted: +| Old function | New Function | +|------------------------------------------------------|---------------------------------------------------------------------------| +|`uint16_t get_tapping_term(uint16_t keycode)` |`uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record)` | +|`bool get_ignore_mod_tap_interrupt(uint16_t keycode)` |`bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record)` | diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md index 84ae589ed6c3..e310daa1ea0c 100644 --- a/docs/custom_quantum_functions.md +++ b/docs/custom_quantum_functions.md @@ -486,56 +486,3 @@ And you're done. The RGB layer indication will only work if you want it to. And * Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)` The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM. - -# Custom Tapping Term - -By default, the tapping term and related options (such as `IGNORE_MOD_TAP_INTERRUPT`) are defined globally, and are not configurable by key. For most users, this is perfectly fine. But in some cases, dual function keys would be greatly improved by different timeout behaviors than `LT` keys, or because some keys may be easier to hold than others. Instead of using custom key codes for each, this allows for per key configurable timeout behaviors. - -There are two configurable options to control per-key timeout behaviors: - -- `TAPPING_TERM_PER_KEY` -- `IGNORE_MOD_TAP_INTERRUPT_PER_KEY` - -You need to add `#define` lines to your `config.h` for each feature you want. - -``` -#define TAPPING_TERM_PER_KEY -#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY -``` - - -## Example `get_tapping_term` Implementation - -To change the `TAPPING_TERM` based on the keycode, you'd want to add something like the following to your `keymap.c` file: - -```c -uint16_t get_tapping_term(uint16_t keycode) { - switch (keycode) { - case SFT_T(KC_SPC): - return TAPPING_TERM + 1250; - case LT(1, KC_GRV): - return 130; - default: - return TAPPING_TERM; - } -} -``` - -## Example `get_ignore_mod_tap_interrupt` Implementation - -To change the `IGNORE_MOD_TAP_INTERRUPT` value based on the keycode, you'd want to add something like the following to your `keymap.c` file: - -```c -bool get_ignore_mod_tap_interrupt(uint16_t keycode) { - switch (keycode) { - case SFT_T(KC_SPC): - return true; - default: - return false; - } -} -``` - -## `get_tapping_term` / `get_ignore_mod_tap_interrupt` Function Documentation - -Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only user level functions are useful here, so no need to mark them as such. diff --git a/docs/ja/custom_quantum_functions.md b/docs/ja/custom_quantum_functions.md index 7e4fbd897eea..e4e23b8b70da 100644 --- a/docs/ja/custom_quantum_functions.md +++ b/docs/ja/custom_quantum_functions.md @@ -511,7 +511,7 @@ void eeconfig_init_user(void) { // EEPROM がリセットされます! キーコードに基づいて `TAPPING_TERM` を変更するには、次のようなものを `keymap.c` ファイルに追加します: ```c -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case SFT_T(KC_SPC): return TAPPING_TERM + 1250; @@ -528,7 +528,7 @@ uint16_t get_tapping_term(uint16_t keycode) { キーコードに基づいて `IGNORE_MOD_TAP_INTERRUPT` の値を変更するには、次のようなものを `keymap.c` ファイルに追加します: ```c -bool get_ignore_mod_tap_interrupt(uint16_t keycode) { +bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case SFT_T(KC_SPC): return true; diff --git a/docs/tap_hold.md b/docs/tap_hold.md index a0b648694b9a..2dc57f03c2d4 100644 --- a/docs/tap_hold.md +++ b/docs/tap_hold.md @@ -4,6 +4,38 @@ While Tap-Hold options are fantastic, they are not without their issues. We hav These options let you modify the behavior of the Tap-Hold keys. +## Tapping Term + +The crux of all of the following features is the tapping term setting. This determines what is a tap and what is a hold. And the exact timing for this to feel natural can vary from keyboard to keyboard, from switch to switch, and from key to key. + +You can set the global time for this by adding the following setting to your `config.h`: + +```c +#define TAPPING_TERM 200 +``` + +This setting is defined in milliseconds, and does default to 200ms. This is a good average for a majority of people. + +For more granular control of this feature, you can add the following to your `config.h`: +```c +#define TAPPING_TERM_PER_KEY +``` + +You can then add the following function to your keymap: + +```c +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case SFT_T(KC_SPC): + return TAPPING_TERM + 1250; + case LT(1, KC_GRV): + return 130; + default: + return TAPPING_TERM; +} +``` + + ## Permissive Hold As of [PR#1359](https://github.com/qmk/qmk_firmware/pull/1359/), there is a new `config.h` option: @@ -27,6 +59,25 @@ Normally, if you do all this within the `TAPPING_TERM` (default: 200ms) this wil ?> If you have `Ignore Mod Tap Interrupt` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`. +For more granular control of this feature, you can add the following to your `config.h`: + +```c +#define PERMISSIVE_HOLD_PER_KEY +``` + +You can then add the following function to your keymap: + +```c +bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case LT(1, KC_BSPC): + return true; + default: + return false; + } +} +``` + ## Ignore Mod Tap Interrupt To enable this setting, add this to your `config.h`: @@ -62,13 +113,13 @@ For more granular control of this feature, you can add the following to your `co You can then add the following function to your keymap: ```c -bool get_ignore_mod_tap_interrupt(uint16_t keycode) { - switch (keycode) { - case SFT_T(KC_SPC): - return true; - default: - return false; - } +bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case SFT_T(KC_SPC): + return true; + default: + return false; + } } ``` @@ -106,12 +157,12 @@ You can then add the following function to your keymap: ```c bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - case LT(1, KC_BSPC): - return true; - default: - return false; - } + switch (keycode) { + case LT(1, KC_BSPC): + return true; + default: + return false; + } } ``` @@ -126,3 +177,13 @@ To enable `retro tapping`, add the following to your `config.h`: Holding and releasing a dual function key without pressing another key will result in nothing happening. With retro tapping enabled, releasing the key without pressing another will send the original keycode even if it is outside the tapping term. For instance, holding and releasing `LT(2, KC_SPACE)` without hitting another key will result in nothing happening. With this enabled, it will send `KC_SPACE` instead. + +## Why do we include the key record for the per key functions? + +One thing that you may notice is that we include the key record for all of the "per key" functions, and may be wondering why we do that. + +Well, it's simply really: customization. But specifically, it depends on how your keyboard is wired up. For instance, if each row is actually using a row in the keyboard's matrix, then it may be simpler to use `if (record->event.row == 3)` instead of checking a whole bunch of keycodes. Which is especially good for those people using the Tap Hold type keys on the home row. So you could fine tune those to not interfere with your normal typing. + +## Why is there no `*_kb` or `*_user` functions?! + +Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only user level functions are useful here, so no need to mark them as such. diff --git a/docs/zh-cn/custom_quantum_functions.md b/docs/zh-cn/custom_quantum_functions.md index f2c6098dcb70..8f8f7dd9c0b6 100644 --- a/docs/zh-cn/custom_quantum_functions.md +++ b/docs/zh-cn/custom_quantum_functions.md @@ -473,7 +473,7 @@ void eeconfig_init_user(void) { // EEPROM正被重置 想要修改基于键码的`TAPPING TERM`,你要向`keymap.c`文件添加如下代码: ```c -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case SFT_T(KC_SPC): return TAPPING_TERM + 1250; diff --git a/keyboards/converter/usb_usb/keymaps/chriskopher/keymap.c b/keyboards/converter/usb_usb/keymaps/chriskopher/keymap.c index c472f78b7de2..716ff19abdd3 100644 --- a/keyboards/converter/usb_usb/keymaps/chriskopher/keymap.c +++ b/keyboards/converter/usb_usb/keymaps/chriskopher/keymap.c @@ -175,7 +175,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { // clang-format on // Configure ignore mod tap interrupt per key -bool get_ignore_mod_tap_interrupt(uint16_t keycode) { +bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { switch (keycode) { // I don't like how mod tap interrupt feels with these keys specifically when I'm typing case LCTL_T(KC_ESC): diff --git a/keyboards/crkbd/keymaps/drashna/keymap.c b/keyboards/crkbd/keymaps/drashna/keymap.c index 55d51eb08ac7..0769edf3b94d 100644 --- a/keyboards/crkbd/keymaps/drashna/keymap.c +++ b/keyboards/crkbd/keymaps/drashna/keymap.c @@ -124,7 +124,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_270; } #endif -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case ALT_T(KC_A): return TAPPING_TERM + 100; diff --git a/keyboards/nomu30/keymaps/center_sprit/keymap.c b/keyboards/nomu30/keymaps/center_sprit/keymap.c index 8ef037f42b64..cc540b891ffa 100644 --- a/keyboards/nomu30/keymaps/center_sprit/keymap.c +++ b/keyboards/nomu30/keymaps/center_sprit/keymap.c @@ -100,7 +100,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_BSLO: return TAPPING_LAYER_TERM; diff --git a/keyboards/nomu30/keymaps/like_jis/keymap.c b/keyboards/nomu30/keymaps/like_jis/keymap.c index 203d0a7a4151..fc2d26ad7a31 100644 --- a/keyboards/nomu30/keymaps/like_jis/keymap.c +++ b/keyboards/nomu30/keymaps/like_jis/keymap.c @@ -100,7 +100,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_BSLO: return TAPPING_LAYER_TERM; diff --git a/keyboards/the_royal/liminal/keymaps/default/keymap.c b/keyboards/the_royal/liminal/keymaps/default/keymap.c index d9d949745308..dd986610116b 100644 --- a/keyboards/the_royal/liminal/keymaps/default/keymap.c +++ b/keyboards/the_royal/liminal/keymaps/default/keymap.c @@ -127,7 +127,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case LT(_LOWER, KC_SPACE): return 160; @@ -136,7 +136,7 @@ uint16_t get_tapping_term(uint16_t keycode) { default: #ifndef TAPPING_TERM return 200; -#else +#else return TAPPING_TERM; #endif } diff --git a/keyboards/the_royal/liminal/keymaps/default_iso/keymap.c b/keyboards/the_royal/liminal/keymaps/default_iso/keymap.c index 3d8debee3d67..62ff2b6a5d49 100644 --- a/keyboards/the_royal/liminal/keymaps/default_iso/keymap.c +++ b/keyboards/the_royal/liminal/keymaps/default_iso/keymap.c @@ -128,7 +128,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case LT(_LOWER, KC_SPACE): return 160; diff --git a/keyboards/thevankeyboards/minivan/keymaps/like_jis/keymap.c b/keyboards/thevankeyboards/minivan/keymaps/like_jis/keymap.c index 3d282e182b38..509b49780281 100644 --- a/keyboards/thevankeyboards/minivan/keymaps/like_jis/keymap.c +++ b/keyboards/thevankeyboards/minivan/keymaps/like_jis/keymap.c @@ -114,7 +114,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; #define TAPPING_LAYER_TERM 150 // Custom LT Tapping term -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_BSLO: return TAPPING_LAYER_TERM; diff --git a/keyboards/treadstone32/keymaps/default/keymap.c b/keyboards/treadstone32/keymaps/default/keymap.c index 7ca797fcc006..791fed059bcb 100644 --- a/keyboards/treadstone32/keymaps/default/keymap.c +++ b/keyboards/treadstone32/keymaps/default/keymap.c @@ -110,7 +110,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_BSLO: return TAPPING_LAYER_TERM; diff --git a/keyboards/treadstone32/keymaps/like_jis/keymap.c b/keyboards/treadstone32/keymaps/like_jis/keymap.c index a738226d991f..92518b11a7f3 100644 --- a/keyboards/treadstone32/keymaps/like_jis/keymap.c +++ b/keyboards/treadstone32/keymaps/like_jis/keymap.c @@ -111,7 +111,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_BSLO: return TAPPING_LAYER_TERM; diff --git a/layouts/community/ergodox/drashna/keymap.c b/layouts/community/ergodox/drashna/keymap.c index 69066a47cc48..cb256e5e57b8 100644 --- a/layouts/community/ergodox/drashna/keymap.c +++ b/layouts/community/ergodox/drashna/keymap.c @@ -457,7 +457,7 @@ void rgb_matrix_indicators_user(void) { #endif // RGB_MATRIX_INIT -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { if (keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) { if (mod_config(keycode & 0xf) & MOD_MASK_ALT) { return (2 * TAPPING_TERM); diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index 3b1268dc940b..7a53e08ed383 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -48,7 +48,7 @@ int retro_tapping_counter = 0; #endif #ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY -__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode) { return false; } +__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } #endif #ifndef TAP_CODE_DELAY @@ -335,7 +335,7 @@ void process_action(keyrecord_t *record, action_t action) { # if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY) if ( # ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY - !get_ignore_mod_tap_interrupt(get_event_keycode(record->event, false)) && + !get_ignore_mod_tap_interrupt(get_event_keycode(record->event, false), &record) && # endif record->tap.interrupted) { dprint("mods_tap: tap: cancel: add_mods\n"); diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c index 34f08d890486..fe545c79a069 100644 --- a/tmk_core/common/action_tapping.c +++ b/tmk_core/common/action_tapping.c @@ -19,10 +19,10 @@ # define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) # define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) -__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode) { return TAPPING_TERM; } +__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; } # ifdef TAPPING_TERM_PER_KEY -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_event_keycode(tapping_key.event, false))) +# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_event_keycode(tapping_key.event, false), &tapping_key)) # else # define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) # endif @@ -122,7 +122,7 @@ bool process_tapping(keyrecord_t *keyp) { # if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) else if ( # ifdef TAPPING_TERM_PER_KEY - (get_tapping_term(get_event_keycode(tapping_key.event, false)) >= 500) && + (get_tapping_term(get_event_keycode(tapping_key.event, false), keyp) >= 500) && # endif # ifdef PERMISSIVE_HOLD_PER_KEY !get_permissive_hold(get_event_keycode(tapping_key.event, false), keyp) && diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h index 5eaef1c5f09a..7015ce76120b 100644 --- a/tmk_core/common/action_tapping.h +++ b/tmk_core/common/action_tapping.h @@ -33,7 +33,7 @@ along with this program. If not, see . #ifndef NO_ACTION_TAPPING uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); -uint16_t get_tapping_term(uint16_t keycode); +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record); void action_tapping_process(keyrecord_t record); #endif diff --git a/users/ridingqwerty/ridingqwerty.c b/users/ridingqwerty/ridingqwerty.c index ee6e7e897a83..19b417a80f40 100644 --- a/users/ridingqwerty/ridingqwerty.c +++ b/users/ridingqwerty/ridingqwerty.c @@ -45,7 +45,7 @@ layer_state_t layer_state_set_user(layer_state_t state) { return state; } -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case RC(ENT): case ED(ESC): diff --git a/users/tominabox1/tominabox1.c b/users/tominabox1/tominabox1.c index 95e6ee780332..d2e9e1258127 100644 --- a/users/tominabox1/tominabox1.c +++ b/users/tominabox1/tominabox1.c @@ -106,7 +106,7 @@ qk_tap_dance_action_t tap_dance_actions[] = { #endif // CRKBD -uint16_t get_tapping_term(uint16_t keycode) { +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case LSFT_T(KC_CAPS): return 250;