]> 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.
 
 
 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!
 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
 
 
 ## 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
 
 ```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;
 typedef struct {
   bool is_press_action;
   int state;
-} xtap;
+} tap;
 
 enum {
   SINGLE_TAP = 1,
 
 enum {
   SINGLE_TAP = 1,
@@ -225,27 +207,21 @@ enum {
 
 //Tap dance enums
 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);
 
 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
 
 ```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.
 /* 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)`.