mirror of
https://github.com/zmkfirmware/zmk.git
synced 2026-03-19 20:45:18 -05:00
chore: Add basic tests for Studio's layer manipulation (#3164)
chore: Add test behaviors for Studio testing chore: Add basic tests for studio layer adjustment chore: Fixes from code review
This commit is contained in:
@@ -11,11 +11,12 @@
|
|||||||
#include <zephyr/devicetree.h>
|
#include <zephyr/devicetree.h>
|
||||||
|
|
||||||
#define ZMK_KEYMAP_LAYERS_FOREACH(_fn) \
|
#define ZMK_KEYMAP_LAYERS_FOREACH(_fn) \
|
||||||
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_STUDIO), (DT_FOREACH_CHILD(DT_INST(0, zmk_keymap), _fn)), \
|
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING), \
|
||||||
|
(DT_FOREACH_CHILD(DT_INST(0, zmk_keymap), _fn)), \
|
||||||
(DT_FOREACH_CHILD_STATUS_OKAY(DT_INST(0, zmk_keymap), _fn)))
|
(DT_FOREACH_CHILD_STATUS_OKAY(DT_INST(0, zmk_keymap), _fn)))
|
||||||
|
|
||||||
#define ZMK_KEYMAP_LAYERS_FOREACH_SEP(_fn, _sep) \
|
#define ZMK_KEYMAP_LAYERS_FOREACH_SEP(_fn, _sep) \
|
||||||
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_STUDIO), \
|
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING), \
|
||||||
(DT_FOREACH_CHILD_SEP(DT_INST(0, zmk_keymap), _fn, _sep)), \
|
(DT_FOREACH_CHILD_SEP(DT_INST(0, zmk_keymap), _fn, _sep)), \
|
||||||
(DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_INST(0, zmk_keymap), _fn, _sep)))
|
(DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_INST(0, zmk_keymap), _fn, _sep)))
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
zephyr_include_directories(include)
|
zephyr_include_directories(include)
|
||||||
|
|
||||||
add_subdirectory(drivers)
|
add_subdirectory(drivers)
|
||||||
|
add_subdirectory(test-behaviors)
|
||||||
add_subdirectory(lib)
|
add_subdirectory(lib)
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
rsource "drivers/Kconfig"
|
rsource "drivers/Kconfig"
|
||||||
rsource "lib/Kconfig"
|
rsource "lib/Kconfig"
|
||||||
|
rsource "test-behaviors/Kconfig"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Copyright (c) 2025 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: Layer Adder Behavior
|
||||||
|
|
||||||
|
compatible: "zmk,behavior-add-layer"
|
||||||
|
|
||||||
|
include: zero_param.yaml
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Copyright (c) 2025 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: Layer Mover Behavior
|
||||||
|
|
||||||
|
compatible: "zmk,behavior-move-layer"
|
||||||
|
|
||||||
|
include: two_param.yaml
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Copyright (c) 2025 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: Layer Remover Behavior
|
||||||
|
|
||||||
|
compatible: "zmk,behavior-remove-layer"
|
||||||
|
|
||||||
|
include: one_param.yaml
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Copyright (c) 2025 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: Layer Binding Setter Behavior
|
||||||
|
|
||||||
|
compatible: "zmk,behavior-set-layer-binding-at-idx"
|
||||||
|
|
||||||
|
include: two_param.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
bindings:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
6
app/module/test-behaviors/CMakeLists.txt
Normal file
6
app/module/test-behaviors/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
if (((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) AND CONFIG_ZMK_TEST_BEHAVIORS)
|
||||||
|
target_sources(app PRIVATE behavior_add_layer.c)
|
||||||
|
target_sources(app PRIVATE behavior_move_layer.c)
|
||||||
|
target_sources(app PRIVATE behavior_remove_layer.c)
|
||||||
|
target_sources(app PRIVATE behavior_set_layer_binding_at_idx.c)
|
||||||
|
endif()
|
||||||
2
app/module/test-behaviors/Kconfig
Normal file
2
app/module/test-behaviors/Kconfig
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
config ZMK_TEST_BEHAVIORS
|
||||||
|
bool "Include behaviors used for testing purposes"
|
||||||
50
app/module/test-behaviors/behavior_add_layer.c
Normal file
50
app/module/test-behaviors/behavior_add_layer.c
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_behavior_add_layer
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
#include <zmk/behavior.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#if (IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)) && (DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT))
|
||||||
|
|
||||||
|
static int on_add_layer_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
int new_layer = zmk_keymap_add_layer();
|
||||||
|
if (new_layer >= 0) {
|
||||||
|
LOG_DBG("Added layer %d", new_layer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (new_layer) {
|
||||||
|
case -ENOSPC:
|
||||||
|
LOG_ERR("No more layers can be added. Out of memory.");
|
||||||
|
return -ENOSPC;
|
||||||
|
default:
|
||||||
|
LOG_ERR("Unknown error adding layer: %d", new_layer);
|
||||||
|
return new_layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_add_layer_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct behavior_driver_api behavior_add_layer_driver_api = {
|
||||||
|
.binding_pressed = on_add_layer_binding_pressed,
|
||||||
|
.binding_released = on_add_layer_binding_released};
|
||||||
|
|
||||||
|
BEHAVIOR_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||||
|
&behavior_add_layer_driver_api);
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) AND
|
||||||
|
// DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
47
app/module/test-behaviors/behavior_move_layer.c
Normal file
47
app/module/test-behaviors/behavior_move_layer.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_behavior_move_layer
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
#include <zmk/behavior.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#if (IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)) && (DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT))
|
||||||
|
|
||||||
|
static int on_move_layer_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
int result = zmk_keymap_move_layer(binding->param1, binding->param2);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
LOG_ERR("Failed to move layer from index %d to index %d (err: %d)", binding->param1,
|
||||||
|
binding->param2, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("Moved layer from index %d to index %d", binding->param1, binding->param2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_move_layer_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct behavior_driver_api behavior_move_layer_driver_api = {
|
||||||
|
.binding_pressed = on_move_layer_binding_pressed,
|
||||||
|
.binding_released = on_move_layer_binding_released};
|
||||||
|
|
||||||
|
BEHAVIOR_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||||
|
&behavior_move_layer_driver_api);
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) AND
|
||||||
|
// DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
49
app/module/test-behaviors/behavior_remove_layer.c
Normal file
49
app/module/test-behaviors/behavior_remove_layer.c
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_behavior_remove_layer
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
#include <zmk/behavior.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#if (IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)) && (DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT))
|
||||||
|
|
||||||
|
static int on_remove_layer_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
int result = zmk_keymap_remove_layer(binding->param1);
|
||||||
|
if (result >= 0) {
|
||||||
|
LOG_DBG("Removed layer at index %d", binding->param1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (result) {
|
||||||
|
case -EINVAL:
|
||||||
|
LOG_ERR("Layer at index %d not found", binding->param1);
|
||||||
|
return -EINVAL;
|
||||||
|
default:
|
||||||
|
LOG_DBG("Unknown error removing layer at index %d: %d", binding->param1, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_remove_layer_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct behavior_driver_api behavior_remove_layer_driver_api = {
|
||||||
|
.binding_pressed = on_remove_layer_binding_pressed,
|
||||||
|
.binding_released = on_remove_layer_binding_released};
|
||||||
|
|
||||||
|
BEHAVIOR_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||||
|
&behavior_remove_layer_driver_api);
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) AND
|
||||||
|
// DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
100
app/module/test-behaviors/behavior_set_layer_binding_at_idx.c
Normal file
100
app/module/test-behaviors/behavior_set_layer_binding_at_idx.c
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_behavior_set_layer_binding_at_idx
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
#include <zmk/behavior.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
|
|
||||||
|
struct behavior_set_layer_binding_at_idx_config {
|
||||||
|
size_t bindings_len;
|
||||||
|
struct zmk_behavior_binding *bindings;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct behavior_set_layer_binding_at_idx_data {
|
||||||
|
size_t current_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int on_set_layer_binding_at_idx_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
const struct device *dev = zmk_behavior_get_binding(binding->behavior_dev);
|
||||||
|
const struct behavior_set_layer_binding_at_idx_config *cfg = dev->config;
|
||||||
|
struct behavior_set_layer_binding_at_idx_data *data = dev->data;
|
||||||
|
|
||||||
|
if (cfg->bindings_len == 0) {
|
||||||
|
LOG_ERR("No bindings configured");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zmk_behavior_binding *binding_to_set = &cfg->bindings[data->current_idx];
|
||||||
|
|
||||||
|
int result =
|
||||||
|
zmk_keymap_set_layer_binding_at_idx(binding->param1, binding->param2, *binding_to_set);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
LOG_ERR("Failed to set binding at layer %d, index %d (err: %d)", binding->param1,
|
||||||
|
binding->param2, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("Set binding at layer %d, index %d to binding %zu/%zu", binding->param1,
|
||||||
|
binding->param2, data->current_idx + 1, cfg->bindings_len);
|
||||||
|
|
||||||
|
// Move to next binding, wrap around if at end
|
||||||
|
data->current_idx = (data->current_idx + 1) % cfg->bindings_len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_set_layer_binding_at_idx_binding_released(struct zmk_behavior_binding *binding,
|
||||||
|
struct zmk_behavior_binding_event event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct behavior_driver_api behavior_set_layer_binding_at_idx_driver_api = {
|
||||||
|
.binding_pressed = on_set_layer_binding_at_idx_binding_pressed,
|
||||||
|
.binding_released = on_set_layer_binding_at_idx_binding_released};
|
||||||
|
|
||||||
|
static int behavior_set_layer_binding_at_idx_init(const struct device *dev) {
|
||||||
|
struct behavior_set_layer_binding_at_idx_data *data = dev->data;
|
||||||
|
data->current_idx = 0;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _TRANSFORM_ENTRY(idx, node) ZMK_KEYMAP_EXTRACT_BINDING(idx, node)
|
||||||
|
|
||||||
|
#define TRANSFORMED_BINDINGS(node) \
|
||||||
|
{LISTIFY(DT_INST_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, (, ), DT_DRV_INST(node))}
|
||||||
|
|
||||||
|
#define SET_LAYER_BINDING_AT_IDX_INST(n) \
|
||||||
|
static struct behavior_set_layer_binding_at_idx_data \
|
||||||
|
behavior_set_layer_binding_at_idx_data_##n = {}; \
|
||||||
|
\
|
||||||
|
static const struct zmk_behavior_binding \
|
||||||
|
behavior_set_layer_binding_at_idx_config_##n##_bindings[DT_INST_PROP_LEN(n, bindings)] = \
|
||||||
|
TRANSFORMED_BINDINGS(n); \
|
||||||
|
static const struct behavior_set_layer_binding_at_idx_config \
|
||||||
|
behavior_set_layer_binding_at_idx_config_##n = { \
|
||||||
|
.bindings_len = DT_INST_PROP_LEN(n, bindings), \
|
||||||
|
.bindings = behavior_set_layer_binding_at_idx_config_##n##_bindings}; \
|
||||||
|
\
|
||||||
|
BEHAVIOR_DT_INST_DEFINE(n, behavior_set_layer_binding_at_idx_init, NULL, \
|
||||||
|
&behavior_set_layer_binding_at_idx_data_##n, \
|
||||||
|
&behavior_set_layer_binding_at_idx_config_##n, POST_KERNEL, \
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||||
|
&behavior_set_layer_binding_at_idx_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(SET_LAYER_BINDING_AT_IDX_INST)
|
||||||
|
|
||||||
|
#endif // DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
@@ -41,6 +41,12 @@ build_cmd="west build ${ZMK_SRC_DIR:+-s $ZMK_SRC_DIR} -d ${ZMK_BUILD_DIR}/tests/
|
|||||||
-b native_sim/native/64 -p -- -DCONFIG_ASSERT=y -DZMK_CONFIG="$(realpath $path)" \
|
-b native_sim/native/64 -p -- -DCONFIG_ASSERT=y -DZMK_CONFIG="$(realpath $path)" \
|
||||||
${ZMK_EXTRA_MODULES:+-DZMK_EXTRA_MODULES="$(realpath ${ZMK_EXTRA_MODULES})"}"
|
${ZMK_EXTRA_MODULES:+-DZMK_EXTRA_MODULES="$(realpath ${ZMK_EXTRA_MODULES})"}"
|
||||||
|
|
||||||
|
# Add extra cmake arguments from file if it exists
|
||||||
|
if [ -f "$path/extra-cmake-args" ]; then
|
||||||
|
extra_args=$(cat "$path/extra-cmake-args" | tr '\n' ' ')
|
||||||
|
build_cmd="$build_cmd $extra_args"
|
||||||
|
fi
|
||||||
|
|
||||||
build_log_tmp="${ZMK_BUILD_DIR}/tmp/$testcase/build.log"
|
build_log_tmp="${ZMK_BUILD_DIR}/tmp/$testcase/build.log"
|
||||||
build_log="${ZMK_BUILD_DIR}/tests/$testcase/build.log"
|
build_log="${ZMK_BUILD_DIR}/tests/$testcase/build.log"
|
||||||
mkdir -p $(dirname $build_log_tmp)
|
mkdir -p $(dirname $build_log_tmp)
|
||||||
|
|||||||
4
app/tests/studio/add-layer/basic/events.patterns
Normal file
4
app/tests/studio/add-layer/basic/events.patterns
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
s/.*on_add_layer_binding_pressed/add_layer/p
|
||||||
|
s/.*on_set_layer_binding_at_idx_binding_pressed/set_layer_binding/p
|
||||||
|
s/.*layer_changed/layer_changed/p
|
||||||
|
s/.*hid_listener_keycode_//p
|
||||||
5
app/tests/studio/add-layer/basic/extra-cmake-args
Normal file
5
app/tests/studio/add-layer/basic/extra-cmake-args
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-DCONFIG_ZMK_BEHAVIOR_METADATA=y
|
||||||
|
-DCONFIG_ZMK_BEHAVIOR_LOCAL_IDS=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_LAYER_REORDERING=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_SETTINGS_STORAGE=y
|
||||||
|
-DCONFIG_SETTINGS=y
|
||||||
6
app/tests/studio/add-layer/basic/keycode_events.snapshot
Normal file
6
app/tests/studio/add-layer/basic/keycode_events.snapshot
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
add_layer: Added layer 1
|
||||||
|
set_layer_binding: Set binding at layer 1, index 0 to binding 1/2
|
||||||
|
layer_changed: layer 1 state 1 locked 0
|
||||||
|
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
layer_changed: layer 1 state 0 locked 0
|
||||||
1
app/tests/studio/add-layer/basic/native_sim.conf
Normal file
1
app/tests/studio/add-layer/basic/native_sim.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZMK_TEST_BEHAVIORS=y
|
||||||
23
app/tests/studio/add-layer/basic/native_sim.keymap
Normal file
23
app/tests/studio/add-layer/basic/native_sim.keymap
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
// Test adding a layer, setting a binding, activating it, and pressing the binding
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
// add a new layer
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
// set binding A at layer 1, position 0
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
// activate layer 1 with momentary
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
// press position 0 on new layer (should be A)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
// release momentary layer 1
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
>;
|
||||||
|
};
|
||||||
32
app/tests/studio/add-layer/behavior_keymap.dtsi
Normal file
32
app/tests/studio/add-layer/behavior_keymap.dtsi
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
add_layer: add_layer {
|
||||||
|
compatible = "zmk,behavior-add-layer";
|
||||||
|
#binding-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
set_binding: set_binding {
|
||||||
|
compatible = "zmk,behavior-set-layer-binding-at-idx";
|
||||||
|
#binding-cells = <2>;
|
||||||
|
bindings = <&kp A>, <&kp B>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&add_layer &set_binding 1 0
|
||||||
|
&mo 1 &kp B>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
status = "reserved";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
3
app/tests/studio/move-layer/basic/events.patterns
Normal file
3
app/tests/studio/move-layer/basic/events.patterns
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
s/.*layer_changed/layer_changed/p
|
||||||
|
s/.*hid_listener_keycode_//p
|
||||||
|
s/.*on_move_layer_binding_pressed/move_layer/p
|
||||||
5
app/tests/studio/move-layer/basic/extra-cmake-args
Normal file
5
app/tests/studio/move-layer/basic/extra-cmake-args
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-DCONFIG_ZMK_BEHAVIOR_METADATA=y
|
||||||
|
-DCONFIG_ZMK_BEHAVIOR_LOCAL_IDS=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_LAYER_REORDERING=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_SETTINGS_STORAGE=y
|
||||||
|
-DCONFIG_SETTINGS=y
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
move_layer: Moved layer from index 1 to index 2
|
||||||
|
layer_changed: layer 1 state 1 locked 0
|
||||||
|
layer_changed: layer 2 state 1 locked 0
|
||||||
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
layer_changed: layer 2 state 0 locked 0
|
||||||
|
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
1
app/tests/studio/move-layer/basic/native_sim.conf
Normal file
1
app/tests/studio/move-layer/basic/native_sim.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZMK_TEST_BEHAVIORS=y
|
||||||
26
app/tests/studio/move-layer/basic/native_sim.keymap
Normal file
26
app/tests/studio/move-layer/basic/native_sim.keymap
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
// Test moving a layer: swap layers 1 and 2, turn both on,
|
||||||
|
// press transparent on layer 1 at index 2
|
||||||
|
// which should fall through to layer 2 at index 1
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
// move layer 1 to position 2 (effectively swapping layers 1 and 2)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
// activate layers 1 and 2
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_PRESS(1,1,10)
|
||||||
|
// press position 0,1 on layer 2 - should output C from layer 2 at index 1
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
// release layer 2 (at index 1)
|
||||||
|
ZMK_MOCK_RELEASE(1,1,10)
|
||||||
|
// press position 0,1 again - should output A from default layer
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
>;
|
||||||
|
};
|
||||||
34
app/tests/studio/move-layer/behavior_keymap.dtsi
Normal file
34
app/tests/studio/move-layer/behavior_keymap.dtsi
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
move_layer: move_layer {
|
||||||
|
compatible = "zmk,behavior-move-layer";
|
||||||
|
#binding-cells = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&move_layer 1 2 &kp A
|
||||||
|
&mo 1 &mo 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&kp B &trans
|
||||||
|
&trans &trans>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_2 {
|
||||||
|
bindings = <
|
||||||
|
&trans &kp C
|
||||||
|
&trans &trans>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
3
app/tests/studio/remove-layer/basic/events.patterns
Normal file
3
app/tests/studio/remove-layer/basic/events.patterns
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
s/.*layer_changed/layer_changed/p
|
||||||
|
s/.*hid_listener_keycode_//p
|
||||||
|
s/.*on_remove_layer_binding_pressed/remove_layer/p
|
||||||
5
app/tests/studio/remove-layer/basic/extra-cmake-args
Normal file
5
app/tests/studio/remove-layer/basic/extra-cmake-args
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-DCONFIG_ZMK_BEHAVIOR_METADATA=y
|
||||||
|
-DCONFIG_ZMK_BEHAVIOR_LOCAL_IDS=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_LAYER_REORDERING=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_SETTINGS_STORAGE=y
|
||||||
|
-DCONFIG_SETTINGS=y
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
remove_layer: Removed layer at index 1
|
||||||
|
layer_changed: layer 1 state 1 locked 1
|
||||||
|
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
layer_changed: layer 2 state 1 locked 1
|
||||||
|
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||||
1
app/tests/studio/remove-layer/basic/native_sim.conf
Normal file
1
app/tests/studio/remove-layer/basic/native_sim.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZMK_TEST_BEHAVIORS=y
|
||||||
25
app/tests/studio/remove-layer/basic/native_sim.keymap
Normal file
25
app/tests/studio/remove-layer/basic/native_sim.keymap
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
// Test removing layer 1
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
// remove layer 1
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
// toggle layer 1 on
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
// press position 0,0 - should output A (layer 0) because layer 1 was removed
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
// toggle layer 2 on
|
||||||
|
ZMK_MOCK_PRESS(1,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,1,10)
|
||||||
|
// press position 0,0 - should output C (layer 2)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
||||||
34
app/tests/studio/remove-layer/behavior_keymap.dtsi
Normal file
34
app/tests/studio/remove-layer/behavior_keymap.dtsi
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
remove_layer_behavior: remove_layer_behavior {
|
||||||
|
compatible = "zmk,behavior-remove-layer";
|
||||||
|
#binding-cells = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&kp A &tog 1
|
||||||
|
&remove_layer_behavior 1 &tog 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&kp B &tog 1
|
||||||
|
&remove_layer_behavior 0 &trans>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_2 {
|
||||||
|
bindings = <
|
||||||
|
&kp C &trans
|
||||||
|
&none &trans>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
s/.*layer_changed/layer_changed/p
|
||||||
|
s/.*hid_listener_keycode_//p
|
||||||
|
s/.*on_remove_layer_binding_pressed/remove_layer/p
|
||||||
|
s/.*tog_keymap_binding_pressed/tog_pressed/p
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-DCONFIG_ZMK_BEHAVIOR_METADATA=y
|
||||||
|
-DCONFIG_ZMK_BEHAVIOR_LOCAL_IDS=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_LAYER_REORDERING=y
|
||||||
|
-DCONFIG_ZMK_KEYMAP_SETTINGS_STORAGE=y
|
||||||
|
-DCONFIG_SETTINGS=y
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
tog_pressed: position 1 layer 1
|
||||||
|
layer_changed: layer 1 state 1 locked 1
|
||||||
|
remove_layer: Removed layer at index 0
|
||||||
|
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
tog_pressed: position 1 layer 1
|
||||||
|
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZMK_TEST_BEHAVIORS=y
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
// Test removing layer 0: layer 1 becomes bottom layer
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
// toggle layer 1 on
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
// remove layer 0
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
// press position 0,0 - should output B (layer 1)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
// try to toggle layer 1 off
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
// press position 0,0 - should output B
|
||||||
|
// (layer 1 is now the bottom layer, so shouldn't be disabled)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
>;
|
||||||
|
};
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
This test fails because the keymap function handling position state changes doesn't work correctly when the default layer is removed.
|
||||||
|
The iteration loop's end condition is incorrect.
|
||||||
Reference in New Issue
Block a user