diff options
Diffstat (limited to 'docs')
41 files changed, 931 insertions, 315 deletions
diff --git a/docs/ChangeLog/20230226/PR15741.md b/docs/ChangeLog/20230226/PR15741.md new file mode 100644 index 0000000000..385816d65b --- /dev/null +++ b/docs/ChangeLog/20230226/PR15741.md @@ -0,0 +1,43 @@ +`IGNORE_MOD_TAP_INTERRUPT_PER_KEY` has been removed and `IGNORE_MOD_TAP_INTERRUPT` deprecated as a stepping stone towards making `IGNORE_MOD_TAP_INTERRUPT` the new default behavior for mod-taps in the future. + +In place of the now removed `IGNORE_MOD_TAP_INTERRUPT_PER_KEY`, one must use the pre-existing `HOLD_ON_OTHER_KEY_PRESS` option. + +In most cases, updating `get_ignore_mod_tap_interrupt` to `get_hold_on_other_key_press` is simply a matter of renaming the function and swapping every `true` by `false` and vice versa. The one subtlety you may need to look out for is that the `get_ignore_mod_tap_interrupt` was only ever called with mod-taps passed in as the `keycode` argument, while the `keycode` argument of `get_hold_on_other_key_press` can be any dual-role key. This includes not only mod-taps, but also layer-taps, one shot keys, `TT(layer)` and more. This has an impact on the effect of the `default` case in a typical per-key configuration making use of a `switch(keycode)` statement. + +To illustrate, let's take the example of a configuration where we'd want all mod-taps to activate the modifier if another key is pressed while held with the exception of `LCTL_T(KC_A)`, which should ignore keys pressed while it is held and activate the modifier only if it has been held for longer than the tapping term. In addition, we would like to keep the default "ignore-interrupt" behavior of layer taps. + +An old way to do this would be via the following code: + +```c +bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { + switch(keycode) { + case LCTL_T(KC_A): + return true; + default: + return false; + } +} +``` + +The correct way to update this code without accidentally changing how the layer-taps work would be the following: + +```c +bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { + switch(keycode) { + // Capture all mod-tap keycodes. + case QK_MOD_TAP ... QK_MOD_TAP_MAX: + if (keycode == LCTL_T(KC_A)) { + // Disable HOLD_ON_OTHER_KEY_PRESS for LCTL_T(KC_A) + // aka enable IGNORE_MOD_TAP_INTERRUPT for LCTL_T(KC_A). + return false; + } else { + // Enable HOLD_ON_OTHER_KEY_PRESS for every other mod-tap keycode. + return true; + } + default: + return false; + } +} +``` + +For more information, you are invited to read the sections on [IGNORE_MOD_TAP_INTERRUPT](tap_hold.md#ignore-mod-tap-interrupt) and [HOLD_ON_OTHER_KEY_PRESS](tap_hold.md#hold-on-other-key-press) in the page on [Tap-Hold configuration options](tap_hold.md). diff --git a/docs/ChangeLog/20230226/PR17007.md b/docs/ChangeLog/20230226/PR17007.md new file mode 100644 index 0000000000..bea04994b5 --- /dev/null +++ b/docs/ChangeLog/20230226/PR17007.md @@ -0,0 +1,31 @@ +`TAPPING_FORCE_HOLD` feature is now replaced by `QUICK_TAP_TERM`. Instead of turning off auto-repeat completely, user will have the option to configure a `QUICK_TAP_TERM` in milliseconds. When the user holds a tap-hold key after tapping it within `QUICK_TAP_TERM`, QMK will send the tap keycode to the host, enabling auto-repeat. + +Its value is set to `TAPPING_TERM` by default and it can be reduced to match typing habits to avoid false triggers. To disable auto-repeat completely, set `QUICK_TAP_TERM` to zero. + +`TAPPING_FORCE_HOLD_PER_KEY` is also deprecated and replaced by `QUICK_TAP_TERM_PER_KEY`. The old granular control function for tapping force hold is: + +```c +bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case LT(1, KC_BSPC): + return true; + default: + return false; + } +} +``` + +That function can be replaced with: + +```c +uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case SFT_T(KC_SPC): + return 0; + default: + return QUICK_TAP_TERM; + } +} +``` + +For more details, please read the updated documentation section on [Quick Tap Term](tap_hold.md#quick-tap-term). diff --git a/docs/_summary.md b/docs/_summary.md index 738c24ee42..b038f08a4d 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -85,6 +85,7 @@ * [Key Overrides](feature_key_overrides.md) * [Layers](feature_layers.md) * [One Shot Keys](one_shot_keys.md) + * [OS Detection](feature_os_detection.md) * [Raw HID](feature_rawhid.md) * [Secure](feature_secure.md) * [Send String](feature_send_string.md) @@ -92,6 +93,7 @@ * [Swap Hands](feature_swap_hands.md) * [Tap Dance](feature_tap_dance.md) * [Tap-Hold Configuration](tap_hold.md) + * [Tri Layer](feature_tri_layer.md) * [Unicode](feature_unicode.md) * [Userspace](feature_userspace.md) * [WPM Calculation](feature_wpm.md) @@ -99,6 +101,7 @@ * Hardware Features * Displays * [Quantum Painter](quantum_painter.md) + * [Quantum Painter LVGL Integration](quantum_painter_lvgl.md) * [HD44780 LCD Driver](feature_hd44780.md) * [ST7565 LCD Driver](feature_st7565.md) * [OLED Driver](feature_oled_driver.md) diff --git a/docs/adc_driver.md b/docs/adc_driver.md index 69fff4b3c2..494d90c94f 100644 --- a/docs/adc_driver.md +++ b/docs/adc_driver.md @@ -43,6 +43,8 @@ Then place this include at the top of your code: ### ARM +#### STM32 + Note that some of these pins are doubled-up on ADCs with the same channel. This is because the pins can be used for either ADC. Also note that the F0 and F3 use different numbering schemes. The F0 has a single ADC and the channels are 0-indexed, whereas the F3 has 4 ADCs and the channels are 1-indexed. This is because the F0 uses the `ADCv1` implementation of the ADC, whereas the F3 uses the `ADCv3` implementation. @@ -121,6 +123,21 @@ Also note that the F0 and F3 use different numbering schemes. The F0 has a singl <sup>² Not all STM32F4xx devices have ADC2 and/or ADC3, therefore some configurations shown in this table may be unavailable; in particular, pins `F4`…`F10` cannot be used as ADC inputs on devices which do not have ADC3. Check the device datasheet to confirm which pin functions are supported.</sup> +#### RP2040 + +RP2040 has only a single ADC (`ADCD1` in ChibiOS); in the QMK API the index for that ADC is 0. + +|Channel|Pin | +|-------|-------------------| +|0 |`GP26` | +|1 |`GP27` | +|2 |`GP28` | +|3 |`GP29` | +|4 |Temperature sensor*| + + +<sup>* The temperature sensor is disabled by default and needs to be enabled by the RP2040-specific function: `adcRPEnableTS(&ADCD1)`. The ADC must be initialized before calling that function; an easy way to ensure that is to perform a dummy conversion.</sup> + ## Functions ### AVR diff --git a/docs/config_options.md b/docs/config_options.md index 6b1f83214c..5bfb7c5d58 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -37,12 +37,7 @@ This level contains all of the options for that particular keymap. If you wish t # The `config.h` File -This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files, or anything besides this: - -```c -#include "config_common.h" -``` - +This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files. ## Hardware Options * `#define VENDOR_ID 0x1234` @@ -169,14 +164,18 @@ If you define these options you will enable the associated feature, which may in * `#define IGNORE_MOD_TAP_INTERRUPT` * makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys. * See [Ignore Mod Tap Interrupt](tap_hold.md#ignore-mod-tap-interrupt) for details -* `#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY` - * enables handling for per key `IGNORE_MOD_TAP_INTERRUPT` settings -* `#define TAPPING_FORCE_HOLD` - * makes it possible to use a dual role key as modifier shortly after having been tapped - * See [Tapping Force Hold](tap_hold.md#tapping-force-hold) - * Breaks any Tap Toggle functionality (`TT` or the One Shot Tap Toggle) -* `#define TAPPING_FORCE_HOLD_PER_KEY` - * enables handling for per key `TAPPING_FORCE_HOLD` settings +* `#define QUICK_TAP_TERM 100` + * tap-then-hold timing to use a dual role key to repeat keycode + * See [Quick Tap Term](tap_hold.md#quick-tap-term) + * Changes the timing of Tap Toggle functionality (`TT` or the One Shot Tap Toggle) + * Defaults to `TAPPING_TERM` if not defined +* `#define QUICK_TAP_TERM_PER_KEY` + * enables handling for per key `QUICK_TAP_TERM` settings +* `#define HOLD_ON_OTHER_KEY_PRESS` + * selects the hold action of a dual-role key as soon as the tap of the dual-role key is interrupted by the press of another key. + * See "[hold on other key press](tap_hold.md#hold-on-other-key-press)" for details +* `#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY` + * enables handling for per key `HOLD_ON_OTHER_KEY_PRESS` settings * `#define LEADER_TIMEOUT 300` * how long before the leader key times out * If you're having issues finishing the sequence before it times out, you may need to increase the timeout setting. Or you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. @@ -212,6 +211,9 @@ If you define these options you will enable the associated feature, which may in * Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPS_LOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 80 ms if not defined. For macOS, you may want to set this to 200 or higher. * `#define KEY_OVERRIDE_REPEAT_DELAY 500` * Sets the key repeat interval for [key overrides](feature_key_overrides.md). +* `#define LEGACY_MAGIC_HANDLING` + * Enables magic configuration handling for advanced keycodes (such as Mod Tap and Layer Tap) + ## RGB Light Configuration @@ -325,7 +327,7 @@ There are a few different ways to set handedness for split keyboards (listed in * `#define SPLIT_USB_TIMEOUT_POLL 10` * Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT` - + * `#define SPLIT_WATCHDOG_ENABLE` * Reboot slave if no communication from master within timeout. * Helps resolve issue where both sides detect as slave using `SPLIT_USB_DETECT` diff --git a/docs/configurator_default_keymaps.md b/docs/configurator_default_keymaps.md index d08ec29539..ec74f4740c 100644 --- a/docs/configurator_default_keymaps.md +++ b/docs/configurator_default_keymaps.md @@ -54,7 +54,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT), [1] = LAYOUT_all( - KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, BL_TOGG, BL_DEC, BL_INC, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, BL_TOGG, BL_DOWN, BL_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_BOOT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, KC_MNXT, KC_VOLD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, @@ -82,7 +82,7 @@ The default keymap uses the `LAYOUT_all` macro, so that will be the value of the "KC_LCTL", "KC_LGUI", "KC_LALT", "KC_SPC", "KC_RALT", "MO(1)", "KC_RGUI", "KC_RCTL", "KC_LEFT", "KC_DOWN", "KC_RGHT" ], [ - "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RGB_TOG", "RGB_MOD", "RGB_HUD", "RGB_HUI", "RGB_SAD", "RGB_SAI", "RGB_VAD", "RGB_VAI", "BL_TOGG", "BL_DEC", "BL_INC", + "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RGB_TOG", "RGB_MOD", "RGB_HUD", "RGB_HUI", "RGB_SAD", "RGB_SAI", "RGB_VAD", "RGB_VAI", "BL_TOGG", "BL_DOWN", "BL_UP", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_VOLU", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "QK_BOOT", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPLY", "KC_MNXT", "KC_VOLD", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", diff --git a/docs/custom_matrix.md b/docs/custom_matrix.md index 6d6ae5e972..ef206944e1 100644 --- a/docs/custom_matrix.md +++ b/docs/custom_matrix.md @@ -77,7 +77,7 @@ void matrix_init(void) { debounce_init(MATRIX_ROWS); // This *must* be called for correct keyboard behavior - matrix_init_quantum(); + matrix_init_kb(); } uint8_t matrix_scan(void) { @@ -89,7 +89,7 @@ uint8_t matrix_scan(void) { changed = debounce(raw_matrix, matrix, MATRIX_ROWS, changed); // This *must* be called for correct keyboard behavior - matrix_scan_quantum(); + matrix_scan_kb(); return changed; } diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md index d3437a9c60..1719807e26 100644 --- a/docs/feature_auto_shift.md +++ b/docs/feature_auto_shift.md @@ -281,16 +281,7 @@ Tap Hold Configurations work a little differently when using Retro Shift. Referencing `TAPPING_TERM` makes little sense, as holding longer would result in shifting one of the keys. -`IGNORE_MOD_TAP_INTERRUPT` changes *only* rolling from a mod tap (releasing it -first), sending both keys instead of the modifier on the second. Its effects on -nested presses are ignored. - -As nested taps were changed to act as though `PERMISSIVE_HOLD` is set unless only -`IGNORE_MOD_TAP_INTERRUPT` is (outside of Retro Shift), and Retro Shift ignores -`IGNORE_MOD_TAP_INTERRUPT`, `PERMISSIVE_HOLD` has no effect on Mod Taps. - -Nested taps will *always* act as though the `TAPPING_TERM` was exceeded for both -Mod and Layer Tap keys. +`RETRO_SHIFT` enables [`PERMISSIVE_HOLD`-like behaviour](tap_hold.md#permissive-hold) (even if not explicitly enabled) on all mod-taps for which `RETRO_SHIFT` applies. ## Using Auto Shift Setup diff --git a/docs/feature_combo.md b/docs/feature_combo.md index c45e3fd0e4..75c78c4cd4 100644 --- a/docs/feature_combo.md +++ b/docs/feature_combo.md @@ -328,6 +328,51 @@ If you, for example, use multiple base layers for different key layouts, one for With `#define COMBO_ONLY_FROM_LAYER 0` in config.h, the combos' keys are always checked from layer `0`, even if other layers are active. +### Combo reference layers by layer. + +If not using `COMBO_ONLY_FROM_LAYER` it is possible to specify a +combo reference layer for any layer using the `combo_ref_from_layer` hook. +The combo macros automatically create this function from the `COMBO_REF_LAYER()` +entries given. + +This function returns the assigned reference layer for the current layer. +if there is no match, it returns the default reference layer if set, +or the current layer otherwise. A default layer can be set with +`DEFAULT_REF_LAYER(_MY_COMBO_REF_LAYER)` + +If not set, the default reference layer selection from the automatically generated +`combo-ref-from-layer()` will be the current layer. + +The following `combo_ref_from_layer` function +will give a reference layer of _QWERTY for the _DVORAK layer and +will give the _NAV layer as a reference to it's self. All other layers +will have the default for their combo reference layer. If the default +is not set, all other layers will reference themselves. + + ```c + #define COMBO_REF_DEFAULT _MY_COMBO_LAYER + ... + + uint8_t combo_ref_from_layer(uint8_t layer){ + switch (get_highest_layer(layer_state)){ + case _DVORAK: return _QWERTY; + case _NAV: return _NAV; + default: return _MY_COMBO_LAYER; + } + return layer; // important if default is not in case. + } + + ``` + + The equivalent definition using the combo macros is this: + + ```c + COMBO_REF_LAYER(_DVORAK, _QWERTY) + COMBO_REF_LAYER(_NAV, _NAV) + DEFAULT_REF_LAYER(_MY_COMBO_LAYER). + ``` + + ## User callbacks In addition to the keycodes, there are a few functions that you can use to set the status, or check it: @@ -350,6 +395,11 @@ First, you need to add `VPATH += keyboards/gboards` to your `rules.mk`. Next, in Then, write your combos in `combos.def` file in the following manner: ```c +// Alternate reference layers by layer +// Layer Reference layer +COMBO_REF_LAYER(_DVORAK, _QWERTY) // reference the qwerty layer for dvorak. +COMBO_REF_LAYER(_NAV, _NAV) // explicit reference to self instead of the default. + // name result chord keys COMB(AB_ESC, KC_ESC, KC_A, KC_B) COMB(JK_TAB, KC_TAB, KC_J, KC_K) diff --git a/docs/feature_converters.md b/docs/feature_converters.md index 0fa677f873..df42acac59 100644 --- a/docs/feature_converters.md +++ b/docs/feature_converters.md @@ -18,6 +18,7 @@ Currently the following converters are available: | `promicro` | `stemcell` | | `promicro` | `bonsai_c4` | | `promicro` | `elite_pi` | +| `promicro` | `michi` | | `elite_c` | `stemcell` | | `elite_c` | `elite_pi` | @@ -81,6 +82,7 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co | [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` | | [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` | | [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` | +| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` | Converter summary: @@ -94,6 +96,7 @@ Converter summary: | `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` | | `bonsai_c4` | `-e CONVERT_TO=bonsai_c4` | `CONVERT_TO=bonsai_c4` | `#ifdef CONVERT_TO_BONSAI_C4` | | `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` | +| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` | ### Proton C :id=proton_c @@ -124,7 +127,7 @@ The following defaults are based on what has been implemented for [RP2040](platf | USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) | | [Split keyboards](feature_split_keyboard.md) | Partial via `PIO` vendor driver - heavily dependent on enabled features | -### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO, and Elite-Pi :id=promicro_rp2040 +### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO, Elite-Pi and Michi :id=promicro_rp2040 Currently identical to [Adafruit KB2040](#kb2040). diff --git a/docs/feature_leader_key.md b/docs/feature_leader_key.md index 28e4501036..72a6818dd1 100644 --- a/docs/feature_leader_key.md +++ b/docs/feature_leader_key.md @@ -1,165 +1,297 @@ -# The Leader Key: A New Kind of Modifier +# The Leader Key: A New Kind of Modifier :id=the-leader-key -If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen. +If you're a Vim user, you probably know what a Leader key is. In contrast to [Combos](feature_combo.md), the Leader key allows you to hit a *sequence* of up to five keys instead, which triggers some custom functionality once complete. -That's what `QK_LEAD` does. Here's an example: +## Usage :id=usage -1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `QK_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else. -2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `QK_LEAD` key. Specifically, when you press the `QK_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low. - * By default, this timeout is how long after pressing `QK_LEAD` to complete your entire sequence. This may be very low for some people. So you may want to increase this timeout. Optionally, you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. This allows you to maintain a low value here, but still be able to use the longer sequences. To enable this option, add `#define LEADER_PER_KEY_TIMING` to your `config.h`. -3. Within your `matrix_scan_user` function, add something like this: +Add the following to your `rules.mk`: -```c -LEADER_EXTERNS(); - -void matrix_scan_user(void) { - LEADER_DICTIONARY() { - leading = false; - leader_end(); - - SEQ_ONE_KEY(KC_F) { - // Anything you can do in a macro. - SEND_STRING("QMK is awesome."); - } - SEQ_TWO_KEYS(KC_D, KC_D) { - SEND_STRING(SS_LCTL("a") SS_LCTL("c")); - } - SEQ_THREE_KEYS(KC_D, KC_D, KC_S) { - SEND_STRING("https://start.duckduckgo.com\n"); - } - SEQ_TWO_KEYS(KC_A, KC_S) { - register_code(KC_LGUI); - register_code(KC_S); - unregister_code(KC_S); - unregister_code(KC_LGUI); - } - } -} +```make +LEADER_ENABLE = yes ``` -As you can see, you have a few functions. You can use `SEQ_ONE_KEY` for single-key sequences (Leader followed by just one key), and `SEQ_TWO_KEYS`, `SEQ_THREE_KEYS` up to `SEQ_FIVE_KEYS` for longer sequences. +Then add the `QK_LEAD` keycode to your keymap. -Each of these accepts one or more keycodes as arguments. This is an important point: You can use keycodes from **any layer on your keyboard**. That layer would need to be active for the leader macro to fire, obviously. +## Callbacks :id=callbacks -## Adding Leader Key Support +These callbacks are invoked when the leader sequence begins and ends. In the latter you can implement your custom functionality based on the contents of the sequence buffer. -To enable Leader Key, add the following line to your keymap's `rules.mk`: +```c +void leader_start_user(void) { + // Do something when the leader key is pressed +} -```make -LEADER_ENABLE = yes +void leader_end_user(void) { + if (leader_sequence_one_key(KC_F)) { + // Leader, f => Types the below string + SEND_STRING("QMK is awesome."); + } else if (leader_sequence_two_keys(KC_D, KC_D)) { + // Leader, d, d => Ctrl+A, Ctrl+C + SEND_STRING(SS_LCTL("a") SS_LCTL("c")); + } else if (leader_sequence_three_keys(KC_D, KC_D, KC_S)) { + // Leader, d, d, s => Types the below string + SEND_STRING("https://start.duckduckgo.com\n"); + } else if (leader_sequence_two_keys(KC_A, KC_S)) { + // Leader, a, s => GUI+S + tap_code16(LGUI(KC_S)); + } +} ``` -Place the following macro in your `keymap.c` or user space source file, before any functional code. It handles declaration of external variables that will be referenced by Leader Key codes that follows: +## Basic Configuration :id=basic-configuration + +### Timeout :id=timeout + +This is the amount of time you have to complete a sequence once the leader key has been pressed. The default value is 300 milliseconds, but you can change this by adding the following to your `config.h`: ```c -LEADER_EXTERNS(); +#define LEADER_TIMEOUT 350 ``` -## Per Key Timing on Leader keys +### Per-Key Timeout :id=per-key-timeout + +Rather than relying on an incredibly high timeout for long leader key strings or those of us without 200 wpm typing skills, you can enable per-key timing to ensure that each key pressed provides you with more time to finish the sequence. This is incredibly helpful with leader key emulation of tap dance (such as multiple taps of the same key like C, C, C). -Rather than relying on an incredibly high timeout for long leader key strings or those of us without 200wpm typing skills, we can enable per key timing to ensure that each key pressed provides us with more time to finish our stroke. This is incredibly helpful with leader key emulation of tap dance (read: multiple taps of the same key like C, C, C). +To enable this, add the following to your `config.h`: -In order to enable this, place this in your `config.h`: ```c #define LEADER_PER_KEY_TIMING ``` -After this, it's recommended that you lower your `LEADER_TIMEOUT` to something less that 300ms. +After this, it's recommended that you lower your timeout below 300 ms: ```c #define LEADER_TIMEOUT 250 ``` -Now, something like this won't seem impossible to do without a 1000MS leader key timeout: +Now, something like this won't seem impossible to do without a 1000 millisecond timeout: ```c -SEQ_THREE_KEYS(KC_C, KC_C, KC_C) { - SEND_STRING("Per key timing is great!!!"); +if (leader_sequence_three_keys(KC_C, KC_C, KC_C)) { + SEND_STRING("Per key timing is great!!!"); } ``` -## Infinite Leader key timeout +### Disabling Initial Timeout :id=disabling-initial-timeout -Sometimes your leader key is not on a comfortable place as the rest of keys on your sequence. Imagine that your leader key is one of your outer top right keys, you may need to reposition your hand just to reach your leader key. -This can make typing the entire sequence on time hard even if you are able to type most of the sequence fast. For example, if your sequence is `Leader + asd` typing `asd` fast is very easy once you have your hands in your home row. However starting the sequence in time after moving your hand out of the home row to reach the leader key and back is not. -To remove the stress this situation produces to your hands you can enable an infinite timeout just for the leader key. This means that after you hit the leader key you will have an infinite amount of time to start the rest of the sequence, allowing you to proper position your hands on the best position to type the rest of the sequence comfortably. -This infinite timeout only affects the leader key, so in our previous example of `Leader + asd` you will have an infinite amount of time between `Leader` and `a`, but once you start the sequence the timeout you have configured (global or per key) will work normally. -This way you can configure a very short `LEADER_TIMEOUT` but still have plenty of time to position your hands. +Sometimes your leader key may be too far away from the rest of the keys in the sequence. Imagine that your leader key is one of your outer top right keys - you may need to reposition your hand just to reach your leader key. This can make typing the entire sequence on time hard difficult if you are able to type most of the sequence fast. For example, if your sequence is `Leader + asd`, typing `asd` fast is very easy once you have your hands in your home row, but starting the sequence in time after moving your hand out of the home row to reach the leader key and back is not. + +To remove the stress this situation produces to your hands, you can disable th |