Skip to content

Commit

Permalink
Merge changes from qmk#9889 to allow for retro shift
Browse files Browse the repository at this point in the history
  • Loading branch information
violet-fish committed Aug 6, 2020
1 parent e28a4e7 commit bb27a31
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 24 deletions.
2 changes: 2 additions & 0 deletions docs/feature_auto_shift.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Yes, unfortunately.
for a shifted version, but we did not. On the other hand, we may think we are
tapping the keys, but really we have held it for a little longer than
anticipated.
3. Auto Shift does not apply to Tap Hold keys. For automatic shifting of Tap Hold
keys see [Retro Shift](tap_hold.md#retro-shift).

## How Do I Enable Auto Shift?

Expand Down
108 changes: 95 additions & 13 deletions docs/tap_hold.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@ 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:
Expand All @@ -27,6 +60,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`:
Expand Down Expand Up @@ -62,13 +114,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;
}
}
```
Expand Down Expand Up @@ -106,12 +158,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;
}
}
```
Expand All @@ -126,3 +178,33 @@ 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.

## Retro Shift

Holding and releasing a Tap Hold key without pressing another key will result in only the hold. With Retro Shift enabled this action will produce a shifted version of the tap keycode.

This is a supplement to [Auto Shift](feature_auto_shift.md), which does not support Tap Hold. Auto Shift is not required to be enabled, but for consistency it should be enabled and configured with the Auto Shift timeout matching the tapping term. Retro Shift applies to the same tap keycodes as Auto Shift and uses the Auto Shift options `NO_AUTO_SHIFT_SPECIAL`, `NO_AUTO_SHIFT_NUMERIC`, `NO_AUTO_SHIFT_ALPHA`, and `AUTO_SHIFT_MODIFIERS` if defined.

Retro Shift does not require [Retro Tapping](#retro-tapping) to be enabled, and if both are enabled Retro Tapping will only apply if the tap keycode is not matched by Retro Shift.

To enable Retro Shift, add the following to your `config.h`:

```c
#define RETRO_SHIFT
```

If `RETRO_SHIFT` is defined to a value, hold times greater than that value will not produce a tap on release. This enables modifiers to be held for combining with mouse clicks without generating taps on release. For example:

```c
#define RETRO_SHIFT 500
```
## 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.
106 changes: 95 additions & 11 deletions tmk_core/common/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.

int tp_buttons;

#ifdef RETRO_TAPPING
#if defined RETRO_TAPPING || defined RETRO_SHIFT
int retro_tapping_counter = 0;
#endif

#ifdef RETRO_SHIFT
# include "quantum.h"
#endif

#ifdef FAUXCLICKY_ENABLE
# include <fauxclicky.h>
#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
Expand All @@ -67,7 +71,7 @@ void action_exec(keyevent_t event) {
dprint("EVENT: ");
debug_event(event);
dprintln();
#ifdef RETRO_TAPPING
#if defined RETRO_TAPPING || defined RETRO_SHIFT
retro_tapping_counter++;
#endif
}
Expand Down Expand Up @@ -98,6 +102,11 @@ void action_exec(keyevent_t event) {
if (has_oneshot_mods_timed_out()) {
clear_oneshot_mods();
}
# ifdef SWAP_HANDS_ENABLE
if (has_oneshot_swaphands_timed_out()) {
clear_oneshot_swaphands();
}
# endif
# endif
#endif

Expand Down Expand Up @@ -165,6 +174,8 @@ void process_record_tap_hint(keyrecord_t *record) {
# ifdef SWAP_HANDS_ENABLE
case ACT_SWAP_HANDS:
switch (action.swap.code) {
case OP_SH_ONESHOT:
break;
case OP_SH_TAP_TOGGLE:
default:
swap_hands = !swap_hands;
Expand All @@ -185,7 +196,14 @@ void process_record(keyrecord_t *record) {
return;
}

if (!process_record_quantum(record)) return;
if (!process_record_quantum(record)) {
#ifndef NO_ACTION_ONESHOT
if (is_oneshot_layer_active() && record->event.pressed) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
#endif
return;
}

process_record_handler(record);
post_process_record_quantum(record);
Expand Down Expand Up @@ -215,16 +233,26 @@ void process_action(keyrecord_t *record, action_t action) {
#ifndef NO_ACTION_TAPPING
uint8_t tap_count = record->tap.count;
#endif
#ifdef RETRO_SHIFT
static uint16_t retro_shift_start_time;
#endif

if (event.pressed) {
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();
#ifdef RETRO_SHIFT
retro_shift_start_time = event.time;
#endif
}

#ifndef NO_ACTION_ONESHOT
bool do_release_oneshot = false;
// notice we only clear the one shot layer if the pressed key is not a modifier.
if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code))
# ifdef SWAP_HANDS_ENABLE
&& !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)
# endif
) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
do_release_oneshot = !is_oneshot_layer_active();
}
Expand Down Expand Up @@ -324,7 +352,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");
Expand All @@ -346,6 +374,8 @@ void process_action(keyrecord_t *record, action_t action) {
dprint("MODS_TAP: Tap: unregister_code\n");
if (action.layer_tap.code == KC_CAPS) {
wait_ms(TAP_HOLD_CAPS_DELAY);
} else {
wait_ms(TAP_CODE_DELAY);
}
unregister_code(action.key.code);
} else {
Expand Down Expand Up @@ -382,7 +412,9 @@ void process_action(keyrecord_t *record, action_t action) {
/* Mouse key */
case ACT_MOUSEKEY:
if (event.pressed) {
mousekey_on(action.key.code);
switch (action.key.code) {
# ifdef PS2_MOUSE_ENABLE
case KC_MS_BTN1:
tp_buttons |= (1 << 0);
break;
Expand All @@ -392,13 +424,15 @@ void process_action(keyrecord_t *record, action_t action) {
case KC_MS_BTN3:
tp_buttons |= (1 << 2);
break;
# endif
default:
mousekey_send();
break;
}
mousekey_on(action.key.code);
mousekey_send();
} else {
mousekey_off(action.key.code);
switch (action.key.code) {
# ifdef PS2_MOUSE_ENABLE
case KC_MS_BTN1:
tp_buttons &= ~(1 << 0);
break;
Expand All @@ -408,11 +442,11 @@ void process_action(keyrecord_t *record, action_t action) {
case KC_MS_BTN3:
tp_buttons &= ~(1 << 2);
break;
# endif
default:
mousekey_send();
break;
}
mousekey_off(action.key.code);
mousekey_send();
}
break;
#endif
Expand Down Expand Up @@ -593,6 +627,16 @@ void process_action(keyrecord_t *record, action_t action) {
swap_hands = false;
}
break;
# ifndef NO_ACTION_ONESHOT
case OP_SH_ONESHOT:
if (event.pressed) {
set_oneshot_swaphands();
} else {
release_oneshot_swaphands();
}
break;
# endif

# ifndef NO_ACTION_TAPPING
case OP_SH_TAP_TOGGLE:
/* tap toggle */
Expand Down Expand Up @@ -658,7 +702,7 @@ void process_action(keyrecord_t *record, action_t action) {
#endif

#ifndef NO_ACTION_TAPPING
# ifdef RETRO_TAPPING
# if defined RETRO_TAPPING || defined RETRO_SHIFT
if (!is_tap_action(action)) {
retro_tapping_counter = 0;
} else {
Expand All @@ -672,7 +716,39 @@ void process_action(keyrecord_t *record, action_t action) {
retro_tapping_counter = 0;
} else {
if (retro_tapping_counter == 2) {
# ifdef RETRO_SHIFT
if(!(RETRO_SHIFT + 0) || TIMER_DIFF_16(event.time, retro_shift_start_time) < (RETRO_SHIFT + 0)){

switch (action.layer_tap.code) {
# ifndef NO_AUTO_SHIFT_ALPHA
case KC_A ... KC_Z:
# endif
# ifndef NO_AUTO_SHIFT_NUMERIC
case KC_1 ... KC_0:
# endif
# ifndef NO_AUTO_SHIFT_SPECIAL
case KC_TAB:
case KC_MINUS ... KC_SLASH:
case KC_NONUS_BSLASH:
# endif
# ifndef AUTO_SHIFT_MODIFIERS
if (get_mods()) {
tap_code(action.layer_tap.code);
break;
}
# endif
tap_code16(LSFT(action.layer_tap.code));
break;
default:
# ifdef RETRO_TAPPING
tap_code(action.layer_tap.code);
# endif
;
}
}
# else
tap_code(action.layer_tap.code);
# endif
}
retro_tapping_counter = 0;
}
Expand All @@ -681,6 +757,14 @@ void process_action(keyrecord_t *record, action_t action) {
# endif
#endif

#ifdef SWAP_HANDS_ENABLE
# ifndef NO_ACTION_ONESHOT
if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) {
use_oneshot_swaphands();
}
# endif
#endif

#ifndef NO_ACTION_ONESHOT
/* Because we switch layers after a oneshot event, we need to release the
* key before we leave the layer or no key up event will be generated.
Expand Down

0 comments on commit bb27a31

Please sign in to comment.