diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h index 31fb43ed..ec42b5ee 100644 --- a/app/include/zmk/behavior.h +++ b/app/include/zmk/behavior.h @@ -19,4 +19,5 @@ struct zmk_behavior_binding_event { int layer; uint32_t position; int64_t timestamp; + uint32_t trace_id; }; \ No newline at end of file diff --git a/app/include/zmk/events/keycode_state_changed.h b/app/include/zmk/events/keycode_state_changed.h index 466bbd76..44661d07 100644 --- a/app/include/zmk/events/keycode_state_changed.h +++ b/app/include/zmk/events/keycode_state_changed.h @@ -17,12 +17,14 @@ struct zmk_keycode_state_changed { uint8_t explicit_modifiers; bool state; int64_t timestamp; + uint32_t trace_id; }; ZMK_EVENT_DECLARE(zmk_keycode_state_changed); static inline struct zmk_keycode_state_changed_event * -zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) { +zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp, + uint32_t trace_id) { uint16_t page = HID_USAGE_PAGE(encoded) & 0xFF; uint16_t id = HID_USAGE_ID(encoded); uint8_t implicit_modifiers = 0x00; @@ -38,11 +40,13 @@ zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t t implicit_modifiers = SELECT_MODS(encoded); } - return new_zmk_keycode_state_changed( - (struct zmk_keycode_state_changed){.usage_page = page, - .keycode = id, - .implicit_modifiers = implicit_modifiers, - .explicit_modifiers = explicit_modifiers, - .state = pressed, - .timestamp = timestamp}); + return new_zmk_keycode_state_changed((struct zmk_keycode_state_changed){ + .usage_page = page, + .keycode = id, + .implicit_modifiers = implicit_modifiers, + .explicit_modifiers = explicit_modifiers, + .state = pressed, + .timestamp = timestamp, + .trace_id = trace_id, + }); } diff --git a/app/include/zmk/events/position_state_changed.h b/app/include/zmk/events/position_state_changed.h index e2f68720..63559f9b 100644 --- a/app/include/zmk/events/position_state_changed.h +++ b/app/include/zmk/events/position_state_changed.h @@ -8,10 +8,15 @@ #include #include +#include + struct zmk_position_state_changed { uint32_t position; bool state; int64_t timestamp; + int32_t trace_id; }; -ZMK_EVENT_DECLARE(zmk_position_state_changed); \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_position_state_changed); + +uint32_t zmk_get_event_trace_id(uint32_t position, bool pressed); \ No newline at end of file diff --git a/app/include/zmk/events/sensor_event.h b/app/include/zmk/events/sensor_event.h index f579bc39..4586d480 100644 --- a/app/include/zmk/events/sensor_event.h +++ b/app/include/zmk/events/sensor_event.h @@ -9,6 +9,7 @@ #include #include #include + struct zmk_sensor_event { uint8_t sensor_number; const struct device *sensor; diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index 7151930a..feadaafa 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -6,6 +6,8 @@ #pragma once +#include + typedef uint32_t zmk_keymap_layers_state_t; uint8_t zmk_keymap_layer_default(); @@ -18,7 +20,7 @@ int zmk_keymap_layer_toggle(uint8_t layer); int zmk_keymap_layer_to(uint8_t layer); const char *zmk_keymap_layer_label(uint8_t layer); -int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp); +int zmk_keymap_position_state_changed(const struct zmk_position_state_changed *pos_ev); #define ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst) \ { \ diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index ab25c3cd..9a103dde 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -50,6 +50,7 @@ struct active_hold_tap { uint32_t param_hold; uint32_t param_tap; int64_t timestamp; + uint32_t trace_id; bool is_decided; bool is_hold; const struct behavior_hold_tap_config *config; @@ -95,25 +96,6 @@ static int capture_event(const zmk_event_t *event) { return -ENOMEM; } -static struct zmk_position_state_changed *find_captured_keydown_event(uint32_t position) { - struct zmk_position_state_changed *last_match = NULL; - for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { - const zmk_event_t *eh = captured_events[i]; - if (eh == NULL) { - return last_match; - } - struct zmk_position_state_changed *position_event = as_zmk_position_state_changed(eh); - if (position_event == NULL) { - continue; - } - - if (position_event->position == position && position_event->state) { - last_match = position_event; - } - } - return last_match; -} - const struct zmk_listener zmk_listener_behavior_hold_tap; static void release_captured_events() { @@ -137,8 +119,7 @@ static void release_captured_events() { // [null, k1_down, k1_up, mt2_up, null, ...] // ^ // k1_down is captured by the mt2 mod-tap - // !note that searches for find_captured_keydown_event by the mt2 behavior will stop at the - // first null encountered [mt1_down, null, k1_up, mt2_up, null, ...] + // [mt1_down, null, k1_up, mt2_up, null, ...] // ^ // k1_up event is captured by the new hold-tap: // [k1_down, k1_up, null, mt2_up, null, ...] @@ -180,6 +161,7 @@ static struct active_hold_tap *find_hold_tap(uint32_t position) { static struct active_hold_tap *store_hold_tap(uint32_t position, uint32_t param_hold, uint32_t param_tap, int64_t timestamp, + uint32_t trace_id, const struct behavior_hold_tap_config *config) { for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) { if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) { @@ -192,6 +174,7 @@ static struct active_hold_tap *store_hold_tap(uint32_t position, uint32_t param_ active_hold_taps[i].param_hold = param_hold; active_hold_taps[i].param_tap = param_tap; active_hold_taps[i].timestamp = timestamp; + active_hold_taps[i].trace_id = trace_id; return &active_hold_taps[i]; } return NULL; @@ -313,6 +296,7 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, + .trace_id = hold_tap->trace_id, }; struct zmk_behavior_binding binding; @@ -341,8 +325,8 @@ static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding, return ZMK_BEHAVIOR_OPAQUE; } - struct active_hold_tap *hold_tap = - store_hold_tap(event.position, binding->param1, binding->param2, event.timestamp, cfg); + struct active_hold_tap *hold_tap = store_hold_tap( + event.position, binding->param1, binding->param2, event.timestamp, event.trace_id, cfg); if (hold_tap == NULL) { LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?", ZMK_BHV_HOLD_TAP_MAX_HELD); @@ -388,6 +372,7 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event sub_behavior_data = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, + .trace_id = hold_tap->trace_id, }; struct zmk_behavior_binding sub_behavior_binding; @@ -428,7 +413,7 @@ static int position_state_changed_listener(const zmk_event_t *eh) { return ZMK_EV_EVENT_BUBBLE; } - if (undecided_hold_tap->position == ev->position) { + if (undecided_hold_tap->trace_id == ev->trace_id) { if (ev->state) { // keydown LOG_ERR("hold-tap listener should be called before before most other listeners!"); return ZMK_EV_EVENT_BUBBLE; @@ -446,9 +431,9 @@ static int position_state_changed_listener(const zmk_event_t *eh) { decide_hold_tap(undecided_hold_tap, HT_TIMER_EVENT); } - if (!ev->state && find_captured_keydown_event(ev->position) == NULL) { - // no keydown event has been captured, let it bubble. - // we'll catch modifiers later in modifier_state_changed_listener + if (ev->trace_id < undecided_hold_tap->trace_id) { + // this key was pressed before the hold-tap was pressed, let it bubble. + // see scenarios 3a/b LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up"); return ZMK_EV_EVENT_BUBBLE; @@ -462,25 +447,16 @@ static int position_state_changed_listener(const zmk_event_t *eh) { } static int keycode_state_changed_listener(const zmk_event_t *eh) { - // we want to catch layer-up events too... how? struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); - - if (undecided_hold_tap == NULL) { - // LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode); - return ZMK_EV_EVENT_BUBBLE; + if (undecided_hold_tap != NULL && is_mod(ev->usage_page, ev->keycode)) { + // Catch mod up events for scenario 3a. + LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode, + ev->state ? "down" : "up"); + capture_event(eh); + return ZMK_EV_EVENT_CAPTURED; } - if (!is_mod(ev->usage_page, ev->keycode)) { - // LOG_DBG("0x%02X bubble (not a mod)", ev->keycode); - return ZMK_EV_EVENT_BUBBLE; - } - - // only key-up events will bubble through position_state_changed_listener - // if a undecided_hold_tap is active. - LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode, - ev->state ? "down" : "up"); - capture_event(eh); - return ZMK_EV_EVENT_CAPTURED; + return ZMK_EV_EVENT_BUBBLE; } int behavior_hold_tap_listener(const zmk_event_t *eh) { diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c index 8282977e..b6315aba 100644 --- a/app/src/behaviors/behavior_key_press.c +++ b/app/src/behaviors/behavior_key_press.c @@ -21,15 +21,15 @@ static int behavior_key_press_init(const struct device *dev) { return 0; }; static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1); - return ZMK_EVENT_RAISE( - zmk_keycode_state_changed_from_encoded(binding->param1, true, event.timestamp)); + return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(binding->param1, true, + event.timestamp, event.trace_id)); } static int on_keymap_binding_released(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1); - return ZMK_EVENT_RAISE( - zmk_keycode_state_changed_from_encoded(binding->param1, false, event.timestamp)); + return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(binding->param1, false, + event.timestamp, event.trace_id)); } static const struct behavior_driver_api behavior_key_press_driver_api = { diff --git a/app/src/behaviors/behavior_sensor_rotate_key_press.c b/app/src/behaviors/behavior_sensor_rotate_key_press.c index 589a3a57..ee314547 100644 --- a/app/src/behaviors/behavior_sensor_rotate_key_press.c +++ b/app/src/behaviors/behavior_sensor_rotate_key_press.c @@ -47,12 +47,12 @@ static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding, LOG_DBG("SEND %d", keycode); - ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, true, timestamp)); + ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, true, timestamp, 0)); // TODO: Better way to do this? k_msleep(5); - return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, false, timestamp)); + return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, false, timestamp, 0)); } static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = { diff --git a/app/src/behaviors/behavior_sticky_key.c b/app/src/behaviors/behavior_sticky_key.c index 20af93a8..c4966a34 100644 --- a/app/src/behaviors/behavior_sticky_key.c +++ b/app/src/behaviors/behavior_sticky_key.c @@ -26,7 +26,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define ZMK_BHV_STICKY_KEY_MAX_HELD 10 -#define ZMK_BHV_STICKY_KEY_POSITION_FREE ULONG_MAX +#define ZMK_BHV_STICKY_KEY_UNUSED ULONG_MAX struct behavior_sticky_key_config { uint32_t release_after_ms; @@ -36,6 +36,7 @@ struct behavior_sticky_key_config { struct active_sticky_key { uint32_t position; + uint32_t trace_id; uint32_t param1; uint32_t param2; const struct behavior_sticky_key_config *config; @@ -45,42 +46,40 @@ struct active_sticky_key { int64_t release_at; struct k_delayed_work release_timer; // usage page and keycode for the key that is being modified by this sticky key - uint8_t modified_key_usage_page; - uint32_t modified_key_keycode; + uint32_t modified_key_trace_id; }; struct active_sticky_key active_sticky_keys[ZMK_BHV_STICKY_KEY_MAX_HELD] = {}; -static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t param1, - uint32_t param2, +static struct active_sticky_key *store_sticky_key(uint32_t trace_id, uint32_t position, + uint32_t param1, uint32_t param2, 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->trace_id != ZMK_BHV_STICKY_KEY_UNUSED || sticky_key->timer_cancelled) { continue; } sticky_key->position = position; + sticky_key->trace_id = trace_id; sticky_key->param1 = param1; sticky_key->param2 = param2; sticky_key->config = config; sticky_key->release_at = 0; sticky_key->timer_cancelled = false; sticky_key->timer_started = false; - sticky_key->modified_key_usage_page = 0; - sticky_key->modified_key_keycode = 0; + sticky_key->modified_key_trace_id = ZMK_BHV_STICKY_KEY_UNUSED; return sticky_key; } return NULL; } static void clear_sticky_key(struct active_sticky_key *sticky_key) { - sticky_key->position = ZMK_BHV_STICKY_KEY_POSITION_FREE; + sticky_key->trace_id = ZMK_BHV_STICKY_KEY_UNUSED; } -static struct active_sticky_key *find_sticky_key(uint32_t position) { +static struct active_sticky_key *find_sticky_key(uint32_t trace_id) { 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].trace_id == trace_id && !active_sticky_keys[i].timer_cancelled) { return &active_sticky_keys[i]; } } @@ -97,6 +96,7 @@ static inline int press_sticky_key_behavior(struct active_sticky_key *sticky_key struct zmk_behavior_binding_event event = { .position = sticky_key->position, .timestamp = timestamp, + .trace_id = sticky_key->trace_id, }; return behavior_keymap_binding_pressed(&binding, event); } @@ -111,6 +111,7 @@ static inline int release_sticky_key_behavior(struct active_sticky_key *sticky_k struct zmk_behavior_binding_event event = { .position = sticky_key->position, .timestamp = timestamp, + .trace_id = sticky_key->trace_id, }; clear_sticky_key(sticky_key); @@ -131,12 +132,13 @@ 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(event.trace_id); if (sticky_key != NULL) { stop_timer(sticky_key); release_sticky_key_behavior(sticky_key, event.timestamp); } - sticky_key = store_sticky_key(event.position, binding->param1, binding->param2, cfg); + sticky_key = + store_sticky_key(event.trace_id, event.position, binding->param1, binding->param2, cfg); if (sticky_key == NULL) { LOG_ERR("unable to store sticky key, did you press more than %d sticky_key?", ZMK_BHV_STICKY_KEY_MAX_HELD); @@ -144,19 +146,19 @@ static int on_sticky_key_binding_pressed(struct zmk_behavior_binding *binding, } press_sticky_key_behavior(sticky_key, event.timestamp); - LOG_DBG("%d new sticky_key", event.position); + LOG_DBG("%d new sticky_key", event.trace_id); 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(event.trace_id); if (sticky_key == NULL) { LOG_ERR("ACTIVE STICKY KEY CLEARED TOO EARLY"); return ZMK_BEHAVIOR_OPAQUE; } - if (sticky_key->modified_key_usage_page != 0 && sticky_key->modified_key_keycode != 0) { + if (sticky_key->modified_key_trace_id != ZMK_BHV_STICKY_KEY_UNUSED) { LOG_DBG("Another key was pressed while the sticky key was pressed. Act like a normal key."); return release_sticky_key_behavior(sticky_key, event.timestamp); } @@ -184,15 +186,12 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) { } 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->trace_id == ZMK_BHV_STICKY_KEY_UNUSED) { continue; } - if (strcmp(sticky_key->config->behavior.behavior_dev, "KEY_PRESS") == 0 && - HID_USAGE_ID(sticky_key->param1) == ev->keycode && - (HID_USAGE_PAGE(sticky_key->param1) & 0xFF) == ev->usage_page && - SELECT_MODS(sticky_key->param1) == ev->implicit_modifiers) { - // don't catch key down events generated by the sticky key behavior itself + if (sticky_key->trace_id == ev->trace_id) { + // don't catch events generated by the sticky key behavior itself continue; } @@ -205,7 +204,7 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) { } if (ev->state) { // key down - if (sticky_key->modified_key_usage_page != 0 || sticky_key->modified_key_keycode != 0) { + if (sticky_key->modified_key_trace_id != ZMK_BHV_STICKY_KEY_UNUSED) { // this sticky key is already in use for a keycode continue; } @@ -215,12 +214,9 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) { release_sticky_key_behavior(sticky_key, ev->timestamp); } } - sticky_key->modified_key_usage_page = ev->usage_page; - sticky_key->modified_key_keycode = ev->keycode; + sticky_key->modified_key_trace_id = ev->trace_id; } else { // key up - if (sticky_key->timer_started && - sticky_key->modified_key_usage_page == ev->usage_page && - sticky_key->modified_key_keycode == ev->keycode) { + if (sticky_key->timer_started && sticky_key->modified_key_trace_id == ev->trace_id) { stop_timer(sticky_key); release_sticky_key_behavior(sticky_key, ev->timestamp); } @@ -235,7 +231,7 @@ ZMK_SUBSCRIPTION(behavior_sticky_key, zmk_keycode_state_changed); 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->trace_id == ZMK_BHV_STICKY_KEY_UNUSED) { return; } if (sticky_key->timer_cancelled) { @@ -251,7 +247,7 @@ static int behavior_sticky_key_init(const struct device *dev) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { k_delayed_work_init(&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].trace_id = ZMK_BHV_STICKY_KEY_UNUSED; } } init_first_run = false; diff --git a/app/src/events/position_state_changed.c b/app/src/events/position_state_changed.c index bb40584e..24dcb6bb 100644 --- a/app/src/events/position_state_changed.c +++ b/app/src/events/position_state_changed.c @@ -7,4 +7,15 @@ #include #include -ZMK_EVENT_IMPL(zmk_position_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_position_state_changed); + +static uint32_t zmk_last_event_trace_id = 0; +static uint32_t zmk_event_trace_ids[ZMK_KEYMAP_LEN] = {0}; + +uint32_t zmk_get_event_trace_id(uint32_t position, bool pressed) { + if (pressed) { + zmk_last_event_trace_id++; + zmk_event_trace_ids[position] = zmk_last_event_trace_id; + } + return zmk_event_trace_ids[position]; +} diff --git a/app/src/keymap.c b/app/src/keymap.c index 1643f647..c0049570 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -152,24 +152,25 @@ const char *zmk_keymap_layer_label(uint8_t layer) { return zmk_keymap_layer_names[layer]; } -int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, int64_t timestamp) { +int zmk_keymap_apply_position_state(const struct zmk_position_state_changed *pos_ev, int layer) { // We want to make a copy of this, since it may be converted from // relative to absolute before being invoked - struct zmk_behavior_binding binding = zmk_keymap[layer][position]; + struct zmk_behavior_binding binding = zmk_keymap[layer][pos_ev->position]; const struct device *behavior; struct zmk_behavior_binding_event event = { .layer = layer, - .position = position, - .timestamp = timestamp, + .position = pos_ev->position, + .timestamp = pos_ev->timestamp, + .trace_id = pos_ev->trace_id, }; - LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, + LOG_DBG("layer: %d position: %d, binding name: %s", event.layer, event.position, log_strdup(binding.behavior_dev)); behavior = device_get_binding(binding.behavior_dev); if (!behavior) { - LOG_DBG("No behavior assigned to %d on layer %d", position, layer); + LOG_DBG("No behavior assigned to %d on layer %d", event.position, event.layer); return 1; } @@ -179,20 +180,21 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, return err; } - if (pressed) { + if (pos_ev->state) { return behavior_keymap_binding_pressed(&binding, event); } else { return behavior_keymap_binding_released(&binding, event); } } -int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp) { - if (pressed) { - zmk_keymap_active_behavior_layer[position] = _zmk_keymap_layer_state; +int zmk_keymap_position_state_changed(const struct zmk_position_state_changed *pos_ev) { + if (pos_ev->state) { + zmk_keymap_active_behavior_layer[pos_ev->position] = _zmk_keymap_layer_state; } 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 (zmk_keymap_layer_active_with_state( + layer, zmk_keymap_active_behavior_layer[pos_ev->position])) { + int ret = zmk_keymap_apply_position_state(pos_ev, layer); if (ret > 0) { LOG_DBG("behavior processing to continue to next layer"); continue; @@ -209,25 +211,25 @@ int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t t } #if ZMK_KEYMAP_HAS_SENSORS -int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sensor, - int64_t timestamp) { +int zmk_keymap_sensor_triggered(const struct zmk_sensor_event *sensor_ev) { for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) { if (zmk_keymap_layer_active(layer) && zmk_sensor_keymap[layer] != NULL) { - struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number]; + struct zmk_behavior_binding *binding = + &zmk_sensor_keymap[layer][sensor_ev->sensor_number]; const struct device *behavior; int ret; - LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number, - log_strdup(binding->behavior_dev)); + LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, + sensor_ev->sensor_number, log_strdup(binding->behavior_dev)); behavior = device_get_binding(binding->behavior_dev); if (!behavior) { - LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer); + LOG_DBG("No behavior assigned to %d on layer %d", sensor_ev->sensor_number, layer); continue; } - - ret = behavior_sensor_keymap_binding_triggered(binding, sensor, timestamp); + ret = behavior_sensor_keymap_binding_triggered(binding, sensor_ev->sensor, + sensor_ev->timestamp); if (ret > 0) { LOG_DBG("behavior processing to continue to next layer"); @@ -249,15 +251,13 @@ int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sens int keymap_listener(const zmk_event_t *eh) { const struct zmk_position_state_changed *pos_ev; if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) { - return zmk_keymap_position_state_changed(pos_ev->position, pos_ev->state, - pos_ev->timestamp); + return zmk_keymap_position_state_changed(pos_ev); } #if ZMK_KEYMAP_HAS_SENSORS const struct zmk_sensor_event *sensor_ev; if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { - return zmk_keymap_sensor_triggered(sensor_ev->sensor_number, sensor_ev->sensor, - sensor_ev->timestamp); + return zmk_keymap_sensor_triggered(sensor_ev); } #endif /* ZMK_KEYMAP_HAS_SENSORS */ diff --git a/app/src/kscan.c b/app/src/kscan.c index 0c128b2d..434f38bf 100644 --- a/app/src/kscan.c +++ b/app/src/kscan.c @@ -50,7 +50,11 @@ void zmk_kscan_process_msgq(struct k_work *item) { LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position, (pressed ? "true" : "false")); ZMK_EVENT_RAISE(new_zmk_position_state_changed((struct zmk_position_state_changed){ - .state = pressed, .position = position, .timestamp = k_uptime_get()})); + .state = pressed, + .position = position, + .timestamp = k_uptime_get(), + .trace_id = zmk_get_event_trace_id(position, pressed), + })); } } diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index a56b0b81..0632ed7c 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -72,7 +72,11 @@ static uint8_t split_central_notify_func(struct bt_conn *conn, uint32_t position = (i * 8) + j; bool pressed = position_state[i] & BIT(j); struct zmk_position_state_changed ev = { - .position = position, .state = pressed, .timestamp = k_uptime_get()}; + .position = position, + .state = pressed, + .timestamp = k_uptime_get(), + .trace_id = zmk_get_event_trace_id(position, pressed), + }; k_msgq_put(&peripheral_event_msgq, &ev, K_NO_WAIT); k_work_submit(&peripheral_event_work); diff --git a/app/tests/sticky-keys/10-overlapping-sticky-keys/events.patterns b/app/tests/sticky-keys/10-overlapping-sticky-keys/events.patterns new file mode 100644 index 00000000..833100f6 --- /dev/null +++ b/app/tests/sticky-keys/10-overlapping-sticky-keys/events.patterns @@ -0,0 +1 @@ +s/.*hid_listener_keycode_//p \ No newline at end of file diff --git a/app/tests/sticky-keys/10-overlapping-sticky-keys/keycode_events.snapshot b/app/tests/sticky-keys/10-overlapping-sticky-keys/keycode_events.snapshot new file mode 100644 index 00000000..465b4cc1 --- /dev/null +++ b/app/tests/sticky-keys/10-overlapping-sticky-keys/keycode_events.snapshot @@ -0,0 +1,6 @@ +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/10-overlapping-sticky-keys/native_posix.keymap b/app/tests/sticky-keys/10-overlapping-sticky-keys/native_posix.keymap new file mode 100644 index 00000000..5bb8f111 --- /dev/null +++ b/app/tests/sticky-keys/10-overlapping-sticky-keys/native_posix.keymap @@ -0,0 +1,41 @@ +#include +#include +#include + +/ { + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &sk LEFT_SHIFT &mo 1 + &none &none + >; + }; + + layer_one { + bindings = < + &sk LEFT_CONTROL &none + &kp A &none + >; + }; + }; +}; + +&kscan { + events = < + /* sticky shift */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + /* layer 1 */ + ZMK_MOCK_PRESS(0,1,10) + /* sticky ctrl */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + /* A */ + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_RELEASE(0,1,1200) + >; +}; \ No newline at end of file diff --git a/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot b/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot index d5bd587e..f220097f 100644 --- a/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot +++ b/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot @@ -1,4 +1,4 @@ pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 -pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/9-sk-dn-up-dn-up/native_posix.keymap b/app/tests/sticky-keys/9-sk-dn-up-dn-up/native_posix.keymap index d4c30fbf..12721c18 100644 --- a/app/tests/sticky-keys/9-sk-dn-up-dn-up/native_posix.keymap +++ b/app/tests/sticky-keys/9-sk-dn-up-dn-up/native_posix.keymap @@ -20,7 +20,7 @@ events = < ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) - /* the sticky key is pressed again, so the previous one must be cancelled */ + /* the sticky key is pressed again. Now it's active twice! */ ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,1200) >;