From 7a4f3a261d0c0f6816553727acb45f6ac05d15ad Mon Sep 17 00:00:00 2001 From: urob <978080+urob@users.noreply.github.com> Date: Fri, 5 Aug 2022 00:18:19 -0400 Subject: [PATCH 1/2] Unit test for ignore-modifiers bug --- .../11-sl-sk-macro/events.patterns | 1 + .../11-sl-sk-macro/keycode_events.snapshot | 4 ++ .../11-sl-sk-macro/native_posix_64.keymap | 54 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 app/tests/sticky-keys/11-sl-sk-macro/events.patterns create mode 100644 app/tests/sticky-keys/11-sl-sk-macro/keycode_events.snapshot create mode 100644 app/tests/sticky-keys/11-sl-sk-macro/native_posix_64.keymap diff --git a/app/tests/sticky-keys/11-sl-sk-macro/events.patterns b/app/tests/sticky-keys/11-sl-sk-macro/events.patterns new file mode 100644 index 00000000..833100f6 --- /dev/null +++ b/app/tests/sticky-keys/11-sl-sk-macro/events.patterns @@ -0,0 +1 @@ +s/.*hid_listener_keycode_//p \ No newline at end of file diff --git a/app/tests/sticky-keys/11-sl-sk-macro/keycode_events.snapshot b/app/tests/sticky-keys/11-sl-sk-macro/keycode_events.snapshot new file mode 100644 index 00000000..abd59edf --- /dev/null +++ b/app/tests/sticky-keys/11-sl-sk-macro/keycode_events.snapshot @@ -0,0 +1,4 @@ +pressed: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/11-sl-sk-macro/native_posix_64.keymap b/app/tests/sticky-keys/11-sl-sk-macro/native_posix_64.keymap new file mode 100644 index 00000000..ef329629 --- /dev/null +++ b/app/tests/sticky-keys/11-sl-sk-macro/native_posix_64.keymap @@ -0,0 +1,54 @@ +#include +#include +#include + +&sl { + ignore-modifiers; +}; + +/ { + macros { + sls: sls { + label = "sticky_layer_shift"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + wait-ms = <0>; + tap-ms = <1>; + bindings + = <&sl 1 &sk LSHFT>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &sls &kp A + &sl 1 &sk LSHFT + >; + }; + + second_layer { + bindings = < + &trans &kp B + &trans &trans + >; + }; + }; +}; + + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,10) // macro should produce same as sl followd by sk + ZMK_MOCK_RELEASE(0,0,10) +// ZMK_MOCK_PRESS(1,0,10) +// ZMK_MOCK_RELEASE(1,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,10) + >; +}; From 59d468e19d6411fdb457e73215d7094d87bdc9d0 Mon Sep 17 00:00:00 2001 From: down Date: Fri, 23 Dec 2022 23:23:20 +0700 Subject: [PATCH 2/2] fix(behaviors): allow saving sticky keys with the same position Previously, `position` was used to search for a sticky key, but it was not sufficient because keys with different layers or generated by macros could have the same position. This caused issues when saving keys with the same position, as only one could be saved at a time. Adding checks on `param1`, `position`, and `layer` resolves the issue, but `param1` alone is sufficient to identify sticky keys. --- app/src/behaviors/behavior_sticky_key.c | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/src/behaviors/behavior_sticky_key.c b/app/src/behaviors/behavior_sticky_key.c index 267b81ab..ef5959b0 100644 --- a/app/src/behaviors/behavior_sticky_key.c +++ b/app/src/behaviors/behavior_sticky_key.c @@ -26,8 +26,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define ZMK_BHV_STICKY_KEY_MAX_HELD 10 -#define ZMK_BHV_STICKY_KEY_POSITION_FREE UINT32_MAX - struct behavior_sticky_key_config { uint32_t release_after_ms; bool quick_release; @@ -36,6 +34,7 @@ struct behavior_sticky_key_config { }; struct active_sticky_key { + bool is_active; uint32_t position; uint32_t param1; uint32_t param2; @@ -57,10 +56,10 @@ static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t pa const struct behavior_sticky_key_config *config) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { struct active_sticky_key *const sticky_key = &active_sticky_keys[i]; - if (sticky_key->position != ZMK_BHV_STICKY_KEY_POSITION_FREE || - sticky_key->timer_cancelled) { + if (sticky_key->is_active || sticky_key->timer_cancelled) { continue; } + sticky_key->is_active = true; sticky_key->position = position; sticky_key->param1 = param1; sticky_key->param2 = param2; @@ -76,12 +75,13 @@ static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t pa } static void clear_sticky_key(struct active_sticky_key *sticky_key) { - sticky_key->position = ZMK_BHV_STICKY_KEY_POSITION_FREE; + sticky_key->is_active = false; } -static struct active_sticky_key *find_sticky_key(uint32_t position) { +static struct active_sticky_key *find_sticky_key(uint32_t param1) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { - if (active_sticky_keys[i].position == position && !active_sticky_keys[i].timer_cancelled) { + if (active_sticky_keys[i].is_active && active_sticky_keys[i].param1 == param1 && + !active_sticky_keys[i].timer_cancelled) { return &active_sticky_keys[i]; } } @@ -132,7 +132,7 @@ static int on_sticky_key_binding_pressed(struct zmk_behavior_binding *binding, const struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_sticky_key_config *cfg = dev->config; struct active_sticky_key *sticky_key; - sticky_key = find_sticky_key(event.position); + sticky_key = find_sticky_key(binding->param1); if (sticky_key != NULL) { stop_timer(sticky_key); release_sticky_key_behavior(sticky_key, event.timestamp); @@ -144,14 +144,14 @@ static int on_sticky_key_binding_pressed(struct zmk_behavior_binding *binding, return ZMK_BEHAVIOR_OPAQUE; } + LOG_DBG("new sticky_key 0x%x", binding->param1); press_sticky_key_behavior(sticky_key, event.timestamp); - LOG_DBG("%d new sticky_key", event.position); return ZMK_BEHAVIOR_OPAQUE; } static int on_sticky_key_binding_released(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { - struct active_sticky_key *sticky_key = find_sticky_key(event.position); + struct active_sticky_key *sticky_key = find_sticky_key(binding->param1); if (sticky_key == NULL) { LOG_ERR("ACTIVE STICKY KEY CLEARED TOO EARLY"); return ZMK_BEHAVIOR_OPAQUE; @@ -193,7 +193,7 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) { bool event_reraised = false; for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { struct active_sticky_key *sticky_key = &active_sticky_keys[i]; - if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) { + if (!sticky_key->is_active) { continue; } @@ -254,7 +254,7 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) { void behavior_sticky_key_timer_handler(struct k_work *item) { struct active_sticky_key *sticky_key = CONTAINER_OF(item, struct active_sticky_key, release_timer); - if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) { + if (!sticky_key->is_active) { return; } if (sticky_key->timer_cancelled) { @@ -270,7 +270,8 @@ static int behavior_sticky_key_init(const struct device *dev) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { k_work_init_delayable(&active_sticky_keys[i].release_timer, behavior_sticky_key_timer_handler); - active_sticky_keys[i].position = ZMK_BHV_STICKY_KEY_POSITION_FREE; + active_sticky_keys[i].is_active = false; + active_sticky_keys[i].timer_cancelled = false; } } init_first_run = false;