Update to tap dance docs (#2895)
* Added more comments * Documentation for 'quad function' tap dance now suggests to use the user's directory, and explains how to do so.master
parent
1806509ad5
commit
e6be4484e9
|
@ -179,42 +179,124 @@ Below is a specific example:
|
||||||
* Double Tap = Send `Escape`
|
* Double Tap = Send `Escape`
|
||||||
* Double Tap and Hold = Send `Alt`
|
* Double Tap and Hold = Send `Alt`
|
||||||
|
|
||||||
The following example can be easily expanded to more than 4 quite easily:
|
## 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
|
```c
|
||||||
//**************** Definitions needed for quad function to work *********************//
|
TAP_DANCE_ENABLE = yes
|
||||||
//Enums used to clearly convey the state of the tap dance
|
SRC += your_name.c
|
||||||
|
```
|
||||||
|
|
||||||
|
Pretty simple. It is a nice way to keep some rules common on all your keymaps.
|
||||||
|
|
||||||
|
|
||||||
|
### In `/qmk_firmware/users/<your_name>/<you_name>.h`
|
||||||
|
|
||||||
|
You will need a few things in this file:
|
||||||
|
|
||||||
|
```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;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SINGLE_TAP = 1,
|
SINGLE_TAP = 1,
|
||||||
SINGLE_HOLD = 2,
|
SINGLE_HOLD = 2,
|
||||||
DOUBLE_TAP = 3,
|
DOUBLE_TAP = 3,
|
||||||
DOUBLE_HOLD = 4,
|
DOUBLE_HOLD = 4,
|
||||||
DOUBLE_SINGLE_TAP = 5 //send SINGLE_TAP twice - NOT DOUBLE_TAP
|
DOUBLE_SINGLE_TAP = 5, //send two single taps
|
||||||
// Add more enums here if you want for triple, quadruple, etc.
|
TRIPLE_TAP = 6,
|
||||||
|
TRIPLE_HOLD = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
//Tap dance enums
|
||||||
bool is_press_action;
|
enum {
|
||||||
int state;
|
CTL_X = 0,
|
||||||
} tap;
|
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:
|
||||||
|
|
||||||
|
```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.
|
||||||
|
*
|
||||||
|
* Interrupted: If the state of a dance dance is "interrupted", that means that another key has been hit
|
||||||
|
* under the tapping term. This is typically indicitive that you are trying to "tap" the key.
|
||||||
|
*
|
||||||
|
* Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term
|
||||||
|
* has ended, but the key is still being pressed down. This generally means the key is being "held".
|
||||||
|
*
|
||||||
|
* One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold"
|
||||||
|
* feature. In general, advanced tap dances do not work well if they are used with commonly typed letters.
|
||||||
|
* For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters.
|
||||||
|
*
|
||||||
|
* Good places to put an advanced tap dance:
|
||||||
|
* z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon
|
||||||
|
*
|
||||||
|
* Criteria for "good placement" of a tap dance key:
|
||||||
|
* Not a key that is hit frequently in a sentence
|
||||||
|
* Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or
|
||||||
|
* in a web form. So 'tab' would be a poor choice for a tap dance.
|
||||||
|
* Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the
|
||||||
|
* letter 'p', the word 'pepper' would be quite frustating to type.
|
||||||
|
*
|
||||||
|
* For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested
|
||||||
|
*
|
||||||
|
*/
|
||||||
int cur_dance (qk_tap_dance_state_t *state) {
|
int cur_dance (qk_tap_dance_state_t *state) {
|
||||||
if (state->count == 1) {
|
if (state->count == 1) {
|
||||||
//If count = 1, and it has been interrupted - it doesn't matter if it is pressed or not: Send SINGLE_TAP
|
if (state->interrupted || !state->pressed) return SINGLE_TAP;
|
||||||
if (state->interrupted || state->pressed==0) return SINGLE_TAP;
|
//key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'.
|
||||||
else return SINGLE_HOLD;
|
else return SINGLE_HOLD;
|
||||||
}
|
}
|
||||||
//If count = 2, and it has been interrupted - assume that user is trying to type the letter associated
|
|
||||||
//with single tap. In example below, that means to send `xx` instead of `Escape`.
|
|
||||||
else if (state->count == 2) {
|
else if (state->count == 2) {
|
||||||
|
/*
|
||||||
|
* DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
|
||||||
|
* action when hitting 'pp'. Suggested use case for this return value is when you want to send two
|
||||||
|
* keystrokes of the key, and not the 'double tap' action/macro.
|
||||||
|
*/
|
||||||
if (state->interrupted) return DOUBLE_SINGLE_TAP;
|
if (state->interrupted) return DOUBLE_SINGLE_TAP;
|
||||||
else if (state->pressed) return DOUBLE_HOLD;
|
else if (state->pressed) return DOUBLE_HOLD;
|
||||||
else return DOUBLE_TAP;
|
else return DOUBLE_TAP;
|
||||||
}
|
}
|
||||||
else return 6; //magic number. At some point this method will expand to work for more presses
|
//Assumes no one is trying to type the same letter three times (at least not quickly).
|
||||||
|
//If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
|
||||||
|
//an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
|
||||||
|
if (state->count == 3) {
|
||||||
|
if (state->interrupted || !state->pressed) return TRIPLE_TAP;
|
||||||
|
else return TRIPLE_HOLD;
|
||||||
|
}
|
||||||
|
else return 8; //magic number. At some point this method will expand to work for more presses
|
||||||
}
|
}
|
||||||
|
|
||||||
//**************** Definitions needed for quad function to work *********************//
|
|
||||||
|
|
||||||
//instanalize an instance of 'tap' for the 'x' tap dance.
|
//instanalize an instance of 'tap' for the 'x' tap dance.
|
||||||
static tap xtap_state = {
|
static tap xtap_state = {
|
||||||
.is_press_action = true,
|
.is_press_action = true,
|
||||||
|
@ -245,6 +327,10 @@ void x_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||||
}
|
}
|
||||||
xtap_state.state = 0;
|
xtap_state.state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||||
|
[X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL,x_finished, x_reset)
|
||||||
|
};
|
||||||
```
|
```
|
||||||
And then simply add this to your list of tap dance functions:
|
|
||||||
`[X_TAP_DANCE] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)`
|
And then simply use TD(X_CTL) anywhere in your keymap.
|
||||||
|
|
Loading…
Reference in New Issue