diff options
author | KemoNine <mcrosson@users.noreply.github.com> | 2021-02-03 23:33:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-03 23:33:09 -0500 |
commit | cd503ed17bb141bd54a777a375b5706acf884318 (patch) | |
tree | 2e9095fad05e8eb0d0545e0a662aca2d6b3084f6 /app | |
parent | 9205ea1c705504844ad3b9e31d6fbd437cb76aba (diff) |
Feat combo layers (#661)
feat(combos): add layer filtering
Co-authored-by: KemoNine <mcrosson@kemonine.info>
Diffstat (limited to 'app')
-rw-r--r-- | app/dts/bindings/zmk,combos.yaml | 3 | ||||
-rw-r--r-- | app/src/combo.c | 31 | ||||
-rw-r--r-- | app/tests/combo/layer-filter-0/events.patterns | 2 | ||||
-rw-r--r-- | app/tests/combo/layer-filter-0/keycode_events.snapshot | 8 | ||||
-rw-r--r-- | app/tests/combo/layer-filter-0/native_posix.keymap | 78 | ||||
-rw-r--r-- | app/tests/combo/layer-filter-1/events.patterns | 2 | ||||
-rw-r--r-- | app/tests/combo/layer-filter-1/keycode_events.snapshot | 4 | ||||
-rw-r--r-- | app/tests/combo/layer-filter-1/native_posix.keymap | 40 |
8 files changed, 164 insertions, 4 deletions
diff --git a/app/dts/bindings/zmk,combos.yaml b/app/dts/bindings/zmk,combos.yaml index 75eaa3e..1a914a7 100644 --- a/app/dts/bindings/zmk,combos.yaml +++ b/app/dts/bindings/zmk,combos.yaml @@ -20,3 +20,6 @@ child-binding: default: 50 slow-release: type: boolean + layers: + type: array + default: [-1]
\ No newline at end of file diff --git a/app/src/combo.c b/app/src/combo.c index 82f6538..b50a0f6 100644 --- a/app/src/combo.c +++ b/app/src/combo.c @@ -17,6 +17,7 @@ #include <zmk/events/position_state_changed.h> #include <zmk/hid.h> #include <zmk/matrix.h> +#include <zmk/keymap.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -33,6 +34,8 @@ struct combo_cfg { // the virtual key position is a key position outside the range used by the keyboard. // it is necessary so hold-taps can uniquely identify a behavior. int32_t virtual_key_position; + int32_t layers_len; + int8_t layers[]; }; struct active_combo { @@ -104,17 +107,35 @@ static int initialize_combo(struct combo_cfg *new_combo) { return 0; } +static bool combo_active_on_layer(struct combo_cfg *combo, uint8_t layer) { + if (combo->layers[0] == -1) { + // -1 in the first layer position is global layer scope + return true; + } + for (int j = 0; j < combo->layers_len; j++) { + if (combo->layers[j] == layer) { + return true; + } + } + return false; +} + static int setup_candidates_for_first_keypress(int32_t position, int64_t timestamp) { + int number_of_combo_candidates = 0; + uint8_t highest_active_layer = zmk_keymap_highest_layer_active(); for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; i++) { struct combo_cfg *combo = combo_lookup[position][i]; if (combo == NULL) { - return i; + return number_of_combo_candidates; + } + if (combo_active_on_layer(combo, highest_active_layer)) { + candidates[number_of_combo_candidates].combo = combo; + candidates[number_of_combo_candidates].timeout_at = timestamp + combo->timeout_ms; + number_of_combo_candidates++; } - candidates[i].combo = combo; - candidates[i].timeout_at = timestamp + combo->timeout_ms; // LOG_DBG("combo timeout %d %d %d", position, i, candidates[i].timeout_at); } - return CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; + return number_of_combo_candidates; } static int filter_candidates(int32_t position) { @@ -451,6 +472,8 @@ ZMK_SUBSCRIPTION(combo, zmk_position_state_changed); .behavior = KEY_BINDING_TO_STRUCT(0, n), \ .virtual_key_position = ZMK_KEYMAP_LEN + __COUNTER__, \ .slow_release = DT_PROP(n, slow_release), \ + .layers = DT_PROP(n, layers), \ + .layers_len = DT_PROP_LEN(n, layers), \ }; #define INITIALIZE_COMBO(n) initialize_combo(&combo_config_##n); diff --git a/app/tests/combo/layer-filter-0/events.patterns b/app/tests/combo/layer-filter-0/events.patterns new file mode 100644 index 0000000..b90d786 --- /dev/null +++ b/app/tests/combo/layer-filter-0/events.patterns @@ -0,0 +1,2 @@ +s/.*hid_listener_keycode_//p +s/.*combo//p
\ No newline at end of file diff --git a/app/tests/combo/layer-filter-0/keycode_events.snapshot b/app/tests/combo/layer-filter-0/keycode_events.snapshot new file mode 100644 index 0000000..f845fd1 --- /dev/null +++ b/app/tests/combo/layer-filter-0/keycode_events.snapshot @@ -0,0 +1,8 @@ +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b 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 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c 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/layer-filter-0/native_posix.keymap b/app/tests/combo/layer-filter-0/native_posix.keymap new file mode 100644 index 0000000..aac330f --- /dev/null +++ b/app/tests/combo/layer-filter-0/native_posix.keymap @@ -0,0 +1,78 @@ +#include <dt-bindings/zmk/keys.h> +#include <behaviors.dtsi> +#include <dt-bindings/zmk/kscan-mock.h> + +/* it is useful to set timeout to a large value when attaching a debugger. */ +#define TIMEOUT (60*60*1000) + +/ { + combos { + compatible = "zmk,combos"; + combo_one { + timeout-ms = <TIMEOUT>; + key-positions = <0 1>; + bindings = <&kp X>; + layers = <0>; + }; + + combo_two { + timeout-ms = <TIMEOUT>; + key-positions = <0 1>; + bindings = <&kp Y>; + layers = <1>; + }; + + combo_three { + timeout-ms = <TIMEOUT>; + key-positions = <0 2>; + bindings = <&kp Z>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &kp A &kp B + &kp C &tog 1 + >; + }; + + filtered_layer { + bindings = < + &kp A &kp B + &kp C &tog 0 + >; + }; + }; +}; + +&kscan { + events = < + /* Combo One */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(0,1,10) + /* Combo Three */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(1,1,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(1,1,10) + /* Toggle Layer */ + ZMK_MOCK_PRESS(1,1,10) + ZMK_MOCK_RELEASE(1,1,10) + /* Combo Two */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(0,1,10) + /* Combo Three */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(1,1,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(1,1,10) + >; +};
\ No newline at end of file diff --git a/app/tests/combo/layer-filter-1/events.patterns b/app/tests/combo/layer-filter-1/events.patterns new file mode 100644 index 0000000..b90d786 --- /dev/null +++ b/app/tests/combo/layer-filter-1/events.patterns @@ -0,0 +1,2 @@ +s/.*hid_listener_keycode_//p +s/.*combo//p
\ No newline at end of file diff --git a/app/tests/combo/layer-filter-1/keycode_events.snapshot b/app/tests/combo/layer-filter-1/keycode_events.snapshot new file mode 100644 index 0000000..bb47d85 --- /dev/null +++ b/app/tests/combo/layer-filter-1/keycode_events.snapshot @@ -0,0 +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 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/layer-filter-1/native_posix.keymap b/app/tests/combo/layer-filter-1/native_posix.keymap new file mode 100644 index 0000000..995f27e --- /dev/null +++ b/app/tests/combo/layer-filter-1/native_posix.keymap @@ -0,0 +1,40 @@ +#include <dt-bindings/zmk/keys.h> +#include <behaviors.dtsi> +#include <dt-bindings/zmk/kscan-mock.h> + +/* it is useful to set timeout to a large value when attaching a debugger. */ +#define TIMEOUT (60*60*1000) + +/ { + combos { + compatible = "zmk,combos"; + combo_one { + timeout-ms = <TIMEOUT>; + key-positions = <0 1>; + bindings = <&kp X>; + layers = <1>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &kp A &kp B + &kp C &tog 1 + >; + }; + }; +}; + +&kscan { + events = < + /* Combo One */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(0,1,10) + >; +};
\ No newline at end of file |