From d8dccd67a6c7a9069333c7171212fd21624875eb Mon Sep 17 00:00:00 2001 From: rootiest Date: Thu, 9 Apr 2026 00:19:04 -0400 Subject: [PATCH 1/4] fix(caps-mod): fixes errant taps of modifiers Prevents modifiers (GUI and ALT) from firing a tap signal when they are used in conjunction with the CAPS_MOD key. --- keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c index 94c30c0c39..5b00e08fe5 100644 --- a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c +++ b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c @@ -176,8 +176,14 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } else { uint8_t mods = get_mods(); if (mods & MOD_MASK_GUI) { + // Clear GUI before acting so the OS doesn't see a GUI tap + del_mods(MOD_MASK_GUI); + send_keyboard_report(); autocorrect_toggle(); } else if (mods & MOD_MASK_ALT) { + // Clear Alt before acting so the OS doesn't see an Alt tap + del_mods(MOD_MASK_ALT); + send_keyboard_report(); caps_word_toggle(); } else if (mods & MOD_MASK_SHIFT) { tap_code(KC_CAPS); // Shift still held → host sees Shift+CapsLock (toggles on most OSes) -- 2.52.0 From c0d868dca3f52eb05b27d283d1c67ea601d8b658 Mon Sep 17 00:00:00 2001 From: rootiest Date: Thu, 9 Apr 2026 00:28:34 -0400 Subject: [PATCH 2/4] fix(caps-mod) implement dummy keypress for capsmod combos Send KC_F24 when modifiers are used with CAPS_MOD to avoid the modifiers being treated as lone taps. --- .../q5_max/ansi_encoder/keymaps/via/keymap.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c index 5b00e08fe5..173888b756 100644 --- a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c +++ b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/keymap.c @@ -169,6 +169,16 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { caps_mod_held = true; caps_mod_timer = timer_read(); + // If a real modifier is held, send a dummy key so the OS sees + // modifier+key rather than a bare modifier hold/tap. Without + // this, the OS never receives any keycode while the modifier is + // down and treats the eventual modifier release as a tap (e.g. + // GUI opening the app menu). KC_F24 is harmless and universally + // ignored by applications. + if (get_mods() & (MOD_MASK_GUI | MOD_MASK_ALT | MOD_MASK_SHIFT)) { + register_code(KC_F24); + unregister_code(KC_F24); + } } else { if (caps_mod_ctrl_registered) { unregister_code(KC_LCTL); @@ -176,14 +186,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } else { uint8_t mods = get_mods(); if (mods & MOD_MASK_GUI) { - // Clear GUI before acting so the OS doesn't see a GUI tap - del_mods(MOD_MASK_GUI); - send_keyboard_report(); autocorrect_toggle(); } else if (mods & MOD_MASK_ALT) { - // Clear Alt before acting so the OS doesn't see an Alt tap - del_mods(MOD_MASK_ALT); - send_keyboard_report(); caps_word_toggle(); } else if (mods & MOD_MASK_SHIFT) { tap_code(KC_CAPS); // Shift still held → host sees Shift+CapsLock (toggles on most OSes) -- 2.52.0 From d4bd9034239bac079567950aeca95192b954adba Mon Sep 17 00:00:00 2001 From: rootiest Date: Fri, 10 Apr 2026 14:19:09 -0400 Subject: [PATCH 3/4] fix(chatter): fix key chatter with stricter tap terms and debounce --- .../keychron/q5_max/ansi_encoder/keymaps/via/config.h | 10 ++++++++++ .../keychron/q5_max/ansi_encoder/keymaps/via/rules.mk | 2 ++ 2 files changed, 12 insertions(+) diff --git a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/config.h b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/config.h index 924e45b5ff..e9fd63dd8e 100644 --- a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/config.h +++ b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/config.h @@ -3,6 +3,16 @@ #pragma once +// Tight, strict combo window for a simultaneous 3-key press. +// This ensures the fallback combo only fires when intended. +#define COMBO_TERM 10 +#define COMBO_STRICT_TIMER + +// Use a more conservative debounce period (20ms is standard for Keychron) +// but since we switched to 'sym_defer_pk' in rules.mk, this will now +// require 20ms of STABILITY before a keypress is reported. +#define DEBOUNCE 20 + // Always resolve combo keycodes from BASE (layer 0) so the // COMM+DOT+SLSH fallback combo fires regardless of the active layer. #define COMBO_ONLY_FROM_LAYER 0 diff --git a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/rules.mk b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/rules.mk index 256b50f150..a2e60506ae 100644 --- a/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/rules.mk +++ b/keyboards/keychron/q5_max/ansi_encoder/keymaps/via/rules.mk @@ -5,3 +5,5 @@ COMBO_ENABLE = yes CAPS_WORD_ENABLE = yes AUTOCORRECT_ENABLE = yes SRC += chord_unicode.c + +DEBOUNCE_TYPE = sym_defer_pk -- 2.52.0 From 9b2cd0cb326694be3b09b84b1c9353c26f64c69a Mon Sep 17 00:00:00 2001 From: rootiest Date: Fri, 10 Apr 2026 14:19:59 -0400 Subject: [PATCH 4/4] chore: ignore gemini session file Session file is only relevant during development and unique to the local machine. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea7ad925a8..e795ba3fb8 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,4 @@ via*.json /.claude_session /.remember/tmp/save-session.pid /.direnv/CACHEDIR.TAG +/.gemini_session -- 2.52.0