at master 18 kB view raw
1/* Copyright 2017 Jeremy Cowgar 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17#include "process_auto_shift.h" 18#include "quantum.h" 19#include "action_util.h" 20#include "timer.h" 21#include "keycodes.h" 22 23#ifndef AUTO_SHIFT_DISABLED_AT_STARTUP 24# define AUTO_SHIFT_STARTUP_STATE true /* enabled */ 25#else 26# define AUTO_SHIFT_STARTUP_STATE false /* disabled */ 27#endif 28 29// Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat. 30static uint16_t autoshift_time = 0; 31#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) 32// Stores the last key's up or down time, to replace autoshift_time so that Tap Hold times are accurate. 33static uint16_t retroshift_time = 0; 34// Stores a possibly Retro Shift key's up or down time, as retroshift_time needs 35// to be set before the Retro Shift key is evaluated if it is interrupted by an 36// Auto Shifted key. 37static uint16_t last_retroshift_time; 38#endif 39static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; 40static uint16_t autoshift_lastkey = KC_NO; 41static keyrecord_t autoshift_lastrecord; 42// Keys take 8 bits if modifiers are excluded. This records the shift state 43// when pressed for each key, so that can be passed to the release function 44// and it knows which key needs to be released (if shifted is different base). 45static uint16_t autoshift_shift_states[((1 << 8) + 15) / 16]; 46static struct { 47 // Whether Auto Shift is enabled. 48 bool enabled : 1; 49 // Whether the last auto-shifted key was released after the timeout. This 50 // is used to replicate the last key for a tap-then-hold. 51 bool lastshifted : 1; 52 // Whether an auto-shiftable key has been pressed but not processed. 53 bool in_progress : 1; 54 // Whether the auto-shifted keypress has been registered. 55 bool holding_shift : 1; 56 // Whether the user is holding a shift and we removed it. 57 bool cancelling_lshift : 1; 58 bool cancelling_rshift : 1; 59 // clang-format wants to remove the true for some reason. 60 // clang-format off 61} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false, false, false}; 62// clang-format on 63 64/** \brief Called on physical press, returns whether key should be added to Auto Shift */ 65__attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { 66 return false; 67} 68 69/** \brief Called on physical press, returns whether key is an Auto Shift key */ 70__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { 71 switch (keycode) { 72#ifndef NO_AUTO_SHIFT_ALPHA 73 case AUTO_SHIFT_ALPHA: 74#endif 75#ifndef NO_AUTO_SHIFT_NUMERIC 76 case AUTO_SHIFT_NUMERIC: 77#endif 78#ifndef NO_AUTO_SHIFT_SPECIAL 79# ifndef NO_AUTO_SHIFT_TAB 80 case KC_TAB: 81# endif 82# ifndef NO_AUTO_SHIFT_SYMBOLS 83 case AUTO_SHIFT_SYMBOLS: 84# endif 85#endif 86#ifdef AUTO_SHIFT_ENTER 87 case KC_ENT: 88#endif 89 return true; 90 } 91 return get_custom_auto_shifted_key(keycode, record); 92} 93 94/** \brief Called to check whether defines should apply if PER_KEY is set for it */ 95__attribute__((weak)) bool get_auto_shift_repeat(uint16_t keycode, keyrecord_t *record) { 96 return true; 97} 98__attribute__((weak)) bool get_auto_shift_no_auto_repeat(uint16_t keycode, keyrecord_t *record) { 99 return true; 100} 101 102/** \brief Called when an Auto Shift key needs to be pressed */ 103__attribute__((weak)) void autoshift_press_user(uint16_t keycode, bool shifted, keyrecord_t *record) { 104 if (shifted) { 105 add_weak_mods(MOD_BIT(KC_LSFT)); 106 } 107 register_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode); 108} 109 110/** \brief Called when an Auto Shift key needs to be released */ 111__attribute__((weak)) void autoshift_release_user(uint16_t keycode, bool shifted, keyrecord_t *record) { 112 unregister_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode); 113} 114 115/** \brief Sets the shift state to use when keyrepeating, required by custom shifts */ 116void set_autoshift_shift_state(uint16_t keycode, bool shifted) { 117 keycode = keycode & 0xFF; 118 if (shifted) { 119 autoshift_shift_states[keycode / 16] |= (uint16_t)1 << keycode % 16; 120 } else { 121 autoshift_shift_states[keycode / 16] &= ~((uint16_t)1 << keycode % 16); 122 } 123} 124 125/** \brief Gets the shift state to use when keyrepeating, required by custom shifts */ 126bool get_autoshift_shift_state(uint16_t keycode) { 127 keycode = keycode & 0xFF; 128 return (autoshift_shift_states[keycode / 16] & (uint16_t)1 << keycode % 16) != (uint16_t)0; 129} 130 131/** \brief Restores the shift key if it was cancelled by Auto Shift */ 132static void autoshift_flush_shift(void) { 133 autoshift_flags.holding_shift = false; 134#ifdef CAPS_WORD_ENABLE 135 if (!is_caps_word_on()) 136#endif // CAPS_WORD_ENABLE 137 { 138 del_weak_mods(MOD_BIT(KC_LSFT)); 139 } 140 if (autoshift_flags.cancelling_lshift) { 141 autoshift_flags.cancelling_lshift = false; 142 add_mods(MOD_BIT(KC_LSFT)); 143 } 144 if (autoshift_flags.cancelling_rshift) { 145 autoshift_flags.cancelling_rshift = false; 146 add_mods(MOD_BIT(KC_RSFT)); 147 } 148 send_keyboard_report(); 149} 150 151/** \brief Record the press of an autoshiftable key 152 * 153 * \return Whether the record should be further processed. 154 */ 155static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) { 156 // clang-format off 157 if ((get_mods() 158#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) 159 | get_oneshot_mods() 160#endif 161 ) & (~MOD_BIT(KC_LSFT)) 162 ) { 163 // clang-format on 164 // Prevents keyrepeating unshifted value of key after using it in a key combo. 165 autoshift_lastkey = KC_NO; 166#ifndef AUTO_SHIFT_MODIFIERS 167 // We can't return true here anymore because custom unshifted values are 168 // possible and there's no good way to tell whether the press returned 169 // true upon release. 170 set_autoshift_shift_state(keycode, false); 171 autoshift_press_user(keycode, false, record); 172# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) 173 set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT))); 174 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); 175# endif 176 return false; 177#endif 178 } 179 180 // Store record to be sent to user functions if there's no release record then. 181 autoshift_lastrecord = *record; 182 autoshift_lastrecord.event.time = 0; 183 // clang-format off 184#if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY) 185 if (keycode == autoshift_lastkey && 186# ifdef AUTO_SHIFT_REPEAT_PER_KEY 187 get_auto_shift_repeat(autoshift_lastkey, record) && 188# endif 189# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY) 190 ( 191 !autoshift_flags.lastshifted 192# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY 193 || get_auto_shift_no_auto_repeat(autoshift_lastkey, record) 194# endif 195 ) && 196# endif 197 TIMER_DIFF_16(now, autoshift_time) < GET_TAPPING_TERM(autoshift_lastkey, record) 198 ) { 199 // clang-format on 200 // Allow a tap-then-hold for keyrepeat. 201 if (get_mods() & MOD_BIT(KC_LSFT)) { 202 autoshift_flags.cancelling_lshift = true; 203 del_mods(MOD_BIT(KC_LSFT)); 204 } 205 if (get_mods() & MOD_BIT(KC_RSFT)) { 206 autoshift_flags.cancelling_rshift = true; 207 del_mods(MOD_BIT(KC_RSFT)); 208 } 209 // autoshift_shift_state doesn't need to be changed. 210 autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record); 211 return false; 212 } 213#endif 214 215 // Use physical shift state of press event to be more like normal typing. 216#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) 217 autoshift_flags.lastshifted = (get_mods() | get_oneshot_mods()) & MOD_BIT(KC_LSFT); 218 set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT))); 219#else 220 autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT); 221#endif 222 // Record the keycode so we can simulate it later. 223 autoshift_lastkey = keycode; 224 autoshift_time = now; 225 autoshift_flags.in_progress = true; 226 227#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) 228 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); 229#endif 230 return false; 231} 232 233/** \brief Registers an autoshiftable key under the right conditions 234 * 235 * If autoshift_timeout has elapsed, register a shift and the key. 236 * 237 * If the Auto Shift key is released before the delay has elapsed, register the 238 * key without a shift. 239 * 240 * Called on key down with keycode=KC_NO, auto-shifted key up, and timeout. 241 */ 242static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, keyrecord_t *record) { 243 if (autoshift_flags.in_progress && (keycode == autoshift_lastkey || keycode == KC_NO)) { 244 // Process the auto-shiftable key. 245 autoshift_flags.in_progress = false; 246 // clang-format off 247 autoshift_flags.lastshifted = 248 autoshift_flags.lastshifted 249 || TIMER_DIFF_16(now, autoshift_time) >= 250#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY 251 get_autoshift_timeout(autoshift_lastkey, record) 252#else 253 autoshift_timeout 254#endif 255 ; 256 // clang-format on 257 set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted); 258 if (get_mods() & MOD_BIT(KC_LSFT)) { 259 autoshift_flags.cancelling_lshift = true; 260 del_mods(MOD_BIT(KC_LSFT)); 261 } 262 if (get_mods() & MOD_BIT(KC_RSFT)) { 263 autoshift_flags.cancelling_rshift = true; 264 del_mods(MOD_BIT(KC_RSFT)); 265 } 266 autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record); 267 268 // clang-format off 269#if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)) 270 if (matrix_trigger 271# ifdef AUTO_SHIFT_REPEAT_PER_KEY 272 && get_auto_shift_repeat(autoshift_lastkey, record) 273# endif 274# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY 275 && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record) 276# endif 277 ) { 278 // Prevents release. 279 return; 280 } 281#endif 282 // clang-format on 283#if TAP_CODE_DELAY > 0 284 wait_ms(TAP_CODE_DELAY); 285#endif 286 287 autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record); 288 autoshift_flush_shift(); 289 } else { 290 // Release after keyrepeat. 291 autoshift_release_user(keycode, get_autoshift_shift_state(keycode), record); 292 if (keycode == autoshift_lastkey) { 293 // This will only fire when the key was the last auto-shiftable 294 // pressed. That prevents 'aaaaBBBB' then releasing a from unshifting 295 // later 'B's (if 'B' wasn't auto-shiftable). 296 autoshift_flush_shift(); 297 } 298 } 299 // Roll the autoshift_time forward for detecting tap-and-hold. 300 autoshift_time = now; 301} 302 303/** \brief Simulates auto-shifted key releases when timeout is hit 304 * 305 * Can be called from \c matrix_scan_user so that auto-shifted keys are sent 306 * immediately after the timeout has expired, rather than waiting for the key 307 * to be released. 308 */ 309void autoshift_matrix_scan(void) { 310 if (autoshift_flags.in_progress) { 311 const uint16_t now = timer_read(); 312 if (TIMER_DIFF_16(now, autoshift_time) >= 313#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY 314 get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord) 315#else 316 autoshift_timeout 317#endif 318 ) { 319 autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord); 320 } 321 } 322} 323 324void autoshift_toggle(void) { 325 autoshift_flags.enabled = !autoshift_flags.enabled; 326 autoshift_flush_shift(); 327} 328 329void autoshift_enable(void) { 330 autoshift_flags.enabled = true; 331} 332 333void autoshift_disable(void) { 334 autoshift_flags.enabled = false; 335 autoshift_flush_shift(); 336} 337 338#ifndef AUTO_SHIFT_NO_SETUP 339void autoshift_timer_report(void) { 340# ifdef SEND_STRING_ENABLE 341 const char *autoshift_timeout_str = get_u16_str(autoshift_timeout, ' '); 342 // Skip padding spaces 343 while (*autoshift_timeout_str == ' ') { 344 autoshift_timeout_str++; 345 } 346 send_string(autoshift_timeout_str); 347# endif 348} 349#endif 350 351bool get_autoshift_state(void) { 352 return autoshift_flags.enabled; 353} 354 355uint16_t get_generic_autoshift_timeout(void) { 356 return autoshift_timeout; 357} 358__attribute__((weak)) uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) { 359 return autoshift_timeout; 360} 361 362void set_autoshift_timeout(uint16_t timeout) { 363 autoshift_timeout = timeout; 364} 365 366bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { 367 // Note that record->event.time isn't reliable, see: 368 // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550 369 // clang-format off 370 const uint16_t now = 371#if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING) 372 timer_read() 373#else 374 (record->event.pressed) ? retroshift_time : timer_read() 375#endif 376 ; 377 // clang-format on 378 379 if (record->event.pressed) { 380 if (autoshift_flags.in_progress) { 381 // Evaluate previous key if there is one. 382 autoshift_end(KC_NO, now, false, &autoshift_lastrecord); 383 } 384 385 switch (keycode) { 386 case AS_TOGG: 387 autoshift_toggle(); 388 break; 389 case AS_ON: 390 autoshift_enable(); 391 break; 392 case AS_OFF: 393 autoshift_disable(); 394 break; 395 396#ifndef AUTO_SHIFT_NO_SETUP 397 case AS_UP: 398 autoshift_timeout += 5; 399 break; 400 case AS_DOWN: 401 autoshift_timeout -= 5; 402 break; 403 case AS_RPT: 404 autoshift_timer_report(); 405 break; 406#endif 407 } 408 // If Retro Shift is disabled, possible custom actions shouldn't happen. 409 // clang-format off 410#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) 411# ifdef HOLD_ON_OTHER_KEY_PRESS 412 const bool is_hold_on_interrupt = (IS_QK_MOD_TAP(keycode) 413# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY 414 && get_hold_on_other_key_press(keycode, record) 415# endif 416 ); 417# else 418 const bool is_hold_on_interrupt = false; 419# endif 420#endif 421 if (IS_RETRO(keycode) 422#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) 423 // Not tapped or #defines mean that rolls should use hold action. 424 && ( 425 record->tap.count == 0 426# ifdef RETRO_TAPPING_PER_KEY 427 || !get_retro_tapping(keycode, record) 428# endif 429 || (record->tap.interrupted && is_hold_on_interrupt)) 430#endif 431 ) { 432 // clang-format on 433 autoshift_lastkey = KC_NO; 434 return true; 435 } 436 } else { 437 if (keycode == KC_LSFT) { 438 autoshift_flags.cancelling_lshift = false; 439 } else if (keycode == KC_RSFT) { 440 autoshift_flags.cancelling_rshift = false; 441 } 442 // Same as above (for pressed), additional checks are not needed because 443 // tap.count gets set to 0 in process_action 444 // clang-format off 445 else if (IS_RETRO(keycode) 446#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) 447 && ( 448 record->tap.count == 0 449# ifdef RETRO_TAPPING_PER_KEY 450 || !get_retro_tapping(keycode, record) 451# endif 452 ) 453#endif 454 ) { 455 // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set. 456#ifdef HOLD_ON_OTHER_KEY_PRESS 457 if (autoshift_flags.in_progress 458# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY 459 && get_hold_on_other_key_press(keycode, record) 460# endif 461 ) { 462 autoshift_end(KC_NO, now, false, &autoshift_lastrecord); 463 } 464#endif 465 // clang-format on 466 return true; 467 } 468 } 469 470 if (!autoshift_flags.enabled) { 471 return true; 472 } 473 if (get_auto_shifted_key(keycode, record)) { 474 if (record->event.pressed) { 475 return autoshift_press(keycode, now, record); 476 } else { 477 autoshift_end(keycode, now, false, record); 478 return false; 479 } 480 } 481 482 // Prevent keyrepeating of older keys upon non-AS key event. 483 // Not commented at above returns but they serve the same function. 484 if (record->event.pressed) { 485 autoshift_lastkey = KC_NO; 486 } 487 return true; 488} 489 490#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) 491// Called to record time before possible delays by action_tapping_process. 492void retroshift_poll_time(keyevent_t *event) { 493 last_retroshift_time = retroshift_time; 494 retroshift_time = timer_read(); 495} 496// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it. 497void retroshift_swap_times(void) { 498 if (autoshift_flags.in_progress) { 499 autoshift_time = last_retroshift_time; 500 } 501} 502#endif