From 5bf75a645bf6a9728998c2fe4d75350314250e71 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich Date: Mon, 16 Dec 2024 17:07:14 +0100 Subject: [PATCH] feat: Allow layer behaviors to "lock" layers on --- app/dts/behaviors/to_layer.dtsi | 1 + app/dts/behaviors/toggle_layer.dtsi | 1 + .../zmk,behavior-momentary-layer.yaml | 5 ++ .../behaviors/zmk,behavior-to-layer.yaml | 5 ++ .../behaviors/zmk,behavior-toggle-layer.yaml | 4 +- app/include/zmk/keymap.h | 8 +-- app/src/behaviors/behavior_momentary_layer.c | 23 +++++-- app/src/behaviors/behavior_to_layer.c | 17 ++++- app/src/behaviors/behavior_toggle_layer.c | 8 ++- app/src/conditional_layer.c | 4 +- app/src/keymap.c | 35 ++++++---- app/src/pointing/input_processor_temp_layer.c | 4 +- .../locked-layers/events.patterns | 4 ++ .../locked-layers/keycode_events.snapshot | 21 ++++++ .../locked-layers/native_posix_64.keymap | 64 +++++++++++++++++++ app/tests/toggle-layer/behavior_keymap.dtsi | 16 ++++- app/tests/toggle-layer/force/events.patterns | 3 + .../force/keycode_events.snapshot | 16 +++++ .../toggle-layer/force/native_posix_64.keymap | 29 +++++++++ 19 files changed, 232 insertions(+), 36 deletions(-) create mode 100644 app/tests/conditional-layer/locked-layers/events.patterns create mode 100644 app/tests/conditional-layer/locked-layers/keycode_events.snapshot create mode 100644 app/tests/conditional-layer/locked-layers/native_posix_64.keymap create mode 100644 app/tests/toggle-layer/force/events.patterns create mode 100644 app/tests/toggle-layer/force/keycode_events.snapshot create mode 100644 app/tests/toggle-layer/force/native_posix_64.keymap diff --git a/app/dts/behaviors/to_layer.dtsi b/app/dts/behaviors/to_layer.dtsi index 532636a6ed2e..89bc91ca56c3 100644 --- a/app/dts/behaviors/to_layer.dtsi +++ b/app/dts/behaviors/to_layer.dtsi @@ -15,6 +15,7 @@ compatible = "zmk,behavior-to-layer"; #binding-cells = <1>; display-name = "To Layer"; + locking; }; }; }; diff --git a/app/dts/behaviors/toggle_layer.dtsi b/app/dts/behaviors/toggle_layer.dtsi index 81846e77c029..a0c853403748 100644 --- a/app/dts/behaviors/toggle_layer.dtsi +++ b/app/dts/behaviors/toggle_layer.dtsi @@ -15,6 +15,7 @@ compatible = "zmk,behavior-toggle-layer"; #binding-cells = <1>; display-name = "Toggle Layer"; + locking; }; }; }; diff --git a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml index 5423e29c402a..453dbcd2cb46 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml @@ -6,3 +6,8 @@ description: Momentary layer on press/release behavior compatible: "zmk,behavior-momentary-layer" include: one_param.yaml + +properties: + locking: + type: boolean + description: Whether to "lock" the layer active, preventing behaviors without the "locking" property from deactivating the layer diff --git a/app/dts/bindings/behaviors/zmk,behavior-to-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-to-layer.yaml index cbafddf73a05..52deecd3c493 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-to-layer.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-to-layer.yaml @@ -6,3 +6,8 @@ description: To Layer compatible: "zmk,behavior-to-layer" include: one_param.yaml + +properties: + locking: + type: boolean + description: Whether to "lock" the layer active, preventing behaviors without the "locking" property from deactivating the layer diff --git a/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml index 1ab0179c4929..71d70a3aaf10 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml @@ -10,9 +10,11 @@ include: one_param.yaml properties: toggle-mode: type: string - required: false default: "flip" enum: - "on" - "off" - "flip" + locking: + type: boolean + description: Whether to "lock" the layer active, preventing behaviors without the "locking" property from deactivating the layer diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index 9b278a6050f9..323e62915427 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -35,10 +35,10 @@ zmk_keymap_layer_id_t zmk_keymap_layer_default(void); zmk_keymap_layers_state_t zmk_keymap_layer_state(void); bool zmk_keymap_layer_active(zmk_keymap_layer_id_t layer); zmk_keymap_layer_index_t zmk_keymap_highest_layer_active(void); -int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer); -int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer); -int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer); -int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer); +int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer, bool locking); +int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer, bool locking); +int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer, bool locking); +int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer, bool locking); const char *zmk_keymap_layer_name(zmk_keymap_layer_id_t layer); const struct zmk_behavior_binding *zmk_keymap_get_layer_binding_at_idx(zmk_keymap_layer_id_t layer, diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c index b781a9537714..363b4f4a9ab0 100644 --- a/app/src/behaviors/behavior_momentary_layer.c +++ b/app/src/behaviors/behavior_momentary_layer.c @@ -36,21 +36,25 @@ static const struct behavior_parameter_metadata metadata = { #endif -struct behavior_mo_config {}; struct behavior_mo_data {}; +struct behavior_mo_config { + bool locking; +}; static int behavior_mo_init(const struct device *dev) { return 0; }; 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 = { @@ -61,9 +65,14 @@ static const struct behavior_driver_api behavior_mo_driver_api = { #endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) }; -static const struct behavior_mo_config behavior_mo_config = {}; - static struct behavior_mo_data behavior_mo_data; -BEHAVIOR_DT_INST_DEFINE(0, behavior_mo_init, NULL, &behavior_mo_data, &behavior_mo_config, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mo_driver_api); +#define KT_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, behavior_mo_init, NULL, &behavior_mo_data, &behavior_mo_config_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &behavior_mo_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(KT_INST) \ No newline at end of file diff --git a/app/src/behaviors/behavior_to_layer.c b/app/src/behaviors/behavior_to_layer.c index f739ec8debfc..b17192448b7e 100644 --- a/app/src/behaviors/behavior_to_layer.c +++ b/app/src/behaviors/behavior_to_layer.c @@ -17,12 +17,17 @@ 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 behavior_to_init(const struct device *dev) { return 0; }; 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; } @@ -61,7 +66,13 @@ static const struct behavior_driver_api behavior_to_driver_api = { #endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) }; -BEHAVIOR_DT_INST_DEFINE(0, behavior_to_init, NULL, NULL, NULL, POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_to_driver_api); +#define KT_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, behavior_to_init, NULL, NULL, &behavior_to_config_##n, POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_to_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(KT_INST) #endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/behaviors/behavior_toggle_layer.c b/app/src/behaviors/behavior_toggle_layer.c index c804f5844c38..70fbb87ffb03 100644 --- a/app/src/behaviors/behavior_toggle_layer.c +++ b/app/src/behaviors/behavior_toggle_layer.c @@ -25,6 +25,7 @@ enum toggle_mode { struct behavior_tog_config { enum toggle_mode toggle_mode; + bool locking; }; static int behavior_tog_init(const struct device *dev) { return 0; }; @@ -36,11 +37,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; }; @@ -84,6 +85,7 @@ static const struct behavior_driver_api behavior_tog_driver_api = { #define KT_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, behavior_tog_init, NULL, NULL, &behavior_tog_config_##n, \ POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ diff --git a/app/src/conditional_layer.c b/app/src/conditional_layer.c index 9ba02a5ce4c8..8d7ea027a9ac 100644 --- a/app/src/conditional_layer.c +++ b/app/src/conditional_layer.c @@ -54,7 +54,7 @@ static void conditional_layer_activate(int8_t layer) { // the process will eventually terminate (at worst, when every layer is active). if (!zmk_keymap_layer_active(layer)) { LOG_DBG("layer %d", layer); - zmk_keymap_layer_activate(layer); + zmk_keymap_layer_activate(layer, false); } } @@ -64,7 +64,7 @@ static void conditional_layer_deactivate(int8_t layer) { // &mo binding are held and then one is released, so it's probably not an issue in practice. if (zmk_keymap_layer_active(layer)) { LOG_DBG("layer %d", layer); - zmk_keymap_layer_deactivate(layer); + zmk_keymap_layer_deactivate(layer, false); } } diff --git a/app/src/keymap.c b/app/src/keymap.c index 16b24bf27462..d760fb2c550e 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -23,6 +23,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +static zmk_keymap_layers_state_t _zmk_keymap_layer_locks = 0; static zmk_keymap_layers_state_t _zmk_keymap_layer_state = 0; static zmk_keymap_layer_id_t _zmk_keymap_layer_default = 0; @@ -131,7 +132,7 @@ uint8_t map_layer_id_to_index(zmk_keymap_layer_id_t layer_id) { #endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) -static inline int set_layer_state(zmk_keymap_layer_id_t layer_id, bool state) { +static inline int set_layer_state(zmk_keymap_layer_id_t layer_id, bool state, bool locking) { int ret = 0; if (layer_id >= ZMK_KEYMAP_LAYERS_LEN) { return -EINVAL; @@ -142,11 +143,21 @@ static inline int set_layer_state(zmk_keymap_layer_id_t layer_id, bool state) { return 0; } + // Non-forcing disables should not change a locked active layer + if (!locking && !state && ((_zmk_keymap_layer_locks >> layer_id) & 1)) { + return ret; + } + zmk_keymap_layers_state_t old_state = _zmk_keymap_layer_state; + zmk_keymap_layers_state_t old_locks = _zmk_keymap_layer_locks; WRITE_BIT(_zmk_keymap_layer_state, layer_id, state); + if (locking) { + WRITE_BIT(_zmk_keymap_layer_locks, layer_id, state); + } // Don't send state changes unless there was an actual change if (old_state != _zmk_keymap_layer_state) { - LOG_DBG("layer_changed: layer %d state %d", layer_id, state); + LOG_DBG("layer_changed: layer %d state %d locked %d", layer_id, state, locking); + ret = raise_layer_state_changed(layer_id, state); if (ret < 0) { LOG_WRN("Failed to raise layer state changed (%d)", ret); @@ -193,26 +204,28 @@ zmk_keymap_layer_index_t zmk_keymap_highest_layer_active(void) { return LAYER_ID_TO_INDEX(zmk_keymap_layer_default()); } -int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer) { return set_layer_state(layer, true); }; +int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer, bool locking) { + return set_layer_state(layer, true, locking); +}; -int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer) { - return set_layer_state(layer, false); +int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer, bool locking) { + return set_layer_state(layer, false, locking); }; -int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer) { +int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer, bool locking) { if (zmk_keymap_layer_active(layer)) { - return zmk_keymap_layer_deactivate(layer); + return zmk_keymap_layer_deactivate(layer, locking); } - return zmk_keymap_layer_activate(layer); + return zmk_keymap_layer_activate(layer, locking); }; -int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer) { +int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer, bool locking) { for (int i = ZMK_KEYMAP_LAYERS_LEN - 1; i >= 0; i--) { - zmk_keymap_layer_deactivate(i); + zmk_keymap_layer_deactivate(i, locking); } - zmk_keymap_layer_activate(layer); + zmk_keymap_layer_activate(layer, locking); return 0; } diff --git a/app/src/pointing/input_processor_temp_layer.c b/app/src/pointing/input_processor_temp_layer.c index 85a394a693ff..c6e65ffc62cd 100644 --- a/app/src/pointing/input_processor_temp_layer.c +++ b/app/src/pointing/input_processor_temp_layer.c @@ -70,10 +70,10 @@ static void update_layer_state(struct temp_layer_state *state, bool activate) { state->is_active = activate; if (activate) { - zmk_keymap_layer_activate(state->toggle_layer); + zmk_keymap_layer_activate(state->toggle_layer, false); LOG_DBG("Layer %d activated", state->toggle_layer); } else { - zmk_keymap_layer_deactivate(state->toggle_layer); + zmk_keymap_layer_deactivate(state->toggle_layer, false); LOG_DBG("Layer %d deactivated", state->toggle_layer); } } diff --git a/app/tests/conditional-layer/locked-layers/events.patterns b/app/tests/conditional-layer/locked-layers/events.patterns new file mode 100644 index 000000000000..30bd2338f690 --- /dev/null +++ b/app/tests/conditional-layer/locked-layers/events.patterns @@ -0,0 +1,4 @@ +s/.*hid_listener_keycode/kp/p +s/.*mo_keymap_binding/mo/p +s/.*tog_keymap_binding/tog/p +s/.*conditional_layer/cl/p diff --git a/app/tests/conditional-layer/locked-layers/keycode_events.snapshot b/app/tests/conditional-layer/locked-layers/keycode_events.snapshot new file mode 100644 index 000000000000..b1845f6bbf6c --- /dev/null +++ b/app/tests/conditional-layer/locked-layers/keycode_events.snapshot @@ -0,0 +1,21 @@ +kp_pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +tog_pressed: position 2 layer 1 +tog_released: position 2 layer 1 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +tog_pressed: position 3 layer 2 +cl_activate: layer 3 +tog_released: position 3 layer 2 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +mo_pressed: position 1 layer 3 +mo_released: position 1 layer 3 +cl_activate: layer 3 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +tog_pressed: position 2 layer 1 +cl_deactivate: layer 3 +tog_released: position 2 layer 1 +kp_pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/conditional-layer/locked-layers/native_posix_64.keymap b/app/tests/conditional-layer/locked-layers/native_posix_64.keymap new file mode 100644 index 000000000000..5c6c15dbba64 --- /dev/null +++ b/app/tests/conditional-layer/locked-layers/native_posix_64.keymap @@ -0,0 +1,64 @@ +#include +#include +#include + +/ { + conditional_layers { + compatible = "zmk,conditional-layers"; + tri_layer { + if-layers = <1 2>; + then-layer = <3>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + default_layer { + bindings = < + &kp A &mo 3 + &tog 1 &tog 2 + >; + }; + layer_1 { + bindings = < + &kp B &trans + &trans &trans + >; + }; + layer_2 { + bindings = < + &kp C &trans + &trans &trans + >; + }; + layer_3 { + bindings = < + &kp D &trans + &trans &trans + >; + }; + }; +}; + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(1,0,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,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,1,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + >; +}; diff --git a/app/tests/toggle-layer/behavior_keymap.dtsi b/app/tests/toggle-layer/behavior_keymap.dtsi index 7c712a874f51..8fbf4858ddfc 100644 --- a/app/tests/toggle-layer/behavior_keymap.dtsi +++ b/app/tests/toggle-layer/behavior_keymap.dtsi @@ -3,13 +3,23 @@ #include / { + behaviors { + tog_off: toggle_layer_off_only { + compatible = "zmk,behavior-toggle-layer"; + #binding-cells = <1>; + display-name = "Toggle Layer Off"; + toggle-mode = "off"; + locking; + }; + }; + keymap { compatible = "zmk,keymap"; default_layer { bindings = < &kp B &tog 1 - &kp D &to 1>; + &mo 2 &to 1>; }; lower_layer { @@ -20,8 +30,8 @@ raise_layer { bindings = < - &kp W &kp U - &kp X &kp M>; + &kp W &tog 2 + &tog_off 2 &mo 2>; }; }; }; diff --git a/app/tests/toggle-layer/force/events.patterns b/app/tests/toggle-layer/force/events.patterns new file mode 100644 index 000000000000..05b8cd15e31c --- /dev/null +++ b/app/tests/toggle-layer/force/events.patterns @@ -0,0 +1,3 @@ +s/.*hid_listener_keycode/kp/p +s/.*tog_keymap_binding/tog/p +s/.*mo_keymap_binding/mo/p \ No newline at end of file diff --git a/app/tests/toggle-layer/force/keycode_events.snapshot b/app/tests/toggle-layer/force/keycode_events.snapshot new file mode 100644 index 000000000000..e5d9061a5c6a --- /dev/null +++ b/app/tests/toggle-layer/force/keycode_events.snapshot @@ -0,0 +1,16 @@ +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +mo_pressed: position 2 layer 2 +tog_pressed: position 1 layer 2 +tog_released: position 1 layer 2 +mo_released: position 2 layer 2 +kp_pressed: usage_page 0x07 keycode 0x1A implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x1A implicit_mods 0x00 explicit_mods 0x00 +mo_pressed: position 3 layer 2 +mo_released: position 3 layer 2 +kp_pressed: usage_page 0x07 keycode 0x1A implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x1A implicit_mods 0x00 explicit_mods 0x00 +tog_pressed: position 2 layer 2 +tog_released: position 2 layer 2 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/toggle-layer/force/native_posix_64.keymap b/app/tests/toggle-layer/force/native_posix_64.keymap new file mode 100644 index 000000000000..6f52e4338e8f --- /dev/null +++ b/app/tests/toggle-layer/force/native_posix_64.keymap @@ -0,0 +1,29 @@ +#include +#include +#include +#include "../behavior_keymap.dtsi" + +&tog { + toggle-mode = "on"; +}; + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,1,10) + ZMK_MOCK_RELEASE(1,0,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,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + >; +}; \ No newline at end of file