Parent directory

examples.c

6613 bytes
  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
 27void 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
 38void 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
 58void 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
 65void 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
 76typedef struct {
 77    uint16_t tap;
 78    uint16_t hold;
 79    uint16_t held;
 80} tap_dance_tap_hold_t;
 81
 82bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 83    tap_dance_action_t *action;
 84
 85    switch (keycode) {
 86        case TD(CT_CLN):
 87            action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
 88            if (!record->event.pressed && action->state.count && !action->state.finished) {
 89                tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
 90                tap_code16(tap_hold->tap);
 91            }
 92    }
 93    return true;
 94}
 95
 96void tap_dance_tap_hold_finished(tap_dance_state_t *state, void *user_data) {
 97    tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
 98
 99    if (state->pressed) {
100        if (state->count == 1
101#ifndef PERMISSIVE_HOLD
102            && !state->interrupted
103#endif
104        ) {
105            register_code16(tap_hold->hold);
106            tap_hold->held = tap_hold->hold;
107        } else {
108            register_code16(tap_hold->tap);
109            tap_hold->held = tap_hold->tap;
110        }
111    }
112}
113
114void tap_dance_tap_hold_reset(tap_dance_state_t *state, void *user_data) {
115    tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
116
117    if (tap_hold->held) {
118        unregister_code16(tap_hold->held);
119        tap_hold->held = 0;
120    }
121}
122
123#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
124    { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
125
126
127// Example 4
128
129typedef enum {
130    TD_NONE,
131    TD_UNKNOWN,
132    TD_SINGLE_TAP,
133    TD_SINGLE_HOLD,
134    TD_DOUBLE_TAP,
135    TD_DOUBLE_HOLD,
136    TD_DOUBLE_SINGLE_TAP,
137    TD_TRIPLE_TAP,
138    TD_TRIPLE_HOLD
139} td_state_t;
140
141typedef struct {
142    bool is_press_action;
143    td_state_t state;
144} td_tap_t;
145
146td_state_t cur_dance(tap_dance_state_t *state) {
147    if (state->count == 1) {
148        if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
149        else return TD_SINGLE_HOLD;
150    } else if (state->count == 2) {
151        if (state->interrupted) return TD_DOUBLE_SINGLE_TAP;
152        else if (state->pressed) return TD_DOUBLE_HOLD;
153        else return TD_DOUBLE_TAP;
154    }
155
156    if (state->count == 3) {
157        if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP;
158        else return TD_TRIPLE_HOLD;
159    } else return TD_UNKNOWN;
160}
161
162static td_tap_t xtap_state = {
163    .is_press_action = true,
164    .state = TD_NONE
165};
166
167void x_finished(tap_dance_state_t *state, void *user_data) {
168    xtap_state.state = cur_dance(state);
169    switch (xtap_state.state) {
170        case TD_SINGLE_TAP: register_code(KC_X); break;
171        case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
172        case TD_DOUBLE_TAP: register_code(KC_ESC); break;
173        case TD_DOUBLE_HOLD: register_code(KC_LALT); break;
174        case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
175        default: break;  // Not present in documentation
176    }
177}
178
179void x_reset(tap_dance_state_t *state, void *user_data) {
180    switch (xtap_state.state) {
181        case TD_SINGLE_TAP: unregister_code(KC_X); break;
182        case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
183        case TD_DOUBLE_TAP: unregister_code(KC_ESC); break;
184        case TD_DOUBLE_HOLD: unregister_code(KC_LALT);
185        case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X);
186        default: break;  // Not present in documentation
187    }
188    xtap_state.state = TD_NONE;
189}
190
191static void release_press(tap_dance_state_t *state, void *user_data) {
192    tap_code16(KC_P);
193}
194
195static void release_unpress(tap_dance_state_t *state, void *user_data) {
196    tap_code16(KC_U);
197}
198
199static void release_unpress_mark_finished(tap_dance_state_t *state, void *user_data) {
200    tap_code16(KC_U);
201    state->finished = true;
202}
203
204static void release_finished(tap_dance_state_t *state, void *user_data) {
205    tap_code16(KC_F);
206}
207
208static void release_reset(tap_dance_state_t *state, void *user_data) {
209    tap_code16(KC_R);
210}
211
212tap_dance_action_t tap_dance_actions[] = {
213    [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
214    [CT_EGG]      = ACTION_TAP_DANCE_FN(dance_egg),
215    [CT_FLSH]     = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset),
216    [CT_CLN]      = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
217    [X_CTL]       = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset),
218    [TD_RELEASE]  = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress, release_finished, release_reset),
219    [TD_RELEASE_AND_FINISH]  = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress_mark_finished, release_finished, release_reset),
220};
221
222// clang-format on