examples.c (6720B)
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 17 #include "quantum.h" 18 #include "examples.h" 19 #include "keymap_introspection.h" 20 21 // Example code from the tap dance documentation, adapted for testing 22 23 // clang-format off 24 25 // Example 1 26 27 void dance_egg(tap_dance_state_t *state, void *user_data) { 28 if (state->count >= 100) { 29 // SEND_STRING("Safety dance!"); 30 tap_code(KC_C); 31 reset_tap_dance(state); 32 } 33 } 34 35 36 // Example 2 37 38 void dance_flsh_each(tap_dance_state_t *state, void *user_data) { 39 switch (state->count) { 40 case 1: 41 register_code(KC_3); 42 break; 43 case 2: 44 register_code(KC_2); 45 break; 46 case 3: 47 register_code(KC_1); 48 break; 49 case 4: 50 unregister_code(KC_3); 51 // wait_ms(50); 52 unregister_code(KC_2); 53 // wait_ms(50); 54 unregister_code(KC_1); 55 } 56 } 57 58 void dance_flsh_finished(tap_dance_state_t *state, void *user_data) { 59 if (state->count >= 4) { 60 // reset_keyboard(); 61 tap_code(KC_R); 62 } 63 } 64 65 void dance_flsh_reset(tap_dance_state_t *state, void *user_data) { 66 unregister_code(KC_1); 67 // wait_ms(50); 68 unregister_code(KC_2); 69 // wait_ms(50); 70 unregister_code(KC_3); 71 } 72 73 74 // Example 3 75 76 typedef struct { 77 uint16_t tap; 78 uint16_t hold; 79 uint16_t held; 80 } tap_dance_tap_hold_t; 81 82 bool process_record_user(uint16_t keycode, keyrecord_t *record) { 83 tap_dance_action_t *action; 84 tap_dance_state_t* state; 85 86 switch (keycode) { 87 case TD(CT_CLN): 88 action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode)); 89 state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode)); 90 if (!record->event.pressed && state != NULL && state->count && !state->finished) { 91 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data; 92 tap_code16(tap_hold->tap); 93 } 94 } 95 return true; 96 } 97 98 void tap_dance_tap_hold_finished(tap_dance_state_t *state, void *user_data) { 99 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; 100 101 if (state->pressed) { 102 if (state->count == 1 103 #ifndef PERMISSIVE_HOLD 104 && !state->interrupted 105 #endif 106 ) { 107 register_code16(tap_hold->hold); 108 tap_hold->held = tap_hold->hold; 109 } else { 110 register_code16(tap_hold->tap); 111 tap_hold->held = tap_hold->tap; 112 } 113 } 114 } 115 116 void tap_dance_tap_hold_reset(tap_dance_state_t *state, void *user_data) { 117 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; 118 119 if (tap_hold->held) { 120 unregister_code16(tap_hold->held); 121 tap_hold->held = 0; 122 } 123 } 124 125 #define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \ 126 { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), } 127 128 129 // Example 4 130 131 typedef enum { 132 TD_NONE, 133 TD_UNKNOWN, 134 TD_SINGLE_TAP, 135 TD_SINGLE_HOLD, 136 TD_DOUBLE_TAP, 137 TD_DOUBLE_HOLD, 138 TD_DOUBLE_SINGLE_TAP, 139 TD_TRIPLE_TAP, 140 TD_TRIPLE_HOLD 141 } td_state_t; 142 143 typedef struct { 144 bool is_press_action; 145 td_state_t state; 146 } td_tap_t; 147 148 td_state_t cur_dance(tap_dance_state_t *state) { 149 if (state->count == 1) { 150 if (state->interrupted || !state->pressed) return TD_SINGLE_TAP; 151 else return TD_SINGLE_HOLD; 152 } else if (state->count == 2) { 153 if (state->interrupted) return TD_DOUBLE_SINGLE_TAP; 154 else if (state->pressed) return TD_DOUBLE_HOLD; 155 else return TD_DOUBLE_TAP; 156 } 157 158 if (state->count == 3) { 159 if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP; 160 else return TD_TRIPLE_HOLD; 161 } else return TD_UNKNOWN; 162 } 163 164 static td_tap_t xtap_state = { 165 .is_press_action = true, 166 .state = TD_NONE 167 }; 168 169 void x_finished(tap_dance_state_t *state, void *user_data) { 170 xtap_state.state = cur_dance(state); 171 switch (xtap_state.state) { 172 case TD_SINGLE_TAP: register_code(KC_X); break; 173 case TD_SINGLE_HOLD: register_code(KC_LCTL); break; 174 case TD_DOUBLE_TAP: register_code(KC_ESC); break; 175 case TD_DOUBLE_HOLD: register_code(KC_LALT); break; 176 case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X); 177 default: break; // Not present in documentation 178 } 179 } 180 181 void x_reset(tap_dance_state_t *state, void *user_data) { 182 switch (xtap_state.state) { 183 case TD_SINGLE_TAP: unregister_code(KC_X); break; 184 case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break; 185 case TD_DOUBLE_TAP: unregister_code(KC_ESC); break; 186 case TD_DOUBLE_HOLD: unregister_code(KC_LALT); 187 case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X); 188 default: break; // Not present in documentation 189 } 190 xtap_state.state = TD_NONE; 191 } 192 193 static void release_press(tap_dance_state_t *state, void *user_data) { 194 tap_code16(KC_P); 195 } 196 197 static void release_unpress(tap_dance_state_t *state, void *user_data) { 198 tap_code16(KC_U); 199 } 200 201 static void release_unpress_mark_finished(tap_dance_state_t *state, void *user_data) { 202 tap_code16(KC_U); 203 state->finished = true; 204 } 205 206 static void release_finished(tap_dance_state_t *state, void *user_data) { 207 tap_code16(KC_F); 208 } 209 210 static void release_reset(tap_dance_state_t *state, void *user_data) { 211 tap_code16(KC_R); 212 } 213 214 tap_dance_action_t tap_dance_actions[] = { 215 [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS), 216 [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg), 217 [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset), 218 [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN), 219 [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset), 220 [TD_RELEASE] = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress, release_finished, release_reset), 221 [TD_RELEASE_AND_FINISH] = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress_mark_finished, release_finished, release_reset), 222 }; 223 224 // clang-format on