The Layer Morph behavior morphs a keypress based on whether a given layer is active.
To load the module, add the following entries to remotes and projects in config/west.yml.
manifest:
remotes:
- name: zmkfirmware
url-base: https://github.com/zmkfirmware
- name: rafaelromao
url-base: https://github.com/rafaelromao
projects:
- name: zmk
remote: zmkfirmware
revision: v0.3
import: app/west.yml
- name: zmk-layer-morph
remote: rafaelromao
revision: v0.3 # set to same as ZMK version above
self:
path: config
To use the layer morph behavior, you need to define it in your keymap file.
bindings: A phandle-array of two bindings. The first binding is the "normal" binding, and the second is the "morphed" binding.layers: The layer (or layers) to check for. If any of the specified layers are active, the morphed binding will be used. Can be a single layer like<1>or a list of layers like<1 2>.
Here is an example of how to define a layer morph behavior in your .keymap file:
/ {
behaviors {
// Define the layer-morph behavior
my_layer_morph: layer_morph {
compatible = "zmk,behavior-layer-morph";
#binding-cells = <0>;
// The layers to check for (e.g., layers 1 and 2)
layers = <1 2>;
// The bindings for the normal and morphed keys
// Normal: 'A', Morphed: 'B'
bindings = <&kp A>, <&kp B>;
};
};
keymap {
compatible = "zmk,keymap";
default_layer {
bindings = <&my_layer_morph>;
};
};
};
In this example, pressing the key will send A. If layer 1 or layer 2 is active, it will send B instead.
This example shows how to use the layer morph behavior to create a keymap that works for both MacOS and Linux.
The keymap has a default base layer for MacOS, and a secondary base layer for Linux that can be toggled on. A third layer contains shortcuts for copy and paste that will behave differently depending on whether the Linux layer is active.
/ {
// Define layer names for clarity
// 0: MacOS (default)
// 1: Linux
// 2: Shortcuts
behaviors {
// Layer morph for copy
lm_copy: layer_morph_copy {
compatible = "zmk,behavior-layer-morph";
#binding-cells = <0>;
layers = <1>; // Check for Linux layer
bindings = <&kp LG(C)>, <&kp LC(C)>; // MacOS, Linux
};
// Layer morph for paste
lm_paste: layer_morph_paste {
compatible = "zmk,behavior-layer-morph";
#binding-cells = <0>;
layers = <1>; // Check for Linux layer
bindings = <&kp LG(V)>, <&kp LC(V)>; // MacOS, Linux
};
};
keymap {
compatible = "zmk,keymap";
macos_layer {
bindings = <
&kp A &kp B &tog 1 &mo 2
>;
};
linux_layer {
bindings = <
&trans &trans &tog 1 &mo 2
>;
};
shortcuts_layer {
bindings = <
&lm_copy &lm_paste &trans &trans
>;
};
};
};
-
Layers:
- The
macos_layeris the default layer (layer 0). - The
linux_layeris layer 1. - The
shortcuts_layeris layer 2.
- The
-
Layer Switching:
- On any of the base layers, pressing the third key (
&tog 1) toggles thelinux_layeron or off. - Pressing and holding the fourth key (
&mo 2) momentarily activates theshortcuts_layer.
- On any of the base layers, pressing the third key (
-
Layer Morph:
- When the
shortcuts_layeris active, the first key triggers the&lm_copybehavior.- If the
linux_layeris not active (i.e., we are in MacOS mode), it sendsLG(C)(Command-C). - If the
linux_layeris active, it sendsLC(C)(Control-C).
- If the
- The second key triggers the
&lm_pastebehavior, which works similarly for pasting (LG(V)orLC(V)).
- When the
You can see a variation of the example above implemented for my Corne-ish Zen here.