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