From 5c93f0b50be586a26f34005f70fd9446c1e05f84 Mon Sep 17 00:00:00 2001 From: Okke Formsma Date: Sat, 19 Dec 2020 14:28:32 +0100 Subject: [PATCH] feature(events): add behavior-state-changed event --- app/CMakeLists.txt | 2 + .../zmk/events/behavior_state_changed.h | 21 +++++++ app/src/behavior.c | 59 +++++++++++++++++++ app/src/event_manager.c | 9 ++- app/src/events/behavior_state_changed.c | 10 ++++ app/src/keymap.c | 29 ++++----- 6 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 app/include/zmk/events/behavior_state_changed.h create mode 100644 app/src/behavior.c create mode 100644 app/src/events/behavior_state_changed.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index e283487f..6bec8f28 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c) target_sources(app PRIVATE src/event_manager.c) target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c) target_sources(app PRIVATE src/events/activity_state_changed.c) +target_sources(app PRIVATE src/events/behavior_state_changed.c) target_sources(app PRIVATE src/events/position_state_changed.c) target_sources(app PRIVATE src/events/layer_state_changed.c) target_sources(app PRIVATE src/events/keycode_state_changed.c) @@ -74,6 +75,7 @@ target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c) target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c) target_sources(app PRIVATE src/endpoints.c) target_sources(app PRIVATE src/hid_listener.c) +target_sources(app PRIVATE src/behavior.c) target_sources(app PRIVATE src/main.c) add_subdirectory(src/display/) diff --git a/app/include/zmk/events/behavior_state_changed.h b/app/include/zmk/events/behavior_state_changed.h new file mode 100644 index 00000000..15c0f6e5 --- /dev/null +++ b/app/include/zmk/events/behavior_state_changed.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include +#include + +struct zmk_behavior_state_changed { + struct zmk_behavior_binding binding; + bool pressed; + int layer; + uint32_t position; + int64_t timestamp; +}; + +ZMK_EVENT_DECLARE(zmk_behavior_state_changed); diff --git a/app/src/behavior.c b/app/src/behavior.c new file mode 100644 index 00000000..7f244b30 --- /dev/null +++ b/app/src/behavior.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int zmk_behavior_state_changed_listener(const zmk_event_t *zmk_ev) { + struct zmk_behavior_state_changed *ev = as_zmk_behavior_state_changed(zmk_ev); + if (ev == NULL) { + return 0; + } + const struct zmk_behavior_binding_event event = { + .layer = ev->layer, + .position = ev->position, + .timestamp = ev->timestamp, + }; + + int err = behavior_keymap_binding_convert_central_state_dependent_params(&ev->binding, event); + if (err) { + LOG_ERR("Failed to convert relative to absolute behavior binding (err %d)", err); + return err; + } + + int ret; + if (ev->pressed) { + ret = behavior_keymap_binding_pressed(&ev->binding, event); + } else { + ret = behavior_keymap_binding_released(&ev->binding, event); + } + if (ret < 0) { + return ret; + } + switch (ret) { + case ZMK_BEHAVIOR_TRANSPARENT: + return ZMK_EV_EVENT_BUBBLE; + case ZMK_BEHAVIOR_OPAQUE: + return ZMK_EV_EVENT_HANDLED; + default: + return -ENOTSUP; + } +} + +ZMK_LISTENER(behavior, zmk_behavior_state_changed_listener); +ZMK_SUBSCRIPTION(behavior, zmk_behavior_state_changed); \ No newline at end of file diff --git a/app/src/event_manager.c b/app/src/event_manager.c index 0399ca80..701bdf75 100644 --- a/app/src/event_manager.c +++ b/app/src/event_manager.c @@ -17,6 +17,12 @@ extern struct zmk_event_type *__event_type_end[]; extern struct zmk_event_subscription __event_subscriptions_start[]; extern struct zmk_event_subscription __event_subscriptions_end[]; +/* + * Returns negative values for errors. + * Returns ZMK_EV_EVENT_HANDLED if the event was handled + * Returns ZMK_EV_EVENT_CAPTURED if the event was captured + * Returns ZMK_EV_EVENT_BUBBLE if no handler handled the event + */ int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) { int ret = 0; uint8_t len = __event_subscriptions_end - __event_subscriptions_start; @@ -31,13 +37,12 @@ int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) { switch (ret) { case ZMK_EV_EVENT_HANDLED: LOG_DBG("Listener handled the event"); - ret = 0; goto release; case ZMK_EV_EVENT_CAPTURED: LOG_DBG("Listener captured the event"); event->last_listener_index = i; // Listeners are expected to free events they capture - return 0; + return ret; } } } diff --git a/app/src/events/behavior_state_changed.c b/app/src/events/behavior_state_changed.c new file mode 100644 index 00000000..55bf5ec7 --- /dev/null +++ b/app/src/events/behavior_state_changed.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(zmk_behavior_state_changed); \ No newline at end of file diff --git a/app/src/keymap.c b/app/src/keymap.c index 1643f647..9dca324f 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -16,6 +16,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#include #include #include @@ -157,11 +158,6 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, // relative to absolute before being invoked struct zmk_behavior_binding binding = zmk_keymap[layer][position]; const struct device *behavior; - struct zmk_behavior_binding_event event = { - .layer = layer, - .position = position, - .timestamp = timestamp, - }; LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding.behavior_dev)); @@ -170,20 +166,17 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, if (!behavior) { LOG_DBG("No behavior assigned to %d on layer %d", position, layer); - return 1; + return ZMK_EV_EVENT_HANDLED; } - int err = behavior_keymap_binding_convert_central_state_dependent_params(&binding, event); - if (err) { - LOG_ERR("Failed to convert relative to absolute behavior binding (err %d)", err); - return err; - } - - if (pressed) { - return behavior_keymap_binding_pressed(&binding, event); - } else { - return behavior_keymap_binding_released(&binding, event); - } + return ZMK_EVENT_RAISE(new_zmk_behavior_state_changed((struct zmk_behavior_state_changed){ + .binding = binding, + .pressed = pressed, + .layer = layer, + .position = position, + .timestamp = timestamp, + })); + ; } int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp) { @@ -193,7 +186,7 @@ int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t t for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) { if (zmk_keymap_layer_active_with_state(layer, zmk_keymap_active_behavior_layer[position])) { int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp); - if (ret > 0) { + if (ret == ZMK_EV_EVENT_BUBBLE) { LOG_DBG("behavior processing to continue to next layer"); continue; } else if (ret < 0) {