aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode/process_tap_dance.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/process_keycode/process_tap_dance.c')
-rw-r--r--quantum/process_keycode/process_tap_dance.c130
1 files changed, 66 insertions, 64 deletions
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index 5429e3438..07de3ecb8 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -1,26 +1,16 @@
1#include "quantum.h" 1#include "quantum.h"
2#include "action_tapping.h"
2 3
3static qk_tap_dance_state_t qk_tap_dance_state; 4static uint16_t last_td;
4bool td_debug_enable = false; 5static int8_t highest_td = -1;
5
6#if CONSOLE_ENABLE
7#define td_debug(s) if (td_debug_enable) \
8 { \
9 xprintf ("D:tap_dance:%s:%s = { keycode = %d, count = %d, active = %d, pressed = %d }\n", __FUNCTION__, s, \
10 qk_tap_dance_state.keycode, qk_tap_dance_state.count, \
11 qk_tap_dance_state.active, qk_tap_dance_state.pressed); \
12 }
13#else
14#define td_debug(s)
15#endif
16 6
17void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { 7void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
18 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 8 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
19 9
20 if (state->count == 1) { 10 if (state->count == 1) {
21 register_code (pair->kc1); 11 register_code16 (pair->kc1);
22 } else if (state->count == 2) { 12 } else if (state->count == 2) {
23 register_code (pair->kc2); 13 register_code16 (pair->kc2);
24 } 14 }
25} 15}
26 16
@@ -28,105 +18,117 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
28 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 18 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
29 19
30 if (state->count == 1) { 20 if (state->count == 1) {
31 unregister_code (pair->kc1); 21 unregister_code16 (pair->kc1);
32 } else if (state->count == 2) { 22 } else if (state->count == 2) {
33 unregister_code (pair->kc2); 23 unregister_code16 (pair->kc2);
34 } 24 }
35} 25}
36 26
37static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, 27static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
38 void *user_data, 28 void *user_data,
39 qk_tap_dance_user_fn_t fn) 29 qk_tap_dance_user_fn_t fn)
40{ 30{
41 if (fn) { 31 if (fn) {
42 fn(state, user_data); 32 fn(state, user_data);
43 } 33 }
44} 34}
45 35
46static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action) 36static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
47{ 37{
48 td_debug("trigger"); 38 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
49 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap);
50} 39}
51 40
52static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action) 41static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
53{ 42{
54 td_debug("trigger"); 43 if (action->state.finished)
55 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished); 44 return;
45 action->state.finished = true;
46 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
56} 47}
57 48
58static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action) 49static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
59{ 50{
60 td_debug("trigger") 51 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
61 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset);
62} 52}
63 53
64bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { 54bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
65 bool r = true;
66 uint16_t idx = keycode - QK_TAP_DANCE; 55 uint16_t idx = keycode - QK_TAP_DANCE;
67 qk_tap_dance_action_t action; 56 qk_tap_dance_action_t *action;
57
58 if (last_td && last_td != keycode) {
59 (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
60 }
68 61
69 switch(keycode) { 62 switch(keycode) {
70 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: 63 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
71 action = tap_dance_actions[idx]; 64 if ((int16_t)idx > highest_td)
72 65 highest_td = idx;
73 process_tap_dance_action_on_each_tap (action); 66 action = &tap_dance_actions[idx];
74 if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) {
75 process_tap_dance_action_on_dance_finished (action);
76 } else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) {
77 reset_tap_dance (&qk_tap_dance_state);
78 } else {
79 r = false;
80 }
81 67
82 qk_tap_dance_state.active = true; 68 action->state.keycode = keycode;
83 qk_tap_dance_state.pressed = record->event.pressed; 69 action->state.pressed = record->event.pressed;
84 if (record->event.pressed) { 70 if (record->event.pressed) {
85 qk_tap_dance_state.keycode = keycode; 71 action->state.count++;
86 qk_tap_dance_state.timer = timer_read (); 72 action->state.timer = timer_read();
87 qk_tap_dance_state.count++; 73
74 if (last_td && last_td != keycode) {
75 qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
76 paction->state.interrupted = true;
77 process_tap_dance_action_on_dance_finished (paction);
78 reset_tap_dance (&paction->state);
79 }
88 } 80 }
81 last_td = keycode;
82
89 break; 83 break;
90 84
91 default: 85 default:
92 if (qk_tap_dance_state.keycode) { 86 if (!record->event.pressed)
93 // if we are here, the tap dance was interrupted by a different key 87 return true;
94 idx = qk_tap_dance_state.keycode - QK_TAP_DANCE; 88
95 action = tap_dance_actions[idx]; 89 if (highest_td == -1)
90 return true;
96 91
97 process_tap_dance_action_on_each_tap (action); 92 for (int i = 0; i <= highest_td; i++) {
93 action = &tap_dance_actions[i];
94 if (action->state.count == 0)
95 continue;
96 action->state.interrupted = true;
98 process_tap_dance_action_on_dance_finished (action); 97 process_tap_dance_action_on_dance_finished (action);
99 reset_tap_dance (&qk_tap_dance_state); 98 reset_tap_dance (&action->state);
100 qk_tap_dance_state.active = false;
101 } 99 }
102 break; 100 break;
103 } 101 }
104 102
105 return r; 103 return true;
106} 104}
107 105
108void matrix_scan_tap_dance () { 106void matrix_scan_tap_dance () {
109 if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) { 107 if (highest_td == -1)
110 // if we are here, the tap dance was timed out 108 return;
111 uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE; 109
112 qk_tap_dance_action_t action = tap_dance_actions[idx]; 110 for (int i = 0; i <= highest_td; i++) {
111 qk_tap_dance_action_t *action = &tap_dance_actions[i];
113 112
114 process_tap_dance_action_on_dance_finished (action); 113 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
115 reset_tap_dance (&qk_tap_dance_state); 114 process_tap_dance_action_on_dance_finished (action);
115 reset_tap_dance (&action->state);
116 }
116 } 117 }
117} 118}
118 119
119void reset_tap_dance (qk_tap_dance_state_t *state) { 120void reset_tap_dance (qk_tap_dance_state_t *state) {
120 uint16_t idx = state->keycode - QK_TAP_DANCE; 121 qk_tap_dance_action_t *action;
121 qk_tap_dance_action_t action;
122 122
123 if (state->pressed) 123 if (state->pressed)
124 return; 124 return;
125 125
126 action = tap_dance_actions[idx]; 126 action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
127
127 process_tap_dance_action_on_reset (action); 128 process_tap_dance_action_on_reset (action);
128 129
129 state->keycode = 0;
130 state->count = 0; 130 state->count = 0;
131 state->active = false; 131 state->interrupted = false;
132 state->finished = false;
133 last_td = 0;
132} 134}