Advertisement
hakbraley

QMK Hold Keys

Jan 10th, 2023
794
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.79 KB | None | 0 0
  1. /*  https://www.reddit.com/r/olkb/comments/105i70g/key_toggling_macro/
  2.  *  https://www.reddit.com/r/olkb/comments/107uzdj/weird_key_macro_help/
  3.  *  This user wanted to be able to tap certains keys and have them held down until they are tapped again.
  4.  *  This behavior should only happen when hold key mode is active, and should only apply to specific keys.
  5.  *  After a key is toggled off (no longer held), it should be automatically tapped again after a delay.
  6.  *  Hold key mode is toggled on and off with the custom HOLD_TOG keycode
  7.  *  Place all of this code in keymap.c
  8.  */
  9.  
  10. const uint16_t keys_to_hold[] = {};  // set your holdkey keycodes here, example: { KC_Q, KC_W, KC_E, KC_R }
  11. const UNTOGGLE_TAP_DELAY = 35;       // set the delay in milliseconds to tap a holdkey after being toggled off
  12.  
  13.  
  14.  
  15. enum custom_keycodes {
  16.     HOLD_TOG = SAFE_RANGE,  // custom keycode called HOLD_TOG that toggles hold_key_mode_active
  17.     // OTHER_MACROS, ...
  18. }
  19.  
  20. struct holdkey {
  21.     uint16_t key;  // keycode to hold
  22.     bool held;     // is it being held?
  23. };
  24.  
  25. const size_t num_holdkeys = sizeof(keys_to_hold) / sizeof(uint16_t);  // calculate number of defined holdkeys
  26. struct key holdkeys[num_holdkeys];                                    // create an empty array of holdkey structs
  27.  
  28. for (int i = 0; i < num_holdkeys; i++) {                              // populate the holdkeys array with keys_to_hold
  29.     holdkeys[i] = (struct holdkey){keys_to_hold[i], false};
  30. }
  31.  
  32. // deferred execution callback
  33. uint16_t delayed_keycode;
  34. uint32_t tap_after_delay(uint32_t trigger_time, void *cb_arg) {
  35.     tapcode_16(delayed_keycode);
  36.     return 0;
  37. }
  38.  
  39. // call this function after toggling hold key mode off
  40. void reset_holdkeys_status() {
  41.     for (int i = 0; i < num_holdkeys; i++) {        // loop through all holdkeys
  42.         if (holdkeys[i].held)                       // if a holdkey is held down
  43.             unregister_code16(holdkeys[i].key);     //   send a keyup event for the held keycode
  44.         holdkeys[i].held = false;                   // set held status to false
  45.     }
  46. }
  47.  
  48. bool hold_key_mode_active = false;
  49.  
  50. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  51.     // holdkey specific code
  52.     if (hold_key_mode_active  &&  record->event.pressed) {  // when a key is pressed while hold key mode is active
  53.         for (int i = 0; i < num_holdkeys; i++) {            // loop thru all holdkeys
  54.             if (keycode == holdkeys[i].key) {               // if the keycode pressed matches this holdkey
  55.                 holdkeys[i].held = !holdkeys[i].held        // flip the held status of this holdkey
  56.                 if (holdkeys[i].held) {                     // if holdkey.held is now true
  57.                     register_code16(keycode);               // send a keydown event for the pressed keycode
  58.                 } else {                                    // otherwise, if holdkey.held is now false
  59.                     unregister_code16(keycode);             // send a keyup event for the pressed keycode
  60.                     delayed_keycode = keycode;                              // save the keycode to tap later
  61.                     defer_exec(UNTOGGLE_TAP_DELAY, tap_after_delay, NULL);  // tap keycode again after UNTOGGLE_TAP_DELAY
  62.                 }
  63.                 break;
  64.             }
  65.         }
  66.     }
  67.    
  68.     // normal macro code
  69.     switch(keycode) {
  70.         case HOLD_TOG:
  71.             if (record->event.pressed) {                        // when HOLD_TOG key is pressed
  72.                 hold_key_mode_active = !hold_key_mode_active;   // toggle hold key mode
  73.                 if (!hold_key_mode_active)                      // when hold key mode is toggled off
  74.                     reset_holdkeys_status();                    //   unhold all active holdkeys
  75.             }        
  76.             break;
  77.  
  78.     //  case OTHER_MACROS: ...
  79.        
  80.     }
  81.     return true;
  82. }
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement