diff --git a/users/timfee/timfee.c b/users/timfee/timfee.c index 4160e9d0..3a476b63 100644 --- a/users/timfee/timfee.c +++ b/users/timfee/timfee.c @@ -26,15 +26,35 @@ const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM = { }; // ── Chordal Hold per-key override ── -// Layer-tap keys (ESC_L2, MIN_L1) must always resolve as hold when -// another key is pressed so the layer activates — even for same-hand keys. -// Mod-tap keys use the default layout-based logic (cross-hand = hold). +// Layer-tap keys always resolve as hold so the layer activates for +// same-hand keys. Cross-hand mod-tap chords always resolve as hold. +// Same-hand mod-tap chords use a timing heuristic: if the other key +// arrives within 150 ms of the tap-hold key press it is a fast typing +// roll (tap); otherwise the user is deliberately holding a modifier +// for a shortcut like Cmd+V or Cmd+Shift+V (hold). +#define CHORDAL_SAME_HAND_MS 150 + bool get_chordal_hold(uint16_t tap_hold_keycode, keyrecord_t *tap_hold_record, uint16_t other_keycode, keyrecord_t *other_record) { + // Layer-tap: always hold (layers need same-hand access). if (IS_QK_LAYER_TAP(tap_hold_keycode)) { return true; } - return get_chordal_hold_default(tap_hold_record, other_record); + + // Cross-hand: always hold (standard chordal behaviour). + if (get_chordal_hold_default(tap_hold_record, other_record)) { + return true; + } + + // Same-hand mod-tap: timing decides tap vs hold. + if (IS_QK_MOD_TAP(tap_hold_keycode)) { + uint16_t elapsed = + other_record->event.time - tap_hold_record->event.time; + return elapsed >= CHORDAL_SAME_HAND_MS; + } + + // Any other same-hand combo: tap. + return false; } // ── Combos (matching Vial config) ──