LUFA USB descriptor cleanup (#4871)
[jackhill/qmk/firmware.git] / docs / feature_combo.md
CommitLineData
a7d05820
DJ
1# Combos
2
3The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the tapping term would hit `ESC` instead, or have it perform even more complex tasks.
4
57540af1 5To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`.
a7d05820
DJ
6
7Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using).
8<!-- At this time, this is necessary -->
9
10Also, by default, the tapping term for the Combos is set to the same value as `TAPPING_TERM` (200 by default on most boards). But you can specify a different value by defining it in your `config.h`. For instance: `#define COMBO_TERM 300` would set the time out period for combos to 300ms.
11
12Then, your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and it's resulting action.
13
14```c
15const uint16_t PROGMEM test_combo[] = {KC_A, KC_B, COMBO_END};
16combo_t key_combos[COMBO_COUNT] = {COMBO(test_combo, KC_ESC)};
17```
18
19This will send "Escape" if you hit the A and B keys.
20
21!> This method only supports [basic keycodes](keycodes_basic.md). See the examples for more control.
22
23## Examples
24
25If you want to add a list, then you'd use something like this:
26
27```c
28enum combos {
29 AB_ESC,
30 JK_TAB
e251850c 31};
b2f79159 32
a7d05820
DJ
33const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
34const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
35
36combo_t key_combos[COMBO_COUNT] = {
37 [AB_ESC] = COMBO(ab_combo, KC_ESC),
38 [JK_TAB] = COMBO(jk_combo, KC_TAB)
39};
40```
41
42For a more complicated implementation, you can use the `process_combo_event` function to add custom handling.
43
44```c
45enum combo_events {
46 ZC_COPY,
26a201e6 47 XV_PASTE
b2f79159 48};
a7d05820
DJ
49
50const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END};
26a201e6 51const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END};
a7d05820
DJ
52
53combo_t key_combos[COMBO_COUNT] = {
54 [ZC_COPY] = COMBO_ACTION(copy_combo),
26a201e6 55 [XV_PASTE] = COMBO_ACTION(paste_combo),
a7d05820
DJ
56};
57
58void process_combo_event(uint8_t combo_index, bool pressed) {
59 switch(combo_index) {
60 case ZC_COPY:
61 if (pressed) {
c44fc682 62 tap_code16(LCTL(KC_C));
a7d05820
DJ
63 }
64 break;
26a201e6 65 case XV_PASTE:
a7d05820 66 if (pressed) {
c44fc682 67 tap_code16(LCTL(KC_V));
a7d05820
DJ
68 }
69 break;
70 }
71}
72```
73
26a201e6 74This will send Ctrl+C if you hit Z and C, and Ctrl+V if you hit X and V. But you could change this to do stuff like change layers, play sounds, or change settings.
a7d05820
DJ
75
76## Additional Configuration
77
78If you're using long combos, or even longer combos, you may run into issues with this, as the structure may not be large enough to accommodate what you're doing.
79
80In this case, you can add either `#define EXTRA_LONG_COMBOS` or `#define EXTRA_EXTRA_LONG_COMBOS` in your `config.h` file.
81
82You may also be able to enable action keys by defining `COMBO_ALLOW_ACTION_KEYS`.
c44fc682
DJ
83
84## Keycodes
85
86You can enable, disable and toggle the Combo feature on the fly. This is useful if you need to disable them temporarily, such as for a game.
87
88|Keycode |Description |
89|----------|---------------------------------|
90|`CMB_ON` |Turns on Combo feature |
91|`CMB_OFF` |Turns off Combo feature |
92|`CMB_TOG` |Toggles Combo feature on and off |
93
94## User callbacks
95
96In addition to the keycodes, there are a few functions that you can use to set the status, or check it:
97
98|Function |Description |
99|-----------|--------------------------------------------------------------------|
100| `combo_enable()` | Enables the combo feature |
101| `combo_disable()` | Disables the combo feature, and clears the combo buffer |
102| `combo_toggle()` | Toggles the state of the combo feature |
103| `is_combo_enabled()` | Returns the status of the combo feature state (true or false) |