mirror of https://github.com/zmkfirmware/zmk.git
Compare commits
16 Commits
2dbd634466
...
bf37575267
| Author | SHA1 | Date |
|---|---|---|
|
|
bf37575267 | |
|
|
ad7fbfef92 | |
|
|
a388b4113b | |
|
|
96f1537a0e | |
|
|
f117af5769 | |
|
|
ab5125a098 | |
|
|
ee4a63be8f | |
|
|
9bed79a543 | |
|
|
f2db79460d | |
|
|
18a636cdbf | |
|
|
ee2e6e5a4a | |
|
|
ec7e38685c | |
|
|
390743a164 | |
|
|
3e5025712a | |
|
|
b4a57566b0 | |
|
|
83bb1c23e2 |
|
|
@ -53,6 +53,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|||
target_sources(app PRIVATE src/behaviors/behavior_caps_word.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_repeat.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_MACRO app PRIVATE src/behaviors/behavior_macro.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_LEADER_KEY app PRIVATE src/behaviors/behavior_leader_key.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_mod_morph.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_outputs.c)
|
||||
|
|
|
|||
16
app/Kconfig
16
app/Kconfig
|
|
@ -25,6 +25,9 @@ config USB_DEVICE_PID
|
|||
config USB_DEVICE_MANUFACTURER
|
||||
default "ZMK Project"
|
||||
|
||||
config BT_DEVICE_APPEARANCE
|
||||
default 961
|
||||
|
||||
config BT_DIS_PNP_VID
|
||||
default 0x1D50
|
||||
|
||||
|
|
@ -458,6 +461,19 @@ config ZMK_COMBO_MAX_KEYS_PER_COMBO
|
|||
# Combo options
|
||||
endmenu
|
||||
|
||||
menu "Leader Options"
|
||||
|
||||
config ZMK_LEADER_MAX_KEYS_PER_SEQUENCE
|
||||
int "Maximum number of key presses in a leader sequence"
|
||||
default 4
|
||||
|
||||
config ZMK_LEADER_MAX_SEQUENCES_PER_KEY
|
||||
int "Maximum number of leader sequences that a key can belong to"
|
||||
default 5
|
||||
|
||||
#Leader options
|
||||
endmenu
|
||||
|
||||
menu "Behavior Options"
|
||||
|
||||
config ZMK_BEHAVIORS_QUEUE_SIZE
|
||||
|
|
|
|||
|
|
@ -134,3 +134,8 @@ config ZMK_BEHAVIOR_MACRO
|
|||
bool
|
||||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_MACRO_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_ONE_PARAM_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_TWO_PARAM_ENABLED
|
||||
|
||||
config ZMK_BEHAVIOR_LEADER_KEY
|
||||
bool
|
||||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_LEADER_KEY_ENABLED
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Leader key behavior
|
||||
|
||||
compatible: "zmk,behavior-leader-key"
|
||||
|
||||
include: zero_param.yaml
|
||||
|
||||
properties:
|
||||
timeout-ms:
|
||||
type: int
|
||||
default: -1
|
||||
overlap-timeout-ms:
|
||||
type: int
|
||||
default: 200
|
||||
|
||||
child-binding:
|
||||
description: "A leader sequence"
|
||||
|
||||
properties:
|
||||
bindings:
|
||||
type: phandle-array
|
||||
required: true
|
||||
key-positions:
|
||||
type: array
|
||||
required: true
|
||||
immediate-trigger:
|
||||
type: boolean
|
||||
|
|
@ -30,3 +30,9 @@
|
|||
#define ZMK_VIRTUAL_KEY_POSITION_BEHAVIOR_INPUT_PROCESSOR(listener_index, processor_index) \
|
||||
(ZMK_VIRTUAL_KEY_POSITION_COMBO(ZMK_COMBOS_LEN) + \
|
||||
(ZMK_INPUT_LISTENERS_LEN * (processor_index)) + (listener_index))
|
||||
|
||||
/**
|
||||
* Gets the virtual key position to use for the leader sequence with the given index.
|
||||
*/
|
||||
#define ZMK_VIRTUAL_KEY_POSITION_LEADER(index) \
|
||||
(ZMK_VIRTUAL_KEY_POSITION_SENSOR(ZMK_KEYMAP_SENSORS_LEN) + (index))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Copyright (c) 2025 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_leader_key
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/keycode_state_changed.h>
|
||||
#include <zmk/events/position_state_changed.h>
|
||||
#include <zmk/keymap.h>
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/matrix.h>
|
||||
#include <zmk/virtual_key_position.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
static bool leader_status;
|
||||
static int32_t press_count;
|
||||
static int32_t release_count;
|
||||
static int32_t timeout_ms;
|
||||
static int32_t overlap_timeout_ms;
|
||||
static int32_t active_leader_position;
|
||||
static bool first_release;
|
||||
static struct k_work_delayable release_timer;
|
||||
static int64_t release_at;
|
||||
// static bool timer_started;
|
||||
static bool timer_cancelled;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT)
|
||||
static uint8_t source;
|
||||
#endif
|
||||
|
||||
struct leader_seq_cfg {
|
||||
int32_t key_positions[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE];
|
||||
int32_t key_position_len;
|
||||
|
||||
bool immediate_trigger;
|
||||
bool is_pressed;
|
||||
|
||||
// the virtual key position is a key position outside the range used by the keyboard.
|
||||
// it is necessary so hold-taps can uniquely identify a behavior.
|
||||
int32_t virtual_key_position;
|
||||
|
||||
struct zmk_behavior_binding behavior;
|
||||
};
|
||||
|
||||
struct behavior_leader_key_config {
|
||||
int32_t timeout_ms;
|
||||
int32_t overlap_timeout_ms;
|
||||
struct leader_seq_cfg *sequences;
|
||||
size_t sequences_len;
|
||||
};
|
||||
|
||||
// leader_pressed_keys is filled with an event when a key is pressed.
|
||||
// The keys are removed from this array when they are released.
|
||||
// Once this array is empty, the behavior is released.
|
||||
static const struct zmk_position_state_changed
|
||||
*leader_pressed_keys[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE] = {NULL};
|
||||
|
||||
static uint32_t current_sequence[CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE] = {-1};
|
||||
|
||||
// the set of candidate leader based on the currently leader_pressed_keys
|
||||
static int num_candidates;
|
||||
|
||||
static struct leader_seq_cfg *sequence_candidates[CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY];
|
||||
static int num_comp_candidates;
|
||||
static struct leader_seq_cfg
|
||||
*completed_sequence_candidates[CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY];
|
||||
|
||||
const static struct behavior_leader_key_config *active_leader_cfg;
|
||||
|
||||
static bool has_current_sequence(struct leader_seq_cfg *sequence, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (sequence->key_positions[i] != current_sequence[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_in_current_sequence(int32_t position) {
|
||||
for (int i = 0; i < CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE; i++) {
|
||||
if (position == current_sequence[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_duplicate(struct leader_seq_cfg *seq) {
|
||||
for (int i = 0; i < CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE; i++) {
|
||||
if (sequence_candidates[i] == seq) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool release_key_in_sequence(int32_t position) {
|
||||
for (int i = 0; i < release_count; i++) {
|
||||
if (leader_pressed_keys[i] && position == leader_pressed_keys[i]->position) {
|
||||
leader_pressed_keys[i] = NULL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool all_keys_released() {
|
||||
for (int i = 0; i < press_count; i++) {
|
||||
if (leader_pressed_keys[i] != NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void clear_candidates() {
|
||||
for (int i = 0; i < CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY; i++) {
|
||||
sequence_candidates[i] = NULL;
|
||||
completed_sequence_candidates[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void leader_find_candidates(int32_t position, int count) {
|
||||
clear_candidates();
|
||||
num_candidates = 0;
|
||||
num_comp_candidates = 0;
|
||||
|
||||
for (int i = 0; i < active_leader_cfg->sequences_len; i++) {
|
||||
struct leader_seq_cfg *sequence = &(active_leader_cfg->sequences[i]);
|
||||
|
||||
if (sequence == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sequence->key_positions[count] == position && has_current_sequence(sequence, count) &&
|
||||
!is_duplicate(sequence)) {
|
||||
sequence_candidates[num_candidates] = sequence;
|
||||
num_candidates++;
|
||||
if (sequence->key_position_len == count + 1) {
|
||||
completed_sequence_candidates[num_comp_candidates] = sequence;
|
||||
num_comp_candidates++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const struct zmk_listener zmk_listener_leader;
|
||||
|
||||
static inline int press_leader_behavior(struct leader_seq_cfg *sequence, int32_t timestamp) {
|
||||
struct zmk_behavior_binding_event event = {
|
||||
.position = sequence->virtual_key_position,
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT)
|
||||
.source = source,
|
||||
#endif
|
||||
.timestamp = timestamp,
|
||||
};
|
||||
|
||||
sequence->is_pressed = true;
|
||||
return behavior_keymap_binding_pressed(&sequence->behavior, event);
|
||||
}
|
||||
|
||||
static inline int release_leader_behavior(struct leader_seq_cfg *sequence, int32_t timestamp) {
|
||||
struct zmk_behavior_binding_event event = {
|
||||
.position = sequence->virtual_key_position,
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT)
|
||||
.source = source,
|
||||
#endif
|
||||
.timestamp = timestamp,
|
||||
};
|
||||
|
||||
sequence->is_pressed = false;
|
||||
return behavior_keymap_binding_released(&sequence->behavior, event);
|
||||
}
|
||||
|
||||
static int stop_timer() {
|
||||
int timer_cancel_result = k_work_cancel_delayable(&release_timer);
|
||||
if (timer_cancel_result == -EINPROGRESS) {
|
||||
// too late to cancel, we'll let the timer handler clear up.
|
||||
timer_cancelled = true;
|
||||
}
|
||||
return timer_cancel_result;
|
||||
}
|
||||
|
||||
static void reset_timer(int32_t timestamp, bool is_overlap) {
|
||||
int32_t wait_time_ms = timeout_ms;
|
||||
|
||||
if (is_overlap) {
|
||||
wait_time_ms = overlap_timeout_ms;
|
||||
}
|
||||
|
||||
release_at = timestamp + wait_time_ms;
|
||||
int32_t ms_left = release_at - k_uptime_get();
|
||||
|
||||
if (ms_left > 0) {
|
||||
k_work_schedule(&release_timer, K_MSEC(ms_left));
|
||||
LOG_DBG("Successfully reset leader timer");
|
||||
}
|
||||
}
|
||||
|
||||
static void activate_leader_key(const struct behavior_leader_key_config *cfg, uint32_t position) {
|
||||
LOG_DBG("leader key activated");
|
||||
|
||||
leader_status = true;
|
||||
press_count = 0;
|
||||
release_count = 0;
|
||||
timeout_ms = cfg->timeout_ms;
|
||||
overlap_timeout_ms = cfg->overlap_timeout_ms;
|
||||
active_leader_position = position;
|
||||
first_release = false;
|
||||
active_leader_cfg = cfg;
|
||||
|
||||
if (timeout_ms > 0) {
|
||||
reset_timer(k_uptime_get(), false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE; i++) {
|
||||
leader_pressed_keys[i] = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
static void deactivate_leader_key() {
|
||||
LOG_DBG("leader key deactivated");
|
||||
leader_status = false;
|
||||
clear_candidates();
|
||||
};
|
||||
|
||||
static void behavior_leader_key_timer_handler(struct k_work *item) {
|
||||
if (!leader_status) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer_cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("deactivating leader due to timeout");
|
||||
|
||||
for (int i = 0; i < num_comp_candidates; i++) {
|
||||
if (!completed_sequence_candidates[i]->is_pressed) {
|
||||
press_leader_behavior(completed_sequence_candidates[i], k_uptime_get());
|
||||
release_leader_behavior(completed_sequence_candidates[i], k_uptime_get());
|
||||
}
|
||||
}
|
||||
|
||||
deactivate_leader_key();
|
||||
}
|
||||
|
||||
static int position_state_changed_listener(const zmk_event_t *ev) {
|
||||
struct zmk_position_state_changed *data = as_zmk_position_state_changed(ev);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!leader_status && !data->state && !all_keys_released()) {
|
||||
if (release_key_in_sequence(data->position)) {
|
||||
return ZMK_EV_EVENT_HANDLED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (leader_status) {
|
||||
if (data->state) { // keydown
|
||||
leader_find_candidates(data->position, press_count);
|
||||
LOG_DBG("leader cands: %d comp: %d", num_candidates, num_comp_candidates);
|
||||
stop_timer();
|
||||
current_sequence[press_count] = data->position;
|
||||
leader_pressed_keys[press_count] = data;
|
||||
press_count++;
|
||||
for (int i = 0; i < num_comp_candidates; i++) {
|
||||
LOG_DBG("leader i is %d", i);
|
||||
struct leader_seq_cfg *seq = completed_sequence_candidates[i];
|
||||
if (seq->immediate_trigger || (num_candidates == 1 && num_comp_candidates == 1)) {
|
||||
press_leader_behavior(seq, data->timestamp);
|
||||
}
|
||||
}
|
||||
} else { // keyup
|
||||
if (data->position == active_leader_position && !first_release) {
|
||||
first_release = true;
|
||||
return 0;
|
||||
}
|
||||
if (!is_in_current_sequence(data->position)) {
|
||||
return 0;
|
||||
}
|
||||
if (num_candidates == 0) {
|
||||
deactivate_leader_key();
|
||||
return ZMK_EV_EVENT_HANDLED;
|
||||
}
|
||||
|
||||
release_count++;
|
||||
release_key_in_sequence(data->position);
|
||||
|
||||
for (int i = 0; i < num_comp_candidates; i++) {
|
||||
struct leader_seq_cfg *seq = completed_sequence_candidates[i];
|
||||
if (seq->is_pressed && all_keys_released()) {
|
||||
release_leader_behavior(seq, data->timestamp);
|
||||
num_comp_candidates--;
|
||||
}
|
||||
if (num_candidates == 1 && num_comp_candidates == 0) {
|
||||
deactivate_leader_key();
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout_ms > 0) {
|
||||
reset_timer(data->timestamp, false);
|
||||
}
|
||||
|
||||
if (num_comp_candidates < num_candidates) {
|
||||
reset_timer(data->timestamp, true);
|
||||
}
|
||||
}
|
||||
return ZMK_EV_EVENT_HANDLED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||
const struct behavior_leader_key_config *cfg = dev->config;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT)
|
||||
source = event.source;
|
||||
#endif
|
||||
|
||||
activate_leader_key(cfg, event.position);
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_leader_key_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
};
|
||||
|
||||
static int behavior_leader_key_init(const struct device *dev) {
|
||||
k_work_init_delayable(&release_timer, behavior_leader_key_timer_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(leader, position_state_changed_listener);
|
||||
ZMK_SUBSCRIPTION(leader, zmk_position_state_changed);
|
||||
|
||||
#define SEQUENCE_ITEM(i, n, prop) DT_PROP_BY_IDX(n, prop, i)
|
||||
|
||||
#define PROP_SEQUENCES(n, prop) \
|
||||
{ \
|
||||
.virtual_key_position = ZMK_VIRTUAL_KEY_POSITION_LEADER(__COUNTER__), \
|
||||
.is_pressed = false, \
|
||||
.immediate_trigger = DT_PROP(n, immediate_trigger), \
|
||||
.key_position_len = DT_PROP_LEN(n, prop), \
|
||||
.key_positions = {LISTIFY(DT_PROP_LEN(n, prop), SEQUENCE_ITEM, (, ), n, prop)}, \
|
||||
.behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, n), \
|
||||
}
|
||||
|
||||
#define LEAD_INST(n) \
|
||||
static struct leader_seq_cfg leader_sequences_##n[] = { \
|
||||
DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP_VARGS(n, PROP_SEQUENCES, (, ), key_positions)}; \
|
||||
static struct behavior_leader_key_config behavior_leader_key_config_##n = { \
|
||||
.timeout_ms = DT_INST_PROP(n, timeout_ms), \
|
||||
.overlap_timeout_ms = DT_INST_PROP(n, overlap_timeout_ms), \
|
||||
.sequences = leader_sequences_##n, \
|
||||
.sequences_len = ARRAY_SIZE(leader_sequences_##n)}; \
|
||||
BEHAVIOR_DT_INST_DEFINE(n, behavior_leader_key_init, NULL, NULL, \
|
||||
&behavior_leader_key_config_##n, POST_KERNEL, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_leader_key_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(LEAD_INST)
|
||||
|
|
@ -65,13 +65,15 @@ static uint8_t active_profile;
|
|||
|
||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||
#define DEVICE_APPEARANCE \
|
||||
(uint8_t) CONFIG_BT_DEVICE_APPEARANCE, (uint8_t)(CONFIG_BT_DEVICE_APPEARANCE >> 8)
|
||||
|
||||
BUILD_ASSERT(
|
||||
DEVICE_NAME_LEN <= CONFIG_BT_DEVICE_NAME_MAX,
|
||||
"ERROR: BLE device name is too long. Max length: " STRINGIFY(CONFIG_BT_DEVICE_NAME_MAX));
|
||||
|
||||
static struct bt_data zmk_ble_ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0xC1, 0x03),
|
||||
BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, DEVICE_APPEARANCE),
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_SOME, 0x12, 0x18, /* HID Service */
|
||||
0x0f, 0x18 /* Battery Service */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
#binding-cells = <0>;
|
||||
timeout-ms = <200>;
|
||||
|
||||
leader_seq_one {
|
||||
key-positions = <0>;
|
||||
bindings = <&kp A>;
|
||||
};
|
||||
|
||||
leader_seq_two {
|
||||
key-positions = <1>;
|
||||
bindings = <&kp B>;
|
||||
};
|
||||
|
||||
leader_seq_three {
|
||||
key-positions = <3>;
|
||||
bindings = <&kp N1>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp N1 &kp N2
|
||||
&kp N3 &leader
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
#binding-cells = <0>;
|
||||
timeout-ms = <200>;
|
||||
|
||||
leader_seq_one {
|
||||
key-positions = <0>;
|
||||
bindings = <&kp A>;
|
||||
};
|
||||
|
||||
leader_seq_two {
|
||||
key-positions = <1>;
|
||||
bindings = <&kp B>;
|
||||
};
|
||||
|
||||
leader_seq_three {
|
||||
key-positions = <0 1>;
|
||||
bindings = <&kp C>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp N1 &kp N2
|
||||
&kp N3 &leader
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
#binding-cells = <0>;
|
||||
timeout-ms = <200>;
|
||||
|
||||
leader_seq_one {
|
||||
key-positions = <0>;
|
||||
bindings = <&kp A>;
|
||||
immediate-trigger;
|
||||
};
|
||||
|
||||
leader_seq_two {
|
||||
key-positions = <1>;
|
||||
bindings = <&kp B>;
|
||||
};
|
||||
|
||||
leader_seq_three {
|
||||
key-positions = <0 1>;
|
||||
bindings = <&kp C>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp N1 &kp N2
|
||||
&kp N3 &leader
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
#binding-cells = <0>;
|
||||
|
||||
leader_seq_one {
|
||||
key-positions = <0>;
|
||||
bindings = <&kp A>;
|
||||
};
|
||||
|
||||
leader_seq_two {
|
||||
key-positions = <0 0>;
|
||||
bindings = <&kp B>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp N1 &kp N2
|
||||
&kp N3 &leader
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
#binding-cells = <0>;
|
||||
|
||||
leader_seq_one {
|
||||
key-positions = <0 1 2>;
|
||||
bindings = <&kp A>;
|
||||
};
|
||||
|
||||
leader_seq_two {
|
||||
key-positions = <3 3>;
|
||||
bindings = <&kp B>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp N1 &kp N2
|
||||
&kp N3 &leader
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x1E implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x1E implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap_three.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
leader: leader key activated
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap_overlap_immediate.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
leader: leader key activated
|
||||
leader: deactivating leader due to timeout
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap_overlap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
leader: leader key activated
|
||||
leader: deactivating leader due to timeout
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap_overlap_timerless.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap_overlap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap_overlap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include "../behavior_keymap_three.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_PRESS(0,2,10)
|
||||
ZMK_MOCK_RELEASE(0,2,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include "../behavior_keymap_three.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_PRESS(0,2,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,2,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include "../behavior_keymap_three.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_PRESS(0,2,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,2,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap_overlap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
leader: leader key activated
|
||||
leader: deactivating leader due to timeout
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*zmk_leader.*:/leader:/p
|
||||
s/.*leader_key.*:/leader:/p
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
leader: leader key activated
|
||||
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
leader: leader key deactivated
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,2000)
|
||||
>;
|
||||
};
|
||||
|
|
@ -16,3 +16,4 @@ See [Configuration Overview](index.md) for instructions on how to change these s
|
|||
| `CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES` | bool | Aggregate config that enables both `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` and `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC`. | n |
|
||||
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts.) | n |
|
||||
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |
|
||||
| `CONFIG_BT_DEVICE_APPEARANCE` | int | Bluetooth device [appearance value](https://bluetooth.com/specifications/assigned-numbers) (should be converted from hexadecimal to decimal). | 961 |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: Leader Configuration
|
||||
sidebar_label: Leader
|
||||
---
|
||||
|
||||
See the [Leader key behavior page](../keymaps/behaviors/leader-key.md) for more details and examples.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ----------------------------------------- | ---- | --------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE` | int | Maximum number of key positions per leader sequence | 4 |
|
||||
| `CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY` | int | Maximum number of sequences allowed per leader key | 5 |
|
||||
|
||||
`CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE` sets the maximum length of a leader sequence.
|
||||
|
||||
If `CONFIG_ZMK_LEADER_MAX_SEQUENCES_PER_KEY` is 5, you can have up to 5 separate leader sequences each for each leader key.
|
||||
|
|
@ -63,6 +63,7 @@ Below table lists major features/capabilities currently supported in ZMK, as wel
|
|||
| [Sticky (One Shot) Keys](keymaps/behaviors/sticky-key.md) | ✅ |
|
||||
| [Combos](keymaps/combos.md) | ✅ |
|
||||
| [Macros](keymaps/behaviors/macros.md) | ✅ |
|
||||
| [Leader Key](keymaps/behaviors/leader-key.md) | ✅ |
|
||||
| [Mouse Keys](keymaps/behaviors/mouse-emulation.md) | ✅ |
|
||||
| [Realtime Keymap Updating](features/studio.md) | 🚧 |
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
title: Leader Key Behavior
|
||||
sidebar_label: Leader Key
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The leader key behavior when triggered will capture all following key presses and trigger a leader sequence's behavior if pressed.
|
||||
|
||||
### Configuration
|
||||
|
||||
#### `timeout-ms`
|
||||
|
||||
Defines the amount of time to wait to trigger a completed leader sequence. Defaults to no timeout and will wait indefinitely.
|
||||
|
||||
#### `overlap-timeout-ms`
|
||||
|
||||
Defines the amount of time to wait to trigger a completed leader sequence after an overlapping sequence is completed. Defaults to 200ms.
|
||||
|
||||
### Leader Sequences
|
||||
|
||||
#### Summary
|
||||
|
||||
Leader sequences are a way to have a sequence of key presses to output a different key. For example, you can hit the leader key followed by Q, then W to output escape.
|
||||
|
||||
#### Configuration
|
||||
|
||||
Leader sequences are configured as child nodes of your leader key behavior(s). They are specified like this:
|
||||
|
||||
```
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
#binding-cells = <0>;
|
||||
|
||||
seq_esc {
|
||||
key-positions = <0 1>;
|
||||
bindings = <&kp ESC>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Each sequence can have the following properties:
|
||||
|
||||
- `key-positions` is an array of key positions. See the info section below about how to figure out the positions on your board.
|
||||
- `bindings` is the behavior that is activated when all the key positions are pressed.
|
||||
- (advanced) you can specify `immediate-trigger` if you want the sequence to be triggered as soon as all key positions are pressed. The default is to wait for the leader key's timeout to trigger the sequence if it overlaps another.
|
||||
|
||||
The `key-positions` array must not be longer than the `CONFIG_ZMK_LEADER_MAX_KEYS_PER_SEQUENCE` setting, which defaults to 4. If you want a leader sequence that triggers when pressing 5 keys, then you must change the setting to 5.
|
||||
|
||||
:::info
|
||||
|
||||
Key positions are numbered like the keys in your keymap, starting at 0. So, if the first key in your keymap is `Q`, this key is in position `0`. The next key (possibly `W`) will have position 1, etcetera.
|
||||
|
||||
:::
|
||||
|
||||
#### Locality
|
||||
|
||||
Sequence behaviors inherit their locality from the position of the leader key. For example, on split keyboards, a sequence using the `&bootloader` behavior will invoke the bootloader on the side on which the leader key is bound.
|
||||
|
||||
::::tip
|
||||
|
||||
Add the same leader key to both sides to be able to reset either side.
|
||||
|
||||
::::
|
||||
|
||||
### Example Usage
|
||||
|
||||
```
|
||||
leader: leader {
|
||||
compatible = "zmk,behavior-leader-key";
|
||||
binding-cells = <0>;
|
||||
|
||||
seq_b {
|
||||
key-positions = <1 1>;
|
||||
bindings = <&kp B>;
|
||||
};
|
||||
|
||||
seq_c {
|
||||
key-positions = <1>;
|
||||
bindings = <&kp C>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Advanced usage
|
||||
|
||||
See [leader configuration](../../config/leader.md) for advanced configuration options.
|
||||
|
|
@ -69,6 +69,7 @@ module.exports = {
|
|||
"keymaps/behaviors/hold-tap",
|
||||
"keymaps/behaviors/mod-morph",
|
||||
"keymaps/behaviors/macros",
|
||||
"keymaps/behaviors/leader-key",
|
||||
"keymaps/behaviors/key-toggle",
|
||||
"keymaps/behaviors/sticky-key",
|
||||
"keymaps/behaviors/sticky-layer",
|
||||
|
|
@ -126,6 +127,7 @@ module.exports = {
|
|||
"config/encoders",
|
||||
"config/lighting",
|
||||
"config/pointing",
|
||||
"config/leader",
|
||||
"config/keymap",
|
||||
"config/layout",
|
||||
"config/kscan",
|
||||
|
|
|
|||
Loading…
Reference in New Issue