Move to 36 key layout possibility, custom shift keys
4 files changed, 210 insertions(+), 16 deletions(-) M keyboards/splitkb/aurora/corne/keymaps/rutherther/keymap.c A users/rutherther/features/custom_shift_keys.c A users/rutherther/features/custom_shift_keys.h M users/rutherther/rules.mk
M keyboards/splitkb/aurora/corne/keymaps/rutherther/keymap.c => keyboards/splitkb/aurora/corne/keymaps/rutherther/keymap.c +16 -15
@@ 2,6 2,7 @@ #include "features/layer_lock.h" #include "features/cz_accent.h" #include "features/achordion.h" #include "features/custom_shift_keys.h" #define LAYOUT LAYOUT_split_3x6_3 @@ 25,14 26,14 @@ enum custom_keycodes { CZ_ACUTED, // on hold send cz acute prepended to each symbol ACHORDION_OFF, ACHORDION_ON, _QK_TAP_HOLD }; const uint16_t QK_TAP_HOLD = _QK_TAP_HOLD; tap_hold_action_t tap_hold_actions[] = { [0] = ACTION_TAP_HOLD(KC_ESC, QK_REP, true), const custom_shift_key_t custom_shift_keys[] = { {KC_DOT , KC_QUES}, // Shift . is ? {KC_COMM, KC_EXLM}, // Shift , is ! }; const uint16_t QK_TAP_HOLD_SIZE = sizeof(tap_hold_actions) / sizeof(tap_hold_actions[0]); uint8_t NUM_CUSTOM_SHIFT_KEYS = sizeof(custom_shift_keys) / sizeof(custom_shift_key_t); #define SYM MO(_SYM) @@ #define NUM MO(_NUM) 56,10 57,10 @@ const uint16_t QK_TAP_HOLD_SIZE = sizeof(tap_hold_actions) / sizeof(tap_hold_act #define OSM_LSFT OSM(MOD_LSFT) #define OSM_RSFT OSM(MOD_RSFT) #define NAV_V LT(_NAV, KC_V) #define NUM_G LT(_NUM, KC_G) #define NUM_SPC LT(_NUM, KC_SPC) #define WM_M LT(_WM, KC_M) #define NAV_ESC LT(_NAV, KC_ESC) #define GUI_Q MT(MOD_LGUI, KC_Q) @@ #define SYM_A LT(_SYM, KC_A) 82,15 83,16 @@ const uint16_t QK_TAP_HOLD_SIZE = sizeof(tap_hold_actions) / sizeof(tap_hold_act #define WM_TERM G(S(KC_ENT)) #define WM_KILL G(S(KC_C)) #define ESC_REP TH(0) #define COMMA_EXCLAM #define DOT_QUES adsfasf0 // clang-format off const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_QWERTY] = LAYOUT( KC_TAB, GUI_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, GUI_P, _______, KC_ESC, SYM_A, LALT_S, LSFT_D, LCTL_F, KC_G, KC_H, LCTL_J, RSFT_K, LALT_L, SYM_SCLN, _______, QK_REP, KC_Z, KC_X, KC_C, NAV_V, KC_B, KC_N, WM_M, KC_COMM, KC_DOT, KC_SLSH, FKEYS, CZ_ACUTED, KC_ESC, NUM_SPC, KC_ENT, KC_BSPC, CZ_CARETED _______, GUI_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, GUI_P, _______, _______, SYM_A, LALT_S, LSFT_D, LCTL_F, KC_G, KC_H, LCTL_J, RSFT_K, LALT_L, SYM_SCLN, _______, QK_REP, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, WM_M, KC_COMM, KC_DOT, KC_SLSH, FKEYS, CZ_ACUTED, NAV_ESC, NUM_SPC, KC_ENT, KC_BSPC, CZ_CARETED ), @@ [_QWERTY_NOHOMEMODS] = LAYOUT( 125,7 127,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _______, KC_LGUI, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END, KC_INS, KC_DEL, _______, KC_LCTL, KC_LALT, OSM_LSFT, KC_LCTL, _______, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, KC_PAUSE, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_PSCR, _______, _______, _______, _______, _______, QK_LLCK _______, _______, _______, _______, KC_TAB, QK_LLCK ), @@ [_FUNCTION] = LAYOUT( 188,7 190,7 @@ void keyboard_pre_init_user(void) { bool process_record_user(uint16_t keycode, keyrecord_t *record) { static bool achordion = true; /* if (!process_record_tap_hold(keycode, record)) { return false; } */ if (!process_custom_shift_keys(keycode, record)) { return false; } if (!process_czech_acute(keycode, record, CZ_ACUTED, _PLAIN)) { return false; } if (!process_czech_caret(keycode, record, CZ_CARETED, _PLAIN)) { return false; } @@ if (!process_layer_lock(keycode, record, QK_LLCK)) { return false; } 226,7 228,6 @@ bool achordion_chord(uint16_t tap_hold_keycode, void matrix_scan_user(void) { achordion_task(); matrix_scan_tap_hold(); } bool achordion_eager_mod(uint8_t mod) {
A users/rutherther/features/custom_shift_keys.c => users/rutherther/features/custom_shift_keys.c +94 -0
@@ 0,0 1,94 @@ // Copyright 2021-2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @file custom_shift_keys.c * @brief Custom Shift Keys implementation * * For full documentation, see * <https://getreuer.info/posts/keyboards/custom-shift-keys> */ #include "custom_shift_keys.h" #if !defined(IS_QK_MOD_TAP) // Attempt to detect out-of-date QMK installation, which would fail with // implicit-function-declaration errors in the code below. #error "custom_shift_keys: QMK version is too old to build. Please update QMK." #else bool process_custom_shift_keys(uint16_t keycode, keyrecord_t *record) { static uint16_t registered_keycode = KC_NO; // If a custom shift key is registered, then this event is either releasing // it or manipulating another key at the same time. Either way, we release // the currently registered key. if (registered_keycode != KC_NO) { unregister_code16(registered_keycode); registered_keycode = KC_NO; } if (record->event.pressed) { // Press event. const uint8_t saved_mods = get_mods(); #ifndef NO_ACTION_ONESHOT const uint8_t mods = saved_mods | get_weak_mods() | get_oneshot_mods(); #else const uint8_t mods = saved_mods | get_weak_mods(); #endif // NO_ACTION_ONESHOT #if CUSTOM_SHIFT_KEYS_LAYER_MASK != 0 const uint8_t layer = read_source_layers_cache(record->event.key); #endif // CUSTOM_SHIFT_KEYS_LAYER_MASK if ((mods & MOD_MASK_SHIFT) != 0 // Shift is held. #if CUSTOM_SHIFT_KEYS_NEGMODS != 0 // Nothing in CUSTOM_SHIFT_KEYS_NEGMODS is held. && (mods & (CUSTOM_SHIFT_KEYS_NEGMODS)) == 0 #endif // CUSTOM_SHIFT_KEYS_NEGMODS != 0 #if CUSTOM_SHIFT_KEYS_LAYER_MASK != 0 // Pressed key is on a layer appearing in the layer mask. && ((1 << layer) & (CUSTOM_SHIFT_KEYS_LAYER_MASK)) != 0 #endif // CUSTOM_SHIFT_KEYS_LAYER_MASK ) { // Continue default handling if this is a tap-hold key being held. if ((IS_QK_MOD_TAP(keycode) || IS_QK_LAYER_TAP(keycode)) && record->tap.count == 0) { return true; } // Search for a custom shift key whose keycode is `keycode`. for (int i = 0; i < NUM_CUSTOM_SHIFT_KEYS; ++i) { if (keycode == custom_shift_keys[i].keycode) { registered_keycode = custom_shift_keys[i].shifted_keycode; if (IS_QK_MODS(registered_keycode) && // Should keycode be shifted? (QK_MODS_GET_MODS(registered_keycode) & MOD_LSFT) != 0) { register_code16(registered_keycode); // If so, press it directly. } else { // Otherwise cancel shift mods, press the key, and restore mods. del_weak_mods(MOD_MASK_SHIFT); #ifndef NO_ACTION_ONESHOT del_oneshot_mods(MOD_MASK_SHIFT); #endif // NO_ACTION_ONESHOT unregister_mods(MOD_MASK_SHIFT); register_code16(registered_keycode); set_mods(saved_mods); } return false; } } } } return true; // Continue with default handling. } #endif // version check
A users/rutherther/features/custom_shift_keys.h => users/rutherther/features/custom_shift_keys.h +99 -0
@@ 0,0 1,99 @@ // Copyright 2021-2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @file custom_shift_keys.h * @brief Custom shift keys: customize what keycode is produced when shifted. * * Overview * -------- * * This library implements custom shift keys, keys where you can customize * what keycode is produced when shifted. * * Step 1: In your keymap.c, define a table of custom shift keys like * * #include "features/custom_shift_keys.h" * * const custom_shift_key_t custom_shift_keys[] = { * {KC_DOT , KC_QUES}, // Shift . is ? * {KC_COMM, KC_EXLM}, // Shift , is ! * {KC_MINS, KC_EQL }, // Shift - is = * {KC_COLN, KC_SCLN}, // Shift : is ; * }; * * Each row defines one key. The first field is the keycode as it appears in * your layout and determines what is typed normally. The second entry is what * you want the key to type when shifted. * * Step 2: Handle custom shift keys from your `process_record_user` function as * * bool process_record_user(uint16_t keycode, keyrecord_t* record) { * if (!process_custom_shift_keys(keycode, record)) { return false; } * // Your macros ... * * return true; * } * * Step 3: add `features/custom_shift_keys.c` to your rules.mk as * * SRC += features/custom_shift_keys.c * * * For full documentation, see * <https://getreuer.info/posts/keyboards/custom-shift-keys> */ #pragma once #include "quantum.h" #ifdef __cplusplus extern "C" { #endif /** * Custom shift key entry. The `keycode` field is the keycode as it appears in * your layout and determines what is typed normally. The `shifted_keycode` is * what you want the key to type when shifted. */ typedef struct { uint16_t keycode; uint16_t shifted_keycode; } custom_shift_key_t; /** Table of custom shift keys. */ extern const custom_shift_key_t custom_shift_keys[]; /** Number of entries in the `custom_shift_keys` table. */ extern uint8_t NUM_CUSTOM_SHIFT_KEYS; /** * Handler function for custom shift keys. * * In keymap.c, call this function from your `process_record_user` function as * * #include "features/custom_shift_keys.h" * * bool process_record_user(uint16_t keycode, keyrecord_t* record) { * if (!process_custom_shift_keys(keycode, record)) { return false; } * // Your macros ... * * return true; * } */ bool process_custom_shift_keys(uint16_t keycode, keyrecord_t *record); #ifdef __cplusplus } #endif
M users/rutherther/rules.mk => users/rutherther/rules.mk +1 -1