diff options
Diffstat (limited to 'app/src/behaviors')
-rw-r--r-- | app/src/behaviors/behavior_hold_tap.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index 4e91846..8f239dc 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -40,6 +40,7 @@ struct behavior_hold_tap_config { int tapping_term_ms; char *hold_behavior_dev; char *tap_behavior_dev; + int quick_tap_ms; enum flavor flavor; }; @@ -67,6 +68,24 @@ struct active_hold_tap active_hold_taps[ZMK_BHV_HOLD_TAP_MAX_HELD] = {}; // We capture most position_state_changed events and some modifiers_state_changed events. const zmk_event_t *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {}; +// Keep track of which key was tapped most recently for 'quick_tap_ms' +struct last_tapped { + int32_t position; + int64_t tap_deadline; +}; + +struct last_tapped last_tapped; + +static void store_last_tapped(struct active_hold_tap *hold_tap) { + last_tapped.position = hold_tap->position; + last_tapped.tap_deadline = hold_tap->timestamp + hold_tap->config->quick_tap_ms; +} + +static bool is_quick_tap(struct active_hold_tap *hold_tap) { + return last_tapped.position == hold_tap->position && + last_tapped.tap_deadline > hold_tap->timestamp; +} + static int capture_event(const zmk_event_t *event) { for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { if (captured_events[i] == NULL) { @@ -191,6 +210,7 @@ enum decision_moment { HT_OTHER_KEY_DOWN = 1, HT_OTHER_KEY_UP = 2, HT_TIMER_EVENT = 3, + HT_QUICK_TAP = 4, }; static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event) { @@ -204,6 +224,10 @@ static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_mome hold_tap->is_hold = 1; hold_tap->is_decided = true; break; + case HT_QUICK_TAP: + hold_tap->is_hold = 0; + hold_tap->is_decided = true; + break; default: return; } @@ -219,6 +243,10 @@ static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision hold_tap->is_hold = 1; hold_tap->is_decided = true; break; + case HT_QUICK_TAP: + hold_tap->is_hold = 0; + hold_tap->is_decided = true; + break; default: return; } @@ -235,6 +263,10 @@ static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decisio hold_tap->is_hold = 1; hold_tap->is_decided = true; break; + case HT_QUICK_TAP: + hold_tap->is_hold = 0; + hold_tap->is_decided = true; + break; default: return; } @@ -293,6 +325,7 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome binding.behavior_dev = hold_tap->config->tap_behavior_dev; binding.param1 = hold_tap->param_tap; binding.param2 = 0; + store_last_tapped(hold_tap); } behavior_keymap_binding_pressed(&binding, event); release_captured_events(); @@ -320,6 +353,10 @@ static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding, LOG_DBG("%d new undecided hold_tap", event.position); undecided_hold_tap = hold_tap; + if (is_quick_tap(hold_tap)) { + decide_hold_tap(hold_tap, HT_QUICK_TAP); + } + // if this behavior was queued we have to adjust the timer to only // wait for the remaining time. int32_t tapping_term_ms_left = (hold_tap->timestamp + cfg->tapping_term_ms) - k_uptime_get(); @@ -492,6 +529,7 @@ static struct behavior_hold_tap_data behavior_hold_tap_data; .tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \ .hold_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 0)), \ .tap_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 1)), \ + .quick_tap_ms = DT_INST_PROP(n, quick_tap_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, \ |