X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=quantum%2Fprocess_keycode%2Fprocess_tap_dance.c;h=6ae362c4c2f32487040ae5041afeccf16aa4cf39;hb=41d7460f538a3b561aa4475c80dbcb602f476b94;hp=b9b836df2e97acb5a1f6618cdfaea4b40c6c439a;hpb=4e6a8627d8ebd7af942f68142d1a959d60361d90;p=qmk_firmware.git diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index b9b836df2..6ae362c4c 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -1,126 +1,136 @@ #include "quantum.h" +#include "action_tapping.h" -static qk_tap_dance_state_t qk_tap_dance_state; +static uint16_t last_td; +static int8_t highest_td = -1; -static void _process_tap_dance_action_pair (qk_tap_dance_state_t *state, - uint16_t kc1, uint16_t kc2) { - uint16_t kc; +void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { + qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; - if (state->count == 0) - return; - - kc = (state->count == 1) ? kc1 : kc2; + if (state->count == 1) { + register_code16 (pair->kc1); + } else if (state->count == 2) { + register_code16 (pair->kc2); + } +} - register_code (kc); - unregister_code (kc); +void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) { + qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; - if (state->count >= 2) { - reset_tap_dance (state); + if (state->count == 1) { + unregister_code16 (pair->kc1); + } else if (state->count == 2) { + unregister_code16 (pair->kc2); } } -static void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, - qk_tap_dance_user_fn_t fn) +static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, + void *user_data, + qk_tap_dance_user_fn_t fn) { if (fn) { - fn(state); + fn(state, user_data); } } -void process_tap_dance_action_on_each_tap (uint16_t keycode) +static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action) { - uint16_t idx = keycode - QK_TAP_DANCE; - qk_tap_dance_action_t action; - - action = tap_dance_actions[idx]; - - switch (action.type) { - case QK_TAP_DANCE_TYPE_FN: - _process_tap_dance_action_fn (&qk_tap_dance_state, action.fn.on_each_tap); - break; - - default: - break; - } + _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap); } -void process_tap_dance_action_on_dance_finished (uint16_t keycode) +static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action) { - uint16_t idx = keycode - QK_TAP_DANCE; - qk_tap_dance_action_t action; - - action = tap_dance_actions[idx]; - - switch (action.type) { - case QK_TAP_DANCE_TYPE_PAIR: - _process_tap_dance_action_pair (&qk_tap_dance_state, - action.pair.kc1, action.pair.kc2); - break; - case QK_TAP_DANCE_TYPE_FN: - _process_tap_dance_action_fn (&qk_tap_dance_state, action.fn.on_dance_finished); - break; + if (action->state.finished) + return; + action->state.finished = true; + _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished); +} - default: - break; - } +static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action) +{ + _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset); } bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { - bool r = true; + uint16_t idx = keycode - QK_TAP_DANCE; + qk_tap_dance_action_t *action; + + if (last_td && last_td != keycode) { + (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true; + } switch(keycode) { case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: - process_tap_dance_action_on_each_tap (qk_tap_dance_state.keycode); - if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) { - process_tap_dance_action_on_dance_finished (qk_tap_dance_state.keycode); - } else { - r = false; - } + if ((int16_t)idx > highest_td) + highest_td = idx; + action = &tap_dance_actions[idx]; + action->state.pressed = record->event.pressed; if (record->event.pressed) { - qk_tap_dance_state.keycode = keycode; - qk_tap_dance_state.timer = timer_read (); - qk_tap_dance_state.count++; + action->state.keycode = keycode; + action->state.count++; + action->state.timer = timer_read(); + process_tap_dance_action_on_each_tap (action); + + if (last_td && last_td != keycode) { + qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE]; + paction->state.interrupted = true; + process_tap_dance_action_on_dance_finished (paction); + reset_tap_dance (&paction->state); + } + + last_td = keycode; } + break; default: - if (qk_tap_dance_state.keycode) { - // if we are here, the tap dance was interrupted by a different key - process_tap_dance_action_on_each_tap (qk_tap_dance_state.keycode); - process_tap_dance_action_on_dance_finished (qk_tap_dance_state.keycode); - reset_tap_dance (&qk_tap_dance_state); + if (!record->event.pressed) + return true; + + if (highest_td == -1) + return true; + + for (int i = 0; i <= highest_td; i++) { + action = &tap_dance_actions[i]; + if (action->state.count == 0) + continue; + action->state.interrupted = true; + process_tap_dance_action_on_dance_finished (action); + reset_tap_dance (&action->state); } break; } - return r; + return true; } void matrix_scan_tap_dance () { - if (qk_tap_dance_state.keycode && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) { - // if we are here, the tap dance was timed out - process_tap_dance_action_on_dance_finished (qk_tap_dance_state.keycode); - reset_tap_dance (&qk_tap_dance_state); + if (highest_td == -1) + return; + + for (int i = 0; i <= highest_td; i++) { + qk_tap_dance_action_t *action = &tap_dance_actions[i]; + + if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) { + process_tap_dance_action_on_dance_finished (action); + reset_tap_dance (&action->state); + } } } void reset_tap_dance (qk_tap_dance_state_t *state) { - uint16_t idx = state->keycode - QK_TAP_DANCE; - qk_tap_dance_action_t action; - - action = tap_dance_actions[idx]; - switch (action.type) { - case QK_TAP_DANCE_TYPE_FN: - if (action.fn.on_reset) { - action.fn.on_reset(state); - } - break; + qk_tap_dance_action_t *action; - default: - break; - } + if (state->pressed) + return; + + action = &tap_dance_actions[state->keycode - QK_TAP_DANCE]; + + process_tap_dance_action_on_reset (action); - state->keycode = 0; state->count = 0; + state->interrupted = false; + state->finished = false; + last_td = 0; }