aboutsummaryrefslogtreecommitdiff
path: root/docs/feature_tap_dance.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/feature_tap_dance.md')
-rw-r--r--docs/feature_tap_dance.md83
1 files changed, 83 insertions, 0 deletions
diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md
index f2f274944..b5e5218b0 100644
--- a/docs/feature_tap_dance.md
+++ b/docs/feature_tap_dance.md
@@ -314,3 +314,86 @@ qk_tap_dance_action_t tap_dance_actions[] = {
314And then simply use `TD(X_CTL)` anywhere in your keymap. 314And then simply use `TD(X_CTL)` anywhere in your keymap.
315 315
316If you want to implement this in your userspace, then you may want to check out how [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) has implemented this in their userspace. 316If you want to implement this in your userspace, then you may want to check out how [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) has implemented this in their userspace.
317
318### Example 5: Using tap dance for advanced mod-tap and layer-tap keys
319
320Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`.
321
322Below your layers and custom keycodes, add the following:
323
324```c
325// tapdance keycodes
326enum td_keycodes {
327 ALT_LP // Our example key: `LALT` when held, `(` when tapped. Add additional keycodes for each tapdance.
328};
329
330// define a type containing as many tapdance states as you need
331typedef enum {
332 SINGLE_TAP,
333 SINGLE_HOLD,
334 DOUBLE_SINGLE_TAP
335} td_state_t;
336
337// create a global instance of the tapdance state type
338static td_state_t td_state;
339
340// declare your tapdance functions:
341
342// function to determine the current tapdance state
343int cur_dance (qk_tap_dance_state_t *state);
344
345// `finished` and `reset` functions for each tapdance keycode
346void altlp_finished (qk_tap_dance_state_t *state, void *user_data);
347void altlp_reset (qk_tap_dance_state_t *state, void *user_data);
348```
349
350Below your `LAYOUT`, define each of the tapdance functions:
351
352```c
353// determine the tapdance state to return
354int cur_dance (qk_tap_dance_state_t *state) {
355 if (state->count == 1) {
356 if (state->interrupted || !state->pressed) { return SINGLE_TAP; }
357 else { return SINGLE_HOLD; }
358 }
359 if (state->count == 2) { return DOUBLE_SINGLE_TAP; }
360 else { return 3; } // any number higher than the maximum state value you return above
361}
362
363// handle the possible states for each tapdance keycode you define:
364
365void altlp_finished (qk_tap_dance_state_t *state, void *user_data) {
366 td_state = cur_dance(state);
367 switch (td_state) {
368 case SINGLE_TAP:
369 register_code16(KC_LPRN);
370 break;
371 case SINGLE_HOLD:
372 register_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_on(_MY_LAYER)` here
373 break;
374 case DOUBLE_SINGLE_TAP: // allow nesting of 2 parens `((` within tapping term
375 tap_code16(KC_LPRN);
376 register_code16(KC_LPRN);
377 }
378}
379
380void altlp_reset (qk_tap_dance_state_t *state, void *user_data) {
381 switch (td_state) {
382 case SINGLE_TAP:
383 unregister_code16(KC_LPRN);
384 break;
385 case SINGLE_HOLD:
386 unregister_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_off(_MY_LAYER)` here
387 break;
388 case DOUBLE_SINGLE_TAP:
389 unregister_code16(KC_LPRN);
390 }
391}
392
393// define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions
394qk_tap_dance_action_t tap_dance_actions[] = {
395 [ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset)
396};
397```
398
399Wrap each tapdance keycode in `TD()` when including it in your keymap, e.g. `TD(ALT_LP)`.