feat(q5_max): Add speculative hold for caps_mod key
This commit is contained in:
@@ -17,7 +17,16 @@
|
||||
// COMM+DOT+SLSH fallback combo fires regardless of the active layer.
|
||||
#define COMBO_ONLY_FROM_LAYER 0
|
||||
|
||||
// Pressing the Shift key continues Caps Word and inverts the shift state
|
||||
#define CAPS_WORD_INVERT_ON_SHIFT
|
||||
|
||||
// Default tapping term for mod-tap, layer-tap, and tap-dance keys.
|
||||
#define TAPPING_TERM 200
|
||||
// Allow per-key overrides via get_tapping_term() in keymap.c.
|
||||
#define TAPPING_TERM_PER_KEY
|
||||
|
||||
// Use right CTRL key to neutralize modifier taps when cancelled.
|
||||
#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL
|
||||
|
||||
// Neutralize left ALT and left GUI (Default value)
|
||||
#define MODS_TO_NEUTRALIZE {MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI)}
|
||||
|
||||
@@ -41,10 +41,11 @@ enum custom_keycodes {
|
||||
LCK_FN4, // Lock/unlock FN4
|
||||
LCK_CTL, // Lock/unlock KEEB_CTL
|
||||
LCK_BASE, // Clear all locks and return to BASE
|
||||
CAPS_MOD, // Tap=ESC, hold=Ctrl, Shift=CapsLock, Alt=CapsWord, GUI=Autocorrect
|
||||
BSP_DEL, // Tap=Backspace, Shift+Tap=Delete
|
||||
};
|
||||
|
||||
#define CAPS_MOD MT(MOD_LCTL, KC_ESC)
|
||||
|
||||
// Declare layers early so the HID functions below can reference KEEB_CTL.
|
||||
enum layers {
|
||||
BASE,
|
||||
@@ -192,10 +193,7 @@ bool kc_raw_hid_rx_kb(uint8_t *data, uint8_t length) {
|
||||
resp[HID_OFF_SRC] = HID_DEV_Q5MAX;
|
||||
resp[HID_OFF_FLAGS] = HID_FLAG_RESPONSE;
|
||||
#ifdef LK_WIRELESS_ENABLE
|
||||
resp[HID_PAYLOAD(HID_BATT_OFF_LEVEL)] =
|
||||
(get_transport() & TRANSPORT_WIRELESS)
|
||||
? battery_get_percentage()
|
||||
: HID_BATT_UNAVAILABLE;
|
||||
resp[HID_PAYLOAD(HID_BATT_OFF_LEVEL)] = (get_transport() & TRANSPORT_WIRELESS) ? battery_get_percentage() : HID_BATT_UNAVAILABLE;
|
||||
#else
|
||||
resp[HID_PAYLOAD(HID_BATT_OFF_LEVEL)] = HID_BATT_UNAVAILABLE;
|
||||
#endif
|
||||
@@ -211,9 +209,7 @@ bool kc_raw_hid_rx_kb(uint8_t *data, uint8_t length) {
|
||||
}
|
||||
|
||||
// CAPS_MOD state: tap=ESC, hold=Ctrl, Shift+tap=CapsLock, Alt+tap=CapsWord, GUI+tap=Autocorrect
|
||||
static bool caps_mod_held = false;
|
||||
static bool caps_mod_ctrl_registered = false;
|
||||
static uint16_t caps_mod_timer = 0;
|
||||
// (Refactored to use MT(MOD_LCTL, KC_ESC) with custom tap logic)
|
||||
|
||||
// clang-format off
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
@@ -350,38 +346,28 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
switch (keycode) {
|
||||
case CAPS_MOD:
|
||||
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);
|
||||
caps_mod_ctrl_registered = false;
|
||||
} else {
|
||||
// Custom tap logic: only intercept if it's a TAP AND a modifier is held.
|
||||
// If it's a pure hold (Ctrl) or a pure tap (Esc), return true to let
|
||||
// the MT() core handle it.
|
||||
if (record->tap.count > 0 && record->event.pressed) {
|
||||
uint8_t mods = get_mods();
|
||||
if (mods & (MOD_MASK_GUI | MOD_MASK_ALT)) {
|
||||
// Neutralize the modifier hold so releasing GUI/Alt doesn't
|
||||
// trigger an OS "tap" action (like opening the Start menu).
|
||||
tap_code(DUMMY_MOD_NEUTRALIZER_KEYCODE);
|
||||
|
||||
if (mods & MOD_MASK_GUI) {
|
||||
autocorrect_toggle();
|
||||
} else if (mods & MOD_MASK_ALT) {
|
||||
caps_word_toggle();
|
||||
} else if (mods & MOD_MASK_SHIFT) {
|
||||
tap_code(KC_CAPS); // Shift still held → host sees Shift+CapsLock (toggles on most OSes)
|
||||
} else {
|
||||
tap_code(KC_ESC);
|
||||
caps_word_toggle();
|
||||
}
|
||||
return false; // suppress default Esc tap
|
||||
} else if (mods & MOD_MASK_SHIFT) {
|
||||
tap_code(KC_CAPS);
|
||||
return false; // suppress default Esc tap
|
||||
}
|
||||
}
|
||||
caps_mod_held = false; // cleared in both hold and tap paths
|
||||
}
|
||||
return false;
|
||||
return true; // let core handle Esc tap or Ctrl hold
|
||||
|
||||
case LCK_FN1:
|
||||
case LCK_FN2:
|
||||
@@ -466,10 +452,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
|
||||
void matrix_scan_user(void) {
|
||||
if (caps_mod_held && !caps_mod_ctrl_registered && timer_elapsed(caps_mod_timer) > TAPPING_TERM) {
|
||||
caps_mod_ctrl_registered = true;
|
||||
register_code(KC_LCTL);
|
||||
}
|
||||
if (alt_tab_active && timer_elapsed(alt_tab_timer) > ALT_TAB_TIMEOUT) {
|
||||
unregister_code(KC_LALT);
|
||||
alt_tab_active = false;
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
"nkro" : true,
|
||||
"rgb_matrix": true,
|
||||
"raw" : true,
|
||||
"send_string": true
|
||||
"send_string": true,
|
||||
"speculative_hold": true
|
||||
},
|
||||
"matrix_pins": {
|
||||
"cols": ["C6", "C7", "C8", "A14", "A15", "C10", "C11", "C13", "C14", "C15", "C0", "C1", "C2", "C3", "A0", "A1", "A2", "A3", "B10"],
|
||||
|
||||
Reference in New Issue
Block a user