|
@@ -314,3 +314,86 @@ qk_tap_dance_action_t tap_dance_actions[] = {
|
|
|
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)`.
|