]> git.donarmstrong.com Git - qmk_firmware.git/blobdiff - docs/feature_tap_dance.md
[Keyboard] leds in default keymap (#6357)
[qmk_firmware.git] / docs / feature_tap_dance.md
index 99298fbda83bb66ee14ab5217ef6fd3bd0f290cd..b5e5218b093d01c7ad8c99bf79c76efbebf2d345 100644 (file)
@@ -26,6 +26,8 @@ This array specifies what actions shall be taken when a tap-dance key is in acti
 
 The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
 
+!> Keep in mind that only [basic keycodes](keycodes_basic.md) are supported here. Custom keycodes are not supported.
+
 And that's the bulk of it!
 
 And now, on to the explanation of how it works!
@@ -183,35 +185,15 @@ Below is a specific example:
 
 ## Setup
 
-You will need a few things that can be used for 'Quad Function Tap-Dance'. The suggested setup is to create a user directory for yourself. This directory will contain rules.mk `<your_name>.c` and `<your_name>.h`. This directory should be called `<your_name>`, and located in the top level `users` directory. There should already be a few examples to look at there.
-
-### In `/qmk_firmware/users/<your_name>/rules.mk`
-
-Put the following:
-```c
-TAP_DANCE_ENABLE = yes
-SRC += your_name.c
-```
-
-Pretty simple. It is a nice way to keep some rules common on all your keymaps.
+You will need a few things that can be used for 'Quad Function Tap-Dance'. 
 
-
-### In `/qmk_firmware/users/<your_name>/<you_name>.h`
-
-You will need a few things in this file:
+You'll need to add these to the top of your `keymap.c` file, before your keymap. 
 
 ```c
-#ifndef YOUR_NAME
-#define YOUR_NAME
-
-#include "quantum.h"
-#include "process_keycode/process_tap_dance.h"
-
-
 typedef struct {
   bool is_press_action;
   int state;
-} xtap;
+} tap;
 
 enum {
   SINGLE_TAP = 1,
@@ -225,27 +207,21 @@ enum {
 
 //Tap dance enums
 enum {
-    CTL_X = 0,
-    SOME_OTHER_DANCE
-}
+  X_CTL = 0,
+  SOME_OTHER_DANCE
+};
 
 int cur_dance (qk_tap_dance_state_t *state);
 
 //for the x tap dance. Put it here so it can be used in any keymap
 void x_finished (qk_tap_dance_state_t *state, void *user_data);
 void x_reset (qk_tap_dance_state_t *state, void *user_data);
-```
 
-### In `/qmk_firmware/users/<your_name>/<your_name>.c`
+```
 
-And then in your user's `.c` file you implement the functions above:
+Now, at the bottom of your `keymap.c` file, you'll need to add the following: 
 
 ```c
-#include "gordon.h"
-#include "quantum.h"
-#include "action.h"
-#include "process_keycode/process_tap_dance.h"
-
 /* Return an integer that corresponds to what kind of tap dance should be executed.
  *
  * How to figure out tap dance state: interrupted and pressed.
@@ -335,4 +311,89 @@ qk_tap_dance_action_t tap_dance_actions[] = {
 };
 ```
 
-And then simply use TD(X_CTL) anywhere in your keymap.
+And then simply use `TD(X_CTL)` anywhere in your keymap.
+
+If 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.
+
+### Example 5: Using tap dance for advanced mod-tap and layer-tap keys
+
+Tap 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`.
+
+Below your layers and custom keycodes, add the following:
+
+```c
+// tapdance keycodes
+enum td_keycodes {
+  ALT_LP // Our example key: `LALT` when held, `(` when tapped. Add additional keycodes for each tapdance.
+};
+
+// define a type containing as many tapdance states as you need
+typedef enum {
+  SINGLE_TAP,
+  SINGLE_HOLD,
+  DOUBLE_SINGLE_TAP
+} td_state_t;
+
+// create a global instance of the tapdance state type
+static td_state_t td_state;
+
+// declare your tapdance functions:
+
+// function to determine the current tapdance state
+int cur_dance (qk_tap_dance_state_t *state);
+
+// `finished` and `reset` functions for each tapdance keycode
+void altlp_finished (qk_tap_dance_state_t *state, void *user_data);
+void altlp_reset (qk_tap_dance_state_t *state, void *user_data);
+```
+
+Below your `LAYOUT`, define each of the tapdance functions:
+
+```c
+// determine the tapdance state to return
+int cur_dance (qk_tap_dance_state_t *state) {
+  if (state->count == 1) {
+    if (state->interrupted || !state->pressed) { return SINGLE_TAP; }
+    else { return SINGLE_HOLD; }
+  }
+  if (state->count == 2) { return DOUBLE_SINGLE_TAP; }
+  else { return 3; } // any number higher than the maximum state value you return above
+}
+// handle the possible states for each tapdance keycode you define:
+
+void altlp_finished (qk_tap_dance_state_t *state, void *user_data) {
+  td_state = cur_dance(state);
+  switch (td_state) {
+    case SINGLE_TAP:
+      register_code16(KC_LPRN);
+      break;
+    case SINGLE_HOLD:
+      register_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_on(_MY_LAYER)` here
+      break;
+    case DOUBLE_SINGLE_TAP: // allow nesting of 2 parens `((` within tapping term
+      tap_code16(KC_LPRN);
+      register_code16(KC_LPRN);
+  }
+}
+
+void altlp_reset (qk_tap_dance_state_t *state, void *user_data) {
+  switch (td_state) {
+    case SINGLE_TAP:
+      unregister_code16(KC_LPRN);
+      break;
+    case SINGLE_HOLD:
+      unregister_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_off(_MY_LAYER)` here
+      break;
+    case DOUBLE_SINGLE_TAP:
+      unregister_code16(KC_LPRN);
+  }
+}
+
+// define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions
+qk_tap_dance_action_t tap_dance_actions[] = {
+  [ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset)
+};
+```
+
+Wrap each tapdance keycode in `TD()` when including it in your keymap, e.g. `TD(ALT_LP)`.