diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index 45b8bea7..1db556c5 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -20,7 +20,7 @@ */ typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1, - u32_t param2); + u32_t param2, s64_t timestamp); typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor, u32_t param1, u32_t param2); @@ -43,17 +43,18 @@ __subsystem struct behavior_driver_api { * @retval Negative errno code if failure. */ __syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, - u32_t param2); + u32_t param2, s64_t timestamp); static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position, - u32_t param1, u32_t param2) { + u32_t param1, u32_t param2, + s64_t timestamp) { const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api; if (api->binding_pressed == NULL) { return -ENOTSUP; } - return api->binding_pressed(dev, position, param1, param2); + return api->binding_pressed(dev, position, param1, param2, timestamp); } /** @@ -65,17 +66,18 @@ static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32 * @retval Negative errno code if failure. */ __syscall int behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1, - u32_t param2); + u32_t param2, s64_t timestamp); static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position, - u32_t param1, u32_t param2) { + u32_t param1, u32_t param2, + s64_t timestamp) { const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api; if (api->binding_released == NULL) { return -ENOTSUP; } - return api->binding_released(dev, position, param1, param2); + return api->binding_released(dev, position, param1, param2, timestamp); } /** diff --git a/app/include/zmk/events/keycode-state-changed.h b/app/include/zmk/events/keycode-state-changed.h index 4c006543..7246b83d 100644 --- a/app/include/zmk/events/keycode-state-changed.h +++ b/app/include/zmk/events/keycode-state-changed.h @@ -14,16 +14,20 @@ struct keycode_state_changed { u8_t usage_page; u32_t keycode; bool state; + u32_t position; + s32_t timestamp; }; ZMK_EVENT_DECLARE(keycode_state_changed); inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_page, u32_t keycode, - bool state) { + bool state, s32_t position, + s32_t timestamp) { struct keycode_state_changed *ev = new_keycode_state_changed(); ev->usage_page = usage_page; ev->keycode = keycode; ev->state = state; - + ev->position = position; + ev->timestamp = timestamp; return ev; } \ No newline at end of file diff --git a/app/include/zmk/events/position-state-changed.h b/app/include/zmk/events/position-state-changed.h index f88080d2..e4cbbbe7 100644 --- a/app/include/zmk/events/position-state-changed.h +++ b/app/include/zmk/events/position-state-changed.h @@ -13,6 +13,7 @@ struct position_state_changed { struct zmk_event_header header; u32_t position; bool state; + s64_t timestamp; }; ZMK_EVENT_DECLARE(position_state_changed); \ No newline at end of file diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index 61925878..b8f49694 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -11,4 +11,4 @@ int zmk_keymap_layer_activate(u8_t layer); int zmk_keymap_layer_deactivate(u8_t layer); int zmk_keymap_layer_toggle(u8_t layer); -int zmk_keymap_position_state_changed(u32_t position, bool pressed); +int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp); diff --git a/app/src/behaviors/behavior_bt.c b/app/src/behaviors/behavior_bt.c index 09fadba2..e62c64be 100644 --- a/app/src/behaviors/behavior_bt.c +++ b/app/src/behaviors/behavior_bt.c @@ -18,7 +18,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include -static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg) { +static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg, s64_t timestamp) { switch (command) { case BT_CLR_CMD: return zmk_ble_clear_bonds(); @@ -38,7 +38,7 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c static int behavior_bt_init(struct device *dev) { return 0; }; static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t command, - u32_t arg) { + u32_t arg, s64_t timestamp) { return 0; } diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index 8f307a6b..ac286e33 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -40,10 +40,8 @@ struct behavior_hold_tap_behaviors { struct zmk_behavior_binding hold; }; -typedef k_timeout_t (*timer_func)(); - struct behavior_hold_tap_config { - timer_func tapping_term_ms; + int tapping_term_ms; struct behavior_hold_tap_behaviors *behaviors; enum flavor flavor; }; @@ -53,6 +51,7 @@ struct active_hold_tap { s32_t position; u32_t param_hold; u32_t param_tap; + s64_t timestamp; bool is_decided; bool is_hold; const struct behavior_hold_tap_config *config; @@ -164,6 +163,7 @@ static struct active_hold_tap *find_hold_tap(u32_t position) { } static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap, + s64_t timestamp, 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) { @@ -175,6 +175,7 @@ static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, active_hold_taps[i].config = config; active_hold_taps[i].param_hold = param_hold; active_hold_taps[i].param_tap = param_tap; + active_hold_taps[i].timestamp = timestamp; return &active_hold_taps[i]; } return NULL; @@ -285,18 +286,18 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome behavior = &hold_tap->config->behaviors->hold; struct device *behavior_device = device_get_binding(behavior->behavior_dev); behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold, - 0); + 0, hold_tap->timestamp); } else { behavior = &hold_tap->config->behaviors->tap; struct device *behavior_device = device_get_binding(behavior->behavior_dev); - behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap, - 0); + behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap, 0, + hold_tap->timestamp); } release_captured_events(); } static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold, - u32_t param_tap) { + u32_t param_tap, s64_t timestamp) { const struct behavior_hold_tap_config *cfg = dev->config_info; if (undecided_hold_tap != NULL) { @@ -305,7 +306,8 @@ static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t return 0; } - struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg); + struct active_hold_tap *hold_tap = + store_hold_tap(position, param_hold, param_tap, timestamp, 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); @@ -314,23 +316,32 @@ static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t LOG_DBG("%d new undecided hold_tap", position); undecided_hold_tap = hold_tap; - k_delayed_work_submit(&hold_tap->work, cfg->tapping_term_ms()); - // todo: once we get timing info for keypresses, start the timer relative to the original - // keypress don't forget to simulate a timer-event before the event after that time was handled. + // if this behavior was queued we have to adjust the timer to only + // wait for the remaining time. + s32_t tapping_term_ms_left = (hold_tap->timestamp + cfg->tapping_term_ms) - k_uptime_get(); + if (tapping_term_ms_left > 0) { + k_delayed_work_submit(&hold_tap->work, K_MSEC(tapping_term_ms_left)); + } return 0; } -static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_t _, u32_t __) { +static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_t _, u32_t __, + s64_t timestamp) { struct active_hold_tap *hold_tap = find_hold_tap(position); - if (hold_tap == NULL) { LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY"); return 0; } + // If these events were queued, the timer event may be queued too late or not at all. + // We insert a timer event before the TH_KEY_UP event to verify. int work_cancel_result = k_delayed_work_cancel(&hold_tap->work); + if (timestamp > (hold_tap->timestamp + hold_tap->config->tapping_term_ms)) { + decide_hold_tap(hold_tap, HT_TIMER_EVENT); + } + decide_hold_tap(hold_tap, HT_KEY_UP); struct zmk_behavior_binding *behavior; @@ -338,12 +349,12 @@ static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_ behavior = &hold_tap->config->behaviors->hold; struct device *behavior_device = device_get_binding(behavior->behavior_dev); behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold, - 0); + 0, timestamp); } else { behavior = &hold_tap->config->behaviors->tap; struct device *behavior_device = device_get_binding(behavior->behavior_dev); behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap, - 0); + 0, timestamp); } if (work_cancel_result == -EINPROGRESS) { @@ -382,6 +393,14 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) { } } + // If these events were queued, the timer event may be queued too late or not at all. + // We make a timer decision before the other key events are handled if the timer would + // have run out. + if (ev->timestamp > + (undecided_hold_tap->timestamp + undecided_hold_tap->config->tapping_term_ms)) { + 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 @@ -473,14 +492,11 @@ static struct behavior_hold_tap_data behavior_hold_tap_data; }, #define KP_INST(n) \ - static k_timeout_t behavior_hold_tap_config_##n##_gettime() { \ - return K_MSEC(DT_INST_PROP(n, tapping_term_ms)); \ - } \ static struct behavior_hold_tap_behaviors behavior_hold_tap_behaviors_##n = { \ .hold = _TRANSFORM_ENTRY(0, n).tap = _TRANSFORM_ENTRY(1, n)}; \ static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \ .behaviors = &behavior_hold_tap_behaviors_##n, \ - .tapping_term_ms = &behavior_hold_tap_config_##n##_gettime, \ + .tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \ .flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \ }; \ DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \ diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c index bbfbe369..fcba451c 100644 --- a/app/src/behaviors/behavior_key_press.c +++ b/app/src/behaviors/behavior_key_press.c @@ -22,18 +22,22 @@ struct behavior_key_press_data {}; static int behavior_key_press_init(struct device *dev) { return 0; }; -static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _) { +static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _, + s64_t timestamp) { const struct behavior_key_press_config *cfg = dev->config_info; LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode); - return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true)); + return ZMK_EVENT_RAISE( + create_keycode_state_changed(cfg->usage_page, keycode, true, position, timestamp)); } -static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _) { +static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _, + s64_t timestamp) { const struct behavior_key_press_config *cfg = dev->config_info; LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode); - return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false)); + return ZMK_EVENT_RAISE( + create_keycode_state_changed(cfg->usage_page, keycode, false, position, timestamp)); } static const struct behavior_driver_api behavior_key_press_driver_api = { diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c index 80b7165b..ddd6192e 100644 --- a/app/src/behaviors/behavior_momentary_layer.c +++ b/app/src/behaviors/behavior_momentary_layer.c @@ -19,15 +19,15 @@ struct behavior_mo_data {}; static int behavior_mo_init(struct device *dev) { return 0; }; -static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) { +static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _, + s64_t _timestamp) { LOG_DBG("position %d layer %d", position, layer); - return zmk_keymap_layer_activate(layer); } -static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) { +static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _, + s64_t _timestamp) { LOG_DBG("position %d layer %d", position, layer); - return zmk_keymap_layer_deactivate(layer); } diff --git a/app/src/behaviors/behavior_none.c b/app/src/behaviors/behavior_none.c index b548e6f7..00fbcdb0 100644 --- a/app/src/behaviors/behavior_none.c +++ b/app/src/behaviors/behavior_none.c @@ -19,12 +19,12 @@ struct behavior_none_data {}; static int behavior_none_init(struct device *dev) { return 0; }; static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { + u32_t _param2, s64_t _timestamp) { return 0; } static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { + u32_t _param2, s64_t _timestamp) { return 0; } diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c index 90de20b0..03c5172d 100644 --- a/app/src/behaviors/behavior_reset.c +++ b/app/src/behaviors/behavior_reset.c @@ -20,7 +20,7 @@ struct behavior_reset_config { static int behavior_reset_init(struct device *dev) { return 0; }; static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { + u32_t _param2, s64_t _timestamp) { const struct behavior_reset_config *cfg = dev->config_info; // TODO: Correct magic code for going into DFU? diff --git a/app/src/behaviors/behavior_rgb_underglow.c b/app/src/behaviors/behavior_rgb_underglow.c index 621eab5e..f5c2d260 100644 --- a/app/src/behaviors/behavior_rgb_underglow.c +++ b/app/src/behaviors/behavior_rgb_underglow.c @@ -17,7 +17,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static int behavior_rgb_underglow_init(struct device *dev) { return 0; } -static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _) { +static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _, + s64_t _timestamp) { switch (action) { case RGB_TOG: return zmk_rgb_underglow_toggle(); diff --git a/app/src/behaviors/behavior_toggle_layer.c b/app/src/behaviors/behavior_toggle_layer.c index 28194519..302de6b8 100644 --- a/app/src/behaviors/behavior_toggle_layer.c +++ b/app/src/behaviors/behavior_toggle_layer.c @@ -19,15 +19,15 @@ struct behavior_tog_data {}; static int behavior_tog_init(struct device *dev) { return 0; }; -static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) { +static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _, + s64_t _timestamp) { LOG_DBG("position %d layer %d", position, layer); - return zmk_keymap_layer_toggle(layer); } -static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) { +static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _, + s64_t _timestamp) { LOG_DBG("position %d layer %d", position, layer); - return 0; } diff --git a/app/src/behaviors/behavior_transparent.c b/app/src/behaviors/behavior_transparent.c index f7852f39..a46a92e0 100644 --- a/app/src/behaviors/behavior_transparent.c +++ b/app/src/behaviors/behavior_transparent.c @@ -19,12 +19,12 @@ struct behavior_transparent_data {}; static int behavior_transparent_init(struct device *dev) { return 0; }; static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { + u32_t _param2, s64_t _timestamp) { return 1; } static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, - u32_t _param2) { + u32_t _param2, s64_t _timestamp) { return 1; } diff --git a/app/src/keymap.c b/app/src/keymap.c index a87ce04b..4e4c9f65 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -104,7 +104,7 @@ bool is_active_layer(u8_t layer, u32_t layer_state) { return (layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default; } -int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) { +int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed, s64_t timestamp) { struct zmk_behavior_binding *binding = &zmk_keymap[layer][position]; struct device *behavior; @@ -119,20 +119,20 @@ int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) { } if (pressed) { - return behavior_keymap_binding_pressed(behavior, position, binding->param1, - binding->param2); + return behavior_keymap_binding_pressed(behavior, position, binding->param1, binding->param2, + timestamp); } else { return behavior_keymap_binding_released(behavior, position, binding->param1, - binding->param2); + binding->param2, timestamp); } } -int zmk_keymap_position_state_changed(u32_t position, bool pressed) { +int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp) { for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) { u32_t layer_state = pressed ? zmk_keymap_layer_state : zmk_keymap_active_behavior_layer[position]; if (is_active_layer(layer, layer_state)) { - int ret = zmk_keymap_apply_position_state(layer, position, pressed); + int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp); zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state; @@ -194,7 +194,7 @@ int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) { int keymap_listener(const struct zmk_event_header *eh) { if (is_position_state_changed(eh)) { const struct position_state_changed *ev = cast_position_state_changed(eh); - return zmk_keymap_position_state_changed(ev->position, ev->state); + return zmk_keymap_position_state_changed(ev->position, ev->state, ev->timestamp); #if ZMK_KEYMAP_HAS_SENSORS } else if (is_sensor_event(eh)) { const struct sensor_event *ev = cast_sensor_event(eh); diff --git a/app/src/kscan.c b/app/src/kscan.c index 0046f5ca..8575e708 100644 --- a/app/src/kscan.c +++ b/app/src/kscan.c @@ -52,6 +52,7 @@ void zmk_kscan_process_msgq(struct k_work *item) { pos_ev = new_position_state_changed(); pos_ev->state = pressed; pos_ev->position = position; + pos_ev->timestamp = k_uptime_get(); ZMK_EVENT_RAISE(pos_ev); } } diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index cb1b68be..ed52ba07 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -60,6 +60,7 @@ static u8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subsc struct position_state_changed *pos_ev = new_position_state_changed(); pos_ev->position = position; pos_ev->state = pressed; + pos_ev->timestamp = k_uptime_get(); LOG_DBG("Trigger key position state change for %d", position); ZMK_EVENT_RAISE(pos_ev); diff --git a/app/tests/hold-tap/balanced/many-nested/events.patterns b/app/tests/hold-tap/balanced/many-nested/events.patterns new file mode 100644 index 00000000..fdf2b15c --- /dev/null +++ b/app/tests/hold-tap/balanced/many-nested/events.patterns @@ -0,0 +1,4 @@ +s/.*hid_listener_keycode/kp/p +s/.*mo_keymap_binding/mo/p +s/.*on_hold_tap_binding/ht_binding/p +s/.*decide_hold_tap/ht_decide/p \ No newline at end of file diff --git a/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot new file mode 100644 index 00000000..806896fb --- /dev/null +++ b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot @@ -0,0 +1,20 @@ +ht_binding_pressed: 0 new undecided hold_tap +ht_decide: 0 decided hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe1 +ht_binding_pressed: 1 new undecided hold_tap +ht_decide: 1 decided hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe0 +ht_binding_pressed: 2 new undecided hold_tap +ht_binding_released: 0 cleaning up hold-tap +ht_decide: 2 decided hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe3 +ht_binding_pressed: 3 new undecided hold_tap +ht_binding_released: 1 cleaning up hold-tap +ht_decide: 3 decided hold (balanced event 3) +kp_pressed: usage_page 0x07 keycode 0xe2 +kp_released: usage_page 0x07 keycode 0xe1 +kp_released: usage_page 0x07 keycode 0xe0 +kp_released: usage_page 0x07 keycode 0xe3 +ht_binding_released: 2 cleaning up hold-tap +kp_released: usage_page 0x07 keycode 0xe2 +ht_binding_released: 3 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/many-nested/native_posix.keymap b/app/tests/hold-tap/balanced/many-nested/native_posix.keymap new file mode 100644 index 00000000..3cb04c34 --- /dev/null +++ b/app/tests/hold-tap/balanced/many-nested/native_posix.keymap @@ -0,0 +1,41 @@ +#include +#include +#include + +/ { + behaviors { + ht_bal: behavior_hold_tap_balanced { + compatible = "zmk,behavior-hold-tap"; + label = "HOLD_TAP_BALANCED"; + #binding-cells = <2>; + flavor = "balanced"; + tapping_term_ms = <300>; + bindings = <&kp>, <&kp>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &ht_bal LSFT F &ht_bal LCTL J + &ht_bal LGUI H &ht_bal LALT L + >; + }; + }; +}; + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,100) + ZMK_MOCK_PRESS(0,1,100) + ZMK_MOCK_PRESS(1,0,100) + ZMK_MOCK_PRESS(1,1,100) + ZMK_MOCK_RELEASE(0,0,100) + ZMK_MOCK_RELEASE(0,1,100) + ZMK_MOCK_RELEASE(1,0,100) + ZMK_MOCK_RELEASE(1,1,100) + >; +};