Fix RPI breaking all mod-tap holds: revert to manual last_key_time

last_input_activity_elapsed() includes the mod-tap key's OWN matrix
event. Since process_record_user fires ~tapping_term ms after the
physical press (after action_tapping resolves tap/hold), the elapsed
time is always ≈ tapping_term < RPI thresholds, so holds never work.

Revert to manual last_key_time updated at the END of process_record_user.
Remove SPLIT_ACTIVITY_ENABLE (not needed — master processes all keys
from both halves).

Agent-Logs-Url: https://github.com/timfee/qmk_userspace/sessions/14d8fea9-7e5d-40c4-9b47-abab68e5d4e2

Co-authored-by: timfee <3246342+timfee@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-04-14 00:37:31 +00:00 committed by GitHub
commit 847d7313b1
Failed to generate hash of commit
2 changed files with 14 additions and 9 deletions

View file

@ -29,6 +29,5 @@
// ── Split transport ── // ── Split transport ──
#define SPLIT_TRANSPORT_MIRROR #define SPLIT_TRANSPORT_MIRROR
#define SPLIT_WPM_ENABLE #define SPLIT_WPM_ENABLE
#define SPLIT_ACTIVITY_ENABLE
#define SPLIT_WATCHDOG_TIMEOUT 4000 #define SPLIT_WATCHDOG_TIMEOUT 4000
#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_OLED_STATE, USER_SYNC_LASTKEY, USER_SYNC_PRESSES #define SPLIT_TRANSACTION_IDS_USER USER_SYNC_OLED_STATE, USER_SYNC_LASTKEY, USER_SYNC_PRESSES

View file

@ -6,8 +6,16 @@
#endif #endif
// ── State for require-prior-idle ── // ── State for require-prior-idle ──
// (last_key_time removed: using last_input_activity_elapsed() instead, which // Manual timestamp of the last key processed through process_record_user.
// is synced from both halves via SPLIT_ACTIVITY_ENABLE, fixing cross-half RPI) // This is intentionally NOT last_input_activity_elapsed() — that API reflects
// the most recent matrix scan change, which includes the current mod-tap key's
// OWN press. Since process_record_user fires ~tapping_term ms after the
// physical press (after tap/hold resolution), the elapsed time would always be
// ≈ tapping_term, which is less than the RPI thresholds — killing every hold.
// A manual variable updated at the END of process_record_user correctly
// captures the previous key's timing. This works for both halves because QMK
// split processes all key events on the master side.
static uint16_t last_key_time = 0;
// ── Combos (matching Vial config) ── // ── Combos (matching Vial config) ──
const uint16_t PROGMEM lparen_combo[] = {KC_R, KC_T, COMBO_END}; const uint16_t PROGMEM lparen_combo[] = {KC_R, KC_T, COMBO_END};
@ -214,12 +222,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
} }
#endif #endif
// Require-prior-idle: force tap if pressed too soon after any recent // Require-prior-idle: force tap if pressed too soon after last key
// activity on either half. SPLIT_ACTIVITY_ENABLE synchronizes the uint16_t elapsed = timer_elapsed(last_key_time);
// underlying activity timestamp from the slave to the master at the
// transport level, so last_input_activity_elapsed() reflects the most
// recent keypress on either half — not just the master side.
uint32_t elapsed = last_input_activity_elapsed();
switch (keycode) { switch (keycode) {
case GU_SPC: case GU_SPC:
@ -271,6 +275,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
} }
break; break;
} }
last_key_time = timer_read();
} }
return true; return true;
} }