You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
5.7 KiB

  1. /* Copyright 2022 Jouke Witteveen
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "quantum.h"
  17. #include "examples.h"
  18. // Example code from the tap dance documentation, adapted for testing
  19. // clang-format off
  20. // Example 1
  21. void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
  22. if (state->count >= 100) {
  23. // SEND_STRING("Safety dance!");
  24. tap_code(KC_C);
  25. reset_tap_dance(state);
  26. }
  27. }
  28. // Example 2
  29. void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
  30. switch (state->count) {
  31. case 1:
  32. register_code(KC_3);
  33. break;
  34. case 2:
  35. register_code(KC_2);
  36. break;
  37. case 3:
  38. register_code(KC_1);
  39. break;
  40. case 4:
  41. unregister_code(KC_3);
  42. // wait_ms(50);
  43. unregister_code(KC_2);
  44. // wait_ms(50);
  45. unregister_code(KC_1);
  46. }
  47. }
  48. void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
  49. if (state->count >= 4) {
  50. // reset_keyboard();
  51. tap_code(KC_R);
  52. }
  53. }
  54. void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
  55. unregister_code(KC_1);
  56. // wait_ms(50);
  57. unregister_code(KC_2);
  58. // wait_ms(50);
  59. unregister_code(KC_3);
  60. }
  61. // Example 3
  62. typedef struct {
  63. uint16_t tap;
  64. uint16_t hold;
  65. uint16_t held;
  66. } tap_dance_tap_hold_t;
  67. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  68. qk_tap_dance_action_t *action;
  69. switch (keycode) {
  70. case TD(CT_CLN):
  71. action = &tap_dance_actions[TD_INDEX(keycode)];
  72. if (!record->event.pressed && action->state.count && !action->state.finished) {
  73. tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
  74. tap_code16(tap_hold->tap);
  75. }
  76. }
  77. return true;
  78. }
  79. void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
  80. tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
  81. if (state->pressed) {
  82. if (state->count == 1
  83. #ifndef PERMISSIVE_HOLD
  84. && !state->interrupted
  85. #endif
  86. ) {
  87. register_code16(tap_hold->hold);
  88. tap_hold->held = tap_hold->hold;
  89. } else {
  90. register_code16(tap_hold->tap);
  91. tap_hold->held = tap_hold->tap;
  92. }
  93. }
  94. }
  95. void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
  96. tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
  97. if (tap_hold->held) {
  98. unregister_code16(tap_hold->held);
  99. tap_hold->held = 0;
  100. }
  101. }
  102. #define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
  103. { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
  104. // Example 4
  105. typedef enum {
  106. TD_NONE,
  107. TD_UNKNOWN,
  108. TD_SINGLE_TAP,
  109. TD_SINGLE_HOLD,
  110. TD_DOUBLE_TAP,
  111. TD_DOUBLE_HOLD,
  112. TD_DOUBLE_SINGLE_TAP,
  113. TD_TRIPLE_TAP,
  114. TD_TRIPLE_HOLD
  115. } td_state_t;
  116. typedef struct {
  117. bool is_press_action;
  118. td_state_t state;
  119. } td_tap_t;
  120. td_state_t cur_dance(qk_tap_dance_state_t *state) {
  121. if (state->count == 1) {
  122. if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
  123. else return TD_SINGLE_HOLD;
  124. } else if (state->count == 2) {
  125. if (state->interrupted) return TD_DOUBLE_SINGLE_TAP;
  126. else if (state->pressed) return TD_DOUBLE_HOLD;
  127. else return TD_DOUBLE_TAP;
  128. }
  129. if (state->count == 3) {
  130. if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP;
  131. else return TD_TRIPLE_HOLD;
  132. } else return TD_UNKNOWN;
  133. }
  134. static td_tap_t xtap_state = {
  135. .is_press_action = true,
  136. .state = TD_NONE
  137. };
  138. void x_finished(qk_tap_dance_state_t *state, void *user_data) {
  139. xtap_state.state = cur_dance(state);
  140. switch (xtap_state.state) {
  141. case TD_SINGLE_TAP: register_code(KC_X); break;
  142. case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
  143. case TD_DOUBLE_TAP: register_code(KC_ESC); break;
  144. case TD_DOUBLE_HOLD: register_code(KC_LALT); break;
  145. case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
  146. default: break; // Not present in documentation
  147. }
  148. }
  149. void x_reset(qk_tap_dance_state_t *state, void *user_data) {
  150. switch (xtap_state.state) {
  151. case TD_SINGLE_TAP: unregister_code(KC_X); break;
  152. case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
  153. case TD_DOUBLE_TAP: unregister_code(KC_ESC); break;
  154. case TD_DOUBLE_HOLD: unregister_code(KC_LALT);
  155. case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X);
  156. default: break; // Not present in documentation
  157. }
  158. xtap_state.state = TD_NONE;
  159. }
  160. qk_tap_dance_action_t tap_dance_actions[] = {
  161. [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
  162. [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
  163. [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset),
  164. [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
  165. [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)
  166. };
  167. // clang-format on