diff options
| author | Pascal Getreuer <[email protected]> | 2022-05-13 23:00:32 -0700 | 
|---|---|---|
| committer | GitHub <[email protected]> | 2022-05-14 16:00:32 +1000 | 
| commit | 68b16bba68d79c63bbd649a5be58756e937c96da (patch) | |
| tree | be0d3d672c13c080f4da58687b5b1a261f465911 /quantum/process_keycode | |
| parent | 90eef4cd153cdc1b00d973e6abb029828f656294 (diff) | |
| download | qmk_firmware-68b16bba68d79c63bbd649a5be58756e937c96da.tar.gz qmk_firmware-68b16bba68d79c63bbd649a5be58756e937c96da.zip | |
[Core] Add Caps Word feature to core (#16588)
Co-authored-by: precondition <[email protected]>
Co-authored-by: Drashna Jaelre <[email protected]>
Diffstat (limited to 'quantum/process_keycode')
| -rw-r--r-- | quantum/process_keycode/process_caps_word.c | 160 | ||||
| -rw-r--r-- | quantum/process_keycode/process_caps_word.h | 37 | 
2 files changed, 197 insertions, 0 deletions
| diff --git a/quantum/process_keycode/process_caps_word.c b/quantum/process_keycode/process_caps_word.c new file mode 100644 index 0000000000..15238f04a1 --- /dev/null +++ b/quantum/process_keycode/process_caps_word.c @@ -0,0 +1,160 @@ +// 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. + +#include "process_caps_word.h" + +bool process_caps_word(uint16_t keycode, keyrecord_t* record) { +    if (keycode == CAPSWRD) { // Pressing CAPSWRD toggles Caps Word. +        if (record->event.pressed) { +            caps_word_toggle(); +        } +        return false; +    } + +#ifndef NO_ACTION_ONESHOT +    const uint8_t mods = get_mods() | get_oneshot_mods(); +#else +    const uint8_t mods = get_mods(); +#endif // NO_ACTION_ONESHOT + +    if (!is_caps_word_on()) { +        // The following optionally turns on Caps Word by holding left and +        // right shifts or by double tapping left shift. This way Caps Word +        // may be used without needing a dedicated key and also without +        // needing combos or tap dance. + +#ifdef BOTH_SHIFTS_TURNS_ON_CAPS_WORD +        // Many keyboards enable the Command feature by default, which also +        // uses left+right shift. It can be configured to use a different +        // key combination by defining IS_COMMAND(). We make a non-fatal +        // warning if Command is enabled but IS_COMMAND() is *not* defined. +#    if defined(COMMAND_ENABLE) && !defined(IS_COMMAND) +#        pragma message "BOTH_SHIFTS_TURNS_ON_CAPS_WORD and Command should not be enabled at the same time, since both use the Left Shift + Right Shift key combination. Please disable Command, or ensure that `IS_COMMAND` is not set to (get_mods() == MOD_MASK_SHIFT)." +#    else +        if (mods == MOD_MASK_SHIFT +#        ifdef COMMAND_ENABLE +            // Don't activate Caps Word at the same time as Command. +            && !(IS_COMMAND()) +#        endif // COMMAND_ENABLE +        ) { +            caps_word_on(); +        } +#    endif     // defined(COMMAND_ENABLE) && !defined(IS_COMMAND) +#endif         // BOTH_SHIFTS_TURNS_ON_CAPS_WORD + +#ifdef DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD +        // Double tapping left shift turns on Caps Word. +        // +        // NOTE: This works with KC_LSFT and one-shot left shift. It +        // wouldn't make sense with mod-tap or Space Cadet shift since +        // double tapping would of course trigger the tapping action. +        if (record->event.pressed) { +            static bool     tapped = false; +            static uint16_t timer  = 0; +            if (keycode == KC_LSFT || keycode == OSM(MOD_LSFT)) { +                if (tapped && !timer_expired(record->event.time, timer)) { +                    // Left shift was double tapped, activate Caps Word. +                    caps_word_on(); +                } +                tapped = true; +                timer  = record->event.time + GET_TAPPING_TERM(keycode, record); +            } else { +                tapped = false; // Reset when any other key is pressed. +            } +        } +#endif // DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD + +        return true; +    } + +#if CAPS_WORD_IDLE_TIMEOUT > 0 +    caps_word_reset_idle_timer(); +#endif // CAPS_WORD_IDLE_TIMEOUT > 0 + +    // From here on, we only take action on press events. +    if (!record->event.pressed) { +        return true; +    } + +    if (!(mods & ~MOD_MASK_SHIFT)) { +        switch (keycode) { +            // Ignore MO, TO, TG, TT, and OSL layer switch keys. +            case QK_MOMENTARY ... QK_MOMENTARY_MAX: +            case QK_TO ... QK_TO_MAX: +            case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: +            case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: +            case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: +                return true; + +#ifndef NO_ACTION_TAPPING +            case QK_MOD_TAP ... QK_MOD_TAP_MAX: +                if (record->tap.count == 0) { +                    // Deactivate if a mod becomes active through holding +                    // a mod-tap key. +                    caps_word_off(); +                    return true; +                } +                keycode &= 0xff; +                break; + +#    ifndef NO_ACTION_LAYER +            case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: +#    endif // NO_ACTION_LAYER +                if (record->tap.count == 0) { +                    return true; +                } +                keycode &= 0xff; +                break; +#endif // NO_ACTION_TAPPING + +#ifdef SWAP_HANDS_ENABLE +            case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: +                if (keycode > 0x56F0 || record->tap.count == 0) { +                    return true; +                } +                keycode &= 0xff; +                break; +#endif // SWAP_HANDS_ENABLE +        } + +        clear_weak_mods(); +        if (caps_word_press_user(keycode)) { +            send_keyboard_report(); +            return true; +        } +    } + +    caps_word_off(); +    return true; +} + +__attribute__((weak)) bool caps_word_press_user(uint16_t keycode) { +    switch (keycode) { +        // Keycodes that continue Caps Word, with shift applied. +        case KC_A ... KC_Z: +        case KC_MINS: +            add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key. +            return true; + +        // Keycodes that continue Caps Word, without shifting. +        case KC_1 ... KC_0: +        case KC_BSPC: +        case KC_DEL: +        case KC_UNDS: +            return true; + +        default: +            return false; // Deactivate Caps Word. +    } +} diff --git a/quantum/process_keycode/process_caps_word.h b/quantum/process_keycode/process_caps_word.h new file mode 100644 index 0000000000..f215bbc3a3 --- /dev/null +++ b/quantum/process_keycode/process_caps_word.h @@ -0,0 +1,37 @@ +// 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. + +#pragma once + +#include "quantum.h" +#include "caps_word.h" + +/** + * @brief Process handler for Caps Word feature. + * + * @param keycode  Keycode registered by matrix press, per keymap + * @param record   keyrecord_t structure + * @return true    Continue processing keycodes, and send to host + * @return false   Stop processing keycodes, and don't send to host + */ +bool process_caps_word(uint16_t keycode, keyrecord_t* record); + +/** + * @brief Weak function for user-level Caps Word press modification. + * + * @param keycode   Keycode registered by matrix press, per keymap + * @return true     Continue Caps Word + * @return false    Stop Caps Word + */ +bool caps_word_press_user(uint16_t keycode); | 
