#include QMK_KEYBOARD_H #include "quad_tapdance.h" #include "tap_hold_dance.h" /* timer for last keyboard activity, use 32bit value and function to make * longer idle time possible */ static uint32_t key_timer; uint16_t tap_hold_dance_tapping_term(uint16_t keycode, keyrecord_t *record) { /* * If no keys where pressed before, reduce the time before activating the * tapdance. * The feedback is given with the LED in the keyboard. */ if (timer_elapsed32(key_timer) > (TAPPING_TERM * 2)) { return TAPPING_TERM / 2; } return TAPPING_TERM; } bool is_blocking_keycode(uint16_t keycode) { uint8_t current_layer = get_highest_layer(layer_state); if (current_layer != LAYER_BASE) { return false; } switch (keycode) { /* List the keys to ignore and should not considered inside a typing * session. */ case LY_KEYPAD: case LY_ARROW: case KC_ESC: case KC_RIGHT: case KEY_DOWN: case KC_LEFT ... KC_UP: case KC_PGUP: case KC_PGDN: case KEY_PGDN: case KC_HOME: case KC_END: case KC_TAB: return false; case AL_ENT: case KC_BSPC: case KC_DELETE: case KC_A ... KC_0: default: return true; } } void tap_hold_dance_process_record(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { return; } if (is_blocking_keycode(keycode)) key_timer = timer_read32(); } void tap_hold_dance_released(tap_dance_state_t *state, void *user_data) { if (state->finished || state->interrupted) return; tap_hold_dance_t *tap_hold_dance = (tap_hold_dance_t *)user_data; tap_code(tap_hold_dance->tap); } void tap_hold_dance_finished(tap_dance_state_t *state, void *user_data) { tap_hold_dance_t *tap_hold_dance = (tap_hold_dance_t *)user_data; tap_hold_dance->state = cur_dance(state); switch (tap_hold_dance->state) { case TD_SINGLE_HOLD: /* If a key is pressed before the TAPPING_TERM delay, consider a * tap instead of switching to the mod. */ if (state->interrupted && is_blocking_keycode(state->interrupting_keycode)) { tap_hold_dance->held = tap_hold_dance->tap; } else { tap_hold_dance->held = tap_hold_dance->hold; } register_code(tap_hold_dance->held); break; case TD_DOUBLE_HOLD: tap_hold_dance->held = tap_hold_dance->tap; register_code(tap_hold_dance->tap); default: break; } } void tap_hold_dance_reset(tap_dance_state_t *state, void *user_data) { tap_hold_dance_t *tap_hold_dance = (tap_hold_dance_t *)user_data; if (tap_hold_dance->state != TD_NONE && tap_hold_dance->held) { unregister_code(tap_hold_dance->held); tap_hold_dance->held = 0; } tap_hold_dance->state = TD_NONE; }