ZMK_BEHAVIOR
ZMK_BEHAVIOR
(explicit variants)ZMK_APPLY_MATRIX_TRANSFORM
ZMK_COMBO
ZMK_CONDITIONAL_LAYER
ZMK_LAYER
ZMK_UNICODE
ZMK_BEHAVIOR(name, type, specification)
Create a behavior instance of type type
and make it accessible under &name
.
name
: a unique string to reference the behavior.type
: any valid ZMK behavior; e.g.,hold_tap
. Multiword behaviors are separated by underscores (_
).specification
: the configuration of the behavior without the#binding-cells
andcompatible
properties and without the surrounding node specification.
Tap-hold
This creates a custom "homerow mod" that can be added to the keymap using &hrm
. For example,
&hrm LSHIFT T
creates a key that yields T
on tap and LSHIFT
on hold.
ZMK_BEHAVIOR(hrm, hold_tap,
flavor = "balanced";
tapping-term-ms = <280>;
quick-tap-ms = <125>;
bindings = <&kp>, <&kp>;
)
Tap-dance
This creates a behavior that yields sticky-shift on tap and caps-word on double tap. It can be added
to the keymap using &ss_cw
.
ZMK_BEHAVIOR(ss_cw, tap_dance,
tapping-term-ms = <200>;
bindings = <&sk LSHFT>, <&caps_word>;
)
Macro
This creates a "Windows sleep macro" that can be added to the keymap using &win_sleep
.
ZMK_BEHAVIOR(win_sleep, macro,
wait-ms = <100>;
tap-ms = <5>;
bindings = <&kp LG(X) &kp U &kp S>;
)
Instead of using ZMK_BEHAVIOR(name, type, specification)
, each behavior type
also has an
explicit variant accessible under ZMK_type(name, specification)
.
For instance, ZMK_MOD_MORPH(name, ...)
is equivalent to ZMK_BEHAVIOR(name, mod_morph, ...)
.
Note
By default, sourcing helper.h
will replace the native implementation of ZMK_MACRO
. To work
reliably, helper.h
should be included after behaviors.dtsi
. To keep the native
implementation of ZMK_MACRO
, set #define ZMK_HELPER_KEEP_NATIVE 1
before including helper.h
.
ZMK_APPLY_MATRIX_TRANSFORM(transform)
Apply a non-default matrix transform to the keymap.
transform
: node name of a validmatrix_transform
without the leading&
This applies the five_column_transform
on a Corne that has the last columns snapped off.
ZMK_APPLY_MATRIX_TRANSFORM(five_column_transform)
ZMK_COMBO(name, bindings, keypos, layers, timeout, prior_idle, extra)
Create a combo that triggers binding
if all keys in position keypos
are pressed.
name
: a unique identifier stringbinding
: a behavior instance that is triggered by the combokeypos
: a list of 2 or more key positions that activate the combolayers
(optional): a list of layers on which the combo can be activated (defaults toAll
)timeout
(optional): combo timeout in ms (defaults toCOMBO_TERM
, see below)prior_idle
(optional): require-prior-idle timout in ms (disabled by default)extra
(optional): additional configuration options (e.g.,slow-release;
)
If not specified, timeout
defaults to the COMBO_TERM
, which in turn default to 30
ms. The
default can be globally overwritten with:
#undef COMBO_TERM
#define COMBO_TERM 50
Simple combo
This creates an "escape" combo that is active on all layers and which is triggered when the 0th and 1st keys are pressed jointly within 25ms.
ZMK_COMBO(esc, &kp ESC, 0 1, ALL, 25)
Using `key-labels` to define combos
This sources key-labels for a 34-keys board like the Sweep. It then creates a "copy"-combo for the middle + ring finger on the left bottom row, and a "paste"-combo for the index + middle finger on the left bottom row. Both combos are active on all layers.
#include "zmk-helpers/key-labels/34.h" // replace with layout file for your keyboard
ZMK_COMBO(copy, &kp LC(C), LB2 LB3)
ZMK_COMBO(paste, &kp LC(V), LB1 LB2)
ZMK_CONDITIONAL_LAYER(name, if_layers, then_layer)
Set up a tri-layer
condition, which activates then_layer
if all layers in if_layers
are
active.
name
: a unique identifier stringif_layers
: a list of layers which trigger thethen_layer
if simultaneously activethen_layer
: the layer which is activated when the if-condition is met. Due to ZMK's layering model, it should generally have a higher number than theif_layers
This triggers "layer 3" if layers "1" and "2" are simultaneously active.
ZMK_CONDITIONAL_LAYER(its_magic, 1 2, 3)
Mind that ZMK's layer numbering starts at 0. One can use layer definitions, as demonstrated in this example, to simplify life.
ZMK_LAYER(name, layout, sensors)
Create a layer with layout layout
and add it to the keymap.
name
: a unique identifier string (this also sets thedisplay-name
if available)layout
: the layout as specified by thebindings
property of the ZMK keymap nodesensors
(optional): sensor-specification if applicable
Multiple layers can be added with repeated calls of ZMK_LAYER
. They will be ordered in the same
order in which they are created, with the first-specified layer being the "lowest" one
(see here for details).
ZMK_LAYER(base,
// ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮ ╭─────────────┬─────────────┬─────────────┬─────────────┬─────────────╮
&kp Q &kp W &kp F &kp P &kp B &kp J &kp L &kp U &kp Y &kp SQT
// ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
&hrm LGUI A &hrm LALT R &hrm LCTRL S &hrm LSHFT T &kp G &kp M &hrm RSHFT N &hrm LCTRL E &hrm LALT I &hrm LGUI O
// ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
&kp Z &kp X &kp C &kp D &kp V &kp K &kp H &kp COMMA &kp DOT &kp SEMI
// ╰─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
&kp ESC < NAV SPACE &kp TAB &kp RET &ss_cw &bs_del_num
// ╰─────────────┴──── ────────┴─────────────╯ ╰─────────────┴─────────────┴─────────────╯
)
ZMK_UNICODE_SINGLE(name, L0, L1, L2, L3)
ZMK_UNICODE_PAIR(name, L0, L1, L2, L3, U0, U1, U2, U3)
Create Unicode characters that can be added to the keymap with &name
. ZMK_UNICODE_SINGLE
creates
a single character. ZMK_UNICODE_PAIR
creates pairs of shifted/unshifted characters.
name:
a unique string to reference the characterL0
toL3
: a 4-digit sequence defining the Unicode string using standard ZMK key codesU0
toU3
(only forZMK_UNICODE_PAIR
): a 4-digit sequence defining the shifted unicode string
The usage of the Unicode helpers is OS-specific. See the following instructions for details.
Windows
On your computer, install WinCompose.
Linux
In your keymap, set HOST_OS
to 1
before sourcing helper.h
:
#define HOST_OS 1
#include "zmk-helpers/helper.h"
macOS
On your computer, enable Unicode input in the system preferences by selecting Unicode Hex Input
as
input source. In your keymap, set HOST_OS
to 2
before sourcing helper.h
.
#define HOST_OS 2
#include "zmk-helpers/helper.h"
Other OS
For non-default input channels or for other operating systems, one can set the variables
OS_UNICODE_LEAD
and OS_UNICODE_TRAIL
to the character sequences that initialize/terminate the
Unicode input.
Euro sign (€)
This creates a Euro character that can be added to the keymap using &euro_sign
.
ZMK_UNICODE_SINGLE(euro_sign, N2, N0, A, C)
German umlauts (ä/Ä, ö/Ö, ü/Ü)
The creates "umlaut" pairs that can be added to the keymap using &de_ae
, &de_oe
and &de_ue
.
// name unshifted shifted
ZMK_UNICODE_PAIR( de_ae, N0, N0, E, N4, N0, N0, C, N4 )
ZMK_UNICODE_PAIR( de_oe, N0, N0, F, N6, N0, N0, D, N6 )
ZMK_UNICODE_PAIR( de_ue, N0, N0, F, C, N0, N0, D, C )