feat: Allow layer behaviors to "lock" layers on (#2717)

* refactor(core)!: Allow layer behaviors to "lock" layers on

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>

* docs: Added documentation note on locking layers

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>

---------

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
This commit is contained in:
Nicolas Munnich
2025-11-14 22:13:35 +00:00
committed by GitHub
parent f9be3ed9c0
commit 5138c6fb14
34 changed files with 433 additions and 75 deletions

View File

@@ -15,6 +15,8 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
static const struct behavior_parameter_value_metadata param_values[] = {
@@ -36,16 +38,22 @@ static const struct behavior_parameter_metadata metadata = {
#endif
struct behavior_mo_config {
bool locking;
};
static int mo_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d layer %d", event.position, binding->param1);
return zmk_keymap_layer_activate(binding->param1);
const struct behavior_mo_config *cfg = zmk_behavior_get_binding(binding->behavior_dev)->config;
return zmk_keymap_layer_activate(binding->param1, cfg->locking);
}
static int mo_keymap_binding_released(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d layer %d", event.position, binding->param1);
return zmk_keymap_layer_deactivate(binding->param1);
const struct behavior_mo_config *cfg = zmk_behavior_get_binding(binding->behavior_dev)->config;
return zmk_keymap_layer_deactivate(binding->param1, cfg->locking);
}
static const struct behavior_driver_api behavior_mo_driver_api = {
@@ -56,5 +64,13 @@ static const struct behavior_driver_api behavior_mo_driver_api = {
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_mo_driver_api);
#define MO_INST(n) \
static const struct behavior_mo_config behavior_mo_config_##n = { \
.locking = DT_INST_PROP_OR(n, locking, false), \
}; \
BEHAVIOR_DT_INST_DEFINE(n, NULL, NULL, NULL, &behavior_mo_config_##n, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mo_driver_api);
DT_INST_FOREACH_STATUS_OKAY(MO_INST)
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View File

@@ -17,10 +17,15 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
struct behavior_to_config {
bool locking;
};
static int to_keymap_binding_pressed(struct zmk_behavior_binding *binding,
struct zmk_behavior_binding_event event) {
LOG_DBG("position %d layer %d", event.position, binding->param1);
zmk_keymap_layer_to(binding->param1);
const struct behavior_to_config *cfg = zmk_behavior_get_binding(binding->behavior_dev)->config;
zmk_keymap_layer_to(binding->param1, cfg->locking);
return ZMK_BEHAVIOR_OPAQUE;
}
@@ -59,7 +64,13 @@ static const struct behavior_driver_api behavior_to_driver_api = {
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
BEHAVIOR_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_to_driver_api);
#define TO_INST(n) \
static const struct behavior_to_config behavior_to_config_##n = { \
.locking = DT_INST_PROP_OR(n, locking, false), \
}; \
BEHAVIOR_DT_INST_DEFINE(n, NULL, NULL, NULL, &behavior_to_config_##n, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_to_driver_api);
DT_INST_FOREACH_STATUS_OKAY(TO_INST)
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

View File

@@ -25,6 +25,7 @@ enum toggle_mode {
struct behavior_tog_config {
enum toggle_mode toggle_mode;
bool locking;
};
static int tog_keymap_binding_pressed(struct zmk_behavior_binding *binding,
@@ -34,11 +35,11 @@ static int tog_keymap_binding_pressed(struct zmk_behavior_binding *binding,
const struct behavior_tog_config *cfg = zmk_behavior_get_binding(binding->behavior_dev)->config;
switch (cfg->toggle_mode) {
case ON:
return zmk_keymap_layer_activate(binding->param1);
return zmk_keymap_layer_activate(binding->param1, cfg->locking);
case OFF:
return zmk_keymap_layer_deactivate(binding->param1);
return zmk_keymap_layer_deactivate(binding->param1, cfg->locking);
case FLIP:
return zmk_keymap_layer_toggle(binding->param1);
return zmk_keymap_layer_toggle(binding->param1, cfg->locking);
default:
return -ENOTSUP;
};
@@ -79,13 +80,14 @@ static const struct behavior_driver_api behavior_tog_driver_api = {
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA)
};
#define KT_INST(n) \
#define TG_INST(n) \
static const struct behavior_tog_config behavior_tog_config_##n = { \
.toggle_mode = DT_ENUM_IDX(DT_DRV_INST(n), toggle_mode), \
.locking = DT_INST_PROP_OR(n, locking, false), \
}; \
BEHAVIOR_DT_INST_DEFINE(n, NULL, NULL, NULL, &behavior_tog_config_##n, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_tog_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KT_INST)
DT_INST_FOREACH_STATUS_OKAY(TG_INST)
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */