Merge remote-tracking branch 'qmk/master' into merge-2023-03-12
This commit is contained in:
85
quantum/process_keycode/autocorrect_data_default.h
Normal file
85
quantum/process_keycode/autocorrect_data_default.h
Normal file
@ -0,0 +1,85 @@
|
||||
// Generated code.
|
||||
|
||||
// Autocorrection dictionary (70 entries):
|
||||
// :guage -> gauge
|
||||
// :the:the: -> the
|
||||
// :thier -> their
|
||||
// :ture -> true
|
||||
// accomodate -> accommodate
|
||||
// acommodate -> accommodate
|
||||
// aparent -> apparent
|
||||
// aparrent -> apparent
|
||||
// apparant -> apparent
|
||||
// apparrent -> apparent
|
||||
// aquire -> acquire
|
||||
// becuase -> because
|
||||
// cauhgt -> caught
|
||||
// cheif -> chief
|
||||
// choosen -> chosen
|
||||
// cieling -> ceiling
|
||||
// collegue -> colleague
|
||||
// concensus -> consensus
|
||||
// contians -> contains
|
||||
// cosnt -> const
|
||||
// dervied -> derived
|
||||
// fales -> false
|
||||
// fasle -> false
|
||||
// fitler -> filter
|
||||
// flase -> false
|
||||
// foward -> forward
|
||||
// frequecy -> frequency
|
||||
// gaurantee -> guarantee
|
||||
// guaratee -> guarantee
|
||||
// heigth -> height
|
||||
// heirarchy -> hierarchy
|
||||
// inclued -> include
|
||||
// interator -> iterator
|
||||
// intput -> input
|
||||
// invliad -> invalid
|
||||
// lenght -> length
|
||||
// liasion -> liaison
|
||||
// libary -> library
|
||||
// listner -> listener
|
||||
// looses: -> loses
|
||||
// looup -> lookup
|
||||
// manefist -> manifest
|
||||
// namesapce -> namespace
|
||||
// namespcae -> namespace
|
||||
// occassion -> occasion
|
||||
// occured -> occurred
|
||||
// ouptut -> output
|
||||
// ouput -> output
|
||||
// overide -> override
|
||||
// postion -> position
|
||||
// priviledge -> privilege
|
||||
// psuedo -> pseudo
|
||||
// recieve -> receive
|
||||
// refered -> referred
|
||||
// relevent -> relevant
|
||||
// repitition -> repetition
|
||||
// retrun -> return
|
||||
// retun -> return
|
||||
// reuslt -> result
|
||||
// reutrn -> return
|
||||
// saftey -> safety
|
||||
// seperate -> separate
|
||||
// singed -> signed
|
||||
// stirng -> string
|
||||
// strign -> string
|
||||
// swithc -> switch
|
||||
// swtich -> switch
|
||||
// thresold -> threshold
|
||||
// udpate -> update
|
||||
// widht -> width
|
||||
|
||||
#define AUTOCORRECT_MIN_LENGTH 5 // ":ture"
|
||||
#define AUTOCORRECT_MAX_LENGTH 10 // "accomodate"
|
||||
|
||||
#define DICTIONARY_SIZE 1104
|
||||
|
||||
static const uint8_t autocorrect_data[DICTIONARY_SIZE] PROGMEM = {108, 43, 0, 6, 71, 0, 7, 81, 0, 8, 199, 0, 9, 240, 1, 10, 250, 1, 11, 26, 2, 17, 53, 2, 18, 190, 2, 19, 202, 2, 21, 212, 2, 22, 20, 3, 23, 67, 3, 28, 16, 4, 0, 72, 50, 0, 22, 60, 0, 0, 11, 23, 44, 8, 11, 23, 44, 0, 132, 0, 8, 22, 18, 18, 15, 0, 132, 115, 101, 115, 0, 11, 23, 12, 26, 22, 0, 129, 99, 104, 0, 68, 94, 0, 8, 106, 0, 15, 174, 0, 21, 187, 0, 0, 12, 15, 25, 17, 12, 0, 131, 97, 108, 105, 100, 0, 74, 119, 0, 12, 129, 0, 21, 140, 0, 24, 165, 0, 0, 17, 12, 22, 0, 131, 103, 110, 101, 100, 0, 25, 21, 8, 7, 0, 131, 105, 118, 101, 100, 0, 72, 147, 0, 24, 156, 0, 0, 9, 8, 21, 0, 129, 114, 101, 100, 0, 6, 6, 18, 0, 129, 114, 101, 100, 0, 15, 6, 17, 12, 0, 129, 100, 101, 0, 18, 22, 8, 21, 11, 23, 0, 130, 104, 111,
|
||||
108, 100, 0, 4, 26, 18, 9, 0, 131, 114, 119, 97, 114, 100, 0, 68, 233, 0, 6, 246, 0, 7, 4, 1, 8, 16, 1, 10, 52, 1, 15, 81, 1, 21, 90, 1, 22, 117, 1, 23, 144, 1, 24, 215, 1, 25, 228, 1, 0, 6, 19, 22, 8, 16, 4, 17, 0, 130, 97, 99, 101, 0, 19, 4, 22, 8, 16, 4, 17, 0, 131, 112, 97, 99, 101, 0, 12, 21, 8, 25, 18, 0, 130, 114, 105, 100, 101, 0, 23, 0, 68, 25, 1, 17, 36, 1, 0, 21, 4, 24, 10, 0, 130, 110, 116, 101, 101, 0, 4, 21, 24, 4, 10, 0, 135, 117, 97, 114, 97, 110, 116, 101, 101, 0, 68, 59, 1, 7, 69, 1, 0, 24, 10, 44, 0, 131, 97, 117, 103, 101, 0, 8, 15, 12, 25, 12, 21, 19, 0, 130, 103, 101, 0, 22, 4, 9, 0, 130, 108, 115, 101, 0, 76, 97, 1, 24, 109, 1, 0, 24, 20, 4, 0, 132, 99, 113, 117, 105, 114, 101, 0, 23, 44, 0,
|
||||
130, 114, 117, 101, 0, 4, 0, 79, 126, 1, 24, 134, 1, 0, 9, 0, 131, 97, 108, 115, 101, 0, 6, 8, 5, 0, 131, 97, 117, 115, 101, 0, 4, 0, 71, 156, 1, 19, 193, 1, 21, 203, 1, 0, 18, 16, 0, 80, 166, 1, 18, 181, 1, 0, 18, 6, 4, 0, 135, 99, 111, 109, 109, 111, 100, 97, 116, 101, 0, 6, 6, 4, 0, 132, 109, 111, 100, 97, 116, 101, 0, 7, 24, 0, 132, 112, 100, 97, 116, 101, 0, 8, 19, 8, 22, 0, 132, 97, 114, 97, 116, 101, 0, 10, 8, 15, 15, 18, 6, 0, 130, 97, 103, 117, 101, 0, 8, 12, 6, 8, 21, 0, 131, 101, 105, 118, 101, 0, 12, 8, 11, 6, 0, 130, 105, 101, 102, 0, 17, 0, 76, 3, 2, 21, 16, 2, 0, 15, 8, 12, 6, 0, 133, 101, 105, 108, 105, 110, 103, 0, 12, 23, 22, 0, 131, 114, 105, 110, 103, 0, 70, 33, 2, 23, 44, 2, 0, 12, 23, 26, 22, 0, 131, 105,
|
||||
116, 99, 104, 0, 10, 12, 8, 11, 0, 129, 104, 116, 0, 72, 69, 2, 10, 80, 2, 18, 89, 2, 21, 156, 2, 24, 167, 2, 0, 22, 18, 18, 11, 6, 0, 131, 115, 101, 110, 0, 12, 21, 23, 22, 0, 129, 110, 103, 0, 12, 0, 86, 98, 2, 23, 124, 2, 0, 68, 105, 2, 22, 114, 2, 0, 12, 15, 0, 131, 105, 115, 111, 110, 0, 4, 6, 6, 18, 0, 131, 105, 111, 110, 0, 76, 131, 2, 22, 146, 2, 0, 23, 12, 19, 8, 21, 0, 134, 101, 116, 105, 116, 105, 111, 110, 0, 18, 19, 0, 131, 105, 116, 105, 111, 110, 0, 23, 24, 8, 21, 0, 131, 116, 117, 114, 110, 0, 85, 174, 2, 23, 183, 2, 0, 23, 8, 21, 0, 130, 117, 114, 110, 0, 8, 21, 0, 128, 114, 110, 0, 7, 8, 24, 22, 19, 0, 131, 101, 117, 100, 111, 0, 24, 18, 18, 15, 0, 129, 107, 117, 112, 0, 72, 219, 2, 18, 3, 3, 0, 76, 229, 2, 15, 238,
|
||||
2, 17, 248, 2, 0, 11, 23, 44, 0, 130, 101, 105, 114, 0, 23, 12, 9, 0, 131, 108, 116, 101, 114, 0, 23, 22, 12, 15, 0, 130, 101, 110, 101, 114, 0, 23, 4, 21, 8, 23, 17, 12, 0, 135, 116, 101, 114, 97, 116, 111, 114, 0, 72, 30, 3, 17, 38, 3, 24, 51, 3, 0, 15, 4, 9, 0, 129, 115, 101, 0, 4, 12, 23, 17, 18, 6, 0, 131, 97, 105, 110, 115, 0, 22, 17, 8, 6, 17, 18, 6, 0, 133, 115, 101, 110, 115, 117, 115, 0, 74, 86, 3, 11, 96, 3, 15, 118, 3, 17, 129, 3, 22, 218, 3, 24, 232, 3, 0, 11, 24, 4, 6, 0, 130, 103, 104, 116, 0, 71, 103, 3, 10, 110, 3, 0, 12, 26, 0, 129, 116, 104, 0, 17, 8, 15, 0, 129, 116, 104, 0, 22, 24, 8, 21, 0, 131, 115, 117, 108, 116, 0, 68, 139, 3, 8, 150, 3, 22, 210, 3, 0, 21, 4, 19, 19, 4, 0, 130, 101, 110, 116, 0, 85, 157,
|
||||
3, 25, 200, 3, 0, 68, 164, 3, 21, 175, 3, 0, 19, 4, 0, 132, 112, 97, 114, 101, 110, 116, 0, 4, 19, 0, 68, 185, 3, 19, 193, 3, 0, 133, 112, 97, 114, 101, 110, 116, 0, 4, 0, 131, 101, 110, 116, 0, 8, 15, 8, 21, 0, 130, 97, 110, 116, 0, 18, 6, 0, 130, 110, 115, 116, 0, 12, 9, 8, 17, 4, 16, 0, 132, 105, 102, 101, 115, 116, 0, 83, 239, 3, 23, 6, 4, 0, 87, 246, 3, 24, 254, 3, 0, 17, 12, 0, 131, 112, 117, 116, 0, 18, 0, 130, 116, 112, 117, 116, 0, 19, 24, 18, 0, 131, 116, 112, 117, 116, 0, 70, 29, 4, 8, 41, 4, 11, 51, 4, 21, 69, 4, 0, 8, 24, 20, 8, 21, 9, 0, 129, 110, 99, 121, 0, 23, 9, 4, 22, 0, 130, 101, 116, 121, 0, 6, 21, 4, 21, 12, 8, 11, 0, 135, 105, 101, 114, 97, 114, 99, 104, 121, 0, 4, 5, 12, 15, 0, 130, 114, 97, 114, 121, 0};
|
@ -16,17 +16,17 @@ float compute_freq_for_midi_note(uint8_t note) {
|
||||
}
|
||||
|
||||
bool process_audio(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == AU_ON && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_ON && record->event.pressed) {
|
||||
audio_on();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == AU_OFF && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_OFF && record->event.pressed) {
|
||||
audio_off();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == AU_TOG && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_TOGGLE && record->event.pressed) {
|
||||
if (is_audio_on()) {
|
||||
audio_off();
|
||||
} else {
|
||||
@ -35,13 +35,13 @@ bool process_audio(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MUV_IN && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_VOICE_NEXT && record->event.pressed) {
|
||||
voice_iterate();
|
||||
PLAY_SONG(voice_change_song);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MUV_DE && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_VOICE_PREVIOUS && record->event.pressed) {
|
||||
voice_deiterate();
|
||||
PLAY_SONG(voice_change_song);
|
||||
return false;
|
||||
@ -62,5 +62,5 @@ void process_audio_all_notes_off(void) {
|
||||
stop_all_notes();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void audio_on_user() {}
|
||||
__attribute__((weak)) void audio_off_user() {}
|
||||
__attribute__((weak)) void audio_on_user(void) {}
|
||||
__attribute__((weak)) void audio_off_user(void) {}
|
||||
|
@ -17,7 +17,6 @@
|
||||
#ifdef AUTO_SHIFT_ENABLE
|
||||
|
||||
# include <stdbool.h>
|
||||
# include <stdio.h>
|
||||
# include "process_auto_shift.h"
|
||||
# include "qmk_settings.h"
|
||||
|
||||
@ -332,11 +331,12 @@ void autoshift_disable(void) {
|
||||
# ifndef AUTO_SHIFT_NO_SETUP
|
||||
void autoshift_timer_report(void) {
|
||||
# ifdef SEND_STRING_ENABLE
|
||||
char display[8];
|
||||
|
||||
snprintf(display, 8, "\n%d\n", autoshift_timeout);
|
||||
|
||||
send_string((const char *)display);
|
||||
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
|
||||
@ -345,7 +345,7 @@ bool get_autoshift_state(void) {
|
||||
return autoshift_flags.enabled;
|
||||
}
|
||||
|
||||
uint16_t get_generic_autoshift_timeout() {
|
||||
uint16_t get_generic_autoshift_timeout(void) {
|
||||
return autoshift_timeout;
|
||||
}
|
||||
__attribute__((weak)) uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) {
|
||||
@ -377,30 +377,39 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
|
||||
switch (keycode) {
|
||||
case KC_ASTG:
|
||||
case AS_TOGG:
|
||||
autoshift_toggle();
|
||||
break;
|
||||
case KC_ASON:
|
||||
case AS_ON:
|
||||
autoshift_enable();
|
||||
break;
|
||||
case KC_ASOFF:
|
||||
case AS_OFF:
|
||||
autoshift_disable();
|
||||
break;
|
||||
|
||||
# ifndef AUTO_SHIFT_NO_SETUP
|
||||
case KC_ASUP:
|
||||
case AS_UP:
|
||||
autoshift_timeout += 5;
|
||||
break;
|
||||
case KC_ASDN:
|
||||
case AS_DOWN:
|
||||
autoshift_timeout -= 5;
|
||||
break;
|
||||
case KC_ASRP:
|
||||
case AS_RPT:
|
||||
autoshift_timer_report();
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
// If Retro Shift is disabled, possible custom actions shouldn't happen.
|
||||
// clang-format off
|
||||
// If Retro Shift is disabled, possible custom actions shouldn't happen.
|
||||
// clang-format off
|
||||
# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
|
||||
# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
|
||||
const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record);
|
||||
# elif defined(IGNORE_MOD_TAP_INTERRUPT)
|
||||
const bool is_hold_on_interrupt = false;
|
||||
# else
|
||||
const bool is_hold_on_interrupt = IS_QK_MOD_TAP(keycode);
|
||||
# endif
|
||||
# endif
|
||||
if (IS_RETRO(keycode)
|
||||
# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
|
||||
// Not tapped or #defines mean that rolls should use hold action.
|
||||
@ -409,27 +418,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
|
||||
# ifdef RETRO_TAPPING_PER_KEY
|
||||
|| !get_retro_tapping(keycode, record)
|
||||
# endif
|
||||
|| (record->tap.interrupted && (IS_LT(keycode)
|
||||
# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
|
||||
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
|
||||
? get_hold_on_other_key_press(keycode, record)
|
||||
# else
|
||||
? true
|
||||
# endif
|
||||
# else
|
||||
? false
|
||||
# endif
|
||||
# if defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
|
||||
# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
|
||||
: !get_ignore_mod_tap_interrupt(keycode, record)
|
||||
# else
|
||||
: false
|
||||
# endif
|
||||
# else
|
||||
: true
|
||||
# endif
|
||||
))
|
||||
)
|
||||
|| (record->tap.interrupted && is_hold_on_interrupt))
|
||||
# endif
|
||||
) {
|
||||
// clang-format on
|
||||
@ -456,10 +445,10 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
|
||||
# endif
|
||||
) {
|
||||
// Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
|
||||
# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
|
||||
# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
|
||||
if (autoshift_flags.in_progress
|
||||
# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
|
||||
&& !get_ignore_mod_tap_interrupt(keycode, record)
|
||||
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
|
||||
&& get_hold_on_other_key_press(keycode, record)
|
||||
# endif
|
||||
) {
|
||||
autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
|
||||
@ -497,7 +486,7 @@ void retroshift_poll_time(keyevent_t *event) {
|
||||
retroshift_time = timer_read();
|
||||
}
|
||||
// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
|
||||
void retroshift_swap_times() {
|
||||
void retroshift_swap_times(void) {
|
||||
if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
|
||||
uint16_t temp = retroshift_time;
|
||||
retroshift_time = last_retroshift_time;
|
||||
|
@ -22,9 +22,8 @@
|
||||
# define AUTO_SHIFT_TIMEOUT 175
|
||||
#endif
|
||||
|
||||
#define IS_LT(kc) ((kc) >= QK_LAYER_TAP && (kc) <= QK_LAYER_TAP_MAX)
|
||||
#define IS_MT(kc) ((kc) >= QK_MOD_TAP && (kc) <= QK_MOD_TAP_MAX)
|
||||
#define IS_RETRO(kc) (IS_MT(kc) || IS_LT(kc))
|
||||
#define IS_RETRO(kc) (IS_QK_MOD_TAP(kc) || IS_QK_LAYER_TAP(kc))
|
||||
|
||||
#define DO_GET_AUTOSHIFT_TIMEOUT(keycode, record, ...) record
|
||||
// clang-format off
|
||||
#define AUTO_SHIFT_ALPHA KC_A ... KC_Z
|
||||
|
305
quantum/process_keycode/process_autocorrect.c
Normal file
305
quantum/process_keycode/process_autocorrect.c
Normal file
@ -0,0 +1,305 @@
|
||||
// Copyright 2021 Google LLC
|
||||
// Copyright 2021 @filterpaper
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Original source: https://getreuer.info/posts/keyboards/autocorrection
|
||||
|
||||
#include "process_autocorrect.h"
|
||||
#include <string.h>
|
||||
#include "keycode_config.h"
|
||||
|
||||
#if __has_include("autocorrect_data.h")
|
||||
# include "autocorrect_data.h"
|
||||
#else
|
||||
# pragma message "Autocorrect is using the default library."
|
||||
# include "autocorrect_data_default.h"
|
||||
#endif
|
||||
|
||||
static uint8_t typo_buffer[AUTOCORRECT_MAX_LENGTH] = {KC_SPC};
|
||||
static uint8_t typo_buffer_size = 1;
|
||||
|
||||
/**
|
||||
* @brief function for querying the enabled state of autocorrect
|
||||
*
|
||||
* @return true if enabled
|
||||
* @return false if disabled
|
||||
*/
|
||||
bool autocorrect_is_enabled(void) {
|
||||
return keymap_config.autocorrect_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables autocorrect and saves state to eeprom
|
||||
*
|
||||
*/
|
||||
void autocorrect_enable(void) {
|
||||
keymap_config.autocorrect_enable = true;
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables autocorrect and saves state to eeprom
|
||||
*
|
||||
*/
|
||||
void autocorrect_disable(void) {
|
||||
keymap_config.autocorrect_enable = false;
|
||||
typo_buffer_size = 0;
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Toggles autocorrect's status and save state to eeprom
|
||||
*
|
||||
*/
|
||||
void autocorrect_toggle(void) {
|
||||
keymap_config.autocorrect_enable = !keymap_config.autocorrect_enable;
|
||||
typo_buffer_size = 0;
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief handler for determining if autocorrect should process keypress
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
__attribute__((weak)) bool process_autocorrect_user(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.
|
||||
case KC_LSFT:
|
||||
case KC_RSFT:
|
||||
case KC_CAPS:
|
||||
case QK_TO ... QK_TO_MAX:
|
||||
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
|
||||
case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
|
||||
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
|
||||
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
|
||||
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
|
||||
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
|
||||
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
|
||||
return false;
|
||||
|
||||
// Mask for base keycode from shifted keys.
|
||||
case QK_LSFT ... QK_LSFT + 255:
|
||||
case QK_RSFT ... QK_RSFT + 255:
|
||||
if (*keycode >= QK_LSFT && *keycode <= (QK_LSFT + 255)) {
|
||||
*mods |= MOD_LSFT;
|
||||
} else {
|
||||
*mods |= MOD_RSFT;
|
||||
}
|
||||
*keycode = QK_MODS_GET_BASIC_KEYCODE(*keycode); // Get the basic keycode.
|
||||
return true;
|
||||
#ifndef NO_ACTION_TAPPING
|
||||
// Exclude tap-hold keys when they are held down
|
||||
// and mask for base keycode when they are tapped.
|
||||
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
|
||||
# ifdef NO_ACTION_LAYER
|
||||
// Exclude Layer Tap, if layers are disabled
|
||||
// but action tapping is still enabled.
|
||||
return false;
|
||||
# else
|
||||
// Exclude hold keycode
|
||||
if (!record->tap.count) {
|
||||
return false;
|
||||
}
|
||||
*keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(*keycode);
|
||||
break;
|
||||
# endif
|
||||
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
|
||||
// Exclude hold keycode
|
||||
if (!record->tap.count) {
|
||||
return false;
|
||||
}
|
||||
*keycode = QK_MOD_TAP_GET_TAP_KEYCODE(*keycode);
|
||||
break;
|
||||
#else
|
||||
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
|
||||
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
|
||||
// Exclude if disabled
|
||||
return false;
|
||||
#endif
|
||||
// Exclude swap hands keys when they are held down
|
||||
// and mask for base keycode when they are tapped.
|
||||
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
|
||||
#ifdef SWAP_HANDS_ENABLE
|
||||
// Note: IS_SWAP_HANDS_KEYCODE() actually tests for the special action keycodes like SH_TOGG, SH_TT, ...,
|
||||
// which currently overlap the SH_T(kc) range.
|
||||
if (IS_SWAP_HANDS_KEYCODE(*keycode)
|
||||
# ifndef NO_ACTION_TAPPING
|
||||
|| !record->tap.count
|
||||
# endif // NO_ACTION_TAPPING
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
*keycode = QK_SWAP_HANDS_GET_TAP_KEYCODE(*keycode);
|
||||
break;
|
||||
#else
|
||||
// Exclude if disabled
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Disable autocorrect while a mod other than shift is active.
|
||||
if ((*mods & ~MOD_MASK_SHIFT) != 0) {
|
||||
*typo_buffer_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief handling for when autocorrection has been triggered
|
||||
*
|
||||
* @param backspaces number of characters to remove
|
||||
* @param str pointer to PROGMEM string to replace mistyped seletion with
|
||||
* @return true apply correction
|
||||
* @return false user handled replacement
|
||||
*/
|
||||
__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process handler for autocorrect 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_autocorrect(uint16_t keycode, keyrecord_t *record) {
|
||||
uint8_t mods = get_mods();
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
mods |= get_oneshot_mods();
|
||||
#endif
|
||||
|
||||
if ((keycode >= QK_AUTOCORRECT_ON && keycode <= QK_AUTOCORRECT_TOGGLE) && record->event.pressed) {
|
||||
if (keycode == QK_AUTOCORRECT_ON) {
|
||||
autocorrect_enable();
|
||||
} else if (keycode == QK_AUTOCORRECT_OFF) {
|
||||
autocorrect_disable();
|
||||
} else if (keycode == QK_AUTOCORRECT_TOGGLE) {
|
||||
autocorrect_toggle();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!keymap_config.autocorrect_enable) {
|
||||
typo_buffer_size = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!record->event.pressed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// autocorrect keycode verification and extraction
|
||||
if (!process_autocorrect_user(&keycode, record, &typo_buffer_size, &mods)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// keycode buffer check
|
||||
switch (keycode) {
|
||||
case KC_A ... KC_Z:
|
||||
// process normally
|
||||
break;
|
||||
case KC_1 ... KC_0:
|
||||
case KC_TAB ... KC_SEMICOLON:
|
||||
case KC_GRAVE ... KC_SLASH:
|
||||
// Set a word boundary if space, period, digit, etc. is pressed.
|
||||
keycode = KC_SPC;
|
||||
break;
|
||||
case KC_ENTER:
|
||||
// Behave more conservatively for the enter key. Reset, so that enter
|
||||
// can't be used on a word ending.
|
||||
typo_buffer_size = 0;
|
||||
keycode = KC_SPC;
|
||||
break;
|
||||
case KC_BSPC:
|
||||
// Remove last character from the buffer.
|
||||
if (typo_buffer_size > 0) {
|
||||
--typo_buffer_size;
|
||||
}
|
||||
return true;
|
||||
case KC_QUOTE:
|
||||
// Treat " (shifted ') as a word boundary.
|
||||
if ((mods & MOD_MASK_SHIFT) != 0) {
|
||||
keycode = KC_SPC;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Clear state if some other non-alpha key is pressed.
|
||||
typo_buffer_size = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rotate oldest character if buffer is full.
|
||||
if (typo_buffer_size >= AUTOCORRECT_MAX_LENGTH) {
|
||||
memmove(typo_buffer, typo_buffer + 1, AUTOCORRECT_MAX_LENGTH - 1);
|
||||
typo_buffer_size = AUTOCORRECT_MAX_LENGTH - 1;
|
||||
}
|
||||
|
||||
// Append `keycode` to buffer.
|
||||
typo_buffer[typo_buffer_size++] = keycode;
|
||||
// Return if buffer is smaller than the shortest word.
|
||||
if (typo_buffer_size < AUTOCORRECT_MIN_LENGTH) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for typo in buffer using a trie stored in `autocorrect_data`.
|
||||
uint16_t state = 0;
|
||||
uint8_t code = pgm_read_byte(autocorrect_data + state);
|
||||
for (int8_t i = typo_buffer_size - 1; i >= 0; --i) {
|
||||
uint8_t const key_i = typo_buffer[i];
|
||||
|
||||
if (code & 64) { // Check for match in node with multiple children.
|
||||
code &= 63;
|
||||
for (; code != key_i; code = pgm_read_byte(autocorrect_data + (state += 3))) {
|
||||
if (!code) return true;
|
||||
}
|
||||
// Follow link to child node.
|
||||
state = (pgm_read_byte(autocorrect_data + state + 1) | pgm_read_byte(autocorrect_data + state + 2) << 8);
|
||||
// Check for match in node with single child.
|
||||
} else if (code != key_i) {
|
||||
return true;
|
||||
} else if (!(code = pgm_read_byte(autocorrect_data + (++state)))) {
|
||||
++state;
|
||||
}
|
||||
|
||||
// Stop if `state` becomes an invalid index. This should not normally
|
||||
// happen, it is a safeguard in case of a bug, data corruption, etc.
|
||||
if (state >= DICTIONARY_SIZE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
code = pgm_read_byte(autocorrect_data + state);
|
||||
|
||||
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))) {
|
||||
for (uint8_t i = 0; i < backspaces; ++i) {
|
||||
tap_code(KC_BSPC);
|
||||
}
|
||||
send_string_P((char const *)(autocorrect_data + state + 1));
|
||||
}
|
||||
|
||||
if (keycode == KC_SPC) {
|
||||
typo_buffer[0] = KC_SPC;
|
||||
typo_buffer_size = 1;
|
||||
return true;
|
||||
} else {
|
||||
typo_buffer_size = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
17
quantum/process_keycode/process_autocorrect.h
Normal file
17
quantum/process_keycode/process_autocorrect.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2021 Google LLC
|
||||
// Copyright 2021 @filterpaper
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Original source: https://getreuer.info/posts/keyboards/autocorrection
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quantum.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 autocorrect_is_enabled(void);
|
||||
void autocorrect_enable(void);
|
||||
void autocorrect_disable(void);
|
||||
void autocorrect_toggle(void);
|
@ -26,45 +26,45 @@ bool process_backlight(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
switch (keycode) {
|
||||
#ifdef LED_MATRIX_ENABLE
|
||||
case BL_ON:
|
||||
case QK_BACKLIGHT_ON:
|
||||
led_matrix_enable();
|
||||
return false;
|
||||
case BL_OFF:
|
||||
case QK_BACKLIGHT_OFF:
|
||||
led_matrix_disable();
|
||||
return false;
|
||||
case BL_DEC:
|
||||
case QK_BACKLIGHT_DOWN:
|
||||
led_matrix_decrease_val();
|
||||
return false;
|
||||
case BL_INC:
|
||||
case QK_BACKLIGHT_UP:
|
||||
led_matrix_increase_val();
|
||||
return false;
|
||||
case BL_TOGG:
|
||||
case QK_BACKLIGHT_TOGGLE:
|
||||
led_matrix_toggle();
|
||||
return false;
|
||||
case BL_STEP:
|
||||
case QK_BACKLIGHT_STEP:
|
||||
led_matrix_step();
|
||||
return false;
|
||||
#else
|
||||
case BL_ON:
|
||||
case QK_BACKLIGHT_ON:
|
||||
backlight_level(BACKLIGHT_LEVELS);
|
||||
return false;
|
||||
case BL_OFF:
|
||||
case QK_BACKLIGHT_OFF:
|
||||
backlight_level(0);
|
||||
return false;
|
||||
case BL_DEC:
|
||||
case QK_BACKLIGHT_DOWN:
|
||||
backlight_decrease();
|
||||
return false;
|
||||
case BL_INC:
|
||||
case QK_BACKLIGHT_UP:
|
||||
backlight_increase();
|
||||
return false;
|
||||
case BL_TOGG:
|
||||
case QK_BACKLIGHT_TOGGLE:
|
||||
backlight_toggle();
|
||||
return false;
|
||||
case BL_STEP:
|
||||
case QK_BACKLIGHT_STEP:
|
||||
backlight_step();
|
||||
return false;
|
||||
# ifdef BACKLIGHT_BREATHING
|
||||
case BL_BRTG:
|
||||
case QK_BACKLIGHT_TOGGLE_BREATHING:
|
||||
backlight_toggle_breathing();
|
||||
return false;
|
||||
# endif
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "process_caps_word.h"
|
||||
|
||||
bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
|
||||
if (keycode == CAPSWRD) { // Pressing CAPSWRD toggles Caps Word.
|
||||
if (keycode == QK_CAPS_WORD_TOGGLE) {
|
||||
if (record->event.pressed) {
|
||||
caps_word_toggle();
|
||||
}
|
||||
@ -109,7 +109,7 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
|
||||
// * Otherwise stop Caps Word.
|
||||
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
|
||||
if (record->tap.count == 0) { // Mod-tap key is held.
|
||||
const uint8_t mods = (keycode >> 8) & 0x1f;
|
||||
const uint8_t mods = QK_MOD_TAP_GET_MODS(keycode);
|
||||
switch (mods) {
|
||||
case MOD_LSFT:
|
||||
keycode = KC_LSFT;
|
||||
@ -127,7 +127,7 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
keycode &= 0xff;
|
||||
keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -137,16 +137,22 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
|
||||
if (record->tap.count == 0) {
|
||||
return true;
|
||||
}
|
||||
keycode &= 0xff;
|
||||
keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
|
||||
break;
|
||||
#endif // NO_ACTION_TAPPING
|
||||
|
||||
#ifdef SWAP_HANDS_ENABLE
|
||||
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
|
||||
if (keycode > 0x56F0 || record->tap.count == 0) {
|
||||
// Note: IS_SWAP_HANDS_KEYCODE() actually tests for the special action keycodes like SH_TOGG, SH_TT, ...,
|
||||
// which currently overlap the SH_T(kc) range.
|
||||
if (IS_SWAP_HANDS_KEYCODE(keycode)
|
||||
# ifndef NO_ACTION_TAPPING
|
||||
|| record->tap.count == 0
|
||||
# endif // NO_ACTION_TAPPING
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
keycode &= 0xff;
|
||||
keycode = QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode);
|
||||
break;
|
||||
#endif // SWAP_HANDS_ENABLE
|
||||
}
|
||||
|
@ -82,31 +82,31 @@ bool is_clicky_on(void) {
|
||||
}
|
||||
|
||||
bool process_clicky(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == CLICKY_TOGGLE && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_CLICKY_TOGGLE && record->event.pressed) {
|
||||
clicky_toggle();
|
||||
}
|
||||
|
||||
if (keycode == CLICKY_ENABLE && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_CLICKY_ON && record->event.pressed) {
|
||||
clicky_on();
|
||||
}
|
||||
if (keycode == CLICKY_DISABLE && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_CLICKY_OFF && record->event.pressed) {
|
||||
clicky_off();
|
||||
}
|
||||
|
||||
if (keycode == CLICKY_RESET && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_CLICKY_RESET && record->event.pressed) {
|
||||
clicky_freq_reset();
|
||||
}
|
||||
|
||||
if (keycode == CLICKY_UP && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_CLICKY_UP && record->event.pressed) {
|
||||
clicky_freq_up();
|
||||
}
|
||||
if (keycode == CLICKY_DOWN && record->event.pressed) {
|
||||
if (keycode == QK_AUDIO_CLICKY_DOWN && record->event.pressed) {
|
||||
clicky_freq_down();
|
||||
}
|
||||
|
||||
if (audio_config.enable && audio_config.clicky_enable) {
|
||||
if (record->event.pressed) { // Leave this separate so it's easier to add upstroke sound
|
||||
if (keycode != AU_OFF && keycode != AU_TOG) { // DO NOT PLAY if audio will be disabled, and causes issuse on ARM
|
||||
if (record->event.pressed) { // Leave this separate so it's easier to add upstroke sound
|
||||
if (keycode != QK_AUDIO_ON && keycode != QK_AUDIO_OFF) { // DO NOT PLAY if audio will be disabled, and causes issuse on ARM
|
||||
clicky_play();
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,12 @@ extern uint16_t COMBO_LEN;
|
||||
|
||||
__attribute__((weak)) void process_combo_event(uint16_t combo_index, bool pressed) {}
|
||||
|
||||
#ifndef COMBO_ONLY_FROM_LAYER
|
||||
__attribute__((weak)) uint8_t combo_ref_from_layer(uint8_t layer) {
|
||||
return layer;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_MUST_HOLD_PER_COMBO
|
||||
__attribute__((weak)) bool get_combo_must_hold(uint16_t index, combo_t *combo) {
|
||||
return false;
|
||||
@ -311,7 +317,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
|
||||
#if defined(EXTRA_EXTRA_LONG_COMBOS)
|
||||
uint32_t state = 0;
|
||||
#elif defined(EXTRA_LONG_COMBOS)
|
||||
uint16_t state = 0;
|
||||
uint16_t state = 0;
|
||||
#else
|
||||
uint8_t state = 0;
|
||||
#endif
|
||||
@ -538,17 +544,17 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
|
||||
bool is_combo_key = false;
|
||||
bool no_combo_keys_pressed = true;
|
||||
|
||||
if (keycode == CMB_ON && record->event.pressed) {
|
||||
if (keycode == QK_COMBO_ON && record->event.pressed) {
|
||||
combo_enable();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keycode == CMB_OFF && record->event.pressed) {
|
||||
if (keycode == QK_COMBO_OFF && record->event.pressed) {
|
||||
combo_disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keycode == CMB_TOG && record->event.pressed) {
|
||||
if (keycode == QK_COMBO_TOGGLE && record->event.pressed) {
|
||||
combo_toggle();
|
||||
return true;
|
||||
}
|
||||
@ -556,6 +562,12 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifdef COMBO_ONLY_FROM_LAYER
|
||||
/* Only check keycodes from one layer. */
|
||||
keycode = keymap_key_to_keycode(COMBO_ONLY_FROM_LAYER, record->event.key);
|
||||
#else
|
||||
uint8_t highest_layer = get_highest_layer(layer_state);
|
||||
uint8_t ref_layer = combo_ref_from_layer(highest_layer);
|
||||
if (ref_layer != highest_layer) {
|
||||
keycode = keymap_key_to_keycode(ref_layer, record->event.key);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint16_t idx = 0; idx < COMBO_LEN; ++idx) {
|
||||
|
@ -69,7 +69,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
/* check if keycode is only modifiers */
|
||||
#define KEYCODE_IS_MOD(code) (IS_MOD(code) || (code >= QK_MODS && code <= QK_MODS_MAX && !(code & QK_BASIC_MAX)))
|
||||
#define KEYCODE_IS_MOD(code) (IS_MODIFIER_KEYCODE(code) || (IS_QK_MODS(code) && !QK_MODS_GET_BASIC_KEYCODE(code)))
|
||||
|
||||
bool process_combo(uint16_t keycode, keyrecord_t *record);
|
||||
void combo_task(void);
|
||||
|
@ -45,6 +45,10 @@ __attribute__((weak)) void dynamic_macro_record_end_user(int8_t direction) {
|
||||
dynamic_macro_led_blink();
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool dynamic_macro_valid_key_user(uint16_t keycode, keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Convenience macros used for retrieving the debug info. All of them
|
||||
* need a `direction` variable accessible at the call site.
|
||||
*/
|
||||
@ -135,7 +139,7 @@ void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_poin
|
||||
dynamic_macro_record_end_user(direction);
|
||||
|
||||
/* Do not save the keys being held when stopping the recording,
|
||||
* i.e. the keys used to access the layer DYN_REC_STOP is on.
|
||||
* i.e. the keys used to access the layer DM_RSTP is on.
|
||||
*/
|
||||
while (macro_pointer != macro_buffer && (macro_pointer - direction)->event.pressed) {
|
||||
dprintln("dynamic macro: trimming a trailing key-down event");
|
||||
@ -208,18 +212,18 @@ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) {
|
||||
/* No macro recording in progress. */
|
||||
if (!record->event.pressed) {
|
||||
switch (keycode) {
|
||||
case DYN_REC_START1:
|
||||
case QK_DYNAMIC_MACRO_RECORD_START_1:
|
||||
dynamic_macro_record_start(¯o_pointer, macro_buffer);
|
||||
macro_id = 1;
|
||||
return false;
|
||||
case DYN_REC_START2:
|
||||
case QK_DYNAMIC_MACRO_RECORD_START_2:
|
||||
dynamic_macro_record_start(¯o_pointer, r_macro_buffer);
|
||||
macro_id = 2;
|
||||
return false;
|
||||
case DYN_MACRO_PLAY1:
|
||||
case QK_DYNAMIC_MACRO_PLAY_1:
|
||||
dynamic_macro_play(macro_buffer, macro_end, +1);
|
||||
return false;
|
||||
case DYN_MACRO_PLAY2:
|
||||
case QK_DYNAMIC_MACRO_PLAY_2:
|
||||
dynamic_macro_play(r_macro_buffer, r_macro_end, -1);
|
||||
return false;
|
||||
}
|
||||
@ -227,13 +231,13 @@ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) {
|
||||
} else {
|
||||
/* A macro is being recorded right now. */
|
||||
switch (keycode) {
|
||||
case DYN_REC_START1:
|
||||
case DYN_REC_START2:
|
||||
case DYN_REC_STOP:
|
||||
case QK_DYNAMIC_MACRO_RECORD_START_1:
|
||||
case QK_DYNAMIC_MACRO_RECORD_START_2:
|
||||
case QK_DYNAMIC_MACRO_RECORD_STOP:
|
||||
/* Stop the macro recording. */
|
||||
if (record->event.pressed ^ (keycode != DYN_REC_STOP)) { /* Ignore the initial release
|
||||
* just after the recording
|
||||
* starts for DYN_REC_STOP. */
|
||||
if (record->event.pressed ^ (keycode != QK_DYNAMIC_MACRO_RECORD_STOP)) { /* Ignore the initial release
|
||||
* just after the recording
|
||||
* starts for DM_RSTP. */
|
||||
switch (macro_id) {
|
||||
case 1:
|
||||
dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end);
|
||||
@ -246,20 +250,22 @@ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
return false;
|
||||
#ifdef DYNAMIC_MACRO_NO_NESTING
|
||||
case DYN_MACRO_PLAY1:
|
||||
case DYN_MACRO_PLAY2:
|
||||
case QK_DYNAMIC_MACRO_PLAY_1:
|
||||
case QK_DYNAMIC_MACRO_PLAY_2:
|
||||
dprintln("dynamic macro: ignoring macro play key while recording");
|
||||
return false;
|
||||
#endif
|
||||
default:
|
||||
/* Store the key in the macro buffer and process it normally. */
|
||||
switch (macro_id) {
|
||||
case 1:
|
||||
dynamic_macro_record_key(macro_buffer, ¯o_pointer, r_macro_end, +1, record);
|
||||
break;
|
||||
case 2:
|
||||
dynamic_macro_record_key(r_macro_buffer, ¯o_pointer, macro_end, -1, record);
|
||||
break;
|
||||
if (dynamic_macro_valid_key_user(keycode, record)) {
|
||||
/* Store the key in the macro buffer and process it normally. */
|
||||
switch (macro_id) {
|
||||
case 1:
|
||||
dynamic_macro_record_key(macro_buffer, ¯o_pointer, r_macro_end, +1, record);
|
||||
break;
|
||||
case 2:
|
||||
dynamic_macro_record_key(r_macro_buffer, ¯o_pointer, macro_end, -1, record);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
@ -35,15 +35,15 @@ static void tapping_term_report(void) {
|
||||
bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
switch (keycode) {
|
||||
case DT_PRNT:
|
||||
case QK_DYNAMIC_TAPPING_TERM_PRINT:
|
||||
tapping_term_report();
|
||||
return false;
|
||||
|
||||
case DT_UP:
|
||||
case QK_DYNAMIC_TAPPING_TERM_UP:
|
||||
g_tapping_term += DYNAMIC_TAPPING_TERM_INCREMENT;
|
||||
return false;
|
||||
|
||||
case DT_DOWN:
|
||||
case QK_DYNAMIC_TAPPING_TERM_DOWN:
|
||||
g_tapping_term -= DYNAMIC_TAPPING_TERM_INCREMENT;
|
||||
return false;
|
||||
}
|
||||
|
@ -88,43 +88,43 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
|
||||
bool process_haptic(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
switch (keycode) {
|
||||
case HPT_ON:
|
||||
case QK_HAPTIC_ON:
|
||||
haptic_enable();
|
||||
break;
|
||||
case HPT_OFF:
|
||||
case QK_HAPTIC_OFF:
|
||||
haptic_disable();
|
||||
break;
|
||||
case HPT_TOG:
|
||||
case QK_HAPTIC_TOGGLE:
|
||||
haptic_toggle();
|
||||
break;
|
||||
case HPT_RST:
|
||||
case QK_HAPTIC_RESET:
|
||||
haptic_reset();
|
||||
break;
|
||||
case HPT_FBK:
|
||||
case QK_HAPTIC_FEEDBACK_TOGGLE:
|
||||
haptic_feedback_toggle();
|
||||
break;
|
||||
case HPT_BUZ:
|
||||
case QK_HAPTIC_BUZZ_TOGGLE:
|
||||
haptic_buzz_toggle();
|
||||
break;
|
||||
case HPT_MODI:
|
||||
case QK_HAPTIC_MODE_NEXT:
|
||||
haptic_mode_increase();
|
||||
break;
|
||||
case HPT_MODD:
|
||||
case QK_HAPTIC_MODE_PREVIOUS:
|
||||
haptic_mode_decrease();
|
||||
break;
|
||||
case HPT_DWLI:
|
||||
case QK_HAPTIC_DWELL_UP:
|
||||
haptic_dwell_increase();
|
||||
break;
|
||||
case HPT_DWLD:
|
||||
case QK_HAPTIC_DWELL_DOWN:
|
||||
haptic_dwell_decrease();
|
||||
break;
|
||||
case HPT_CONT:
|
||||
case QK_HAPTIC_CONTINUOUS_TOGGLE:
|
||||
haptic_toggle_continuous();
|
||||
break;
|
||||
case HPT_CONI:
|
||||
case QK_HAPTIC_CONTINUOUS_UP:
|
||||
haptic_cont_increase();
|
||||
break;
|
||||
case HPT_COND:
|
||||
case QK_HAPTIC_CONTINUOUS_DOWN:
|
||||
haptic_cont_decrease();
|
||||
break;
|
||||
}
|
||||
|
@ -1,149 +1,31 @@
|
||||
#include "joystick.h"
|
||||
/* Copyright 2022
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "process_joystick.h"
|
||||
|
||||
#include "analog.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "joystick.h"
|
||||
|
||||
bool process_joystick(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case JS_BUTTON0 ... JS_BUTTON_MAX:
|
||||
case QK_JOYSTICK ... QK_JOYSTICK_MAX:
|
||||
if (record->event.pressed) {
|
||||
register_joystick_button(keycode - JS_BUTTON0);
|
||||
register_joystick_button(keycode - QK_JOYSTICK);
|
||||
} else {
|
||||
unregister_joystick_button(keycode - JS_BUTTON0);
|
||||
unregister_joystick_button(keycode - QK_JOYSTICK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void joystick_task(void) {
|
||||
if (process_joystick_analogread()) {
|
||||
joystick_flush();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t savePinState(pin_t pin) {
|
||||
#ifdef __AVR__
|
||||
uint8_t pinNumber = pin & 0xF;
|
||||
return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1);
|
||||
#elif defined(PROTOCOL_CHIBIOS)
|
||||
/*
|
||||
The pin configuration is backed up in the following format :
|
||||
bit 15 9 8 7 6 5 4 3 2 1 0
|
||||
|unused|ODR|IDR|PUPDR|OSPEEDR|OTYPER|MODER|
|
||||
*/
|
||||
return ((PAL_PORT(pin)->MODER >> (2 * PAL_PAD(pin))) & 0x3) | (((PAL_PORT(pin)->OTYPER >> (1 * PAL_PAD(pin))) & 0x1) << 2) | (((PAL_PORT(pin)->OSPEEDR >> (2 * PAL_PAD(pin))) & 0x3) << 3) | (((PAL_PORT(pin)->PUPDR >> (2 * PAL_PAD(pin))) & 0x3) << 5) | (((PAL_PORT(pin)->IDR >> (1 * PAL_PAD(pin))) & 0x1) << 7) | (((PAL_PORT(pin)->ODR >> (1 * PAL_PAD(pin))) & 0x1) << 8);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void restorePinState(pin_t pin, uint16_t restoreState) {
|
||||
#if defined(PROTOCOL_LUFA)
|
||||
uint8_t pinNumber = pin & 0xF;
|
||||
PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber);
|
||||
DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber);
|
||||
#elif defined(PROTOCOL_CHIBIOS)
|
||||
PAL_PORT(pin)->MODER = (PAL_PORT(pin)->MODER & ~(0x3 << (2 * PAL_PAD(pin)))) | (restoreState & 0x3) << (2 * PAL_PAD(pin));
|
||||
PAL_PORT(pin)->OTYPER = (PAL_PORT(pin)->OTYPER & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 2) & 0x1) << (1 * PAL_PAD(pin));
|
||||
PAL_PORT(pin)->OSPEEDR = (PAL_PORT(pin)->OSPEEDR & ~(0x3 << (2 * PAL_PAD(pin)))) | ((restoreState >> 3) & 0x3) << (2 * PAL_PAD(pin));
|
||||
PAL_PORT(pin)->PUPDR = (PAL_PORT(pin)->PUPDR & ~(0x3 << (2 * PAL_PAD(pin)))) | ((restoreState >> 5) & 0x3) << (2 * PAL_PAD(pin));
|
||||
PAL_PORT(pin)->IDR = (PAL_PORT(pin)->IDR & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 7) & 0x1) << (1 * PAL_PAD(pin));
|
||||
PAL_PORT(pin)->ODR = (PAL_PORT(pin)->ODR & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 8) & 0x1) << (1 * PAL_PAD(pin));
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool process_joystick_analogread() {
|
||||
return process_joystick_analogread_quantum();
|
||||
}
|
||||
|
||||
bool process_joystick_analogread_quantum() {
|
||||
#if JOYSTICK_AXES_COUNT > 0
|
||||
for (int axis_index = 0; axis_index < JOYSTICK_AXES_COUNT; ++axis_index) {
|
||||
if (joystick_axes[axis_index].input_pin == JS_VIRTUAL_AXIS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// save previous input pin status as well
|
||||
uint16_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin);
|
||||
|
||||
// disable pull-up resistor
|
||||
writePinLow(joystick_axes[axis_index].input_pin);
|
||||
|
||||
// if pin was a pull-up input, we need to uncharge it by turning it low
|
||||
// before making it a low input
|
||||
setPinOutput(joystick_axes[axis_index].input_pin);
|
||||
|
||||
wait_us(10);
|
||||
|
||||
// save and apply output pin status
|
||||
uint16_t outputSavedState = 0;
|
||||
if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
|
||||
// save previous output pin status
|
||||
outputSavedState = savePinState(joystick_axes[axis_index].output_pin);
|
||||
|
||||
setPinOutput(joystick_axes[axis_index].output_pin);
|
||||
writePinHigh(joystick_axes[axis_index].output_pin);
|
||||
}
|
||||
|
||||
uint16_t groundSavedState = 0;
|
||||
if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
|
||||
// save previous output pin status
|
||||
groundSavedState = savePinState(joystick_axes[axis_index].ground_pin);
|
||||
|
||||
setPinOutput(joystick_axes[axis_index].ground_pin);
|
||||
writePinLow(joystick_axes[axis_index].ground_pin);
|
||||
}
|
||||
|
||||
wait_us(10);
|
||||
|
||||
setPinInput(joystick_axes[axis_index].input_pin);
|
||||
|
||||
wait_us(10);
|
||||
|
||||
# if defined(ANALOG_JOYSTICK_ENABLE) && (defined(__AVR__) || defined(PROTOCOL_CHIBIOS))
|
||||
int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin);
|
||||
# else
|
||||
// default to resting position
|
||||
int16_t axis_val = joystick_axes[axis_index].mid_digit;
|
||||
# endif
|
||||
|
||||
// test the converted value against the lower range
|
||||
int32_t ref = joystick_axes[axis_index].mid_digit;
|
||||
int32_t range = joystick_axes[axis_index].min_digit;
|
||||
int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_RESOLUTION) / (range - ref);
|
||||
|
||||
if (ranged_val > 0) {
|
||||
// the value is in the higher range
|
||||
range = joystick_axes[axis_index].max_digit;
|
||||
ranged_val = ((axis_val - ref) * JOYSTICK_RESOLUTION) / (range - ref);
|
||||
}
|
||||
|
||||
// clamp the result in the valid range
|
||||
ranged_val = ranged_val < -JOYSTICK_RESOLUTION ? -JOYSTICK_RESOLUTION : ranged_val;
|
||||
ranged_val = ranged_val > JOYSTICK_RESOLUTION ? JOYSTICK_RESOLUTION : ranged_val;
|
||||
|
||||
if (ranged_val != joystick_status.axes[axis_index]) {
|
||||
joystick_status.axes[axis_index] = ranged_val;
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
}
|
||||
|
||||
// restore output, ground and input status
|
||||
if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
|
||||
restorePinState(joystick_axes[axis_index].output_pin, outputSavedState);
|
||||
}
|
||||
if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
|
||||
restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState);
|
||||
}
|
||||
|
||||
restorePinState(joystick_axes[axis_index].input_pin, inputSavedState);
|
||||
}
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -1,11 +1,22 @@
|
||||
/* Copyright 2022
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
|
||||
bool process_joystick(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
void joystick_task(void);
|
||||
|
||||
bool process_joystick_analogread(void);
|
||||
bool process_joystick_analogread_quantum(void);
|
||||
|
@ -70,7 +70,7 @@ bool process_key_lock(uint16_t *keycode, keyrecord_t *record) {
|
||||
// reset the state in our map and return false. When the user releases the
|
||||
// key, the up event will no longer be masked and the OS will observe the
|
||||
// released key.
|
||||
// 3. KC_LOCK was just pressed. In this case, we set up the state machine
|
||||
// 3. QK_LOCK was just pressed. In this case, we set up the state machine
|
||||
// to watch for the next key down event, and finish processing
|
||||
// 4. The keycode is below 0xFF, and we are watching for new keys. In this case,
|
||||
// we will send the key down event to the os, and set the key_state for that
|
||||
@ -95,20 +95,20 @@ bool process_key_lock(uint16_t *keycode, keyrecord_t *record) {
|
||||
|
||||
if (record->event.pressed) {
|
||||
// Non-standard keycode, reset and return
|
||||
if (!(IS_STANDARD_KEYCODE(translated_keycode) || translated_keycode == KC_LOCK)) {
|
||||
if (!(IS_STANDARD_KEYCODE(translated_keycode) || translated_keycode == QK_LOCK)) {
|
||||
watching = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we're already watching, turn off the watch.
|
||||
if (translated_keycode == KC_LOCK) {
|
||||
if (translated_keycode == QK_LOCK) {
|
||||
watching = !watching;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IS_STANDARD_KEYCODE(translated_keycode)) {
|
||||
// We check watching first. This is so that in the following scenario, we continue to
|
||||
// hold the key: KC_LOCK, KC_F, KC_LOCK, KC_F
|
||||
// hold the key: QK_LOCK, KC_F, QK_LOCK, KC_F
|
||||
// If we checked in reverse order, we'd end up holding the key pressed after the second
|
||||
// KC_F press is registered, when the user likely meant to hold F
|
||||
if (watching) {
|
||||
|
@ -186,7 +186,7 @@ const key_override_t *clear_active_override(const bool allow_reregister) {
|
||||
|
||||
// Then unregister the mod-free replacement key if desired
|
||||
if (unregister_replacement) {
|
||||
if (IS_KEY(mod_free_replacement)) {
|
||||
if (IS_BASIC_KEYCODE(mod_free_replacement)) {
|
||||
del_key(mod_free_replacement);
|
||||
} else {
|
||||
key_override_printf("NOT KEY 1\n");
|
||||
@ -329,7 +329,7 @@ static bool try_activating_override(const uint16_t keycode, const uint8_t layer,
|
||||
|
||||
if (!trigger_down && !no_trigger) {
|
||||
// When activating a key override the trigger is is always unregistered. In the case where the key that newly pressed is not the trigger key, we have to explicitly remove the trigger key from the keyboard report. If the trigger was just pressed down we simply suppress the event which also has the effect of the trigger key not being registered in the keyboard report.
|
||||
if (IS_KEY(override->trigger)) {
|
||||
if (IS_BASIC_KEYCODE(override->trigger)) {
|
||||
del_key(override->trigger);
|
||||
} else {
|
||||
unregister_code(override->trigger);
|
||||
@ -356,7 +356,7 @@ static bool try_activating_override(const uint16_t keycode, const uint8_t layer,
|
||||
schedule_deferred_register(mod_free_replacement);
|
||||
send_keyboard_report();
|
||||
} else {
|
||||
if (IS_KEY(mod_free_replacement)) {
|
||||
if (IS_BASIC_KEYCODE(mod_free_replacement)) {
|
||||
add_key(mod_free_replacement);
|
||||
} else {
|
||||
key_override_printf("NOT KEY 2\n");
|
||||
@ -402,19 +402,19 @@ bool process_key_override(const uint16_t keycode, const keyrecord_t *const recor
|
||||
#endif
|
||||
|
||||
const bool key_down = record->event.pressed;
|
||||
const bool is_mod = IS_MOD(keycode);
|
||||
const bool is_mod = IS_MODIFIER_KEYCODE(keycode);
|
||||
|
||||
if (key_down) {
|
||||
switch (keycode) {
|
||||
case KEY_OVERRIDE_TOGGLE:
|
||||
case QK_KEY_OVERRIDE_TOGGLE:
|
||||
key_override_toggle();
|
||||
return false;
|
||||
|
||||
case KEY_OVERRIDE_ON:
|
||||
case QK_KEY_OVERRIDE_ON:
|
||||
key_override_on();
|
||||
return false;
|
||||
|
||||
case KEY_OVERRIDE_OFF:
|
||||
case QK_KEY_OVERRIDE_OFF:
|
||||
key_override_off();
|
||||
return false;
|
||||
|
||||
|
@ -14,70 +14,35 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef LEADER_ENABLE
|
||||
|
||||
# include "process_leader.h"
|
||||
# include <string.h>
|
||||
|
||||
# ifndef LEADER_TIMEOUT
|
||||
# define LEADER_TIMEOUT 300
|
||||
# endif
|
||||
|
||||
__attribute__((weak)) void leader_start(void) {}
|
||||
|
||||
__attribute__((weak)) void leader_end(void) {}
|
||||
|
||||
// Leader key stuff
|
||||
bool leading = false;
|
||||
uint16_t leader_time = 0;
|
||||
|
||||
uint16_t leader_sequence[5] = {0, 0, 0, 0, 0};
|
||||
uint8_t leader_sequence_size = 0;
|
||||
|
||||
void qk_leader_start(void) {
|
||||
if (leading) {
|
||||
return;
|
||||
}
|
||||
leader_start();
|
||||
leading = true;
|
||||
leader_time = timer_read();
|
||||
leader_sequence_size = 0;
|
||||
memset(leader_sequence, 0, sizeof(leader_sequence));
|
||||
}
|
||||
#include "process_leader.h"
|
||||
#include "leader.h"
|
||||
|
||||
bool process_leader(uint16_t keycode, keyrecord_t *record) {
|
||||
// Leader key set-up
|
||||
if (record->event.pressed) {
|
||||
if (leading) {
|
||||
# ifndef LEADER_NO_TIMEOUT
|
||||
if (timer_elapsed(leader_time) < LEADER_TIMEOUT)
|
||||
# endif // LEADER_NO_TIMEOUT
|
||||
{
|
||||
# ifndef LEADER_KEY_STRICT_KEY_PROCESSING
|
||||
if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
|
||||
keycode = keycode & 0xFF;
|
||||
}
|
||||
# endif // LEADER_KEY_STRICT_KEY_PROCESSING
|
||||
if (leader_sequence_size < (sizeof(leader_sequence) / sizeof(leader_sequence[0]))) {
|
||||
leader_sequence[leader_sequence_size] = keycode;
|
||||
leader_sequence_size++;
|
||||
} else {
|
||||
leading = false;
|
||||
leader_end();
|
||||
return true;
|
||||
}
|
||||
# ifdef LEADER_PER_KEY_TIMING
|
||||
leader_time = timer_read();
|
||||
# endif
|
||||
return false;
|
||||
if (leader_sequence_active() && !leader_sequence_timed_out()) {
|
||||
#ifndef LEADER_KEY_STRICT_KEY_PROCESSING
|
||||
if (IS_QK_MOD_TAP(keycode)) {
|
||||
keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
|
||||
} else if (IS_QK_LAYER_TAP(keycode)) {
|
||||
keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
|
||||
}
|
||||
} else {
|
||||
if (keycode == KC_LEAD) {
|
||||
qk_leader_start();
|
||||
#endif
|
||||
|
||||
if (!leader_sequence_add(keycode)) {
|
||||
leader_end();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef LEADER_PER_KEY_TIMING
|
||||
leader_reset_timer();
|
||||
#endif
|
||||
|
||||
return false;
|
||||
} else if (keycode == QK_LEADER) {
|
||||
leader_start();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,25 +19,3 @@
|
||||
#include "quantum.h"
|
||||
|
||||
bool process_leader(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
void leader_start(void);
|
||||
void leader_end(void);
|
||||
void qk_leader_start(void);
|
||||
|
||||
#define SEQ_ONE_KEY(key) if (leader_sequence[0] == (key) && leader_sequence[1] == 0 && leader_sequence[2] == 0 && leader_sequence[3] == 0 && leader_sequence[4] == 0)
|
||||
#define SEQ_TWO_KEYS(key1, key2) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == 0 && leader_sequence[3] == 0 && leader_sequence[4] == 0)
|
||||
#define SEQ_THREE_KEYS(key1, key2, key3) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == 0 && leader_sequence[4] == 0)
|
||||
#define SEQ_FOUR_KEYS(key1, key2, key3, key4) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == 0)
|
||||
#define SEQ_FIVE_KEYS(key1, key2, key3, key4, key5) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == (key5))
|
||||
|
||||
#define LEADER_EXTERNS() \
|
||||
extern bool leading; \
|
||||
extern uint16_t leader_time; \
|
||||
extern uint16_t leader_sequence[5]; \
|
||||
extern uint8_t leader_sequence_size
|
||||
|
||||
#ifdef LEADER_NO_TIMEOUT
|
||||
# define LEADER_DICTIONARY() if (leading && leader_sequence_size > 0 && timer_elapsed(leader_time) > LEADER_TIMEOUT)
|
||||
#else
|
||||
# define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
|
||||
#endif
|
||||
|
@ -40,154 +40,152 @@ float cg_swap_song[][2] = CG_SWAP_SONG;
|
||||
bool process_magic(uint16_t keycode, keyrecord_t *record) {
|
||||
// skip anything that isn't a keyup
|
||||
if (record->event.pressed) {
|
||||
switch (keycode) {
|
||||
case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_ALT_GUI:
|
||||
case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT:
|
||||
case MAGIC_TOGGLE_GUI:
|
||||
case MAGIC_TOGGLE_CONTROL_CAPSLOCK:
|
||||
case MAGIC_SWAP_ESCAPE_CAPSLOCK ... MAGIC_TOGGLE_ESCAPE_CAPSLOCK:
|
||||
/* keymap config */
|
||||
keymap_config.raw = eeconfig_read_keymap();
|
||||
switch (keycode) {
|
||||
case MAGIC_SWAP_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = true;
|
||||
break;
|
||||
case MAGIC_SWAP_ESCAPE_CAPSLOCK:
|
||||
keymap_config.swap_escape_capslock = true;
|
||||
break;
|
||||
case MAGIC_CAPSLOCK_TO_CONTROL:
|
||||
keymap_config.capslock_to_control = true;
|
||||
break;
|
||||
case MAGIC_SWAP_LALT_LGUI:
|
||||
keymap_config.swap_lalt_lgui = true;
|
||||
break;
|
||||
case MAGIC_SWAP_RALT_RGUI:
|
||||
keymap_config.swap_ralt_rgui = true;
|
||||
break;
|
||||
case MAGIC_SWAP_LCTL_LGUI:
|
||||
keymap_config.swap_lctl_lgui = true;
|
||||
break;
|
||||
case MAGIC_SWAP_RCTL_RGUI:
|
||||
keymap_config.swap_rctl_rgui = true;
|
||||
break;
|
||||
case MAGIC_NO_GUI:
|
||||
keymap_config.no_gui = true;
|
||||
break;
|
||||
case MAGIC_SWAP_GRAVE_ESC:
|
||||
keymap_config.swap_grave_esc = true;
|
||||
break;
|
||||
case MAGIC_SWAP_BACKSLASH_BACKSPACE:
|
||||
keymap_config.swap_backslash_backspace = true;
|
||||
break;
|
||||
case MAGIC_HOST_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = true;
|
||||
break;
|
||||
case MAGIC_SWAP_ALT_GUI:
|
||||
keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true;
|
||||
if (IS_MAGIC_KEYCODE(keycode)) {
|
||||
/* keymap config */
|
||||
keymap_config.raw = eeconfig_read_keymap();
|
||||
switch (keycode) {
|
||||
case QK_MAGIC_SWAP_CONTROL_CAPS_LOCK:
|
||||
keymap_config.swap_control_capslock = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_ESCAPE_CAPS_LOCK:
|
||||
keymap_config.swap_escape_capslock = true;
|
||||
break;
|
||||
case QK_MAGIC_CAPS_LOCK_AS_CONTROL_ON:
|
||||
keymap_config.capslock_to_control = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_LALT_LGUI:
|
||||
keymap_config.swap_lalt_lgui = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_RALT_RGUI:
|
||||
keymap_config.swap_ralt_rgui = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_LCTL_LGUI:
|
||||
keymap_config.swap_lctl_lgui = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_RCTL_RGUI:
|
||||
keymap_config.swap_rctl_rgui = true;
|
||||
break;
|
||||
case QK_MAGIC_GUI_OFF:
|
||||
keymap_config.no_gui = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_GRAVE_ESC:
|
||||
keymap_config.swap_grave_esc = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_BACKSLASH_BACKSPACE:
|
||||
keymap_config.swap_backslash_backspace = true;
|
||||
break;
|
||||
case QK_MAGIC_NKRO_ON:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = true;
|
||||
break;
|
||||
case QK_MAGIC_SWAP_ALT_GUI:
|
||||
keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true;
|
||||
#ifdef AUDIO_ENABLE
|
||||
PLAY_SONG(ag_swap_song);
|
||||
#endif
|
||||
break;
|
||||
case QK_MAGIC_SWAP_CTL_GUI:
|
||||
keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true;
|
||||
#ifdef AUDIO_ENABLE
|
||||
PLAY_SONG(cg_swap_song);
|
||||
#endif
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK:
|
||||
keymap_config.swap_control_capslock = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_ESCAPE_CAPS_LOCK:
|
||||
keymap_config.swap_escape_capslock = false;
|
||||
break;
|
||||
case QK_MAGIC_CAPS_LOCK_AS_CONTROL_OFF:
|
||||
keymap_config.capslock_to_control = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_LALT_LGUI:
|
||||
keymap_config.swap_lalt_lgui = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_RALT_RGUI:
|
||||
keymap_config.swap_ralt_rgui = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_LCTL_LGUI:
|
||||
keymap_config.swap_lctl_lgui = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_RCTL_RGUI:
|
||||
keymap_config.swap_rctl_rgui = false;
|
||||
break;
|
||||
case QK_MAGIC_GUI_ON:
|
||||
keymap_config.no_gui = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_GRAVE_ESC:
|
||||
keymap_config.swap_grave_esc = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
|
||||
keymap_config.swap_backslash_backspace = false;
|
||||
break;
|
||||
case QK_MAGIC_NKRO_OFF:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = false;
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_ALT_GUI:
|
||||
keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false;
|
||||
#ifdef AUDIO_ENABLE
|
||||
PLAY_SONG(ag_norm_song);
|
||||
#endif
|
||||
break;
|
||||
case QK_MAGIC_UNSWAP_CTL_GUI:
|
||||
keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false;
|
||||
#ifdef AUDIO_ENABLE
|
||||
PLAY_SONG(cg_norm_song);
|
||||
#endif
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_ALT_GUI:
|
||||
keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
|
||||
keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui;
|
||||
#ifdef AUDIO_ENABLE
|
||||
if (keymap_config.swap_ralt_rgui) {
|
||||
PLAY_SONG(ag_swap_song);
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_SWAP_CTL_GUI:
|
||||
keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true;
|
||||
#ifdef AUDIO_ENABLE
|
||||
PLAY_SONG(cg_swap_song);
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_ESCAPE_CAPSLOCK:
|
||||
keymap_config.swap_escape_capslock = false;
|
||||
break;
|
||||
case MAGIC_UNCAPSLOCK_TO_CONTROL:
|
||||
keymap_config.capslock_to_control = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_LALT_LGUI:
|
||||
keymap_config.swap_lalt_lgui = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_RALT_RGUI:
|
||||
keymap_config.swap_ralt_rgui = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_LCTL_LGUI:
|
||||
keymap_config.swap_lctl_lgui = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_RCTL_RGUI:
|
||||
keymap_config.swap_rctl_rgui = false;
|
||||
break;
|
||||
case MAGIC_UNNO_GUI:
|
||||
keymap_config.no_gui = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_GRAVE_ESC:
|
||||
keymap_config.swap_grave_esc = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
|
||||
keymap_config.swap_backslash_backspace = false;
|
||||
break;
|
||||
case MAGIC_UNHOST_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = false;
|
||||
break;
|
||||
case MAGIC_UNSWAP_ALT_GUI:
|
||||
keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false;
|
||||
#ifdef AUDIO_ENABLE
|
||||
} else {
|
||||
PLAY_SONG(ag_norm_song);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_UNSWAP_CTL_GUI:
|
||||
keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false;
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_CTL_GUI:
|
||||
keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui;
|
||||
keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui;
|
||||
#ifdef AUDIO_ENABLE
|
||||
if (keymap_config.swap_rctl_rgui) {
|
||||
PLAY_SONG(cg_swap_song);
|
||||
} else {
|
||||
PLAY_SONG(cg_norm_song);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_TOGGLE_ALT_GUI:
|
||||
keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
|
||||
keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui;
|
||||
#ifdef AUDIO_ENABLE
|
||||
if (keymap_config.swap_ralt_rgui) {
|
||||
PLAY_SONG(ag_swap_song);
|
||||
} else {
|
||||
PLAY_SONG(ag_norm_song);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_TOGGLE_CTL_GUI:
|
||||
keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui;
|
||||
keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui;
|
||||
#ifdef AUDIO_ENABLE
|
||||
if (keymap_config.swap_rctl_rgui) {
|
||||
PLAY_SONG(cg_swap_song);
|
||||
} else {
|
||||
PLAY_SONG(cg_norm_song);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MAGIC_TOGGLE_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = !keymap_config.nkro;
|
||||
break;
|
||||
case MAGIC_EE_HANDS_LEFT:
|
||||
eeconfig_update_handedness(true);
|
||||
break;
|
||||
case MAGIC_EE_HANDS_RIGHT:
|
||||
eeconfig_update_handedness(false);
|
||||
break;
|
||||
case MAGIC_TOGGLE_GUI:
|
||||
keymap_config.no_gui = !keymap_config.no_gui;
|
||||
break;
|
||||
case MAGIC_TOGGLE_CONTROL_CAPSLOCK:
|
||||
keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
|
||||
break;
|
||||
case MAGIC_TOGGLE_ESCAPE_CAPSLOCK:
|
||||
keymap_config.swap_escape_capslock = !keymap_config.swap_escape_capslock;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_BACKSLASH_BACKSPACE:
|
||||
keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_NKRO:
|
||||
clear_keyboard(); // clear first buffer to prevent stuck keys
|
||||
keymap_config.nkro = !keymap_config.nkro;
|
||||
break;
|
||||
case QK_MAGIC_EE_HANDS_LEFT:
|
||||
eeconfig_update_handedness(true);
|
||||
break;
|
||||
case QK_MAGIC_EE_HANDS_RIGHT:
|
||||
eeconfig_update_handedness(false);
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_GUI:
|
||||
keymap_config.no_gui = !keymap_config.no_gui;
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK:
|
||||
keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
|
||||
break;
|
||||
case QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK:
|
||||
keymap_config.swap_escape_capslock = !keymap_config.swap_escape_capslock;
|
||||
break;
|
||||
}
|
||||
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
clear_keyboard(); // clear to prevent stuck keys
|
||||
eeconfig_update_keymap(keymap_config.raw);
|
||||
clear_keyboard(); // clear to prevent stuck keys
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ inline uint8_t compute_velocity(uint8_t setting) {
|
||||
}
|
||||
|
||||
void midi_init(void) {
|
||||
midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
|
||||
midi_config.octave = QK_MIDI_OCTAVE_2 - MIDI_OCTAVE_MIN;
|
||||
midi_config.transpose = 0;
|
||||
midi_config.velocity = 127;
|
||||
midi_config.channel = 0;
|
||||
@ -103,13 +103,13 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
dprintf("midi octave %d\n", midi_config.octave);
|
||||
}
|
||||
return false;
|
||||
case MI_OCTD:
|
||||
case QK_MIDI_OCTAVE_DOWN:
|
||||
if (record->event.pressed && midi_config.octave > 0) {
|
||||
midi_config.octave--;
|
||||
dprintf("midi octave %d\n", midi_config.octave);
|
||||
}
|
||||
return false;
|
||||
case MI_OCTU:
|
||||
case QK_MIDI_OCTAVE_UP:
|
||||
if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
|
||||
midi_config.octave++;
|
||||
dprintf("midi octave %d\n", midi_config.octave);
|
||||
@ -117,18 +117,18 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX:
|
||||
if (record->event.pressed) {
|
||||
midi_config.transpose = keycode - MI_TRNS_0;
|
||||
midi_config.transpose = keycode - QK_MIDI_TRANSPOSE_0;
|
||||
dprintf("midi transpose %d\n", midi_config.transpose);
|
||||
}
|
||||
return false;
|
||||
case MI_TRNSD:
|
||||
if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - MI_TRNS_0)) {
|
||||
case QK_MIDI_TRANSPOSE_DOWN:
|
||||
if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - QK_MIDI_TRANSPOSE_0)) {
|
||||
midi_config.transpose--;
|
||||
dprintf("midi transpose %d\n", midi_config.transpose);
|
||||
}
|
||||
return false;
|
||||
case MI_TRNSU:
|
||||
if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) {
|
||||
case QK_MIDI_TRANSPOSE_UP:
|
||||
if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - QK_MIDI_TRANSPOSE_0)) {
|
||||
const bool positive = midi_config.transpose > 0;
|
||||
midi_config.transpose++;
|
||||
if (positive && midi_config.transpose < 0) midi_config.transpose--;
|
||||
@ -141,7 +141,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
dprintf("midi velocity %d\n", midi_config.velocity);
|
||||
}
|
||||
return false;
|
||||
case MI_VELD:
|
||||
case QK_MIDI_VELOCITY_DOWN:
|
||||
if (record->event.pressed && midi_config.velocity > 0) {
|
||||
if (midi_config.velocity == 127) {
|
||||
midi_config.velocity -= 10;
|
||||
@ -154,7 +154,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
dprintf("midi velocity %d\n", midi_config.velocity);
|
||||
}
|
||||
return false;
|
||||
case MI_VELU:
|
||||
case QK_MIDI_VELOCITY_UP:
|
||||
if (record->event.pressed && midi_config.velocity < 127) {
|
||||
if (midi_config.velocity < 115) {
|
||||
midi_config.velocity += 13;
|
||||
@ -170,48 +170,48 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
dprintf("midi channel %d\n", midi_config.channel);
|
||||
}
|
||||
return false;
|
||||
case MI_CHD:
|
||||
case QK_MIDI_CHANNEL_DOWN:
|
||||
if (record->event.pressed) {
|
||||
midi_config.channel--;
|
||||
dprintf("midi channel %d\n", midi_config.channel);
|
||||
}
|
||||
return false;
|
||||
case MI_CHU:
|
||||
case QK_MIDI_CHANNEL_UP:
|
||||
if (record->event.pressed) {
|
||||
midi_config.channel++;
|
||||
dprintf("midi channel %d\n", midi_config.channel);
|
||||
}
|
||||
return false;
|
||||
case MI_ALLOFF:
|
||||
case QK_MIDI_ALL_NOTES_OFF:
|
||||
if (record->event.pressed) {
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
|
||||
dprintf("midi all notes off\n");
|
||||
}
|
||||
return false;
|
||||
case MI_SUS:
|
||||
case QK_MIDI_SUSTAIN:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi sustain %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_PORT:
|
||||
case QK_MIDI_PORTAMENTO:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi portamento %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_SOST:
|
||||
case QK_MIDI_SOSTENUTO:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi sostenuto %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_SOFT:
|
||||
case QK_MIDI_SOFT:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi soft %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_LEG:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
|
||||
case QK_MIDI_LEGATO:
|
||||
midi_send_cc(&midi_device, midi_config.channel, 0x44, record->event.pressed ? 127 : 0);
|
||||
dprintf("midi legato %d\n", record->event.pressed);
|
||||
return false;
|
||||
case MI_MOD:
|
||||
case QK_MIDI_MODULATION:
|
||||
midi_modulation_step = record->event.pressed ? 1 : -1;
|
||||
return false;
|
||||
case MI_MODSD:
|
||||
case QK_MIDI_MODULATION_SPEED_DOWN:
|
||||
if (record->event.pressed) {
|
||||
midi_config.modulation_interval++;
|
||||
// prevent overflow
|
||||
@ -219,13 +219,13 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
|
||||
}
|
||||
return false;
|
||||
case MI_MODSU:
|
||||
case QK_MIDI_MODULATION_SPEED_UP:
|
||||
if (record->event.pressed && midi_config.modulation_interval > 0) {
|
||||
midi_config.modulation_interval--;
|
||||
dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
|
||||
}
|
||||
return false;
|
||||
case MI_BENDD:
|
||||
case QK_MIDI_PITCH_BEND_DOWN:
|
||||
if (record->event.pressed) {
|
||||
midi_send_pitchbend(&midi_device, midi_config.channel, -0x2000);
|
||||
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, -0x2000);
|
||||
@ -234,7 +234,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
|
||||
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
|
||||
}
|
||||
return false;
|
||||
case MI_BENDU:
|
||||
case QK_MIDI_PITCH_BEND_UP:
|
||||
if (record->event.pressed) {
|
||||
midi_send_pitchbend(&midi_device, midi_config.channel, 0x1fff);
|
||||
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0x1fff);
|
||||
|
@ -101,17 +101,17 @@ void music_all_notes_off(void) {
|
||||
}
|
||||
|
||||
bool process_music(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == MU_ON && record->event.pressed) {
|
||||
if (keycode == QK_MUSIC_ON && record->event.pressed) {
|
||||
music_on();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MU_OFF && record->event.pressed) {
|
||||
if (keycode == QK_MUSIC_OFF && record->event.pressed) {
|
||||
music_off();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MU_TOG && record->event.pressed) {
|
||||
if (keycode == QK_MUSIC_TOGGLE && record->event.pressed) {
|
||||
if (music_activated) {
|
||||
music_off();
|
||||
} else {
|
||||
@ -120,17 +120,17 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MI_ON && record->event.pressed) {
|
||||
if (keycode == QK_MIDI_ON && record->event.pressed) {
|
||||
midi_on();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MI_OFF && record->event.pressed) {
|
||||
if (keycode == QK_MIDI_OFF && record->event.pressed) {
|
||||
midi_off();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MI_TOG && record->event.pressed) {
|
||||
if (keycode == QK_MIDI_TOGGLE && record->event.pressed) {
|
||||
if (midi_activated) {
|
||||
midi_off();
|
||||
} else {
|
||||
@ -139,7 +139,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keycode == MU_MOD && record->event.pressed) {
|
||||
if (keycode == QK_MUSIC_MODE_NEXT && record->event.pressed) {
|
||||
music_mode_cycle();
|
||||
return false;
|
||||
}
|
||||
@ -317,10 +317,10 @@ void music_task(void) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) void music_on_user() {}
|
||||
__attribute__((weak)) void music_on_user(void) {}
|
||||
|
||||
__attribute__((weak)) void midi_on_user() {}
|
||||
__attribute__((weak)) void midi_on_user(void) {}
|
||||
|
||||
__attribute__((weak)) void music_scale_user() {}
|
||||
__attribute__((weak)) void music_scale_user(void) {}
|
||||
|
||||
#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
|
||||
|
@ -1,269 +0,0 @@
|
||||
/* Copyright 2016 Jack Humbert
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "process_printer.h"
|
||||
#include "action_util.h"
|
||||
#include "uart.h"
|
||||
|
||||
bool printing_enabled = false;
|
||||
uint8_t character_shift = 0;
|
||||
|
||||
void enable_printing(void) {
|
||||
printing_enabled = true;
|
||||
uart_init(19200);
|
||||
}
|
||||
|
||||
void disable_printing(void) {
|
||||
printing_enabled = false;
|
||||
}
|
||||
|
||||
uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
|
||||
|
||||
// uint8_t keycode_to_ascii[0xFF][2];
|
||||
|
||||
// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F};
|
||||
|
||||
void print_char(char c) {
|
||||
USB_Disable();
|
||||
uart_write(c);
|
||||
USB_Init();
|
||||
}
|
||||
|
||||
void print_string(char c[]) {
|
||||
for (uint8_t i = 0; i < strlen(c); i++)
|
||||
print_char(c[i]);
|
||||
}
|
||||
|
||||
void print_box_string(const char text[]) {
|
||||
size_t len = strlen(text);
|
||||
char out[len * 3 + 8];
|
||||
out[0] = 0xDA;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
out[i + 1] = 0xC4;
|
||||
}
|
||||
out[len + 1] = 0xBF;
|
||||
out[len + 2] = '\n';
|
||||
|
||||
out[len + 3] = 0xB3;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
out[len + 4 + i] = text[i];
|
||||
}
|
||||
out[len * 2 + 4] = 0xB3;
|
||||
out[len * 2 + 5] = '\n';
|
||||
|
||||
out[len * 2 + 6] = 0xC0;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
out[len * 2 + 7 + i] = 0xC4;
|
||||
}
|
||||
out[len * 3 + 7] = 0xD9;
|
||||
out[len * 3 + 8] = '\n';
|
||||
|
||||
print_string(out);
|
||||
}
|
||||
|
||||
bool process_printer(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == PRINT_ON) {
|
||||
enable_printing();
|
||||
return false;
|
||||
}
|
||||
if (keycode == PRINT_OFF) {
|
||||
disable_printing();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (printing_enabled) {
|
||||
switch (keycode) {
|
||||
case KC_EXLM ... KC_RPRN:
|
||||
case KC_UNDS:
|
||||
case KC_PLUS:
|
||||
case KC_LCBR:
|
||||
case KC_RCBR:
|
||||
case KC_PIPE:
|
||||
case KC_TILD:
|
||||
keycode &= 0xFF;
|
||||
case KC_LEFT_SHIFT:
|
||||
case KC_RIGHT_SHIFT:
|
||||
if (record->event.pressed) {
|
||||
character_shift++;
|
||||
} else {
|
||||
character_shift--;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (keycode) {
|
||||
case KC_F1:
|
||||
if (record->event.pressed) {
|
||||
print_box_string("This is a line of text!");
|
||||
}
|
||||
return false;
|
||||
case KC_ESCAPE:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x1B);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SPACE:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x20);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_A ... KC_Z:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x41 + (keycode - KC_A));
|
||||
} else {
|
||||
print_char(0x61 + (keycode - KC_A));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_1 ... KC_0:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(shifted_numbers[keycode - KC_1]);
|
||||
} else {
|
||||
print_char(0x30 + ((keycode - KC_1 + 1) % 10));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_ENTER:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x0C);
|
||||
} else {
|
||||
print_char(0x0A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BACKSPACE:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x18);
|
||||
} else {
|
||||
print_char(0x1A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_DOT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3E);
|
||||
} else {
|
||||
print_char(0x2E);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_COMMA:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3C);
|
||||
} else {
|
||||
print_char(0x2C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SLASH:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3F);
|
||||
} else {
|
||||
print_char(0x2F);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_QUOTE:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x22);
|
||||
} else {
|
||||
print_char(0x27);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_GRAVE:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7E);
|
||||
} else {
|
||||
print_char(0x60);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_MINUS:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x5F);
|
||||
} else {
|
||||
print_char(0x2D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_EQUAL:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x2B);
|
||||
} else {
|
||||
print_char(0x3D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_LEFT_BRACKET:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7B);
|
||||
} else {
|
||||
print_char(0x5B);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_RIGHT_BRACKET:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7D);
|
||||
} else {
|
||||
print_char(0x5D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BACKSLASH:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7C);
|
||||
} else {
|
||||
print_char(0x5C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/* Copyright 2016 Jack Humbert
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
bool process_printer(uint16_t keycode, keyrecord_t *record);
|
@ -1,270 +0,0 @@
|
||||
/* Copyright 2016 Jack Humbert
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "process_printer.h"
|
||||
#include "action_util.h"
|
||||
|
||||
bool printing_enabled = false;
|
||||
uint8_t character_shift = 0;
|
||||
|
||||
#define SERIAL_PIN_DDR DDRD
|
||||
#define SERIAL_PIN_PORT PORTD
|
||||
#define SERIAL_PIN_MASK _BV(PD3)
|
||||
#define SERIAL_DELAY 52
|
||||
|
||||
inline static void serial_delay(void) {
|
||||
_delay_us(SERIAL_DELAY);
|
||||
}
|
||||
|
||||
inline static void serial_high(void) {
|
||||
SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
|
||||
}
|
||||
|
||||
inline static void serial_low(void) {
|
||||
SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
|
||||
}
|
||||
|
||||
inline static void serial_output(void) {
|
||||
SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
|
||||
}
|
||||
|
||||
void enable_printing() {
|
||||
printing_enabled = true;
|
||||
serial_output();
|
||||
serial_high();
|
||||
}
|
||||
|
||||
void disable_printing() {
|
||||
printing_enabled = false;
|
||||
}
|
||||
|
||||
uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
|
||||
|
||||
// uint8_t keycode_to_ascii[0xFF][2];
|
||||
|
||||
// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F};
|
||||
|
||||
void print_char(char c) {
|
||||
uint8_t b = 8;
|
||||
serial_output();
|
||||
while (b--) {
|
||||
if (c & (1 << b)) {
|
||||
serial_high();
|
||||
} else {
|
||||
serial_low();
|
||||
}
|
||||
serial_delay();
|
||||
}
|
||||
}
|
||||
|
||||
void print_string(char c[]) {
|
||||
for (uint8_t i = 0; i < strlen(c); i++)
|
||||
print_char(c[i]);
|
||||
}
|
||||
|
||||
bool process_printer(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode == PRINT_ON) {
|
||||
enable_printing();
|
||||
return false;
|
||||
}
|
||||
if (keycode == PRINT_OFF) {
|
||||
disable_printing();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (printing_enabled) {
|
||||
switch (keycode) {
|
||||
case KC_EXLM ... KC_RPRN:
|
||||
case KC_UNDS:
|
||||
case KC_PLUS:
|
||||
case KC_LCBR:
|
||||
case KC_RCBR:
|
||||
case KC_PIPE:
|
||||
case KC_TILD:
|
||||
keycode &= 0xFF;
|
||||
case KC_LEFT_SHIFT:
|
||||
case KC_RIGHT_SHIFT:
|
||||
if (record->event.pressed) {
|
||||
character_shift++;
|
||||
} else {
|
||||
character_shift--;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (keycode) {
|
||||
case KC_F1:
|
||||
if (record->event.pressed) {
|
||||
print_string("This is a line of text!\n\n\n");
|
||||
}
|
||||
return false;
|
||||
case KC_ESCAPE:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x1B);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SPACE:
|
||||
if (record->event.pressed) {
|
||||
print_char(0x20);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_A ... KC_Z:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x41 + (keycode - KC_A));
|
||||
} else {
|
||||
print_char(0x61 + (keycode - KC_A));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_1 ... KC_0:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(shifted_numbers[keycode - KC_1]);
|
||||
} else {
|
||||
print_char(0x30 + ((keycode - KC_1 + 1) % 10));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_ENTER:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x0C);
|
||||
} else {
|
||||
print_char(0x0A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BACKSPACE:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x18);
|
||||
} else {
|
||||
print_char(0x1A);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_DOT:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3E);
|
||||
} else {
|
||||
print_char(0x2E);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_COMMA:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3C);
|
||||
} else {
|
||||
print_char(0x2C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_SLASH:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x3F);
|
||||
} else {
|
||||
print_char(0x2F);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_QUOTE:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x22);
|
||||
} else {
|
||||
print_char(0x27);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_GRAVE:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7E);
|
||||
} else {
|
||||
print_char(0x60);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_MINUS:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x5F);
|
||||
} else {
|
||||
print_char(0x2D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_EQUAL:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x2B);
|
||||
} else {
|
||||
print_char(0x3D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_LEFT_BRACKET:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7B);
|
||||
} else {
|
||||
print_char(0x5B);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_RIGHT_BRACKET:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7D);
|
||||
} else {
|
||||
print_char(0x5D);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
case KC_BACKSLASH:
|
||||
if (record->event.pressed) {
|
||||
if (character_shift) {
|
||||
print_char(0x7C);
|
||||
} else {
|
||||
print_char(0x5C);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
@ -19,12 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "programmable_button.h"
|
||||
|
||||
bool process_programmable_button(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) {
|
||||
uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1;
|
||||
if (IS_QK_PROGRAMMABLE_BUTTON(keycode)) {
|
||||
uint8_t button = keycode - QK_PROGRAMMABLE_BUTTON + 1;
|
||||
if (record->event.pressed) {
|
||||
programmable_button_on(button);
|
||||
programmable_button_register(button);
|
||||
} else {
|
||||
programmable_button_off(button);
|
||||
programmable_button_unregister(button);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -23,19 +23,19 @@ bool preprocess_secure(uint16_t keycode, keyrecord_t *record) {
|
||||
bool process_secure(uint16_t keycode, keyrecord_t *record) {
|
||||
#ifndef SECURE_DISABLE_KEYCODES
|
||||
if (!record->event.pressed) {
|
||||
if (keycode == SECURE_LOCK) {
|
||||
if (keycode == QK_SECURE_LOCK) {
|
||||
secure_lock();
|
||||
return false;
|
||||
}
|
||||
if (keycode == SECURE_UNLOCK) {
|
||||
if (keycode == QK_SECURE_UNLOCK) {
|
||||
secure_unlock();
|
||||
return false;
|
||||
}
|
||||
if (keycode == SECURE_TOGGLE) {
|
||||
if (keycode == QK_SECURE_TOGGLE) {
|
||||
secure_is_locked() ? secure_unlock() : secure_lock();
|
||||
return false;
|
||||
}
|
||||
if (keycode == SECURE_REQUEST) {
|
||||
if (keycode == QK_SECURE_REQUEST) {
|
||||
secure_request_unlock();
|
||||
return false;
|
||||
}
|
||||
|
@ -19,39 +19,39 @@
|
||||
bool process_sequencer(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
switch (keycode) {
|
||||
case SQ_ON:
|
||||
case QK_SEQUENCER_ON:
|
||||
sequencer_on();
|
||||
return false;
|
||||
case SQ_OFF:
|
||||
case QK_SEQUENCER_OFF:
|
||||
sequencer_off();
|
||||
return false;
|
||||
case SQ_TOG:
|
||||
case QK_SEQUENCER_TOGGLE:
|
||||
sequencer_toggle();
|
||||
return false;
|
||||
case SQ_TMPD:
|
||||
case QK_SEQUENCER_TEMPO_DOWN:
|
||||
sequencer_decrease_tempo();
|
||||
return false;
|
||||
case SQ_TMPU:
|
||||
case QK_SEQUENCER_TEMPO_UP:
|
||||
sequencer_increase_tempo();
|
||||
return false;
|
||||
case SEQUENCER_RESOLUTION_MIN ... SEQUENCER_RESOLUTION_MAX:
|
||||
sequencer_set_resolution(keycode - SEQUENCER_RESOLUTION_MIN);
|
||||
return false;
|
||||
case SQ_RESD:
|
||||
case QK_SEQUENCER_RESOLUTION_DOWN:
|
||||
sequencer_decrease_resolution();
|
||||
return false;
|
||||
case SQ_RESU:
|
||||
case QK_SEQUENCER_RESOLUTION_UP:
|
||||
sequencer_increase_resolution();
|
||||
return false;
|
||||
case SQ_SALL:
|
||||
case QK_SEQUENCER_STEPS_ALL:
|
||||
sequencer_set_all_steps_on();
|
||||
return false;
|
||||
case SQ_SCLR:
|
||||
case QK_SEQUENCER_STEPS_CLEAR:
|
||||
sequencer_set_all_steps_off();
|
||||
return false;
|
||||
case SEQUENCER_STEP_MIN ... SEQUENCER_STEP_MAX:
|
||||
sequencer_toggle_step(keycode - SEQUENCER_STEP_MIN);
|
||||
return false;
|
||||
case SEQUENCER_RESOLUTION_MIN ... SEQUENCER_RESOLUTION_MAX:
|
||||
sequencer_set_resolution(keycode - SEQUENCER_RESOLUTION_MIN);
|
||||
return false;
|
||||
case SEQUENCER_TRACK_MIN ... SEQUENCER_TRACK_MAX:
|
||||
sequencer_toggle_single_active_track(keycode - SEQUENCER_TRACK_MIN);
|
||||
return false;
|
||||
|
@ -89,16 +89,16 @@ void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdM
|
||||
#ifdef SPACE_CADET_MODIFIER_CARRYOVER
|
||||
sc_mods = get_mods();
|
||||
#endif
|
||||
if (IS_MOD(holdMod)) {
|
||||
if (IS_MODIFIER_KEYCODE(holdMod)) {
|
||||
register_mods(MOD_BIT(holdMod));
|
||||
}
|
||||
} else {
|
||||
if (sc_last == holdMod && timer_elapsed(sc_timer) < GET_TAPPING_TERM(sc_keycode, record)) {
|
||||
if (holdMod != tapMod) {
|
||||
if (IS_MOD(holdMod)) {
|
||||
if (IS_MODIFIER_KEYCODE(holdMod)) {
|
||||
unregister_mods(MOD_BIT(holdMod));
|
||||
}
|
||||
if (IS_MOD(tapMod)) {
|
||||
if (IS_MODIFIER_KEYCODE(tapMod)) {
|
||||
register_mods(MOD_BIT(tapMod));
|
||||
}
|
||||
}
|
||||
@ -109,11 +109,11 @@ void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdM
|
||||
#ifdef SPACE_CADET_MODIFIER_CARRYOVER
|
||||
clear_weak_mods();
|
||||
#endif
|
||||
if (IS_MOD(tapMod)) {
|
||||
if (IS_MODIFIER_KEYCODE(tapMod)) {
|
||||
unregister_mods(MOD_BIT(tapMod));
|
||||
}
|
||||
} else {
|
||||
if (IS_MOD(holdMod)) {
|
||||
if (IS_MODIFIER_KEYCODE(holdMod)) {
|
||||
unregister_mods(MOD_BIT(holdMod));
|
||||
}
|
||||
}
|
||||
@ -122,31 +122,31 @@ void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdM
|
||||
|
||||
bool process_space_cadet(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case KC_LSPO: {
|
||||
case QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN: {
|
||||
perform_space_cadet(record, keycode, LSPO_KEYS);
|
||||
return false;
|
||||
}
|
||||
case KC_RSPC: {
|
||||
case QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE: {
|
||||
perform_space_cadet(record, keycode, RSPC_KEYS);
|
||||
return false;
|
||||
}
|
||||
case KC_LCPO: {
|
||||
case QK_SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN: {
|
||||
perform_space_cadet(record, keycode, LCPO_KEYS);
|
||||
return false;
|
||||
}
|
||||
case KC_RCPC: {
|
||||
case QK_SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE: {
|
||||
perform_space_cadet(record, keycode, RCPC_KEYS);
|
||||
return false;
|
||||
}
|
||||
case KC_LAPO: {
|
||||
case QK_SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN: {
|
||||
perform_space_cadet(record, keycode, LAPO_KEYS);
|
||||
return false;
|
||||
}
|
||||
case KC_RAPC: {
|
||||
case QK_SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE: {
|
||||
perform_space_cadet(record, keycode, RAPC_KEYS);
|
||||
return false;
|
||||
}
|
||||
case KC_SFTENT: {
|
||||
case QK_SPACE_CADET_RIGHT_SHIFT_ENTER: {
|
||||
perform_space_cadet(record, keycode, SFTENT_KEYS);
|
||||
return false;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, ST
|
||||
#endif
|
||||
|
||||
#ifdef STENO_ENABLE_ALL
|
||||
void steno_init() {
|
||||
void steno_init(void) {
|
||||
if (!eeconfig_is_enabled()) {
|
||||
eeconfig_init();
|
||||
}
|
||||
|
@ -18,8 +18,8 @@
|
||||
static uint16_t active_td;
|
||||
static uint16_t last_tap_time;
|
||||
|
||||
void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
|
||||
void tap_dance_pair_on_each_tap(tap_dance_state_t *state, void *user_data) {
|
||||
tap_dance_pair_t *pair = (tap_dance_pair_t *)user_data;
|
||||
|
||||
if (state->count == 2) {
|
||||
register_code16(pair->kc2);
|
||||
@ -27,14 +27,14 @@ void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
|
||||
void tap_dance_pair_finished(tap_dance_state_t *state, void *user_data) {
|
||||
tap_dance_pair_t *pair = (tap_dance_pair_t *)user_data;
|
||||
|
||||
register_code16(pair->kc1);
|
||||
}
|
||||
|
||||
void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
|
||||
void tap_dance_pair_reset(tap_dance_state_t *state, void *user_data) {
|
||||
tap_dance_pair_t *pair = (tap_dance_pair_t *)user_data;
|
||||
|
||||
if (state->count == 1) {
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
@ -44,8 +44,8 @@ void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
}
|
||||
}
|
||||
|
||||
void qk_tap_dance_dual_role_on_each_tap(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data;
|
||||
void tap_dance_dual_role_on_each_tap(tap_dance_state_t *state, void *user_data) {
|
||||
tap_dance_dual_role_t *pair = (tap_dance_dual_role_t *)user_data;
|
||||
|
||||
if (state->count == 2) {
|
||||
layer_move(pair->layer);
|
||||
@ -53,8 +53,8 @@ void qk_tap_dance_dual_role_on_each_tap(qk_tap_dance_state_t *state, void *user_
|
||||
}
|
||||
}
|
||||
|
||||
void qk_tap_dance_dual_role_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data;
|
||||
void tap_dance_dual_role_finished(tap_dance_state_t *state, void *user_data) {
|
||||
tap_dance_dual_role_t *pair = (tap_dance_dual_role_t *)user_data;
|
||||
|
||||
if (state->count == 1) {
|
||||
register_code16(pair->kc);
|
||||
@ -63,8 +63,8 @@ void qk_tap_dance_dual_role_finished(qk_tap_dance_state_t *state, void *user_dat
|
||||
}
|
||||
}
|
||||
|
||||
void qk_tap_dance_dual_role_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data;
|
||||
void tap_dance_dual_role_reset(tap_dance_state_t *state, void *user_data) {
|
||||
tap_dance_dual_role_t *pair = (tap_dance_dual_role_t *)user_data;
|
||||
|
||||
if (state->count == 1) {
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
@ -72,13 +72,13 @@ void qk_tap_dance_dual_role_reset(qk_tap_dance_state_t *state, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _process_tap_dance_action_fn(qk_tap_dance_state_t *state, void *user_data, qk_tap_dance_user_fn_t fn) {
|
||||
static inline void _process_tap_dance_action_fn(tap_dance_state_t *state, void *user_data, tap_dance_user_fn_t fn) {
|
||||
if (fn) {
|
||||
fn(state, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void process_tap_dance_action_on_each_tap(qk_tap_dance_action_t *action) {
|
||||
static inline void process_tap_dance_action_on_each_tap(tap_dance_action_t *action) {
|
||||
action->state.count++;
|
||||
action->state.weak_mods = get_mods();
|
||||
action->state.weak_mods |= get_weak_mods();
|
||||
@ -88,17 +88,17 @@ static inline void process_tap_dance_action_on_each_tap(qk_tap_dance_action_t *a
|
||||
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap);
|
||||
}
|
||||
|
||||
static inline void process_tap_dance_action_on_reset(qk_tap_dance_action_t *action) {
|
||||
static inline void process_tap_dance_action_on_reset(tap_dance_action_t *action) {
|
||||
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset);
|
||||
del_weak_mods(action->state.weak_mods);
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
del_mods(action->state.oneshot_mods);
|
||||
#endif
|
||||
send_keyboard_report();
|
||||
action->state = (const qk_tap_dance_state_t){0};
|
||||
action->state = (const tap_dance_state_t){0};
|
||||
}
|
||||
|
||||
void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
|
||||
void process_tap_dance_action_on_dance_finished(tap_dance_action_t *action) {
|
||||
if (!action->state.finished) {
|
||||
action->state.finished = true;
|
||||
add_weak_mods(action->state.weak_mods);
|
||||
@ -115,12 +115,12 @@ void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
|
||||
}
|
||||
}
|
||||
|
||||
void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
qk_tap_dance_action_t *action;
|
||||
bool preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
tap_dance_action_t *action;
|
||||
|
||||
if (!record->event.pressed) return;
|
||||
if (!record->event.pressed) return false;
|
||||
|
||||
if (!active_td || keycode == active_td) return;
|
||||
if (!active_td || keycode == active_td) return false;
|
||||
|
||||
action = &tap_dance_actions[TD_INDEX(active_td)];
|
||||
action->state.interrupted = true;
|
||||
@ -130,10 +130,16 @@ void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
// Tap dance actions can leave some weak mods active (e.g., if the tap dance is mapped to a keycode with
|
||||
// modifiers), but these weak mods should not affect the keypress which interrupted the tap dance.
|
||||
clear_weak_mods();
|
||||
|
||||
// Signal that a tap dance has been finished due to being interrupted,
|
||||
// therefore the keymap lookup for the currently processed event needs to
|
||||
// be repeated with the current layer state that might have been updated by
|
||||
// the finished tap dance.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
qk_tap_dance_action_t *action;
|
||||
tap_dance_action_t *action;
|
||||
|
||||
switch (keycode) {
|
||||
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
|
||||
@ -156,8 +162,8 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void tap_dance_task() {
|
||||
qk_tap_dance_action_t *action;
|
||||
void tap_dance_task(void) {
|
||||
tap_dance_action_t *action;
|
||||
|
||||
if (!active_td || timer_elapsed(last_tap_time) <= GET_TAPPING_TERM(active_td, &(keyrecord_t){})) return;
|
||||
|
||||
@ -167,7 +173,7 @@ void tap_dance_task() {
|
||||
}
|
||||
}
|
||||
|
||||
void reset_tap_dance(qk_tap_dance_state_t *state) {
|
||||
void reset_tap_dance(tap_dance_state_t *state) {
|
||||
active_td = 0;
|
||||
process_tap_dance_action_on_reset((qk_tap_dance_action_t *)state);
|
||||
process_tap_dance_action_on_reset((tap_dance_action_t *)state);
|
||||
}
|
||||
|
@ -31,39 +31,39 @@ typedef struct {
|
||||
bool pressed : 1;
|
||||
bool finished : 1;
|
||||
bool interrupted : 1;
|
||||
} qk_tap_dance_state_t;
|
||||
} tap_dance_state_t;
|
||||
|
||||
typedef void (*qk_tap_dance_user_fn_t)(qk_tap_dance_state_t *state, void *user_data);
|
||||
typedef void (*tap_dance_user_fn_t)(tap_dance_state_t *state, void *user_data);
|
||||
|
||||
typedef struct {
|
||||
qk_tap_dance_state_t state;
|
||||
tap_dance_state_t state;
|
||||
struct {
|
||||
qk_tap_dance_user_fn_t on_each_tap;
|
||||
qk_tap_dance_user_fn_t on_dance_finished;
|
||||
qk_tap_dance_user_fn_t on_reset;
|
||||
tap_dance_user_fn_t on_each_tap;
|
||||
tap_dance_user_fn_t on_dance_finished;
|
||||
tap_dance_user_fn_t on_reset;
|
||||
} fn;
|
||||
void *user_data;
|
||||
} qk_tap_dance_action_t;
|
||||
} tap_dance_action_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t kc1;
|
||||
uint16_t kc2;
|
||||
} qk_tap_dance_pair_t;
|
||||
} tap_dance_pair_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t kc;
|
||||
uint8_t layer;
|
||||
void (*layer_function)(uint8_t);
|
||||
} qk_tap_dance_dual_role_t;
|
||||
} tap_dance_dual_role_t;
|
||||
|
||||
# define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \
|
||||
{ .fn = {qk_tap_dance_pair_on_each_tap, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset}, .user_data = (void *)&((qk_tap_dance_pair_t){kc1, kc2}), }
|
||||
{ .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \
|
||||
{ .fn = {qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer, layer_move}), }
|
||||
{ .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \
|
||||
{ .fn = {NULL, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer, layer_invert}), }
|
||||
{ .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), }
|
||||
|
||||
# define ACTION_TAP_DANCE_FN(user_fn) \
|
||||
{ .fn = {NULL, user_fn, NULL}, .user_data = NULL, }
|
||||
@ -73,25 +73,25 @@ typedef struct {
|
||||
|
||||
# define TD(n) (QK_TAP_DANCE | TD_INDEX(n))
|
||||
# define TD_INDEX(code) ((code)&0xFF)
|
||||
# define TAP_DANCE_KEYCODE(state) TD(((qk_tap_dance_action_t *)state) - tap_dance_actions)
|
||||
# define TAP_DANCE_KEYCODE(state) TD(((tap_dance_action_t *)state) - tap_dance_actions)
|
||||
|
||||
extern qk_tap_dance_action_t tap_dance_actions[];
|
||||
extern tap_dance_action_t tap_dance_actions[];
|
||||
|
||||
void reset_tap_dance(qk_tap_dance_state_t *state);
|
||||
void reset_tap_dance(tap_dance_state_t *state);
|
||||
|
||||
/* To be used internally */
|
||||
|
||||
void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record);
|
||||
bool preprocess_tap_dance(uint16_t keycode, keyrecord_t *record);
|
||||
bool process_tap_dance(uint16_t keycode, keyrecord_t *record);
|
||||
void tap_dance_task(void);
|
||||
|
||||
void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data);
|
||||
void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data);
|
||||
void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data);
|
||||
void tap_dance_pair_on_each_tap(tap_dance_state_t *state, void *user_data);
|
||||
void tap_dance_pair_finished(tap_dance_state_t *state, void *user_data);
|
||||
void tap_dance_pair_reset(tap_dance_state_t *state, void *user_data);
|
||||
|
||||
void qk_tap_dance_dual_role_on_each_tap(qk_tap_dance_state_t *state, void *user_data);
|
||||
void qk_tap_dance_dual_role_finished(qk_tap_dance_state_t *state, void *user_data);
|
||||
void qk_tap_dance_dual_role_reset(qk_tap_dance_state_t *state, void *user_data);
|
||||
void tap_dance_dual_role_on_each_tap(tap_dance_state_t *state, void *user_data);
|
||||
void tap_dance_dual_role_finished(tap_dance_state_t *state, void *user_data);
|
||||
void tap_dance_dual_role_reset(tap_dance_state_t *state, void *user_data);
|
||||
|
||||
#else
|
||||
|
||||
|
30
quantum/process_keycode/process_tri_layer.c
Normal file
30
quantum/process_keycode/process_tri_layer.c
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "process_tri_layer.h"
|
||||
#include "tri_layer.h"
|
||||
#include "action_layer.h"
|
||||
|
||||
bool process_tri_layer(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case QK_TRI_LAYER_LOWER:
|
||||
if (record->event.pressed) {
|
||||
layer_on(get_tri_layer_lower_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
} else {
|
||||
layer_off(get_tri_layer_lower_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
}
|
||||
return false;
|
||||
case QK_TRI_LAYER_UPPER:
|
||||
if (record->event.pressed) {
|
||||
layer_on(get_tri_layer_upper_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
} else {
|
||||
layer_off(get_tri_layer_upper_layer());
|
||||
update_tri_layer(get_tri_layer_lower_layer(), get_tri_layer_upper_layer(), get_tri_layer_adjust_layer());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
16
quantum/process_keycode/process_tri_layer.h
Normal file
16
quantum/process_keycode/process_tri_layer.h
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "action.h"
|
||||
|
||||
/**
|
||||
* @brief Handles tri layer behavior
|
||||
*
|
||||
* @param keycode the keycode
|
||||
* @param record the key record structure
|
||||
* @return true continue handling keycodes
|
||||
* @return false stop handling keycodes
|
||||
*/
|
||||
bool process_tri_layer(uint16_t keycode, keyrecord_t *record);
|
@ -15,23 +15,24 @@
|
||||
*/
|
||||
|
||||
#include "process_ucis.h"
|
||||
#include "unicode.h"
|
||||
#include "keycode.h"
|
||||
#include "wait.h"
|
||||
|
||||
qk_ucis_state_t qk_ucis_state;
|
||||
ucis_state_t ucis_state;
|
||||
|
||||
void qk_ucis_start(void) {
|
||||
qk_ucis_state.count = 0;
|
||||
qk_ucis_state.in_progress = true;
|
||||
void ucis_start(void) {
|
||||
ucis_state.count = 0;
|
||||
ucis_state.in_progress = true;
|
||||
|
||||
qk_ucis_start_user();
|
||||
ucis_start_user();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void qk_ucis_start_user(void) {
|
||||
unicode_input_start();
|
||||
register_hex(0x2328); // ⌨
|
||||
unicode_input_finish();
|
||||
__attribute__((weak)) void ucis_start_user(void) {
|
||||
register_unicode(0x2328); // ⌨
|
||||
}
|
||||
|
||||
__attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {}
|
||||
__attribute__((weak)) void ucis_success(uint8_t symbol_index) {}
|
||||
|
||||
static bool is_uni_seq(char *seq) {
|
||||
uint8_t i;
|
||||
@ -42,66 +43,60 @@ static bool is_uni_seq(char *seq) {
|
||||
} else {
|
||||
keycode = seq[i] - 'a' + KC_A;
|
||||
}
|
||||
if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != keycode) {
|
||||
if (i > ucis_state.count || ucis_state.codes[i] != keycode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return qk_ucis_state.codes[i] == KC_ENTER || qk_ucis_state.codes[i] == KC_SPACE;
|
||||
return ucis_state.codes[i] == KC_ENTER || ucis_state.codes[i] == KC_SPACE;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
|
||||
for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
|
||||
uint8_t keycode = qk_ucis_state.codes[i];
|
||||
register_code(keycode);
|
||||
unregister_code(keycode);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
__attribute__((weak)) void ucis_symbol_fallback(void) {
|
||||
for (uint8_t i = 0; i < ucis_state.count - 1; i++) {
|
||||
tap_code(ucis_state.codes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) void qk_ucis_cancel(void) {}
|
||||
__attribute__((weak)) void ucis_cancel(void) {}
|
||||
|
||||
void register_ucis(const uint32_t *code_points) {
|
||||
for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) {
|
||||
register_unicode(code_points[i]);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
bool process_ucis(uint16_t keycode, keyrecord_t *record) {
|
||||
if (!qk_ucis_state.in_progress || !record->event.pressed) {
|
||||
if (!ucis_state.in_progress || !record->event.pressed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool special = keycode == KC_SPACE || keycode == KC_ENTER || keycode == KC_ESCAPE || keycode == KC_BACKSPACE;
|
||||
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
|
||||
if (ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
qk_ucis_state.codes[qk_ucis_state.count] = keycode;
|
||||
qk_ucis_state.count++;
|
||||
ucis_state.codes[ucis_state.count] = keycode;
|
||||
ucis_state.count++;
|
||||
|
||||
switch (keycode) {
|
||||
case KC_BACKSPACE:
|
||||
if (qk_ucis_state.count >= 2) {
|
||||
qk_ucis_state.count -= 2;
|
||||
if (ucis_state.count >= 2) {
|
||||
ucis_state.count -= 2;
|
||||
return true;
|
||||
} else {
|
||||
qk_ucis_state.count--;
|
||||
ucis_state.count--;
|
||||
return false;
|
||||
}
|
||||
|
||||
case KC_SPACE:
|
||||
case KC_ENTER:
|
||||
case KC_ESCAPE:
|
||||
for (uint8_t i = 0; i < qk_ucis_state.count; i++) {
|
||||
register_code(KC_BACKSPACE);
|
||||
unregister_code(KC_BACKSPACE);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
for (uint8_t i = 0; i < ucis_state.count; i++) {
|
||||
tap_code(KC_BACKSPACE);
|
||||
}
|
||||
|
||||
if (keycode == KC_ESCAPE) {
|
||||
qk_ucis_state.in_progress = false;
|
||||
qk_ucis_cancel();
|
||||
ucis_state.in_progress = false;
|
||||
ucis_cancel();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -115,12 +110,12 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
}
|
||||
if (symbol_found) {
|
||||
qk_ucis_success(i);
|
||||
ucis_success(i);
|
||||
} else {
|
||||
qk_ucis_symbol_fallback();
|
||||
ucis_symbol_fallback();
|
||||
}
|
||||
|
||||
qk_ucis_state.in_progress = false;
|
||||
ucis_state.in_progress = false;
|
||||
return false;
|
||||
|
||||
default:
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
#include "process_unicode_common.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "action.h"
|
||||
|
||||
#ifndef UCIS_MAX_SYMBOL_LENGTH
|
||||
# define UCIS_MAX_SYMBOL_LENGTH 32
|
||||
@ -29,15 +31,15 @@
|
||||
typedef struct {
|
||||
char * symbol;
|
||||
uint32_t code_points[UCIS_MAX_CODE_POINTS];
|
||||
} qk_ucis_symbol_t;
|
||||
} ucis_symbol_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t count;
|
||||
uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
|
||||
bool in_progress : 1;
|
||||
} qk_ucis_state_t;
|
||||
} ucis_state_t;
|
||||
|
||||
extern qk_ucis_state_t qk_ucis_state;
|
||||
extern ucis_state_t ucis_state;
|
||||
|
||||
// clang-format off
|
||||
|
||||
@ -51,12 +53,12 @@ extern qk_ucis_state_t qk_ucis_state;
|
||||
|
||||
// clang-format on
|
||||
|
||||
extern const qk_ucis_symbol_t ucis_symbol_table[];
|
||||
extern const ucis_symbol_t ucis_symbol_table[];
|
||||
|
||||
void qk_ucis_start(void);
|
||||
void qk_ucis_start_user(void);
|
||||
void qk_ucis_symbol_fallback(void);
|
||||
void qk_ucis_success(uint8_t symbol_index);
|
||||
void ucis_start(void);
|
||||
void ucis_start_user(void);
|
||||
void ucis_symbol_fallback(void);
|
||||
void ucis_success(uint8_t symbol_index);
|
||||
|
||||
void register_ucis(const uint32_t *code_points);
|
||||
|
||||
|
@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
#include "process_unicode.h"
|
||||
#include "action_util.h"
|
||||
#include "eeprom.h"
|
||||
#include "unicode.h"
|
||||
#include "quantum_keycodes.h"
|
||||
|
||||
bool process_unicode(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode >= QK_UNICODE && keycode <= QK_UNICODE_MAX && record->event.pressed) {
|
||||
unicode_input_start();
|
||||
register_hex(keycode & 0x7FFF);
|
||||
unicode_input_finish();
|
||||
if (record->event.pressed) {
|
||||
if (keycode >= QK_UNICODE && keycode <= QK_UNICODE_MAX) {
|
||||
register_unicode(QK_UNICODE_GET_CODE_POINT(keycode));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "process_unicode_common.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "action.h"
|
||||
|
||||
bool process_unicode(uint16_t keycode, keyrecord_t *record);
|
||||
|
@ -15,325 +15,45 @@
|
||||
*/
|
||||
|
||||
#include "process_unicode_common.h"
|
||||
#include "eeprom.h"
|
||||
#include "utf8.h"
|
||||
#include "unicode.h"
|
||||
#include "action_util.h"
|
||||
#include "keycode.h"
|
||||
|
||||
unicode_config_t unicode_config;
|
||||
uint8_t unicode_saved_mods;
|
||||
bool unicode_saved_caps_lock;
|
||||
bool unicode_saved_num_lock;
|
||||
|
||||
#if UNICODE_SELECTED_MODES != -1
|
||||
static uint8_t selected[] = {UNICODE_SELECTED_MODES};
|
||||
static int8_t selected_count = sizeof selected / sizeof *selected;
|
||||
static int8_t selected_index;
|
||||
#if defined(UNICODE_ENABLE)
|
||||
# include "process_unicode.h"
|
||||
#elif defined(UNICODEMAP_ENABLE)
|
||||
# include "process_unicodemap.h"
|
||||
#elif defined(UCIS_ENABLE)
|
||||
# include "process_ucis.h"
|
||||
#endif
|
||||
|
||||
void unicode_input_mode_init(void) {
|
||||
unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE);
|
||||
#if UNICODE_SELECTED_MODES != -1
|
||||
# if UNICODE_CYCLE_PERSIST
|
||||
// Find input_mode in selected modes
|
||||
int8_t i;
|
||||
for (i = 0; i < selected_count; i++) {
|
||||
if (selected[i] == unicode_config.input_mode) {
|
||||
selected_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == selected_count) {
|
||||
// Not found: input_mode isn't selected, change to one that is
|
||||
unicode_config.input_mode = selected[selected_index = 0];
|
||||
}
|
||||
# else
|
||||
// Always change to the first selected input mode
|
||||
unicode_config.input_mode = selected[selected_index = 0];
|
||||
# endif
|
||||
#endif
|
||||
dprintf("Unicode input mode init to: %u\n", unicode_config.input_mode);
|
||||
}
|
||||
|
||||
uint8_t get_unicode_input_mode(void) {
|
||||
return unicode_config.input_mode;
|
||||
}
|
||||
|
||||
void set_unicode_input_mode(uint8_t mode) {
|
||||
unicode_config.input_mode = mode;
|
||||
persist_unicode_input_mode();
|
||||
dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
|
||||
}
|
||||
|
||||
void cycle_unicode_input_mode(int8_t offset) {
|
||||
#if UNICODE_SELECTED_MODES != -1
|
||||
selected_index = (selected_index + offset) % selected_count;
|
||||
if (selected_index < 0) {
|
||||
selected_index += selected_count;
|
||||
}
|
||||
unicode_config.input_mode = selected[selected_index];
|
||||
# if UNICODE_CYCLE_PERSIST
|
||||
persist_unicode_input_mode();
|
||||
# endif
|
||||
dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void persist_unicode_input_mode(void) {
|
||||
eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void unicode_input_start(void) {
|
||||
unicode_saved_caps_lock = host_keyboard_led_state().caps_lock;
|
||||
unicode_saved_num_lock = host_keyboard_led_state().num_lock;
|
||||
|
||||
// Note the order matters here!
|
||||
// Need to do this before we mess around with the mods, or else
|
||||
// UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work
|
||||
// correctly in the shifted case.
|
||||
if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) {
|
||||
tap_code(KC_CAPS_LOCK);
|
||||
}
|
||||
|
||||
unicode_saved_mods = get_mods(); // Save current mods
|
||||
clear_mods(); // Unregister mods to start from a clean state
|
||||
clear_weak_mods();
|
||||
|
||||
switch (unicode_config.input_mode) {
|
||||
case UC_MAC:
|
||||
register_code(UNICODE_KEY_MAC);
|
||||
break;
|
||||
case UC_LNX:
|
||||
tap_code16(UNICODE_KEY_LNX);
|
||||
break;
|
||||
case UC_WIN:
|
||||
// For increased reliability, use numpad keys for inputting digits
|
||||
if (!unicode_saved_num_lock) {
|
||||
tap_code(KC_NUM_LOCK);
|
||||
}
|
||||
register_code(KC_LEFT_ALT);
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
tap_code(KC_KP_PLUS);
|
||||
break;
|
||||
case UC_WINC:
|
||||
tap_code(UNICODE_KEY_WINC);
|
||||
tap_code(KC_U);
|
||||
break;
|
||||
case UC_EMACS:
|
||||
// The usual way to type unicode in emacs is C-x-8 <RET> then the unicode number in hex
|
||||
tap_code16(LCTL(KC_X));
|
||||
tap_code16(KC_8);
|
||||
tap_code16(KC_ENTER);
|
||||
break;
|
||||
}
|
||||
|
||||
wait_ms(UNICODE_TYPE_DELAY);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void unicode_input_finish(void) {
|
||||
switch (unicode_config.input_mode) {
|
||||
case UC_MAC:
|
||||
unregister_code(UNICODE_KEY_MAC);
|
||||
break;
|
||||
case UC_LNX:
|
||||
tap_code(KC_SPACE);
|
||||
if (unicode_saved_caps_lock) {
|
||||
tap_code(KC_CAPS_LOCK);
|
||||
}
|
||||
break;
|
||||
case UC_WIN:
|
||||
unregister_code(KC_LEFT_ALT);
|
||||
if (!unicode_saved_num_lock) {
|
||||
tap_code(KC_NUM_LOCK);
|
||||
}
|
||||
break;
|
||||
case UC_WINC:
|
||||
tap_code(KC_ENTER);
|
||||
break;
|
||||
case UC_EMACS:
|
||||
tap_code16(KC_ENTER);
|
||||
break;
|
||||
}
|
||||
|
||||
set_mods(unicode_saved_mods); // Reregister previously set mods
|
||||
}
|
||||
|
||||
__attribute__((weak)) void unicode_input_cancel(void) {
|
||||
switch (unicode_config.input_mode) {
|
||||
case UC_MAC:
|
||||
unregister_code(UNICODE_KEY_MAC);
|
||||
break;
|
||||
case UC_LNX:
|
||||
tap_code(KC_ESCAPE);
|
||||
if (unicode_saved_caps_lock) {
|
||||
tap_code(KC_CAPS_LOCK);
|
||||
}
|
||||
break;
|
||||
case UC_WINC:
|
||||
tap_code(KC_ESCAPE);
|
||||
break;
|
||||
case UC_WIN:
|
||||
unregister_code(KC_LEFT_ALT);
|
||||
if (!unicode_saved_num_lock) {
|
||||
tap_code(KC_NUM_LOCK);
|
||||
}
|
||||
break;
|
||||
case UC_EMACS:
|
||||
tap_code16(LCTL(KC_G)); // C-g cancels
|
||||
break;
|
||||
}
|
||||
|
||||
set_mods(unicode_saved_mods); // Reregister previously set mods
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
static void send_nibble_wrapper(uint8_t digit) {
|
||||
if (unicode_config.input_mode == UC_WIN) {
|
||||
uint8_t kc = digit < 10
|
||||
? KC_KP_1 + (10 + digit - 1) % 10
|
||||
: KC_A + (digit - 10);
|
||||
tap_code(kc);
|
||||
return;
|
||||
}
|
||||
send_nibble(digit);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
void register_hex(uint16_t hex) {
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
uint8_t digit = ((hex >> (i * 4)) & 0xF);
|
||||
send_nibble_wrapper(digit);
|
||||
}
|
||||
}
|
||||
|
||||
void register_hex32(uint32_t hex) {
|
||||
bool onzerostart = true;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
if (i <= 3) {
|
||||
onzerostart = false;
|
||||
}
|
||||
uint8_t digit = ((hex >> (i * 4)) & 0xF);
|
||||
if (digit == 0) {
|
||||
if (!onzerostart) {
|
||||
send_nibble_wrapper(digit);
|
||||
}
|
||||
} else {
|
||||
send_nibble_wrapper(digit);
|
||||
onzerostart = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void register_unicode(uint32_t code_point) {
|
||||
if (code_point > 0x10FFFF || (code_point > 0xFFFF && unicode_config.input_mode == UC_WIN)) {
|
||||
// Code point out of range, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
unicode_input_start();
|
||||
if (code_point > 0xFFFF && unicode_config.input_mode == UC_MAC) {
|
||||
// Convert code point to UTF-16 surrogate pair on macOS
|
||||
code_point -= 0x10000;
|
||||
uint32_t lo = code_point & 0x3FF, hi = (code_point & 0xFFC00) >> 10;
|
||||
register_hex32(hi + 0xD800);
|
||||
register_hex32(lo + 0xDC00);
|
||||
} else {
|
||||
register_hex32(code_point);
|
||||
}
|
||||
unicode_input_finish();
|
||||
}
|
||||
|
||||
void send_unicode_string(const char *str) {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (*str) {
|
||||
int32_t code_point = 0;
|
||||
str = decode_utf8(str, &code_point);
|
||||
|
||||
if (code_point >= 0) {
|
||||
register_unicode(code_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
static void audio_helper(void) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
switch (get_unicode_input_mode()) {
|
||||
# ifdef UNICODE_SONG_MAC
|
||||
static float song_mac[][2] = UNICODE_SONG_MAC;
|
||||
case UC_MAC:
|
||||
PLAY_SONG(song_mac);
|
||||
break;
|
||||
# endif
|
||||
# ifdef UNICODE_SONG_LNX
|
||||
static float song_lnx[][2] = UNICODE_SONG_LNX;
|
||||
case UC_LNX:
|
||||
PLAY_SONG(song_lnx);
|
||||
break;
|
||||
# endif
|
||||
# ifdef UNICODE_SONG_WIN
|
||||
static float song_win[][2] = UNICODE_SONG_WIN;
|
||||
case UC_WIN:
|
||||
PLAY_SONG(song_win);
|
||||
break;
|
||||
# endif
|
||||
# ifdef UNICODE_SONG_BSD
|
||||
static float song_bsd[][2] = UNICODE_SONG_BSD;
|
||||
case UC_BSD:
|
||||
PLAY_SONG(song_bsd);
|
||||
break;
|
||||
# endif
|
||||
# ifdef UNICODE_SONG_WINC
|
||||
static float song_winc[][2] = UNICODE_SONG_WINC;
|
||||
case UC_WINC:
|
||||
PLAY_SONG(song_winc);
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
bool shifted = get_mods() & MOD_MASK_SHIFT;
|
||||
switch (keycode) {
|
||||
case UNICODE_MODE_FORWARD:
|
||||
case QK_UNICODE_MODE_NEXT:
|
||||
cycle_unicode_input_mode(shifted ? -1 : +1);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_REVERSE:
|
||||
case QK_UNICODE_MODE_PREVIOUS:
|
||||
cycle_unicode_input_mode(shifted ? +1 : -1);
|
||||
audio_helper();
|
||||
break;
|
||||
case UNICODE_MODE_MAC:
|
||||
set_unicode_input_mode(UC_MAC);
|
||||
audio_helper();
|
||||
case QK_UNICODE_MODE_MACOS:
|
||||
set_unicode_input_mode(UNICODE_MODE_MACOS);
|
||||
break;
|
||||
case UNICODE_MODE_LNX:
|
||||
set_unicode_input_mode(UC_LNX);
|
||||
audio_helper();
|
||||
case QK_UNICODE_MODE_LINUX:
|
||||
set_unicode_input_mode(UNICODE_MODE_LINUX);
|
||||
break;
|
||||
case UNICODE_MODE_WIN:
|
||||
set_unicode_input_mode(UC_WIN);
|
||||
audio_helper();
|
||||
case QK_UNICODE_MODE_WINDOWS:
|
||||
set_unicode_input_mode(UNICODE_MODE_WINDOWS);
|
||||
break;
|
||||
case UNICODE_MODE_BSD:
|
||||
set_unicode_input_mode(UC_BSD);
|
||||
audio_helper();
|
||||
case QK_UNICODE_MODE_BSD:
|
||||
set_unicode_input_mode(UNICODE_MODE_BSD);
|
||||
break;
|
||||
case UNICODE_MODE_WINC:
|
||||
set_unicode_input_mode(UC_WINC);
|
||||
audio_helper();
|
||||
case QK_UNICODE_MODE_WINCOMPOSE:
|
||||
set_unicode_input_mode(UNICODE_MODE_WINCOMPOSE);
|
||||
break;
|
||||
case UNICODE_MODE_EMACS:
|
||||
set_unicode_input_mode(UC_EMACS);
|
||||
audio_helper();
|
||||
case QK_UNICODE_MODE_EMACS:
|
||||
set_unicode_input_mode(UNICODE_MODE_EMACS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -16,187 +16,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(UNICODE_ENABLE) + defined(UNICODEMAP_ENABLE) + defined(UCIS_ENABLE) > 1
|
||||
# error "Cannot enable more than one Unicode method (UNICODE, UNICODEMAP, UCIS) at the same time"
|
||||
#endif
|
||||
|
||||
// Keycodes used for starting Unicode input on different platforms
|
||||
#ifndef UNICODE_KEY_MAC
|
||||
# define UNICODE_KEY_MAC KC_LEFT_ALT
|
||||
#endif
|
||||
#ifndef UNICODE_KEY_LNX
|
||||
# define UNICODE_KEY_LNX LCTL(LSFT(KC_U))
|
||||
#endif
|
||||
#ifndef UNICODE_KEY_WINC
|
||||
# define UNICODE_KEY_WINC KC_RIGHT_ALT
|
||||
#endif
|
||||
|
||||
// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle)
|
||||
// Example: #define UNICODE_SELECTED_MODES UC_WINC, UC_LNX
|
||||
#ifndef UNICODE_SELECTED_MODES
|
||||
# define UNICODE_SELECTED_MODES -1
|
||||
#endif
|
||||
|
||||
// Whether input mode changes in cycle should be written to EEPROM
|
||||
#ifndef UNICODE_CYCLE_PERSIST
|
||||
# define UNICODE_CYCLE_PERSIST true
|
||||
#endif
|
||||
|
||||
// Delay between starting Unicode input and sending a sequence, in ms
|
||||
#ifndef UNICODE_TYPE_DELAY
|
||||
# define UNICODE_TYPE_DELAY 10
|
||||
#endif
|
||||
|
||||
// Deprecated aliases
|
||||
#if !defined(UNICODE_KEY_MAC) && defined(UNICODE_KEY_OSX)
|
||||
# define UNICODE_KEY_MAC UNICODE_KEY_OSX
|
||||
#endif
|
||||
#if !defined(UNICODE_SONG_MAC) && defined(UNICODE_SONG_OSX)
|
||||
# define UNICODE_SONG_MAC UNICODE_SONG_OSX
|
||||
#endif
|
||||
#define UC_OSX UC_MAC
|
||||
|
||||
enum unicode_input_modes {
|
||||
UC_MAC, // macOS using Unicode Hex Input
|
||||
UC_LNX, // Linux using IBus
|
||||
UC_WIN, // Windows using EnableHexNumpad
|
||||
UC_BSD, // BSD (not implemented)
|
||||
UC_WINC, // Windows using WinCompose (https://github.com/samhocevar/wincompose)
|
||||
UC_EMACS, // Emacs is an operating system in search of a good text editor
|
||||
UC__COUNT // Number of available input modes (always leave at the end)
|
||||
};
|
||||
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t input_mode : 8;
|
||||
};
|
||||
} unicode_config_t;
|
||||
|
||||
extern unicode_config_t unicode_config;
|
||||
|
||||
void unicode_input_mode_init(void);
|
||||
uint8_t get_unicode_input_mode(void);
|
||||
void set_unicode_input_mode(uint8_t mode);
|
||||
void cycle_unicode_input_mode(int8_t offset);
|
||||
void persist_unicode_input_mode(void);
|
||||
|
||||
void unicode_input_start(void);
|
||||
void unicode_input_finish(void);
|
||||
void unicode_input_cancel(void);
|
||||
|
||||
void register_hex(uint16_t hex);
|
||||
void register_hex32(uint32_t hex);
|
||||
void register_unicode(uint32_t code_point);
|
||||
|
||||
void send_unicode_string(const char *str);
|
||||
#include "action.h"
|
||||
|
||||
bool process_unicode_common(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
#define UC_BSPC UC(0x0008)
|
||||
#define UC_SPC UC(0x0020)
|
||||
|
||||
#define UC_EXLM UC(0x0021)
|
||||
#define UC_DQUT UC(0x0022)
|
||||
#define UC_HASH UC(0x0023)
|
||||
#define UC_DLR UC(0x0024)
|
||||
#define UC_PERC UC(0x0025)
|
||||
#define UC_AMPR UC(0x0026)
|
||||
#define UC_QUOT UC(0x0027)
|
||||
#define UC_LPRN UC(0x0028)
|
||||
#define UC_RPRN UC(0x0029)
|
||||
#define UC_ASTR UC(0x002A)
|
||||
#define UC_PLUS UC(0x002B)
|
||||
#define UC_COMM UC(0x002C)
|
||||
#define UC_DASH UC(0x002D)
|
||||
#define UC_DOT UC(0x002E)
|
||||
#define UC_SLSH UC(0x002F)
|
||||
|
||||
#define UC_0 UC(0x0030)
|
||||
#define UC_1 UC(0x0031)
|
||||
#define UC_2 UC(0x0032)
|
||||
#define UC_3 UC(0x0033)
|
||||
#define UC_4 UC(0x0034)
|
||||
#define UC_5 UC(0x0035)
|
||||
#define UC_6 UC(0x0036)
|
||||
#define UC_7 UC(0x0037)
|
||||
#define UC_8 UC(0x0038)
|
||||
#define UC_9 UC(0x0039)
|
||||
|
||||
#define UC_COLN UC(0x003A)
|
||||
#define UC_SCLN UC(0x003B)
|
||||
#define UC_LT UC(0x003C)
|
||||
#define UC_EQL UC(0x003D)
|
||||
#define UC_GT UC(0x003E)
|
||||
#define UC_QUES UC(0x003F)
|
||||
#define UC_AT UC(0x0040)
|
||||
|
||||
#define UC_A UC(0x0041)
|
||||
#define UC_B UC(0x0042)
|
||||
#define UC_C UC(0x0043)
|
||||
#define UC_D UC(0x0044)
|
||||
#define UC_E UC(0x0045)
|
||||
#define UC_F UC(0x0046)
|
||||
#define UC_G UC(0x0047)
|
||||
#define UC_H UC(0x0048)
|
||||
#define UC_I UC(0x0049)
|
||||
#define UC_J UC(0x004A)
|
||||
#define UC_K UC(0x004B)
|
||||
#define UC_L UC(0x004C)
|
||||
#define UC_M UC(0x004D)
|
||||
#define UC_N UC(0x004E)
|
||||
#define UC_O UC(0x004F)
|
||||
#define UC_P UC(0x0050)
|
||||
#define UC_Q UC(0x0051)
|
||||
#define UC_R UC(0x0052)
|
||||
#define UC_S UC(0x0053)
|
||||
#define UC_T UC(0x0054)
|
||||
#define UC_U UC(0x0055)
|
||||
#define UC_V UC(0x0056)
|
||||
#define UC_W UC(0x0057)
|
||||
#define UC_X UC(0x0058)
|
||||
#define UC_Y UC(0x0059)
|
||||
#define UC_Z UC(0x005A)
|
||||
|
||||
#define UC_LBRC UC(0x005B)
|
||||
#define UC_BSLS UC(0x005C)
|
||||
#define UC_RBRC UC(0x005D)
|
||||
#define UC_CIRM UC(0x005E)
|
||||
#define UC_UNDR UC(0x005F)
|
||||
|
||||
#define UC_GRV UC(0x0060)
|
||||
|
||||
#define UC_a UC(0x0061)
|
||||
#define UC_b UC(0x0062)
|
||||
#define UC_c UC(0x0063)
|
||||
#define UC_d UC(0x0064)
|
||||
#define UC_e UC(0x0065)
|
||||
#define UC_f UC(0x0066)
|
||||
#define UC_g UC(0x0067)
|
||||
#define UC_h UC(0x0068)
|
||||
#define UC_i UC(0x0069)
|
||||
#define UC_j UC(0x006A)
|
||||
#define UC_k UC(0x006B)
|
||||
#define UC_l UC(0x006C)
|
||||
#define UC_m UC(0x006D)
|
||||
#define UC_n UC(0x006E)
|
||||
#define UC_o UC(0x006F)
|
||||
#define UC_p UC(0x0070)
|
||||
#define UC_q UC(0x0071)
|
||||
#define UC_r UC(0x0072)
|
||||
#define UC_s UC(0x0073)
|
||||
#define UC_t UC(0x0074)
|
||||
#define UC_u UC(0x0075)
|
||||
#define UC_v UC(0x0076)
|
||||
#define UC_w UC(0x0077)
|
||||
#define UC_x UC(0x0078)
|
||||
#define UC_y UC(0x0079)
|
||||
#define UC_z UC(0x007A)
|
||||
|
||||
#define UC_LCBR UC(0x007B)
|
||||
#define UC_PIPE UC(0x007C)
|
||||
#define UC_RCBR UC(0x007D)
|
||||
#define UC_TILD UC(0x007E)
|
||||
#define UC_DEL UC(0x007F)
|
||||
|
@ -15,11 +15,16 @@
|
||||
*/
|
||||
|
||||
#include "process_unicodemap.h"
|
||||
#include "unicode.h"
|
||||
#include "quantum_keycodes.h"
|
||||
#include "keycode.h"
|
||||
#include "action_util.h"
|
||||
#include "host.h"
|
||||
|
||||
__attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
|
||||
if (keycode >= QK_UNICODEMAP_PAIR) {
|
||||
// Keycode is a pair: extract index based on Shift / Caps Lock state
|
||||
uint16_t index = keycode - QK_UNICODEMAP_PAIR;
|
||||
uint16_t index;
|
||||
|
||||
uint8_t mods = get_mods() | get_weak_mods();
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
@ -29,13 +34,15 @@ __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
|
||||
bool shift = mods & MOD_MASK_SHIFT;
|
||||
bool caps = host_keyboard_led_state().caps_lock;
|
||||
if (shift ^ caps) {
|
||||
index >>= 7;
|
||||
index = QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(keycode);
|
||||
} else {
|
||||
index = QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(keycode);
|
||||
}
|
||||
|
||||
return index & 0x7F;
|
||||
return index;
|
||||
} else {
|
||||
// Keycode is a regular index
|
||||
return keycode - QK_UNICODEMAP;
|
||||
return QK_UNICODEMAP_GET_INDEX(keycode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "process_unicode_common.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern const uint32_t PROGMEM unicode_map[];
|
||||
#include "action.h"
|
||||
#include "progmem.h"
|
||||
|
||||
extern const uint32_t unicode_map[] PROGMEM;
|
||||
|
||||
uint16_t unicodemap_index(uint16_t keycode);
|
||||
bool process_unicodemap(uint16_t keycode, keyrecord_t *record);
|
||||
|
Reference in New Issue
Block a user