From 0c9112bcaddd76cc5776e40a891cd2b6cde8a5cc Mon Sep 17 00:00:00 2001 From: Christoph Cullmann Date: Sun, 15 Sep 2024 16:45:49 +0200 Subject: [PATCH] update Achordion --- common/achordion.c | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/common/achordion.c b/common/achordion.c index 07c1835..4968e9d 100644 --- a/common/achordion.c +++ b/common/achordion.c @@ -74,6 +74,16 @@ static void update_streak_timer(uint16_t keycode, keyrecord_t* record) { } #endif +// Presses or releases eager_mods through process_action(), which skips the +// usual event handling pipeline. The action is considered as a mod-tap hold or +// release, with Retro Tapping if enabled. +static void process_eager_mods_action(void) { + action_t action; + action.code = ACTION_MODS_TAP_KEY( + eager_mods, QK_MOD_TAP_GET_TAP_KEYCODE(tap_hold_keycode)); + process_action(&tap_hold_record, action); +} + // Calls `process_record()` with state set to RECURSING. static void recursively_process_record(keyrecord_t* record, uint8_t state) { achordion_state = STATE_RECURSING; @@ -92,9 +102,11 @@ static void settle_as_hold(void) { if (eager_mods) { // If eager mods are being applied, nothing needs to be done besides // updating the state. + dprintln("Achordion: Settled eager mod as hold."); achordion_state = STATE_HOLDING; } else { // Create hold press event. + dprintln("Achordion: Plumbing hold press."); recursively_process_record(&tap_hold_record, STATE_HOLDING); } } @@ -102,14 +114,22 @@ static void settle_as_hold(void) { // Sends tap press and release and settles the active tap-hold key as tapped. static void settle_as_tap(void) { if (eager_mods) { // Clear eager mods if set. +#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) #ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE neutralize_flashing_modifiers(get_mods()); #endif // DUMMY_MOD_NEUTRALIZER_KEYCODE - unregister_mods(eager_mods); +#endif // defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) + tap_hold_record.event.pressed = false; + // To avoid falsely triggering Retro Tapping, process eager mods release as + // a regular mods release rather than a mod-tap release. + action_t action; + action.code = ACTION_MODS(eager_mods); + process_action(&tap_hold_record, action); eager_mods = 0; } dprintln("Achordion: Plumbing tap press."); + tap_hold_record.event.pressed = true; tap_hold_record.tap.count = 1; // Revise event as a tap. tap_hold_record.tap.interrupted = true; // Plumb tap press event. @@ -155,9 +175,16 @@ bool process_achordion(uint16_t keycode, keyrecord_t* record) { if (is_mt) { // Apply mods immediately if they are "eager." const uint8_t mod = mod_config(QK_MOD_TAP_GET_MODS(keycode)); - if (achordion_eager_mod(mod)) { - eager_mods = ((mod & 0x10) == 0) ? mod : (mod << 4); - register_mods(eager_mods); + if ( +#if defined(CAPS_WORD_ENABLE) && defined(CAPS_WORD_INVERT_ON_SHIFT) + // Since eager mods bypass normal event handling, eager Shift does + // not work with CAPS_WORD_INVERT_ON_SHIFT. So if this option is + // enabled, we don't apply Shift eagerly when Caps Word is on. + !(is_caps_word_on() && (mod & MOD_LSFT) != 0) && +#endif // defined(CAPS_WORD_ENABLE) && defined(CAPS_WORD_INVERT_ON_SHIFT) + achordion_eager_mod(mod)) { + eager_mods = mod; + process_eager_mods_action(); } } @@ -180,18 +207,8 @@ bool process_achordion(uint16_t keycode, keyrecord_t* record) { if (keycode == tap_hold_keycode && !record->event.pressed) { if (eager_mods) { dprintln("Achordion: Key released. Clearing eager mods."); - // If Retro Tapping and no other key was pressed, settle as tapped. -#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) - if (!pressed_another_key_before_release -#ifdef RETRO_TAPPING_PER_KEY - && get_retro_tapping(tap_hold_keycode, &tap_hold_record) -#endif // RETREO_TAPPING_PER_KEY - ) { - settle_as_tap(); - } -#endif // defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) - - unregister_mods(eager_mods); + tap_hold_record.event.pressed = false; + process_eager_mods_action(); } else if (achordion_state == STATE_HOLDING) { dprintln("Achordion: Key released. Plumbing hold release."); tap_hold_record.event.pressed = false; @@ -238,7 +255,6 @@ bool process_achordion(uint16_t keycode, keyrecord_t* record) { (!is_key_event || (is_tap_hold && record->tap.count == 0) || achordion_chord(tap_hold_keycode, &tap_hold_record, keycode, record))) { - dprintln("Achordion: Plumbing hold press."); settle_as_hold(); #ifdef REPEAT_KEY_ENABLE @@ -285,7 +301,6 @@ bool process_achordion(uint16_t keycode, keyrecord_t* record) { void achordion_task(void) { if (achordion_state == STATE_UNSETTLED && timer_expired(timer_read(), hold_timer)) { - dprintln("Achordion: Timeout. Plumbing hold press."); settle_as_hold(); // Timeout expired, settle the key as held. }