]> git.donarmstrong.com Git - qmk_firmware.git/blob - users/konstantin/tap_dance.c
Update KBD67 readme so that it mentions the KBD65 PCB (#5143)
[qmk_firmware.git] / users / konstantin / tap_dance.c
1 #include "tap_dance.h"
2 #include "konstantin.h"
3
4 #define ACTION_TAP_DANCE_DOUBLE_MOD(mod1, mod2) {                   \
5     .fn        = { td_double_mod_each, NULL, td_double_mod_reset }, \
6     .user_data = &(qk_tap_dance_pair_t){ mod1, mod2 },              \
7   }
8
9 void td_double_mod_each(qk_tap_dance_state_t *state, void *user_data) {
10   qk_tap_dance_pair_t *data = (qk_tap_dance_pair_t *)user_data;
11
12   // Single tap → mod1, double tap → mod2, triple tap etc. → mod1+mod2
13   if (state->count == 1 || state->count == 3) {
14     register_code(data->kc1);
15   } else if (state->count == 2) {
16     unregister_code(data->kc1);
17     register_code(data->kc2);
18   }
19   // Prevent tap dance from sending the mods as weak mods
20   state->weak_mods &= ~(MOD_BIT(data->kc1) | MOD_BIT(data->kc2));
21 }
22
23 void td_double_mod_reset(qk_tap_dance_state_t *state, void *user_data) {
24   qk_tap_dance_pair_t *data = (qk_tap_dance_pair_t *)user_data;
25
26   if (state->count == 1 || state->count >= 3) {
27     unregister_code(data->kc1);
28   }
29   if (state->count >= 2) {
30     unregister_code(data->kc2);
31   }
32 }
33
34 #define ACTION_TAP_DANCE_MOD_LAYER(mod, layer) {                  \
35     .fn        = { td_mod_layer_each, NULL, td_mod_layer_reset }, \
36     .user_data = &(qk_tap_dance_dual_role_t){ mod, layer },       \
37   }
38
39 void td_mod_layer_each(qk_tap_dance_state_t *state, void *user_data) {
40   qk_tap_dance_dual_role_t *data = (qk_tap_dance_dual_role_t *)user_data;
41
42   // Single tap → mod, double tap → layer, triple tap etc. → mod+layer
43   if (state->count == 1 || state->count == 3) {
44     register_code(data->kc);
45   } else if (state->count == 2) {
46     unregister_code(data->kc);
47     // Prevent tap dance from sending the mod as a weak mod
48     state->weak_mods &= ~MOD_BIT(data->kc);
49     layer_on(data->layer);
50   }
51 }
52
53 void td_mod_layer_reset(qk_tap_dance_state_t *state, void *user_data) {
54   qk_tap_dance_dual_role_t *data = (qk_tap_dance_dual_role_t *)user_data;
55
56   if (state->count == 1 || state->count >= 3) {
57     unregister_code(data->kc);
58   }
59   if (state->count >= 2) {
60     layer_off(data->layer);
61   }
62 }
63
64 #define ACTION_TAP_DANCE_LAYER_MOD(layer, mod) {                  \
65     .fn        = { td_layer_mod_each, NULL, td_layer_mod_reset }, \
66     .user_data = &(qk_tap_dance_layer_mod_t){ layer, mod, 0, 0 }, \
67   }
68
69 typedef struct {
70   uint8_t  layer;
71   uint16_t kc;
72   bool     layer_on;  // Layer state when tap dance started
73   bool     started;
74 } qk_tap_dance_layer_mod_t;
75
76 void td_layer_mod_each(qk_tap_dance_state_t *state, void *user_data) {
77   qk_tap_dance_layer_mod_t *data = (qk_tap_dance_layer_mod_t *)user_data;
78   if (!data->started) {
79     data->layer_on = IS_LAYER_ON(data->layer);
80     data->started = true;
81   }
82
83   // Single tap → layer, double tap → mod, triple tap etc. → layer+mod
84   if (state->count == 1 || state->count == 3) {
85     layer_on(data->layer);
86   } else if (state->count == 2) {
87     if (!data->layer_on) {
88       layer_off(data->layer);
89     }
90     register_code(data->kc);
91   }
92 }
93
94 void td_layer_mod_reset(qk_tap_dance_state_t *state, void *user_data) {
95   qk_tap_dance_layer_mod_t *data = (qk_tap_dance_layer_mod_t *)user_data;
96
97   if ((state->count == 1 || state->count >= 3) && !data->layer_on) {
98     layer_off(data->layer);
99   }
100   if (state->count >= 2) {
101     unregister_code(data->kc);
102   }
103
104   data->started = false;
105 }
106
107 qk_tap_dance_action_t tap_dance_actions[] = {
108   [TD_DST_A_R] = ACTION_TAP_DANCE_DOUBLE(DST_ADD, DST_REM),
109
110   [TD_RAL_LAL] = ACTION_TAP_DANCE_DOUBLE_MOD(KC_RALT, KC_LALT),
111   [TD_RAL_RGU] = ACTION_TAP_DANCE_DOUBLE_MOD(KC_RALT, KC_RGUI),
112   [TD_RCT_RSF] = ACTION_TAP_DANCE_DOUBLE_MOD(KC_RCTL, KC_RSFT),
113
114   [TD_LSFT_FN] = ACTION_TAP_DANCE_MOD_LAYER(KC_LSFT, L_FN),
115   [TD_RCTL_FN] = ACTION_TAP_DANCE_MOD_LAYER(KC_RCTL, L_FN),
116   [TD_FN_RCTL] = ACTION_TAP_DANCE_LAYER_MOD(L_FN, KC_RCTL),
117 };