From 11c58a82fc7505e8faa3794aaf2bde04933c80b7 Mon Sep 17 00:00:00 2001 From: Sviatoslav Bulbakha Date: Fri, 20 Dec 2024 18:14:59 +0400 Subject: [PATCH] feat(combos): do not interrupt combo on active combo release --- app/src/combo.c | 7 ++- .../combo/other-key-release-2/events.patterns | 1 + .../keycode_events.snapshot | 4 ++ .../native_posix_64.keymap | 57 +++++++++++++++++++ .../keycode_events.snapshot | 2 +- 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 app/tests/combo/other-key-release-2/events.patterns create mode 100644 app/tests/combo/other-key-release-2/keycode_events.snapshot create mode 100644 app/tests/combo/other-key-release-2/native_posix_64.keymap diff --git a/app/src/combo.c b/app/src/combo.c index f3fd641fe8c..02105151c71 100644 --- a/app/src/combo.c +++ b/app/src/combo.c @@ -508,7 +508,7 @@ static bool is_key_part_of_any_combo(int32_t position) { static int position_state_up(const zmk_event_t *ev, struct zmk_position_state_changed *data) { // Check if the released key is part of any combo candidate or active combo - if (is_key_part_of_any_combo(data->position)) { + if (is_key_part_of_candidate(data->position)) { int released_keys = cleanup(); if (release_combo_key(data->position, data->timestamp)) { return ZMK_EV_EVENT_HANDLED; @@ -521,7 +521,12 @@ static int position_state_up(const zmk_event_t *ev, struct zmk_position_state_ch ZMK_EVENT_RAISE(dupe_ev); return ZMK_EV_EVENT_CAPTURED; } + } else if (is_key_part_of_active_combo(data->position)) { + if (release_combo_key(data->position, data->timestamp)) { + return ZMK_EV_EVENT_HANDLED; + } } + release_pressed_key(data->position); return ZMK_EV_EVENT_BUBBLE; } diff --git a/app/tests/combo/other-key-release-2/events.patterns b/app/tests/combo/other-key-release-2/events.patterns new file mode 100644 index 00000000000..b1342af4d97 --- /dev/null +++ b/app/tests/combo/other-key-release-2/events.patterns @@ -0,0 +1 @@ +s/.*hid_listener_keycode_//p diff --git a/app/tests/combo/other-key-release-2/keycode_events.snapshot b/app/tests/combo/other-key-release-2/keycode_events.snapshot new file mode 100644 index 00000000000..5e451bc8d7b --- /dev/null +++ b/app/tests/combo/other-key-release-2/keycode_events.snapshot @@ -0,0 +1,4 @@ +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/other-key-release-2/native_posix_64.keymap b/app/tests/combo/other-key-release-2/native_posix_64.keymap new file mode 100644 index 00000000000..bc6d308d579 --- /dev/null +++ b/app/tests/combo/other-key-release-2/native_posix_64.keymap @@ -0,0 +1,57 @@ +#include +#include +#include + +/* +Combo on positions 01 and 23. + +- press 2 and 3 +- press 0 +- release 2 +- press 1 +- release the rest + +Both combos should actuate. +*/ + +/ { + combos { + compatible = "zmk,combos"; + + combo_a { + timeout-ms = <50>; + key-positions = <0 1>; + bindings = <&kp A>; + }; + + combo_b { + timeout-ms = <50>; + key-positions = <2 3>; + bindings = <&kp B>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + + default_layer { + bindings = < + &kp N0 &kp N1 + &kp N2 &kp N3 + >; + }; + }; +}; + +&kscan { + events = < + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_PRESS(1,1,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(1,1,0) + ZMK_MOCK_RELEASE(0,0,0) + ZMK_MOCK_RELEASE(0,1,0) + >; +}; diff --git a/app/tests/combo/overlapping-combos-5/keycode_events.snapshot b/app/tests/combo/overlapping-combos-5/keycode_events.snapshot index bb47d85203c..b809163ddca 100644 --- a/app/tests/combo/overlapping-combos-5/keycode_events.snapshot +++ b/app/tests/combo/overlapping-combos-5/keycode_events.snapshot @@ -1,4 +1,4 @@ pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 -pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00