process_auto_shift.c (17619B)
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. 30 static 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. 33 static 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. 37 static uint16_t last_retroshift_time; 38 #endif 39 static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; 40 static uint16_t autoshift_lastkey = KC_NO; 41 static 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). 45 static uint16_t autoshift_shift_states[((1 << 8) + 15) / 16]; 46 static 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 */ 116 void 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 */ 126 bool 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 */ 132 static 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 */ 155 static 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 */ 242 static 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 */ 309 void 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 324 void autoshift_toggle(void) { 325 autoshift_flags.enabled = !autoshift_flags.enabled; 326 autoshift_flush_shift(); 327 } 328 329 void autoshift_enable(void) { 330 autoshift_flags.enabled = true; 331 } 332 333 void autoshift_disable(void) { 334 autoshift_flags.enabled = false; 335 autoshift_flush_shift(); 336 } 337 338 #ifndef AUTO_SHIFT_NO_SETUP 339 void 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 351 bool get_autoshift_state(void) { 352 return autoshift_flags.enabled; 353 } 354 355 uint16_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 362 void set_autoshift_timeout(uint16_t timeout) { 363 autoshift_timeout = timeout; 364 } 365 366 bool 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. 492 void 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. 497 void retroshift_swap_times(void) { 498 if (autoshift_flags.in_progress) { 499 autoshift_time = last_retroshift_time; 500 } 501 } 502 #endif