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

New feature: PERMISSIVE_HOLD_PER_KEY #7994

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ If you define these options you will enable the associated feature, which may in
* `#define PERMISSIVE_HOLD`
* makes tap and hold keys trigger the hold if another key is pressed before releasing, even if it hasn't hit the `TAPPING_TERM`
* See [Permissive Hold](feature_advanced_keycodes.md#permissive-hold) for details
* `#define PERMISSIVE_HOLD_PER_KEY`
* enabled handling for per key `PERMISSIVE_HOLD` settings
* `#define IGNORE_MOD_TAP_INTERRUPT`
* makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys.
* See [Mod tap interrupt](feature_advanced_keycodes.md#ignore-mod-tap-interrupt) for details
Expand Down
19 changes: 19 additions & 0 deletions docs/feature_advanced_keycodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,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 SFT_T(KC_A):
return true;
default:
return false;
}
}
```

## Ignore Mod Tap Interrupt

To enable this setting, add this to your `config.h`:
Expand Down
15 changes: 11 additions & 4 deletions tmk_core/common/action_tapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ __attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode) { return TAPPI
__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { return false; }
# endif

# ifdef PERMISSIVE_HOLD_PER_KEY
__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; }
# endif

static keyrecord_t tapping_key = {};
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
static uint8_t waiting_buffer_head = 0;
Expand Down Expand Up @@ -115,12 +119,15 @@ bool process_tapping(keyrecord_t *keyp) {
* This can register the key before settlement of tapping,
* useful for long TAPPING_TERM but may prevent fast typing.
*/
# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD)
# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY)
else if (
# ifdef TAPPING_TERM_PER_KEY
else if ((get_tapping_term(get_event_keycode(tapping_key.event)) >= 500) && IS_RELEASED(event) && waiting_buffer_typed(event))
# else
else if (IS_RELEASED(event) && waiting_buffer_typed(event))
(get_tapping_term(get_event_keycode(tapping_key.event)) >= 500) &&
# endif
# ifdef PERMISSIVE_HOLD_PER_KEY
!get_permissive_hold(get_event_keycode(tapping_key.event), keyp) &&
# endif
IS_RELEASED(event) && waiting_buffer_typed(event))
{
debug("Tapping: End. No tap. Interfered by typing key\n");
process_record(&tapping_key);
Expand Down