diff options
Diffstat (limited to 'quantum/process_keycode')
46 files changed, 431 insertions, 220 deletions
diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index c189dd02b7..a8464e1b83 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -1,5 +1,6 @@ #include "audio.h" #include "process_audio.h" +#include <math.h> #ifndef VOICE_CHANGE_SONG # define VOICE_CHANGE_SONG SONG(VOICE_CHANGE_SOUND) @@ -12,7 +13,7 @@ float voice_change_song[][2] = VOICE_CHANGE_SONG; float compute_freq_for_midi_note(uint8_t note) { // https://en.wikipedia.org/wiki/MIDI_tuning_standard - return pow(2.0, (note - 69) / 12.0) * PITCH_STANDARD_A; + return powf(2.0f, (note - 69) / 12.0f) * PITCH_STANDARD_A; } bool process_audio(uint16_t keycode, keyrecord_t *record) { @@ -61,6 +62,3 @@ void process_audio_noteoff(uint8_t note) { void process_audio_all_notes_off(void) { stop_all_notes(); } - -__attribute__((weak)) void audio_on_user(void) {} -__attribute__((weak)) void audio_off_user(void) {} diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h index 42cfab4af2..69e201e447 100644 --- a/quantum/process_keycode/process_audio.h +++ b/quantum/process_keycode/process_audio.h @@ -1,11 +1,12 @@ #pragma once +#include <stdint.h> +#include <stdbool.h> +#include "action.h" + float compute_freq_for_midi_note(uint8_t note); bool process_audio(uint16_t keycode, keyrecord_t *record); void process_audio_noteon(uint8_t note); void process_audio_noteoff(uint8_t note); void process_audio_all_notes_off(void); - -void audio_on_user(void); -void audio_off_user(void); diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 62c347ae0c..9b78214e43 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -14,27 +14,28 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef AUTO_SHIFT_ENABLE - -# include <stdbool.h> -# include "process_auto_shift.h" - -# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP -# define AUTO_SHIFT_STARTUP_STATE true /* enabled */ -# else -# define AUTO_SHIFT_STARTUP_STATE false /* disabled */ -# endif +#include "process_auto_shift.h" +#include "quantum.h" +#include "action_util.h" +#include "timer.h" +#include "keycodes.h" + +#ifndef AUTO_SHIFT_DISABLED_AT_STARTUP +# define AUTO_SHIFT_STARTUP_STATE true /* enabled */ +#else +# define AUTO_SHIFT_STARTUP_STATE false /* disabled */ +#endif // Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat. static uint16_t autoshift_time = 0; -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) // Stores the last key's up or down time, to replace autoshift_time so that Tap Hold times are accurate. static uint16_t retroshift_time = 0; // Stores a possibly Retro Shift key's up or down time, as retroshift_time needs // to be set before the Retro Shift key is evaluated if it is interrupted by an // Auto Shifted key. static uint16_t last_retroshift_time; -# endif +#endif static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; static uint16_t autoshift_lastkey = KC_NO; static keyrecord_t autoshift_lastrecord; @@ -68,15 +69,23 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco /** \brief Called on physical press, returns whether is Auto Shift key */ __attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { switch (keycode) { -# ifndef NO_AUTO_SHIFT_ALPHA +#ifndef NO_AUTO_SHIFT_ALPHA case AUTO_SHIFT_ALPHA: -# endif -# ifndef NO_AUTO_SHIFT_NUMERIC +#endif +#ifndef NO_AUTO_SHIFT_NUMERIC case AUTO_SHIFT_NUMERIC: +#endif +#ifndef NO_AUTO_SHIFT_SPECIAL +# ifndef NO_AUTO_SHIFT_TAB + case KC_TAB: # endif -# ifndef NO_AUTO_SHIFT_SPECIAL - case AUTO_SHIFT_SPECIAL: +# ifndef NO_AUTO_SHIFT_SYMBOLS + case AUTO_SHIFT_SYMBOLS: # endif +#endif +#ifdef AUTO_SHIFT_ENTER + case KC_ENT: +#endif return true; } return get_custom_auto_shifted_key(keycode, record); @@ -122,9 +131,9 @@ bool get_autoshift_shift_state(uint16_t keycode) { /** \brief Restores the shift key if it was cancelled by Auto Shift */ static void autoshift_flush_shift(void) { autoshift_flags.holding_shift = false; -# ifdef CAPS_WORD_ENABLE +#ifdef CAPS_WORD_ENABLE if (!is_caps_word_on()) -# endif // CAPS_WORD_ENABLE +#endif // CAPS_WORD_ENABLE { del_weak_mods(MOD_BIT(KC_LSFT)); } @@ -146,26 +155,26 @@ static void autoshift_flush_shift(void) { static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) { // clang-format off if ((get_mods() -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) | get_oneshot_mods() -# endif +#endif ) & (~MOD_BIT(KC_LSFT)) ) { // clang-format on // Prevents keyrepeating unshifted value of key after using it in a key combo. autoshift_lastkey = KC_NO; -# ifndef AUTO_SHIFT_MODIFIERS +#ifndef AUTO_SHIFT_MODIFIERS // We can't return true here anymore because custom unshifted values are // possible and there's no good way to tell whether the press returned // true upon release. set_autoshift_shift_state(keycode, false); autoshift_press_user(keycode, false, record); -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT))); clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); -# endif - return false; # endif + return false; +#endif } // Store record to be sent to user functions if there's no release record then. @@ -173,19 +182,19 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) autoshift_lastrecord.event.pressed = false; autoshift_lastrecord.event.time = 0; // clang-format off -# if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY) +#if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY) if (keycode == autoshift_lastkey && -# ifdef AUTO_SHIFT_REPEAT_PER_KEY +# ifdef AUTO_SHIFT_REPEAT_PER_KEY get_auto_shift_repeat(autoshift_lastkey, record) && -# endif -# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY) +# endif +# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY) ( !autoshift_flags.lastshifted -# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY +# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY || get_auto_shift_no_auto_repeat(autoshift_lastkey, record) -# endif - ) && # endif + ) && +# endif TIMER_DIFF_16(now, autoshift_time) < GET_TAPPING_TERM(autoshift_lastkey, record) ) { // clang-format on @@ -202,23 +211,23 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record); return false; } -# endif +#endif // Use physical shift state of press event to be more like normal typing. -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) autoshift_flags.lastshifted = (get_mods() | get_oneshot_mods()) & MOD_BIT(KC_LSFT); set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT))); -# else +#else autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT); -# endif +#endif // Record the keycode so we can simulate it later. autoshift_lastkey = keycode; autoshift_time = now; autoshift_flags.in_progress = true; -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); -# endif +#endif return false; } @@ -239,11 +248,11 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, k autoshift_flags.lastshifted = autoshift_flags.lastshifted || TIMER_DIFF_16(now, autoshift_time) >= -# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY +#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY get_autoshift_timeout(autoshift_lastkey, record) -# else +#else autoshift_timeout -# endif +#endif ; // clang-format on set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted); @@ -258,23 +267,23 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, k autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record); // clang-format off -# if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)) +#if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)) if (matrix_trigger -# ifdef AUTO_SHIFT_REPEAT_PER_KEY +# ifdef AUTO_SHIFT_REPEAT_PER_KEY && get_auto_shift_repeat(autoshift_lastkey, record) -# endif -# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY +# endif +# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record) -# endif +# endif ) { // Prevents release. return; } -# endif +#endif // clang-format on -# if TAP_CODE_DELAY > 0 +#if TAP_CODE_DELAY > 0 wait_ms(TAP_CODE_DELAY); -# endif +#endif autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record); autoshift_flush_shift(); @@ -302,11 +311,11 @@ void autoshift_matrix_scan(void) { if (autoshift_flags.in_progress) { const uint16_t now = timer_read(); if (TIMER_DIFF_16(now, autoshift_time) >= -# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY +#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord) -# else +#else autoshift_timeout -# endif +#endif ) { autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord); } @@ -327,18 +336,18 @@ void autoshift_disable(void) { autoshift_flush_shift(); } -# ifndef AUTO_SHIFT_NO_SETUP +#ifndef AUTO_SHIFT_NO_SETUP void autoshift_timer_report(void) { -# ifdef SEND_STRING_ENABLE +# ifdef SEND_STRING_ENABLE const char *autoshift_timeout_str = get_u16_str(autoshift_timeout, ' '); // Skip padding spaces while (*autoshift_timeout_str == ' ') { autoshift_timeout_str++; } send_string(autoshift_timeout_str); -# endif -} # endif +} +#endif bool get_autoshift_state(void) { return autoshift_flags.enabled; @@ -360,11 +369,11 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550 // clang-format off const uint16_t now = -# if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING) +#if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING) timer_read() -# else +#else (record->event.pressed) ? retroshift_time : timer_read() -# endif +#endif ; // clang-format on @@ -385,7 +394,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { autoshift_disable(); break; -# ifndef AUTO_SHIFT_NO_SETUP +#ifndef AUTO_SHIFT_NO_SETUP case AS_UP: autoshift_timeout += 5; break; @@ -395,27 +404,27 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { case AS_RPT: autoshift_timer_report(); break; -# endif +#endif } // If Retro Shift is disabled, possible custom actions shouldn't happen. // clang-format off -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) -# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record); -# else +# else const bool is_hold_on_interrupt = false; -# endif -# endif +# endif +#endif if (IS_RETRO(keycode) -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) // Not tapped or #defines mean that rolls should use hold action. && ( record->tap.count == 0 -# ifdef RETRO_TAPPING_PER_KEY +# ifdef RETRO_TAPPING_PER_KEY || !get_retro_tapping(keycode, record) -# endif - || (record->tap.interrupted && is_hold_on_interrupt)) # endif + || (record->tap.interrupted && is_hold_on_interrupt)) +#endif ) { // clang-format on autoshift_lastkey = KC_NO; @@ -431,21 +440,21 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { // tap.count gets set to 0 in process_action // clang-format off else if (IS_RETRO(keycode) -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) && ( record->tap.count == 0 -# ifdef RETRO_TAPPING_PER_KEY +# ifdef RETRO_TAPPING_PER_KEY || !get_retro_tapping(keycode, record) -# endif - ) # endif + ) +#endif ) { // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set. -# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) { autoshift_end(KC_NO, now, false, &autoshift_lastrecord); } -# endif +#endif // clang-format on return true; } @@ -471,7 +480,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { return true; } -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) // Called to record time before possible delays by action_tapping_process. void retroshift_poll_time(keyevent_t *event) { last_retroshift_time = retroshift_time; @@ -485,6 +494,4 @@ void retroshift_swap_times(void) { last_retroshift_time = temp; } } -# endif - #endif diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index 66a4b3138a..885a47b533 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -16,7 +16,11 @@ #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h" +#include "keyboard.h" +#include "keycodes.h" #ifndef AUTO_SHIFT_TIMEOUT # define AUTO_SHIFT_TIMEOUT 175 @@ -28,10 +32,14 @@ // clang-format off #define AUTO_SHIFT_ALPHA KC_A ... KC_Z #define AUTO_SHIFT_NUMERIC KC_1 ... KC_0 +#define AUTO_SHIFT_SYMBOLS \ + KC_MINUS ... KC_SLASH: \ + case KC_NONUS_BACKSLASH + +// Kept to avoid breaking existing keymaps. #define AUTO_SHIFT_SPECIAL \ KC_TAB: \ - case KC_MINUS ... KC_SLASH: \ - case KC_NONUS_BACKSLASH + case AUTO_SHIFT_SYMBOLS // clang-format on bool process_auto_shift(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c index 1376788266..edc47718f3 100644 --- a/quantum/process_keycode/process_autocorrect.c +++ b/quantum/process_keycode/process_autocorrect.c @@ -1,11 +1,16 @@ // Copyright 2021 Google LLC // Copyright 2021 @filterpaper +// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev> // SPDX-License-Identifier: Apache-2.0 // Original source: https://getreuer.info/posts/keyboards/autocorrection #include "process_autocorrect.h" #include <string.h> +#include "keycodes.h" +#include "quantum_keycodes.h" #include "keycode_config.h" +#include "send_string.h" +#include "action_util.h" #if __has_include("autocorrect_data.h") # include "autocorrect_data.h" @@ -57,7 +62,7 @@ void autocorrect_toggle(void) { } /** - * @brief handler for determining if autocorrect should process keypress + * @brief handler for user to override whether autocorrect should process this keypress * * @param keycode Keycode registered by matrix press, per keymap * @param record keyrecord_t structure @@ -67,6 +72,23 @@ void autocorrect_toggle(void) { * @return false Stop processing and escape from autocorrect. */ __attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) { + return process_autocorrect_default_handler(keycode, record, typo_buffer_size, mods); +} + +/** + * @brief fallback handler for determining if autocorrect should process this keypress + * can be used by user callback to get the basic keycode being "wrapped" + * + * NOTE: These values may have been edited by user callback before getting here + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @param typo_buffer_size passed along to allow resetting of autocorrect buffer + * @param mods allow processing of mod status + * @return true Allow autocorection + * @return false Stop processing and escape from autocorrect. + */ +bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) { // See quantum_keycodes.h for reference on these matched ranges. switch (*keycode) { // Exclude these keycodes from processing. @@ -157,10 +179,12 @@ __attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord * * @param backspaces number of characters to remove * @param str pointer to PROGMEM string to replace mistyped seletion with + * @param typo the wrong string that triggered a correction + * @param correct what it would become after the changes * @return true apply correction * @return false user handled replacement */ -__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) { +__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) { return true; } @@ -284,11 +308,57 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record) { if (code & 128) { // A typo was found! Apply autocorrect. const uint8_t backspaces = (code & 63) + !record->event.pressed; - if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) { + const char * changes = (const char *)(autocorrect_data + state + 1); + + /* Gather info about the typo'd word + * + * Since buffer may contain several words, delimited by spaces, we + * iterate from the end to find the start and length of the typo + */ + char typo[AUTOCORRECT_MAX_LENGTH + 1] = {0}; // extra char for null terminator + + uint8_t typo_len = 0; + uint8_t typo_start = 0; + bool space_last = typo_buffer[typo_buffer_size - 1] == KC_SPC; + for (uint8_t i = typo_buffer_size; i > 0; --i) { + // stop counting after finding space (unless it is the last thing) + if (typo_buffer[i - 1] == KC_SPC && i != typo_buffer_size) { + typo_start = i; + break; + } + + ++typo_len; + } + + // when detecting 'typo:', reduce the length of the string by one + if (space_last) { + --typo_len; + } + + // convert buffer of keycodes into a string + for (uint8_t i = 0; i < typo_len; ++i) { + typo[i] = typo_buffer[typo_start + i] - KC_A + 'a'; + } + + /* Gather the corrected word + * + * A) Correction of 'typo:' -- Code takes into account + * an extra backspace to delete the space (which we dont copy) + * for this reason the offset is correct to "skip" the null terminator + * + * B) When correcting 'typo' -- Need extra offset for terminator + */ + char correct[AUTOCORRECT_MAX_LENGTH + 10] = {0}; // let's hope this is big enough + + uint8_t offset = space_last ? backspaces : backspaces + 1; + strcpy(correct, typo); + strcpy_P(correct + typo_len - offset, changes); + + if (apply_autocorrect(backspaces, changes, typo, correct)) { for (uint8_t i = 0; i < backspaces; ++i) { tap_code(KC_BSPC); } - send_string_P((char const *)(autocorrect_data + state + 1)); + send_string_P(changes); } if (keycode == KC_SPC) { diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h index c7596107e5..ea77d6f56f 100644 --- a/quantum/process_keycode/process_autocorrect.h +++ b/quantum/process_keycode/process_autocorrect.h @@ -1,15 +1,19 @@ // Copyright 2021 Google LLC // Copyright 2021 @filterpaper +// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev> // SPDX-License-Identifier: Apache-2.0 // Original source: https://getreuer.info/posts/keyboards/autocorrection #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h" bool process_autocorrect(uint16_t keycode, keyrecord_t *record); bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); -bool apply_autocorrect(uint8_t backspaces, const char *str); +bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); +bool apply_autocorrect(uint8_t backs |