aboutsummaryrefslogtreecommitdiff
path: root/qmk/keyboards/sofle_choc/keymaps/custom/tap_hold_dance.c
diff options
context:
space:
mode:
Diffstat (limited to 'qmk/keyboards/sofle_choc/keymaps/custom/tap_hold_dance.c')
-rw-r--r--qmk/keyboards/sofle_choc/keymaps/custom/tap_hold_dance.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/tap_hold_dance.c b/qmk/keyboards/sofle_choc/keymaps/custom/tap_hold_dance.c
new file mode 100644
index 0000000..907a0f2
--- /dev/null
+++ b/qmk/keyboards/sofle_choc/keymaps/custom/tap_hold_dance.c
@@ -0,0 +1,103 @@
+#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;
+}