From 7cf4c429fa07d7ea7d1e787596c99c5811507828 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 6 Nov 2023 12:58:20 -0800 Subject: [PATCH] allow custom &molock fallback behaviors --- app/dts/behaviors/momentary_layer_lock.dtsi | 3 +- .../zmk,behavior-momentary-layer-lock.yaml | 7 +- .../behaviors/behavior_momentary_layer_lock.c | 72 ++++++++++++++++--- 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/app/dts/behaviors/momentary_layer_lock.dtsi b/app/dts/behaviors/momentary_layer_lock.dtsi index 792c2195..e1d49201 100644 --- a/app/dts/behaviors/momentary_layer_lock.dtsi +++ b/app/dts/behaviors/momentary_layer_lock.dtsi @@ -9,7 +9,8 @@ /omit-if-no-ref/ molock: behavior_momentary_layer_lock { compatible = "zmk,behavior-momentary-layer-lock"; label = "MO_LOCK"; - #binding-cells = <1>; + #binding-cells = <0>; + bindings = <&to 0>; }; }; }; diff --git a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer-lock.yaml b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer-lock.yaml index 9d32afc1..dc7138fb 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer-lock.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer-lock.yaml @@ -5,4 +5,9 @@ description: Momentary layer on press/release behavior compatible: "zmk,behavior-momentary-layer-lock" -include: one_param.yaml +include: zero_param.yaml + +properties: + bindings: + type: phandle-array + required: true diff --git a/app/src/behaviors/behavior_momentary_layer_lock.c b/app/src/behaviors/behavior_momentary_layer_lock.c index b2d03792..cca22397 100644 --- a/app/src/behaviors/behavior_momentary_layer_lock.c +++ b/app/src/behaviors/behavior_momentary_layer_lock.c @@ -18,23 +18,79 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +struct behavior_mo_lock_config { + struct zmk_behavior_binding fallback_binding; +}; + +struct behavior_mo_lock_data { + bool is_fallback_binding_pressed; +}; + static int behavior_mo_lock_init(const struct device *dev) { return 0; }; static int mo_lock_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { - int fallback_layer = binding->param1; - zmk_keymap_layers_state_t locked = zmk_lock_active_momentary_layers(); - if (!locked && fallback_layer >= 0) { - return zmk_keymap_layer_to(fallback_layer); + LOG_DBG("%d molock pressed", event.position); + + zmk_keymap_layers_state_t locked_layers = zmk_lock_active_momentary_layers(); + + if (!locked_layers) { + LOG_DBG("no layers locked, falling back to %s", binding->behavior_dev); + + const struct device *dev = zmk_behavior_get_binding(binding->behavior_dev); + const struct behavior_mo_lock_config *config = dev->config; + struct zmk_behavior_binding fallback_binding = config->fallback_binding; + struct behavior_mo_lock_data *data = dev->data; + + data->is_fallback_binding_pressed = true; + return behavior_keymap_binding_pressed(&fallback_binding, event); + } else { + LOG_DBG("locked layers: %#08x", locked_layers); } return 0; } -static const struct behavior_driver_api behavior_mo_lock_driver_api = { - .binding_pressed = mo_lock_keymap_binding_pressed}; +static int mo_lock_keymap_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + LOG_DBG("%d molock released", event.position); -DEVICE_DT_INST_DEFINE(0, behavior_mo_lock_init, NULL, NULL, NULL, APPLICATION, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mo_lock_driver_api); + const struct device *dev = zmk_behavior_get_binding(binding->behavior_dev); + struct behavior_mo_lock_data *data = dev->data; + + if (data->is_fallback_binding_pressed) { + const struct behavior_mo_lock_config *config = dev->config; + struct zmk_behavior_binding fallback_binding = config->fallback_binding; + + data->is_fallback_binding_pressed = false; + return behavior_keymap_binding_released(&fallback_binding, event); + } + + return 0; +} + +#define KP_INST(n) \ + static struct behavior_mo_lock_config behavior_mo_lock_config_##n = { \ + .fallback_binding = \ + { \ + .behavior_dev = DT_PROP(DT_INST_PHANDLE_BY_IDX(n, bindings, 0), label), \ + .param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(n, bindings, 0, param1), (0), \ + (DT_INST_PHA_BY_IDX(n, bindings, 0, param1))), \ + .param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(n, bindings, 0, param2), (0), \ + (DT_INST_PHA_BY_IDX(n, bindings, 0, param))), \ + }, \ + }; \ + static struct behavior_mo_lock_data behavior_mo_lock_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, behavior_mo_lock_init, NULL, &behavior_mo_lock_data_##n, \ + &behavior_mo_lock_config_##n, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mo_lock_driver_api); + +static const struct behavior_driver_api behavior_mo_lock_driver_api = { + .binding_pressed = mo_lock_keymap_binding_pressed, + .binding_released = mo_lock_keymap_binding_released, +}; + +DT_INST_FOREACH_STATUS_OKAY(KP_INST) #endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ \ No newline at end of file