qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

action.c (44328B)


      1 /*
      2 Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
      3 
      4 This program is free software: you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation, either version 2 of the License, or
      7 (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17 #include <limits.h>
     18 
     19 #include "host.h"
     20 #include "keycode.h"
     21 #include "keyboard.h"
     22 #include "mousekey.h"
     23 #include "programmable_button.h"
     24 #include "command.h"
     25 #include "led.h"
     26 #include "action_layer.h"
     27 #include "action_tapping.h"
     28 #include "action_util.h"
     29 #include "action.h"
     30 #include "wait.h"
     31 #include "keycode_config.h"
     32 #include "debug.h"
     33 #include "quantum.h"
     34 
     35 #ifdef BACKLIGHT_ENABLE
     36 #    include "backlight.h"
     37 #endif
     38 
     39 #ifdef POINTING_DEVICE_ENABLE
     40 #    include "pointing_device.h"
     41 #endif
     42 
     43 #if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) && defined(SWAP_HANDS_ENABLE)
     44 #    include "encoder.h"
     45 #endif
     46 
     47 int tp_buttons;
     48 
     49 #if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
     50 bool     retro_tap_primed   = false;
     51 uint16_t retro_tap_curr_key = 0;
     52 #    if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
     53 uint8_t retro_tap_curr_mods = 0;
     54 uint8_t retro_tap_next_mods = 0;
     55 #    endif
     56 #endif
     57 
     58 #if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
     59 #    include "process_auto_shift.h"
     60 #endif
     61 
     62 #ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
     63 __attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) {
     64     return false;
     65 }
     66 #endif
     67 
     68 #ifdef RETRO_TAPPING_PER_KEY
     69 __attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) {
     70     return false;
     71 }
     72 #endif
     73 
     74 /** \brief Called to execute an action.
     75  *
     76  * FIXME: Needs documentation.
     77  */
     78 void action_exec(keyevent_t event) {
     79     if (IS_EVENT(event)) {
     80         ac_dprintf("\n---- action_exec: start -----\n");
     81         ac_dprintf("EVENT: ");
     82         debug_event(event);
     83         ac_dprintf("\n");
     84 #if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
     85         uint16_t event_keycode = get_event_keycode(event, false);
     86         if (event.pressed) {
     87             retro_tap_primed   = false;
     88             retro_tap_curr_key = event_keycode;
     89         } else if (retro_tap_curr_key == event_keycode) {
     90             retro_tap_primed = true;
     91         }
     92 #endif
     93     }
     94 
     95     if (event.pressed) {
     96         // clear the potential weak mods left by previously pressed keys
     97         clear_weak_mods();
     98     }
     99 
    100 #ifdef SWAP_HANDS_ENABLE
    101     // Swap hands handles both keys and encoders, if ENCODER_MAP_ENABLE is defined.
    102     if (IS_EVENT(event)) {
    103         process_hand_swap(&event);
    104     }
    105 #endif
    106 
    107     keyrecord_t record = {.event = event};
    108 
    109 #ifndef NO_ACTION_ONESHOT
    110     if (keymap_config.oneshot_enable) {
    111 #    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
    112         if (has_oneshot_layer_timed_out()) {
    113             clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
    114         }
    115         if (has_oneshot_mods_timed_out()) {
    116             clear_oneshot_mods();
    117         }
    118 #        ifdef SWAP_HANDS_ENABLE
    119         if (has_oneshot_swaphands_timed_out()) {
    120             clear_oneshot_swaphands();
    121         }
    122 #        endif
    123 #    endif
    124     }
    125 #endif
    126 
    127 #ifndef NO_ACTION_TAPPING
    128 #    if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
    129     if (event.pressed) {
    130         retroshift_poll_time(&event);
    131     }
    132 #    endif
    133     if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) {
    134         action_tapping_process(record);
    135     }
    136 #else
    137     if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) {
    138         process_record(&record);
    139     }
    140     if (IS_EVENT(record.event)) {
    141         ac_dprintf("processed: ");
    142         debug_record(record);
    143         dprintln();
    144     }
    145 #endif
    146 }
    147 
    148 #ifdef SWAP_HANDS_ENABLE
    149 extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
    150 #    ifdef ENCODER_MAP_ENABLE
    151 extern const uint8_t PROGMEM encoder_hand_swap_config[NUM_ENCODERS];
    152 #    endif // ENCODER_MAP_ENABLE
    153 
    154 bool swap_hands = false;
    155 bool swap_held  = false;
    156 
    157 bool should_swap_hands(size_t index, uint8_t *swap_state, bool pressed) {
    158     size_t  array_index = index / (CHAR_BIT);
    159     size_t  bit_index   = index % (CHAR_BIT);
    160     uint8_t bit_val     = 1 << bit_index;
    161     bool    do_swap     = pressed ? swap_hands : swap_state[array_index] & bit_val;
    162     return do_swap;
    163 }
    164 
    165 void set_swap_hands_state(size_t index, uint8_t *swap_state, bool on) {
    166     size_t  array_index = index / (CHAR_BIT);
    167     size_t  bit_index   = index % (CHAR_BIT);
    168     uint8_t bit_val     = 1 << bit_index;
    169     if (on) {
    170         swap_state[array_index] |= bit_val;
    171     } else {
    172         swap_state[array_index] &= ~bit_val;
    173     }
    174 }
    175 
    176 void swap_hands_on(void) {
    177     swap_hands = true;
    178 }
    179 
    180 void swap_hands_off(void) {
    181     swap_hands = false;
    182 }
    183 
    184 void swap_hands_toggle(void) {
    185     swap_hands = !swap_hands;
    186 }
    187 
    188 bool is_swap_hands_on(void) {
    189     return swap_hands;
    190 }
    191 
    192 /** \brief Process Hand Swap
    193  *
    194  * FIXME: Needs documentation.
    195  */
    196 void process_hand_swap(keyevent_t *event) {
    197     keypos_t pos = event->key;
    198     if (IS_KEYEVENT(*event) && pos.row < MATRIX_ROWS && pos.col < MATRIX_COLS) {
    199         static uint8_t matrix_swap_state[((MATRIX_ROWS * MATRIX_COLS) + (CHAR_BIT)-1) / (CHAR_BIT)];
    200         size_t         index   = (size_t)(pos.row * MATRIX_COLS) + pos.col;
    201         bool           do_swap = should_swap_hands(index, matrix_swap_state, event->pressed);
    202         if (do_swap) {
    203             event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row);
    204             event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col);
    205             set_swap_hands_state(index, matrix_swap_state, true);
    206         } else {
    207             set_swap_hands_state(index, matrix_swap_state, false);
    208         }
    209     }
    210 #    ifdef ENCODER_MAP_ENABLE
    211     else if (IS_ENCODEREVENT(*event) && (pos.row == KEYLOC_ENCODER_CW || pos.row == KEYLOC_ENCODER_CCW)) {
    212         static uint8_t encoder_swap_state[((NUM_ENCODERS) + (CHAR_BIT)-1) / (CHAR_BIT)];
    213         size_t         index   = pos.col;
    214         bool           do_swap = should_swap_hands(index, encoder_swap_state, event->pressed);
    215         if (do_swap) {
    216             event->key.row = pos.row;
    217             event->key.col = pgm_read_byte(&encoder_hand_swap_config[pos.col]);
    218             set_swap_hands_state(index, encoder_swap_state, true);
    219         } else {
    220             set_swap_hands_state(index, encoder_swap_state, false);
    221         }
    222     }
    223 #    endif // ENCODER_MAP_ENABLE
    224 }
    225 #endif
    226 
    227 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
    228 bool disable_action_cache = false;
    229 
    230 void process_record_nocache(keyrecord_t *record) {
    231     disable_action_cache = true;
    232     process_record(record);
    233     disable_action_cache = false;
    234 }
    235 #else
    236 void process_record_nocache(keyrecord_t *record) {
    237     process_record(record);
    238 }
    239 #endif
    240 
    241 __attribute__((weak)) bool process_record_quantum(keyrecord_t *record) {
    242     return true;
    243 }
    244 
    245 __attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {}
    246 
    247 #ifndef NO_ACTION_TAPPING
    248 /** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress.
    249  *
    250  * FIXME: Needs documentation.
    251  */
    252 void process_record_tap_hint(keyrecord_t *record) {
    253     if (!IS_KEYEVENT(record->event)) {
    254         return;
    255     }
    256 
    257     action_t action = layer_switch_get_action(record->event.key);
    258 
    259     switch (action.kind.id) {
    260 #    ifdef SWAP_HANDS_ENABLE
    261         case ACT_SWAP_HANDS:
    262             switch (action.swap.code) {
    263                 case OP_SH_ONESHOT:
    264                     break;
    265                 case OP_SH_TAP_TOGGLE:
    266                 default:
    267                     swap_hands = !swap_hands;
    268                     swap_held  = true;
    269             }
    270             break;
    271 #    endif
    272     }
    273 }
    274 #endif
    275 
    276 /** \brief Take a key event (key press or key release) and processes it.
    277  *
    278  * FIXME: Needs documentation.
    279  */
    280 void process_record(keyrecord_t *record) {
    281     if (IS_NOEVENT(record->event)) {
    282         return;
    283     }
    284 #ifdef SPECULATIVE_HOLD
    285     if (record->event.pressed) {
    286         speculative_key_settled(record);
    287     }
    288 #endif // SPECULATIVE_HOLD
    289 #ifdef FLOW_TAP_TERM
    290     flow_tap_update_last_event(record);
    291 #endif // FLOW_TAP_TERM
    292 
    293     if (!process_record_quantum(record)) {
    294 #ifndef NO_ACTION_ONESHOT
    295         if (is_oneshot_layer_active() && record->event.pressed && keymap_config.oneshot_enable) {
    296             clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
    297         }
    298 #endif
    299         return;
    300     }
    301 
    302     process_record_handler(record);
    303     post_process_record_quantum(record);
    304 }
    305 
    306 void process_record_handler(keyrecord_t *record) {
    307 #if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE)
    308     action_t action;
    309     if (record->keycode) {
    310         action = action_for_keycode(record->keycode);
    311     } else {
    312         action = store_or_get_action(record->event.pressed, record->event.key);
    313     }
    314 #else
    315     action_t action = store_or_get_action(record->event.pressed, record->event.key);
    316 #endif
    317     ac_dprintf("ACTION: ");
    318     debug_action(action);
    319 #ifndef NO_ACTION_LAYER
    320     ac_dprintf(" layer_state: ");
    321     layer_debug();
    322     ac_dprintf(" default_layer_state: ");
    323     default_layer_debug();
    324 #endif
    325     ac_dprintf("\n");
    326 
    327     process_action(record, action);
    328 }
    329 
    330 /**
    331  * @brief handles all the messy mouse stuff
    332  *
    333  * Handles all the edgecases and special stuff that is needed for coexistense
    334  * of the multiple mouse subsystems.
    335  *
    336  * @param mouse_keycode[in] uint8_t mouse keycode
    337  * @param pressed[in] bool
    338  */
    339 
    340 void register_mouse(uint8_t mouse_keycode, bool pressed) {
    341 #ifdef MOUSEKEY_ENABLE
    342     // if mousekeys is enabled, let it do the brunt of the work
    343     if (pressed) {
    344         mousekey_on(mouse_keycode);
    345     } else {
    346         mousekey_off(mouse_keycode);
    347     }
    348     // should mousekeys send report, or does something else handle this?
    349     switch (mouse_keycode) {
    350 #    if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE)
    351         case QK_MOUSE_BUTTON_1 ... QK_MOUSE_BUTTON_8:
    352             // let pointing device handle the buttons
    353             // expand if/when it handles more of the code
    354 #        if defined(POINTING_DEVICE_ENABLE)
    355             pointing_device_keycode_handler(mouse_keycode, pressed);
    356 #        endif
    357             break;
    358 #    endif
    359         default:
    360             mousekey_send();
    361             break;
    362     }
    363 #elif defined(POINTING_DEVICE_ENABLE)
    364     // if mousekeys isn't enabled, and pointing device is enabled, then
    365     // let pointing device do all the heavy lifting, then
    366     if (IS_MOUSE_KEYCODE(mouse_keycode)) {
    367         pointing_device_keycode_handler(mouse_keycode, pressed);
    368     }
    369 #endif
    370 
    371 #ifdef PS2_MOUSE_ENABLE
    372     // make sure that ps2 mouse has button report synced
    373     if (QK_MOUSE_BUTTON_1 <= mouse_keycode && mouse_keycode <= QK_MOUSE_BUTTON_3) {
    374         uint8_t tmp_button_msk = MOUSE_BTN_MASK(mouse_keycode - QK_MOUSE_BUTTON_1);
    375         tp_buttons             = pressed ? tp_buttons | tmp_button_msk : tp_buttons & ~tmp_button_msk;
    376     }
    377 #endif
    378 }
    379 
    380 /** \brief Take an action and processes it.
    381  *
    382  * FIXME: Needs documentation.
    383  */
    384 void process_action(keyrecord_t *record, action_t action) {
    385     keyevent_t event = record->event;
    386 #ifndef NO_ACTION_TAPPING
    387     uint8_t tap_count = record->tap.count;
    388 #endif
    389 
    390 #ifndef NO_ACTION_ONESHOT
    391     bool do_release_oneshot = false;
    392     // notice we only clear the one shot layer if the pressed key is not a modifier.
    393     if (is_oneshot_layer_active() && event.pressed &&
    394         (action.kind.id == ACT_USAGE || !(IS_MODIFIER_KEYCODE(action.key.code)
    395 #    ifndef NO_ACTION_TAPPING
    396                                           || ((action.kind.id == ACT_LMODS_TAP || action.kind.id == ACT_RMODS_TAP) && (action.layer_tap.code <= MODS_TAP_TOGGLE || tap_count == 0))
    397 #    endif
    398                                               ))
    399 #    ifdef SWAP_HANDS_ENABLE
    400         && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)
    401 #    endif
    402         && keymap_config.oneshot_enable) {
    403         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
    404         do_release_oneshot = !is_oneshot_layer_active();
    405     }
    406 #endif
    407 
    408     switch (action.kind.id) {
    409         /* Key and Mods */
    410         case ACT_LMODS:
    411         case ACT_RMODS: {
    412             uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods << 4;
    413             if (event.pressed) {
    414                 if (mods) {
    415                     if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) {
    416                         // e.g. LSFT(KC_LEFT_GUI): we don't want the LSFT to be weak as it would make it useless.
    417                         // This also makes LSFT(KC_LEFT_GUI) behave exactly the same as LGUI(KC_LEFT_SHIFT).
    418                         // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
    419                         add_mods(mods);
    420                     } else {
    421                         add_weak_mods(mods);
    422                     }
    423                     send_keyboard_report();
    424                 }
    425                 register_code(action.key.code);
    426             } else {
    427                 unregister_code(action.key.code);
    428                 if (mods) {
    429                     if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) {
    430                         del_mods(mods);
    431                     } else {
    432                         del_weak_mods(mods);
    433                     }
    434                     send_keyboard_report();
    435                 }
    436             }
    437         } break;
    438         case ACT_LMODS_TAP:
    439         case ACT_RMODS_TAP: {
    440 #ifndef NO_ACTION_TAPPING
    441             uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4;
    442             switch (action.layer_tap.code) {
    443 #    ifndef NO_ACTION_ONESHOT
    444                 case MODS_ONESHOT:
    445                     // Oneshot modifier
    446                     if (!keymap_config.oneshot_enable) {
    447                         if (event.pressed) {
    448                             if (mods) {
    449                                 if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) {
    450                                     // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
    451                                     // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
    452                                     // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
    453                                     add_mods(mods);
    454                                 } else {
    455                                     add_weak_mods(mods);
    456                                 }
    457                                 send_keyboard_report();
    458                             }
    459                             register_code(action.key.code);
    460                         } else {
    461                             unregister_code(action.key.code);
    462                             if (mods) {
    463                                 if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) {
    464                                     del_mods(mods);
    465                                 } else {
    466                                     del_weak_mods(mods);
    467                                 }
    468                                 send_keyboard_report();
    469                             }
    470                         }
    471                     } else {
    472                         if (event.pressed) {
    473                             if (tap_count == 0) {
    474                                 // Not a tap, but a hold: register the held mod
    475                                 ac_dprintf("MODS_TAP: Oneshot: 0\n");
    476                                 register_mods(mods);
    477                             } else if (tap_count == 1) {
    478                                 ac_dprintf("MODS_TAP: Oneshot: start\n");
    479                                 add_oneshot_mods(mods);
    480 #        if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
    481                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
    482                                 ac_dprintf("MODS_TAP: Toggling oneshot");
    483                                 register_mods(mods);
    484                                 del_oneshot_mods(mods);
    485                                 add_oneshot_locked_mods(mods);
    486 #        endif
    487                             }
    488                         } else {
    489                             if (tap_count == 0) {
    490                                 // Release hold: unregister the held mod and its variants
    491                                 unregister_mods(mods);
    492                                 del_oneshot_mods(mods);
    493                                 del_oneshot_locked_mods(mods);
    494 #        if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
    495                             } else if (tap_count == 1 && (mods & get_mods())) {
    496                                 unregister_mods(mods);
    497                                 del_oneshot_mods(mods);
    498                                 del_oneshot_locked_mods(mods);
    499 #        endif
    500                             }
    501                         }
    502                     }
    503                     break;
    504 #    endif
    505                 case MODS_TAP_TOGGLE:
    506                     if (event.pressed) {
    507                         if (tap_count <= TAPPING_TOGGLE) {
    508                             register_mods(mods);
    509                         }
    510                     } else {
    511                         if (tap_count < TAPPING_TOGGLE) {
    512                             unregister_mods(mods);
    513                         }
    514                     }
    515                     break;
    516                 default:
    517                     if (event.pressed) {
    518                         if (tap_count > 0) {
    519 #    ifdef HOLD_ON_OTHER_KEY_PRESS
    520                             if (
    521 #        ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
    522                                 get_hold_on_other_key_press(get_event_keycode(record->event, false), record) &&
    523 #        endif
    524                                 record->tap.interrupted) {
    525                                 ac_dprintf("mods_tap: tap: cancel: add_mods\n");
    526                                 // ad hoc: set 0 to cancel tap
    527                                 record->tap.count = 0;
    528                                 register_mods(mods);
    529                             } else
    530 #    endif
    531                             {
    532                                 ac_dprintf("MODS_TAP: Tap: register_code\n");
    533                                 register_code(action.key.code);
    534                             }
    535                         } else {
    536                             ac_dprintf("MODS_TAP: No tap: add_mods\n");
    537                             register_mods(mods);
    538                         }
    539                     } else {
    540                         if (tap_count > 0) {
    541                             ac_dprintf("MODS_TAP: Tap: unregister_code\n");
    542                             if (action.layer_tap.code == KC_CAPS_LOCK) {
    543                                 wait_ms(TAP_HOLD_CAPS_DELAY);
    544                             } else {
    545                                 wait_ms(TAP_CODE_DELAY);
    546                             }
    547                             unregister_code(action.key.code);
    548                         } else {
    549                             ac_dprintf("MODS_TAP: No tap: add_mods\n");
    550 #    if defined(RETRO_TAPPING) && defined(DUMMY_MOD_NEUTRALIZER_KEYCODE)
    551                             // Send a dummy keycode to neutralize flashing modifiers
    552                             // if the key was held and then released with no interruptions.
    553                             uint16_t ev_kc = get_event_keycode(event, false);
    554                             if (retro_tap_primed && retro_tap_curr_key == ev_kc) {
    555                                 neutralize_flashing_modifiers(get_mods());
    556                             }
    557 #    endif
    558                             unregister_mods(mods);
    559                         }
    560                     }
    561                     break;
    562             }
    563 #endif // NO_ACTION_TAPPING
    564         } break;
    565 #ifdef EXTRAKEY_ENABLE
    566         /* other HID usage */
    567         case ACT_USAGE:
    568             switch (action.usage.page) {
    569                 case PAGE_SYSTEM:
    570                     host_system_send(event.pressed ? action.usage.code : 0);
    571                     break;
    572                 case PAGE_CONSUMER:
    573                     host_consumer_send(event.pressed ? action.usage.code : 0);
    574                     break;
    575             }
    576             break;
    577 #endif // EXTRAKEY_ENABLE
    578         /* Mouse key */
    579         case ACT_MOUSEKEY:
    580             register_mouse(action.key.code, event.pressed);
    581             break;
    582 #ifndef NO_ACTION_LAYER
    583         case ACT_LAYER:
    584             if (action.layer_bitop.on == 0) {
    585                 /* Default Layer Bitwise Operation */
    586                 if (!event.pressed) {
    587                     uint8_t       shift = action.layer_bitop.part * 4;
    588                     layer_state_t bits  = ((layer_state_t)action.layer_bitop.bits) << shift;
    589                     layer_state_t mask  = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0;
    590                     switch (action.layer_bitop.op) {
    591                         case OP_BIT_AND:
    592                             default_layer_and(bits | mask);
    593                             break;
    594                         case OP_BIT_OR:
    595                             default_layer_or(bits | mask);
    596                             break;
    597                         case OP_BIT_XOR:
    598                             default_layer_xor(bits | mask);
    599                             break;
    600                         case OP_BIT_SET:
    601                             default_layer_set(bits | mask);
    602                             break;
    603                     }
    604                 }
    605             } else {
    606                 /* Layer Bitwise Operation */
    607                 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) {
    608                     uint8_t       shift = action.layer_bitop.part * 4;
    609                     layer_state_t bits  = ((layer_state_t)action.layer_bitop.bits) << shift;
    610                     layer_state_t mask  = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0;
    611                     switch (action.layer_bitop.op) {
    612                         case OP_BIT_AND:
    613                             layer_and(bits | mask);
    614                             break;
    615                         case OP_BIT_OR:
    616                             layer_or(bits | mask);
    617                             break;
    618                         case OP_BIT_XOR:
    619                             layer_xor(bits | mask);
    620                             break;
    621                         case OP_BIT_SET:
    622                             layer_state_set(bits | mask);
    623                             break;
    624                     }
    625                 }
    626             }
    627             break;
    628         case ACT_LAYER_MODS:
    629             if (event.pressed) {
    630                 layer_on(action.layer_mods.layer);
    631                 register_mods(action.layer_mods.mods);
    632             } else {
    633                 unregister_mods(action.layer_mods.mods);
    634                 layer_off(action.layer_mods.layer);
    635             }
    636             break;
    637         case ACT_LAYER_TAP:
    638         case ACT_LAYER_TAP_EXT:
    639             switch (action.layer_tap.code) {
    640 #    ifndef NO_ACTION_TAPPING
    641                 case OP_TAP_TOGGLE:
    642                     /* tap toggle */
    643                     if (event.pressed) {
    644                         if (tap_count < TAPPING_TOGGLE) {
    645                             layer_invert(action.layer_tap.val);
    646                         }
    647                     } else {
    648                         if (tap_count <= TAPPING_TOGGLE) {
    649                             layer_invert(action.layer_tap.val);
    650                         }
    651                     }
    652                     break;
    653 #    endif
    654                 case OP_ON_OFF:
    655                     event.pressed ? layer_on(action.layer_tap.val) : layer_off(action.layer_tap.val);
    656                     break;
    657                 case OP_OFF_ON:
    658                     event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val);
    659                     break;
    660                 case OP_SET_CLEAR:
    661                     event.pressed ? layer_move(action.layer_tap.val) : layer_clear();
    662                     break;
    663 #    if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
    664                 case OP_ONESHOT:
    665                     // Oneshot modifier
    666                     if (!keymap_config.oneshot_enable) {
    667                         if (event.pressed) {
    668                             layer_on(action.layer_tap.val);
    669                         } else {
    670                             layer_off(action.layer_tap.val);
    671                         }
    672                     } else {
    673 #        if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
    674                         do_release_oneshot = false;
    675                         if (event.pressed) {
    676                             if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
    677                                 reset_oneshot_layer();
    678                                 layer_off(action.layer_tap.val);
    679                                 break;
    680                             } else if (tap_count < ONESHOT_TAP_TOGGLE) {
    681                                 set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
    682                             }
    683                         } else {
    684                             if (tap_count >= ONESHOT_TAP_TOGGLE) {
    685                                 reset_oneshot_layer();
    686                                 set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
    687                             } else {
    688                                 clear_oneshot_layer_state(ONESHOT_PRESSED);
    689                             }
    690                         }
    691 #        else
    692                         if (event.pressed) {
    693                             set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
    694                         } else {
    695                             clear_oneshot_layer_state(ONESHOT_PRESSED);
    696                             if (tap_count > 1) {
    697                                 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
    698                             }
    699                         }
    700 #        endif
    701                     }
    702 #    else  // NO_ACTION_ONESHOT && NO_ACTION_TAPPING
    703                     if (event.pressed) {
    704                         layer_on(action.layer_tap.val);
    705                     } else {
    706                         layer_off(action.layer_tap.val);
    707                     }
    708 #    endif // !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
    709                     break;
    710                 default:
    711 #    ifndef NO_ACTION_TAPPING /* tap key */
    712                     if (event.pressed) {
    713                         if (tap_count > 0) {
    714                             ac_dprintf("KEYMAP_TAP_KEY: Tap: register_code\n");
    715                             register_code(action.layer_tap.code);
    716                         } else {
    717                             ac_dprintf("KEYMAP_TAP_KEY: No tap: On on press\n");
    718                             layer_on(action.layer_tap.val);
    719                         }
    720                     } else {
    721                         if (tap_count > 0) {
    722                             ac_dprintf("KEYMAP_TAP_KEY: Tap: unregister_code\n");
    723                             if (action.layer_tap.code == KC_CAPS_LOCK) {
    724                                 wait_ms(TAP_HOLD_CAPS_DELAY);
    725                             } else {
    726                                 wait_ms(TAP_CODE_DELAY);
    727                             }
    728                             unregister_code(action.layer_tap.code);
    729                         } else {
    730                             ac_dprintf("KEYMAP_TAP_KEY: No tap: Off on release\n");
    731                             layer_off(action.layer_tap.val);
    732                         }
    733                     }
    734 #    else
    735                     if (event.pressed) {
    736                         ac_dprintf("KEYMAP_TAP_KEY: Tap: register_code\n");
    737                         register_code(action.layer_tap.code);
    738                     } else {
    739                         ac_dprintf("KEYMAP_TAP_KEY: Tap: unregister_code\n");
    740                         if (action.layer_tap.code == KC_CAPS) {
    741                             wait_ms(TAP_HOLD_CAPS_DELAY);
    742                         } else {
    743                             wait_ms(TAP_CODE_DELAY);
    744                         }
    745                         unregister_code(action.layer_tap.code);
    746                     }
    747 #    endif
    748                     break;
    749             }
    750             break;
    751 #endif // NO_ACTION_LAYER
    752 
    753 #ifdef SWAP_HANDS_ENABLE
    754         case ACT_SWAP_HANDS:
    755             switch (action.swap.code) {
    756                 case OP_SH_TOGGLE:
    757                     if (event.pressed) {
    758                         swap_hands = !swap_hands;
    759                     }
    760                     break;
    761                 case OP_SH_ON_OFF:
    762                     swap_hands = event.pressed;
    763                     break;
    764                 case OP_SH_OFF_ON:
    765                     swap_hands = !event.pressed;
    766                     break;
    767                 case OP_SH_ON:
    768                     if (!event.pressed) {
    769                         swap_hands = true;
    770                     }
    771                     break;
    772                 case OP_SH_OFF:
    773                     if (!event.pressed) {
    774                         swap_hands = false;
    775                     }
    776                     break;
    777 #    ifndef NO_ACTION_ONESHOT
    778                 case OP_SH_ONESHOT:
    779                     if (event.pressed) {
    780                         set_oneshot_swaphands();
    781                     } else {
    782                         release_oneshot_swaphands();
    783                     }
    784                     break;
    785 #    endif
    786 
    787 #    ifndef NO_ACTION_TAPPING
    788                 case OP_SH_TAP_TOGGLE:
    789                     /* tap toggle */
    790 
    791                     if (event.pressed) {
    792                         if (swap_held) {
    793                             swap_held = false;
    794                         } else {
    795                             swap_hands = !swap_hands;
    796                         }
    797                     } else {
    798                         if (tap_count < TAPPING_TOGGLE) {
    799                             swap_hands = !swap_hands;
    800                         }
    801                     }
    802                     break;
    803                 default:
    804                     /* tap key */
    805                     if (tap_count > 0) {
    806                         if (swap_held) {
    807                             swap_hands = !swap_hands; // undo hold set up in _tap_hint
    808                             swap_held  = false;
    809                         }
    810                         if (event.pressed) {
    811                             register_code(action.swap.code);
    812                         } else {
    813                             wait_ms(TAP_CODE_DELAY);
    814                             unregister_code(action.swap.code);
    815                             *record = (keyrecord_t){}; // hack: reset tap mode
    816                         }
    817                     } else {
    818                         if (swap_held && !event.pressed) {
    819                             swap_hands = !swap_hands; // undo hold set up in _tap_hint
    820                             swap_held  = false;
    821                         }
    822                     }
    823 #    endif
    824             }
    825 #endif
    826         default:
    827             break;
    828     }
    829 
    830 #ifndef NO_ACTION_LAYER
    831     // if this event is a layer action, update the leds
    832     switch (action.kind.id) {
    833         case ACT_LAYER:
    834         case ACT_LAYER_MODS:
    835 #    ifndef NO_ACTION_TAPPING
    836         case ACT_LAYER_TAP:
    837         case ACT_LAYER_TAP_EXT:
    838 #    endif
    839             led_set(host_keyboard_leds());
    840 #    ifndef NO_ACTION_ONESHOT
    841             // don't release the key
    842             do_release_oneshot = false;
    843 #    endif
    844             break;
    845         default:
    846             break;
    847     }
    848 #endif
    849 
    850 #ifndef NO_ACTION_TAPPING
    851 #    if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
    852     if (is_tap_action(action)) {
    853         if (event.pressed) {
    854             if (tap_count > 0) {
    855                 retro_tap_primed = false;
    856             } else {
    857 #        if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
    858                 retro_tap_curr_mods = retro_tap_next_mods;
    859                 retro_tap_next_mods = get_mods();
    860 #        endif
    861             }
    862         } else {
    863             uint16_t event_keycode = get_event_keycode(event, false);
    864 #        if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
    865             uint8_t curr_mods = get_mods();
    866 #        endif
    867             if (tap_count > 0) {
    868                 retro_tap_primed = false;
    869             } else if (retro_tap_curr_key == event_keycode) {
    870                 if (
    871 #        ifdef RETRO_TAPPING_PER_KEY
    872                     get_retro_tapping(event_keycode, record) &&
    873 #        endif
    874                     retro_tap_primed) {
    875 #        if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
    876                     process_auto_shift(action.layer_tap.code, record);
    877 #        else
    878                     register_mods(retro_tap_curr_mods);
    879                     wait_ms(TAP_CODE_DELAY);
    880                     tap_code(action.layer_tap.code);
    881                     wait_ms(TAP_CODE_DELAY);
    882                     unregister_mods(retro_tap_curr_mods);
    883 #        endif
    884                 }
    885                 retro_tap_primed = false;
    886             }
    887 #        if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
    888             retro_tap_next_mods = curr_mods;
    889 #        endif
    890         }
    891     }
    892 #    endif
    893 #endif
    894 
    895 #ifdef SWAP_HANDS_ENABLE
    896 #    ifndef NO_ACTION_ONESHOT
    897     if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) {
    898         use_oneshot_swaphands();
    899     }
    900 #    endif
    901 #endif
    902 
    903 #ifndef NO_ACTION_ONESHOT
    904     /* Because we switch layers after a oneshot event, we need to release the
    905      * key before we leave the layer or no key up event will be generated.
    906      */
    907     if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED)) {
    908         record->event.pressed = false;
    909         layer_on(get_oneshot_layer());
    910         process_record(record);
    911         layer_off(get_oneshot_layer());
    912     }
    913 #endif
    914 }
    915 
    916 /** \brief Utilities for actions. (FIXME: Needs better description)
    917  *
    918  * FIXME: Needs documentation.
    919  */
    920 __attribute__((weak)) void register_code(uint8_t code) {
    921     if (code == KC_NO) {
    922         return;
    923 
    924 #ifdef LOCKING_SUPPORT_ENABLE
    925     } else if (KC_LOCKING_CAPS_LOCK == code) {
    926 #    ifdef LOCKING_RESYNC_ENABLE
    927         // Resync: ignore if caps lock already is on
    928         if (host_keyboard_led_state().caps_lock) return;
    929 #    endif
    930         add_key(KC_CAPS_LOCK);
    931         send_keyboard_report();
    932         wait_ms(TAP_HOLD_CAPS_DELAY);
    933         del_key(KC_CAPS_LOCK);
    934         send_keyboard_report();
    935 
    936     } else if (KC_LOCKING_NUM_LOCK == code) {
    937 #    ifdef LOCKING_RESYNC_ENABLE
    938         if (host_keyboard_led_state().num_lock) return;
    939 #    endif
    940         add_key(KC_NUM_LOCK);
    941         send_keyboard_report();
    942         wait_ms(100);
    943         del_key(KC_NUM_LOCK);
    944         send_keyboard_report();
    945 
    946     } else if (KC_LOCKING_SCROLL_LOCK == code) {
    947 #    ifdef LOCKING_RESYNC_ENABLE
    948         if (host_keyboard_led_state().scroll_lock) return;
    949 #    endif
    950         add_key(KC_SCROLL_LOCK);
    951         send_keyboard_report();
    952         wait_ms(100);
    953         del_key(KC_SCROLL_LOCK);
    954         send_keyboard_report();
    955 #endif
    956 
    957     } else if (IS_BASIC_KEYCODE(code)) {
    958         // TODO: should push command_proc out of this block?
    959         if (command_proc(code)) return;
    960 
    961         // Force a new key press if the key is already pressed
    962         // without this, keys with the same keycode, but different
    963         // modifiers will be reported incorrectly, see issue #1708
    964         if (is_key_pressed(code)) {
    965             del_key(code);
    966             send_keyboard_report();
    967         }
    968         add_key(code);
    969         send_keyboard_report();
    970     } else if (IS_MODIFIER_KEYCODE(code)) {
    971         add_mods(MOD_BIT(code));
    972         send_keyboard_report();
    973 
    974 #ifdef EXTRAKEY_ENABLE
    975     } else if (IS_SYSTEM_KEYCODE(code)) {
    976         host_system_send(KEYCODE2SYSTEM(code));
    977     } else if (IS_CONSUMER_KEYCODE(code)) {
    978         host_consumer_send(KEYCODE2CONSUMER(code));
    979 #endif
    980 
    981     } else if (IS_MOUSE_KEYCODE(code)) {
    982         register_mouse(code, true);
    983     }
    984 }
    985 
    986 /** \brief Utilities for actions. (FIXME: Needs better description)
    987  *
    988  * FIXME: Needs documentation.
    989  */
    990 __attribute__((weak)) void unregister_code(uint8_t code) {
    991     if (code == KC_NO) {
    992         return;
    993 
    994 #ifdef LOCKING_SUPPORT_ENABLE
    995     } else if (KC_LOCKING_CAPS_LOCK == code) {
    996 #    ifdef LOCKING_RESYNC_ENABLE
    997         // Resync: ignore if caps lock already is off
    998         if (!host_keyboard_led_state().caps_lock) return;
    999 #    endif
   1000         add_key(KC_CAPS_LOCK);
   1001         send_keyboard_report();
   1002         del_key(KC_CAPS_LOCK);
   1003         send_keyboard_report();
   1004 
   1005     } else if (KC_LOCKING_NUM_LOCK == code) {
   1006 #    ifdef LOCKING_RESYNC_ENABLE
   1007         if (!host_keyboard_led_state().num_lock) return;
   1008 #    endif
   1009         add_key(KC_NUM_LOCK);
   1010         send_keyboard_report();
   1011         del_key(KC_NUM_LOCK);
   1012         send_keyboard_report();
   1013 
   1014     } else if (KC_LOCKING_SCROLL_LOCK == code) {
   1015 #    ifdef LOCKING_RESYNC_ENABLE
   1016         if (!host_keyboard_led_state().scroll_lock) return;
   1017 #    endif
   1018         add_key(KC_SCROLL_LOCK);
   1019         send_keyboard_report();
   1020         del_key(KC_SCROLL_LOCK);
   1021         send_keyboard_report();
   1022 #endif
   1023 
   1024     } else if (IS_BASIC_KEYCODE(code)) {
   1025         del_key(code);
   1026         send_keyboard_report();
   1027     } else if (IS_MODIFIER_KEYCODE(code)) {
   1028         del_mods(MOD_BIT(code));
   1029         send_keyboard_report();
   1030 
   1031 #ifdef EXTRAKEY_ENABLE
   1032     } else if (IS_SYSTEM_KEYCODE(code)) {
   1033         host_system_send(0);
   1034     } else if (IS_CONSUMER_KEYCODE(code)) {
   1035         host_consumer_send(0);
   1036 #endif
   1037 
   1038     } else if (IS_MOUSE_KEYCODE(code)) {
   1039         register_mouse(code, false);
   1040     }
   1041 }
   1042 
   1043 /** \brief Tap a keycode with a delay.
   1044  *
   1045  * \param code The basic keycode to tap.
   1046  * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it.
   1047  */
   1048 __attribute__((weak)) void tap_code_delay(uint8_t code, uint16_t delay) {
   1049     register_code(code);
   1050     wait_ms(delay);
   1051     unregister_code(code);
   1052 }
   1053 
   1054 /** \brief Tap a keycode with the default delay.
   1055  *
   1056  * \param code The basic keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
   1057  */
   1058 __attribute__((weak)) void tap_code(uint8_t code) {
   1059     tap_code_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY);
   1060 }
   1061 
   1062 /** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
   1063  *
   1064  * \param mods A bitfield of modifiers to register.
   1065  */
   1066 __attribute__((weak)) void register_mods(uint8_t mods) {
   1067     if (mods) {
   1068         add_mods(mods);
   1069         send_keyboard_report();
   1070     }
   1071 }
   1072 
   1073 /** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately.
   1074  *
   1075  * \param mods A bitfield of modifiers to unregister.
   1076  */
   1077 __attribute__((weak)) void unregister_mods(uint8_t mods) {
   1078     if (mods) {
   1079         del_mods(mods);
   1080         send_keyboard_report();
   1081     }
   1082 }
   1083 
   1084 /** \brief Adds the given weak modifiers and sends a keyboard report immediately.
   1085  *
   1086  * \param mods A bitfield of modifiers to register.
   1087  */
   1088 __attribute__((weak)) void register_weak_mods(uint8_t mods) {
   1089     if (mods) {
   1090         add_weak_mods(mods);
   1091         send_keyboard_report();
   1092     }
   1093 }
   1094 
   1095 /** \brief Removes the given weak modifiers and sends a keyboard report immediately.
   1096  *
   1097  * \param mods A bitfield of modifiers to unregister.
   1098  */
   1099 __attribute__((weak)) void unregister_weak_mods(uint8_t mods) {
   1100     if (mods) {
   1101         del_weak_mods(mods);
   1102         send_keyboard_report();
   1103     }
   1104 }
   1105 
   1106 /** \brief Utilities for actions. (FIXME: Needs better description)
   1107  *
   1108  * FIXME: Needs documentation.
   1109  */
   1110 void clear_keyboard(void) {
   1111     clear_mods();
   1112     clear_keyboard_but_mods();
   1113 }
   1114 
   1115 /** \brief Utilities for actions. (FIXME: Needs better description)
   1116  *
   1117  * FIXME: Needs documentation.
   1118  */
   1119 void clear_keyboard_but_mods(void) {
   1120     clear_keys();
   1121     clear_keyboard_but_mods_and_keys();
   1122 }
   1123 
   1124 /** \brief Utilities for actions. (FIXME: Needs better description)
   1125  *
   1126  * FIXME: Needs documentation.
   1127  */
   1128 void clear_keyboard_but_mods_and_keys(void) {
   1129 #ifdef EXTRAKEY_ENABLE
   1130     host_system_send(0);
   1131     host_consumer_send(0);
   1132 #endif
   1133     clear_weak_mods();
   1134     send_keyboard_report();
   1135 #ifdef MOUSEKEY_ENABLE
   1136     mousekey_clear();
   1137     mousekey_send();
   1138 #endif
   1139 #ifdef PROGRAMMABLE_BUTTON_ENABLE
   1140     programmable_button_clear();
   1141 #endif
   1142 }
   1143 
   1144 /** \brief Utilities for actions. (FIXME: Needs better description)
   1145  *
   1146  * FIXME: Needs documentation.
   1147  */
   1148 bool is_tap_record(keyrecord_t *record) {
   1149     if (IS_NOEVENT(record->event)) {
   1150         return false;
   1151     }
   1152 
   1153 #if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE)
   1154     action_t action;
   1155     if (record->keycode) {
   1156         action = action_for_keycode(record->keycode);
   1157     } else {
   1158         action = layer_switch_get_action(record->event.key);
   1159     }
   1160 #else
   1161     action_t action = layer_switch_get_action(record->event.key);
   1162 #endif
   1163     return is_tap_action(action);
   1164 }
   1165 
   1166 /** \brief Utilities for actions. (FIXME: Needs better description)
   1167  *
   1168  * FIXME: Needs documentation.
   1169  */
   1170 bool is_tap_action(action_t action) {
   1171     switch (action.kind.id) {
   1172         case ACT_LMODS_TAP:
   1173         case ACT_RMODS_TAP:
   1174         case ACT_LAYER_TAP:
   1175         case ACT_LAYER_TAP_EXT:
   1176             switch (action.layer_tap.code) {
   1177                 case KC_NO ... KC_RIGHT_GUI:
   1178                 case OP_TAP_TOGGLE:
   1179                 case OP_ONESHOT:
   1180                     return true;
   1181             }
   1182             return false;
   1183         case ACT_SWAP_HANDS:
   1184             switch (action.swap.code) {
   1185                 case KC_NO ... KC_RIGHT_GUI:
   1186                 case OP_SH_TAP_TOGGLE:
   1187                     return true;
   1188             }
   1189             return false;
   1190     }
   1191     return false;
   1192 }
   1193 
   1194 uint16_t get_tap_keycode(uint16_t keycode) {
   1195     switch (keycode) {
   1196         case QK_MOD_TAP ... QK_MOD_TAP_MAX:
   1197             return QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
   1198         case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
   1199             return QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
   1200         case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
   1201             // IS_SWAP_HANDS_KEYCODE() tests for the special action keycodes
   1202             // like SH_TOGG, SH_TT, ..., which overlap the SH_T(kc) range.
   1203             if (!IS_SWAP_HANDS_KEYCODE(keycode)) {
   1204                 return QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode);
   1205             }
   1206             break;
   1207     }
   1208     return keycode;
   1209 }
   1210 
   1211 /** \brief Debug print (FIXME: Needs better description)
   1212  *
   1213  * FIXME: Needs documentation.
   1214  */
   1215 void debug_event(keyevent_t event) {
   1216     ac_dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
   1217 }
   1218 /** \brief Debug print (FIXME: Needs better description)
   1219  *
   1220  * FIXME: Needs documentation.
   1221  */
   1222 void debug_record(keyrecord_t record) {
   1223     debug_event(record.event);
   1224 #ifndef NO_ACTION_TAPPING
   1225     ac_dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
   1226 #endif
   1227 }
   1228 
   1229 /** \brief Debug print (FIXME: Needs better description)
   1230  *
   1231  * FIXME: Needs documentation.
   1232  */
   1233 void debug_action(action_t action) {
   1234     switch (action.kind.id) {
   1235         case ACT_LMODS:
   1236             ac_dprintf("ACT_LMODS");
   1237             break;
   1238         case ACT_RMODS:
   1239             ac_dprintf("ACT_RMODS");
   1240             break;
   1241         case ACT_LMODS_TAP:
   1242             ac_dprintf("ACT_LMODS_TAP");
   1243             break;
   1244         case ACT_RMODS_TAP:
   1245             ac_dprintf("ACT_RMODS_TAP");
   1246             break;
   1247         case ACT_USAGE:
   1248             ac_dprintf("ACT_USAGE");
   1249             break;
   1250         case ACT_MOUSEKEY:
   1251             ac_dprintf("ACT_MOUSEKEY");
   1252             break;
   1253         case ACT_LAYER:
   1254             ac_dprintf("ACT_LAYER");
   1255             break;
   1256         case ACT_LAYER_MODS:
   1257             ac_dprintf("ACT_LAYER_MODS");
   1258             break;
   1259         case ACT_LAYER_TAP:
   1260             ac_dprintf("ACT_LAYER_TAP");
   1261             break;
   1262         case ACT_LAYER_TAP_EXT:
   1263             ac_dprintf("ACT_LAYER_TAP_EXT");
   1264             break;
   1265         case ACT_SWAP_HANDS:
   1266             ac_dprintf("ACT_SWAP_HANDS");
   1267             break;
   1268         default:
   1269             ac_dprintf("UNKNOWN");
   1270             break;
   1271     }
   1272     ac_dprintf("[%X:%02X]", action.kind.param >> 8, action.kind.param & 0xff);
   1273 }