process_tap_dance.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "quantum.h"
  2. #include "action_tapping.h"
  3. static uint16_t last_td;
  4. static int8_t highest_td = -1;
  5. void 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;
  7. if (state->count == 1) {
  8. register_code16 (pair->kc1);
  9. } else if (state->count == 2) {
  10. register_code16 (pair->kc2);
  11. }
  12. }
  13. void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
  14. qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
  15. if (state->count == 1) {
  16. unregister_code16 (pair->kc1);
  17. } else if (state->count == 2) {
  18. unregister_code16 (pair->kc2);
  19. }
  20. }
  21. static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
  22. void *user_data,
  23. qk_tap_dance_user_fn_t fn)
  24. {
  25. if (fn) {
  26. fn(state, user_data);
  27. }
  28. }
  29. static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
  30. {
  31. _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
  32. }
  33. static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
  34. {
  35. if (action->state.finished)
  36. return;
  37. action->state.finished = true;
  38. _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
  39. }
  40. static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
  41. {
  42. _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
  43. }
  44. bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
  45. uint16_t idx = keycode - QK_TAP_DANCE;
  46. qk_tap_dance_action_t *action;
  47. if (last_td && last_td != keycode) {
  48. (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
  49. }
  50. switch(keycode) {
  51. case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
  52. if ((int16_t)idx > highest_td)
  53. highest_td = idx;
  54. action = &tap_dance_actions[idx];
  55. action->state.pressed = record->event.pressed;
  56. if (record->event.pressed) {
  57. action->state.keycode = keycode;
  58. action->state.count++;
  59. action->state.timer = timer_read();
  60. process_tap_dance_action_on_each_tap (action);
  61. if (last_td && last_td != keycode) {
  62. qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
  63. paction->state.interrupted = true;
  64. process_tap_dance_action_on_dance_finished (paction);
  65. reset_tap_dance (&paction->state);
  66. }
  67. last_td = keycode;
  68. }
  69. break;
  70. default:
  71. if (!record->event.pressed)
  72. return true;
  73. if (highest_td == -1)
  74. return true;
  75. for (int i = 0; i <= highest_td; i++) {
  76. action = &tap_dance_actions[i];
  77. if (action->state.count == 0)
  78. continue;
  79. action->state.interrupted = true;
  80. process_tap_dance_action_on_dance_finished (action);
  81. reset_tap_dance (&action->state);
  82. }
  83. break;
  84. }
  85. return true;
  86. }
  87. void matrix_scan_tap_dance () {
  88. if (highest_td == -1)
  89. return;
  90. for (int i = 0; i <= highest_td; i++) {
  91. qk_tap_dance_action_t *action = &tap_dance_actions[i];
  92. if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
  93. process_tap_dance_action_on_dance_finished (action);
  94. reset_tap_dance (&action->state);
  95. }
  96. }
  97. }
  98. void reset_tap_dance (qk_tap_dance_state_t *state) {
  99. qk_tap_dance_action_t *action;
  100. if (state->pressed)
  101. return;
  102. action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
  103. process_tap_dance_action_on_reset (action);
  104. state->count = 0;
  105. state->interrupted = false;
  106. state->finished = false;
  107. last_td = 0;
  108. }