]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/action.c
Make Caps Lock delay more reasonable (#6199)
[qmk_firmware.git] / tmk_core / common / action.c
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 "host.h"
18 #include "keycode.h"
19 #include "keyboard.h"
20 #include "mousekey.h"
21 #include "command.h"
22 #include "led.h"
23 #include "backlight.h"
24 #include "action_layer.h"
25 #include "action_tapping.h"
26 #include "action_macro.h"
27 #include "action_util.h"
28 #include "action.h"
29 #include "wait.h"
30
31 #ifdef DEBUG_ACTION
32 #include "debug.h"
33 #else
34 #include "nodebug.h"
35 #endif
36
37 int tp_buttons;
38
39 #ifdef RETRO_TAPPING
40 int retro_tapping_counter = 0;
41 #endif
42
43 #ifdef FAUXCLICKY_ENABLE
44 #include <fauxclicky.h>
45 #endif
46
47 #ifndef TAP_HOLD_CAPS_DELAY
48 #  define TAP_HOLD_CAPS_DELAY 80
49 #endif
50 /** \brief Called to execute an action.
51  *
52  * FIXME: Needs documentation.
53  */
54 void action_exec(keyevent_t event)
55 {
56     if (!IS_NOEVENT(event)) {
57         dprint("\n---- action_exec: start -----\n");
58         dprint("EVENT: "); debug_event(event); dprintln();
59 #ifdef RETRO_TAPPING
60         retro_tapping_counter++;
61 #endif
62     }
63
64 #ifdef FAUXCLICKY_ENABLE
65     if (IS_PRESSED(event)) {
66         FAUXCLICKY_ACTION_PRESS;
67     }
68     if (IS_RELEASED(event)) {
69         FAUXCLICKY_ACTION_RELEASE;
70     }
71     fauxclicky_check();
72 #endif
73
74 #ifdef SWAP_HANDS_ENABLE
75     if (!IS_NOEVENT(event)) {
76         process_hand_swap(&event);
77     }
78 #endif
79
80     keyrecord_t record = { .event = event };
81
82 #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
83     if (has_oneshot_layer_timed_out()) {
84         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
85     }
86     if (has_oneshot_mods_timed_out()) {
87         clear_oneshot_mods();
88     }
89 #endif
90
91 #ifndef NO_ACTION_TAPPING
92     action_tapping_process(record);
93 #else
94     process_record(&record);
95     if (!IS_NOEVENT(record.event)) {
96         dprint("processed: "); debug_record(record); dprintln();
97     }
98 #endif
99 }
100
101 #ifdef SWAP_HANDS_ENABLE
102 bool swap_hands = false;
103 bool swap_held = false;
104
105 /** \brief Process Hand Swap
106  *
107  * FIXME: Needs documentation.
108  */
109 void process_hand_swap(keyevent_t *event) {
110     static swap_state_row_t swap_state[MATRIX_ROWS];
111
112     keypos_t pos = event->key;
113     swap_state_row_t col_bit = (swap_state_row_t)1<<pos.col;
114     bool do_swap = event->pressed ? swap_hands :
115                                     swap_state[pos.row] & (col_bit);
116
117     if (do_swap) {
118         event->key = hand_swap_config[pos.row][pos.col];
119         swap_state[pos.row] |= col_bit;
120     } else {
121         swap_state[pos.row] &= ~(col_bit);
122     }
123 }
124 #endif
125
126 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
127 bool disable_action_cache = false;
128
129 void process_record_nocache(keyrecord_t *record)
130 {
131     disable_action_cache = true;
132     process_record(record);
133     disable_action_cache = false;
134 }
135 #else
136 void process_record_nocache(keyrecord_t *record)
137 {
138     process_record(record);
139 }
140 #endif
141
142 __attribute__ ((weak))
143 bool process_record_quantum(keyrecord_t *record) {
144     return true;
145 }
146
147 #ifndef NO_ACTION_TAPPING
148 /** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress.
149  *
150  * FIXME: Needs documentation.
151  */
152 void process_record_tap_hint(keyrecord_t *record)
153 {
154     action_t action = layer_switch_get_action(record->event.key);
155
156     switch (action.kind.id) {
157 #ifdef SWAP_HANDS_ENABLE
158         case ACT_SWAP_HANDS:
159             switch (action.swap.code) {
160                 case OP_SH_TAP_TOGGLE:
161                 default:
162                     swap_hands = !swap_hands;
163                     swap_held = true;
164             }
165             break;
166 #endif
167     }
168 }
169 #endif
170
171 /** \brief Take a key event (key press or key release) and processes it.
172  *
173  * FIXME: Needs documentation.
174  */
175 void process_record(keyrecord_t *record)
176 {
177     if (IS_NOEVENT(record->event)) { return; }
178
179     if(!process_record_quantum(record))
180         return;
181
182     action_t action = store_or_get_action(record->event.pressed, record->event.key);
183     dprint("ACTION: "); debug_action(action);
184 #ifndef NO_ACTION_LAYER
185     dprint(" layer_state: "); layer_debug();
186     dprint(" default_layer_state: "); default_layer_debug();
187 #endif
188     dprintln();
189
190     process_action(record, action);
191 }
192
193 /** \brief Take an action and processes it.
194  *
195  * FIXME: Needs documentation.
196  */
197 void process_action(keyrecord_t *record, action_t action)
198 {
199     keyevent_t event = record->event;
200 #ifndef NO_ACTION_TAPPING
201     uint8_t tap_count = record->tap.count;
202 #endif
203
204     if (event.pressed) {
205         // clear the potential weak mods left by previously pressed keys
206         clear_weak_mods();
207     }
208
209 #ifndef NO_ACTION_ONESHOT
210     bool do_release_oneshot = false;
211     // notice we only clear the one shot layer if the pressed key is not a modifier.
212     if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
213         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
214         do_release_oneshot = !is_oneshot_layer_active();
215     }
216 #endif
217
218     switch (action.kind.id) {
219         /* Key and Mods */
220         case ACT_LMODS:
221         case ACT_RMODS:
222             {
223                 uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
224                                                                 action.key.mods<<4;
225                 if (event.pressed) {
226                     if (mods) {
227                         if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
228                             // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
229                             // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
230                             // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
231                             add_mods(mods);
232                         } else {
233                             add_weak_mods(mods);
234                         }
235                         send_keyboard_report();
236                     }
237                     register_code(action.key.code);
238                 } else {
239                     unregister_code(action.key.code);
240                     if (mods) {
241                         if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
242                             del_mods(mods);
243                         } else {
244                             del_weak_mods(mods);
245                         }
246                         send_keyboard_report();
247                     }
248                 }
249             }
250             break;
251 #ifndef NO_ACTION_TAPPING
252         case ACT_LMODS_TAP:
253         case ACT_RMODS_TAP:
254             {
255                 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
256                                                                     action.key.mods<<4;
257                 switch (action.layer_tap.code) {
258     #ifndef NO_ACTION_ONESHOT
259                     case MODS_ONESHOT:
260                         // Oneshot modifier
261                         if (event.pressed) {
262                             if (tap_count == 0) {
263                                 dprint("MODS_TAP: Oneshot: 0\n");
264                                 register_mods(mods | get_oneshot_mods());
265                             } else if (tap_count == 1) {
266                                 dprint("MODS_TAP: Oneshot: start\n");
267                                 set_oneshot_mods(mods | get_oneshot_mods());
268                     #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
269                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
270                                 dprint("MODS_TAP: Toggling oneshot");
271                                 clear_oneshot_mods();
272                                 set_oneshot_locked_mods(mods);
273                                 register_mods(mods);
274                     #endif
275                             } else {
276                                 register_mods(mods | get_oneshot_mods());
277                             }
278                         } else {
279                             if (tap_count == 0) {
280                                 clear_oneshot_mods();
281                                 unregister_mods(mods);
282                             } else if (tap_count == 1) {
283                                 // Retain Oneshot mods
284                     #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
285                                 if (mods & get_mods()) {
286                                     clear_oneshot_locked_mods();
287                                     clear_oneshot_mods();
288                                     unregister_mods(mods);
289                                 }
290                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
291                                 // Toggle Oneshot Layer
292                     #endif
293                             } else {
294                                 clear_oneshot_mods();
295                                 unregister_mods(mods);
296                             }
297                         }
298                         break;
299     #endif
300                     case MODS_TAP_TOGGLE:
301                         if (event.pressed) {
302                             if (tap_count <= TAPPING_TOGGLE) {
303                                 register_mods(mods);
304                             }
305                         } else {
306                             if (tap_count < TAPPING_TOGGLE) {
307                                 unregister_mods(mods);
308                             }
309                         }
310                         break;
311                     default:
312                         if (event.pressed) {
313                             if (tap_count > 0) {
314 #ifndef IGNORE_MOD_TAP_INTERRUPT
315                                 if (record->tap.interrupted) {
316                                     dprint("mods_tap: tap: cancel: add_mods\n");
317                                     // ad hoc: set 0 to cancel tap
318                                     record->tap.count = 0;
319                                     register_mods(mods);
320                                 } else
321 #endif
322                                 {
323                                     dprint("MODS_TAP: Tap: register_code\n");
324                                     register_code(action.key.code);
325                                 }
326                             } else {
327                                 dprint("MODS_TAP: No tap: add_mods\n");
328                                 register_mods(mods);
329                             }
330                         } else {
331                             if (tap_count > 0) {
332                                 dprint("MODS_TAP: Tap: unregister_code\n");
333                                 unregister_code(action.key.code);
334                             } else {
335                                 dprint("MODS_TAP: No tap: add_mods\n");
336                                 unregister_mods(mods);
337                             }
338                         }
339                         break;
340                 }
341             }
342             break;
343 #endif
344 #ifdef EXTRAKEY_ENABLE
345         /* other HID usage */
346         case ACT_USAGE:
347             switch (action.usage.page) {
348                 case PAGE_SYSTEM:
349                     if (event.pressed) {
350                         host_system_send(action.usage.code);
351                     } else {
352                         host_system_send(0);
353                     }
354                     break;
355                 case PAGE_CONSUMER:
356                     if (event.pressed) {
357                         host_consumer_send(action.usage.code);
358                     } else {
359                         host_consumer_send(0);
360                     }
361                     break;
362             }
363             break;
364 #endif
365 #ifdef MOUSEKEY_ENABLE
366         /* Mouse key */
367         case ACT_MOUSEKEY:
368             if (event.pressed) {
369                 switch (action.key.code) {
370                     case KC_MS_BTN1:
371                         tp_buttons |= (1<<0);
372                         break;
373                     case KC_MS_BTN2:
374                         tp_buttons |= (1<<1);
375                         break;
376                     case KC_MS_BTN3:
377                         tp_buttons |= (1<<2);
378                         break;
379                     default:
380                         break;
381                 }
382                 mousekey_on(action.key.code);
383                 mousekey_send();
384             } else {
385                 switch (action.key.code) {
386                     case KC_MS_BTN1:
387                         tp_buttons &= ~(1<<0);
388                         break;
389                     case KC_MS_BTN2:
390                         tp_buttons &= ~(1<<1);
391                         break;
392                     case KC_MS_BTN3:
393                         tp_buttons &= ~(1<<2);
394                         break;
395                     default:
396                         break;
397                 }
398                 mousekey_off(action.key.code);
399                 mousekey_send();
400             }
401             break;
402 #endif
403 #ifndef NO_ACTION_LAYER
404         case ACT_LAYER:
405             if (action.layer_bitop.on == 0) {
406                 /* Default Layer Bitwise Operation */
407                 if (!event.pressed) {
408                     uint8_t shift = action.layer_bitop.part*4;
409                     layer_state_t bits = ((layer_state_t)action.layer_bitop.bits)<<shift;
410                     layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf)<<shift) : 0;
411                     switch (action.layer_bitop.op) {
412                         case OP_BIT_AND: default_layer_and(bits | mask); break;
413                         case OP_BIT_OR:  default_layer_or(bits | mask);  break;
414                         case OP_BIT_XOR: default_layer_xor(bits | mask); break;
415                         case OP_BIT_SET: default_layer_set(bits | mask); break;
416                     }
417                 }
418             } else {
419                 /* Layer Bitwise Operation */
420                 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
421                                     (action.layer_bitop.on & ON_RELEASE)) {
422                     uint8_t shift = action.layer_bitop.part*4;
423                     layer_state_t bits = ((layer_state_t)action.layer_bitop.bits)<<shift;
424                     layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf)<<shift) : 0;
425                     switch (action.layer_bitop.op) {
426                         case OP_BIT_AND: layer_and(bits | mask); break;
427                         case OP_BIT_OR:  layer_or(bits | mask);  break;
428                         case OP_BIT_XOR: layer_xor(bits | mask); break;
429                         case OP_BIT_SET: layer_state_set(bits | mask); break;
430                     }
431                 }
432             }
433             break;
434     #ifndef NO_ACTION_TAPPING
435         case ACT_LAYER_TAP:
436         case ACT_LAYER_TAP_EXT:
437             switch (action.layer_tap.code) {
438                 case 0xe0 ... 0xef:
439                     /* layer On/Off with modifiers(left only) */
440                     if (event.pressed) {
441                         layer_on(action.layer_tap.val);
442                         register_mods(action.layer_tap.code & 0x0f);
443                     } else {
444                         layer_off(action.layer_tap.val);
445                         unregister_mods(action.layer_tap.code & 0x0f);
446                     }
447                     break;
448                 case OP_TAP_TOGGLE:
449                     /* tap toggle */
450                     if (event.pressed) {
451                         if (tap_count < TAPPING_TOGGLE) {
452                             layer_invert(action.layer_tap.val);
453                         }
454                     } else {
455                         if (tap_count <= TAPPING_TOGGLE) {
456                             layer_invert(action.layer_tap.val);
457                         }
458                     }
459                     break;
460                 case OP_ON_OFF:
461                     event.pressed ? layer_on(action.layer_tap.val) :
462                                     layer_off(action.layer_tap.val);
463                     break;
464                 case OP_OFF_ON:
465                     event.pressed ? layer_off(action.layer_tap.val) :
466                                     layer_on(action.layer_tap.val);
467                     break;
468                 case OP_SET_CLEAR:
469                     event.pressed ? layer_move(action.layer_tap.val) :
470                                     layer_clear();
471                     break;
472             #ifndef NO_ACTION_ONESHOT
473                 case OP_ONESHOT:
474                     // Oneshot modifier
475                 #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
476                     do_release_oneshot = false;
477                     if (event.pressed) {
478                         del_mods(get_oneshot_locked_mods());
479                         if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
480                             reset_oneshot_layer();
481                             layer_off(action.layer_tap.val);
482                             break;
483                         } else if (tap_count < ONESHOT_TAP_TOGGLE) {
484                             layer_on(action.layer_tap.val);
485                             set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
486                         }
487                     } else {
488                         add_mods(get_oneshot_locked_mods());
489                         if (tap_count >= ONESHOT_TAP_TOGGLE) {
490                             reset_oneshot_layer();
491                             clear_oneshot_locked_mods();
492                             set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
493                         } else {
494                             clear_oneshot_layer_state(ONESHOT_PRESSED);
495                         }
496                     }
497                 #else
498                     if (event.pressed) {
499                         layer_on(action.layer_tap.val);
500                         set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
501                     } else {
502                         clear_oneshot_layer_state(ONESHOT_PRESSED);
503                         if (tap_count > 1) {
504                             clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
505                         }
506                     }
507                 #endif
508                     break;
509             #endif
510                 default:
511                     /* tap key */
512                     if (event.pressed) {
513                         if (tap_count > 0) {
514                             dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
515                             register_code(action.layer_tap.code);
516                         } else {
517                             dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
518                             layer_on(action.layer_tap.val);
519                         }
520                     } else {
521                         if (tap_count > 0) {
522                             dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
523                             if (action.layer_tap.code == KC_CAPS) {
524                                 wait_ms(TAP_HOLD_CAPS_DELAY);
525                             }
526                             unregister_code(action.layer_tap.code);
527                         } else {
528                             dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
529                             layer_off(action.layer_tap.val);
530                         }
531                     }
532                     break;
533             }
534             break;
535     #endif
536 #endif
537         /* Extentions */
538 #ifndef NO_ACTION_MACRO
539         case ACT_MACRO:
540             action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
541             break;
542 #endif
543 #if defined(BACKLIGHT_ENABLE) | defined(LED_MATRIX_ENABLE)
544         case ACT_BACKLIGHT:
545             if (!event.pressed) {
546                 switch (action.backlight.opt) {
547                     case BACKLIGHT_INCREASE:
548                         backlight_increase();
549                         break;
550                     case BACKLIGHT_DECREASE:
551                         backlight_decrease();
552                         break;
553                     case BACKLIGHT_TOGGLE:
554                         backlight_toggle();
555                         break;
556                     case BACKLIGHT_STEP:
557                         backlight_step();
558                         break;
559                     case BACKLIGHT_ON:
560                         backlight_level(BACKLIGHT_LEVELS);
561                         break;
562                     case BACKLIGHT_OFF:
563                         backlight_level(0);
564                         break;
565                 }
566             }
567             break;
568 #endif
569         case ACT_COMMAND:
570             break;
571 #ifdef SWAP_HANDS_ENABLE
572         case ACT_SWAP_HANDS:
573             switch (action.swap.code) {
574                 case OP_SH_TOGGLE:
575                     if (event.pressed) {
576                         swap_hands = !swap_hands;
577                     }
578                     break;
579                 case OP_SH_ON_OFF:
580                     swap_hands = event.pressed;
581                     break;
582                 case OP_SH_OFF_ON:
583                     swap_hands = !event.pressed;
584                     break;
585                 case OP_SH_ON:
586                     if (!event.pressed) {
587                         swap_hands = true;
588                     }
589                     break;
590                 case OP_SH_OFF:
591                     if (!event.pressed) {
592                         swap_hands = false;
593                     }
594                     break;
595     #ifndef NO_ACTION_TAPPING
596                 case OP_SH_TAP_TOGGLE:
597                     /* tap toggle */
598
599                     if (event.pressed) {
600                         if (swap_held) {
601                             swap_held = false;
602                         } else {
603                             swap_hands = !swap_hands;
604                         }
605                     } else {
606                         if (tap_count < TAPPING_TOGGLE) {
607                             swap_hands = !swap_hands;
608                         }
609                     }
610                     break;
611                 default:
612                     /* tap key */
613                     if (tap_count > 0) {
614                         if (swap_held) {
615                             swap_hands = !swap_hands; // undo hold set up in _tap_hint
616                             swap_held = false;
617                         }
618                         if (event.pressed) {
619                             register_code(action.swap.code);
620                         } else {
621                             unregister_code(action.swap.code);
622                             *record = (keyrecord_t){}; // hack: reset tap mode
623                         }
624                     } else {
625                         if (swap_held && !event.pressed) {
626                             swap_hands = !swap_hands; // undo hold set up in _tap_hint
627                             swap_held = false;
628                         }
629                     }
630     #endif
631             }
632 #endif
633 #ifndef NO_ACTION_FUNCTION
634         case ACT_FUNCTION:
635             action_function(record, action.func.id, action.func.opt);
636             break;
637 #endif
638         default:
639             break;
640     }
641
642 #ifndef NO_ACTION_LAYER
643     // if this event is a layer action, update the leds
644     switch (action.kind.id) {
645         case ACT_LAYER:
646         #ifndef NO_ACTION_TAPPING
647         case ACT_LAYER_TAP:
648         case ACT_LAYER_TAP_EXT:
649         #endif
650             led_set(host_keyboard_leds());
651             break;
652         default:
653             break;
654     }
655 #endif
656
657 #ifndef NO_ACTION_TAPPING
658   #ifdef RETRO_TAPPING
659   if (!is_tap_action(action)) {
660     retro_tapping_counter = 0;
661   } else {
662     if (event.pressed) {
663         if (tap_count > 0) {
664           retro_tapping_counter = 0;
665         } else {
666
667         }
668     } else {
669       if (tap_count > 0) {
670         retro_tapping_counter = 0;
671       } else {
672         if (retro_tapping_counter == 2) {
673           register_code(action.layer_tap.code);
674           unregister_code(action.layer_tap.code);
675         }
676         retro_tapping_counter = 0;
677       }
678     }
679   }
680   #endif
681 #endif
682
683 #ifndef NO_ACTION_ONESHOT
684     /* Because we switch layers after a oneshot event, we need to release the
685      * key before we leave the layer or no key up event will be generated.
686      */
687     if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED )   ) {
688         record->event.pressed = false;
689         layer_on(get_oneshot_layer());
690         process_record(record);
691         layer_off(get_oneshot_layer());
692     }
693 #endif
694 }
695
696
697
698
699 /** \brief Utilities for actions. (FIXME: Needs better description)
700  *
701  * FIXME: Needs documentation.
702  */
703 void register_code(uint8_t code)
704 {
705     if (code == KC_NO) {
706         return;
707     }
708
709 #ifdef LOCKING_SUPPORT_ENABLE
710     else if (KC_LOCKING_CAPS == code) {
711 #ifdef LOCKING_RESYNC_ENABLE
712         // Resync: ignore if caps lock already is on
713         if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
714 #endif
715         add_key(KC_CAPSLOCK);
716         send_keyboard_report();
717         wait_ms(100);
718         del_key(KC_CAPSLOCK);
719         send_keyboard_report();
720     }
721
722     else if (KC_LOCKING_NUM == code) {
723 #ifdef LOCKING_RESYNC_ENABLE
724         if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
725 #endif
726         add_key(KC_NUMLOCK);
727         send_keyboard_report();
728         wait_ms(100);
729         del_key(KC_NUMLOCK);
730         send_keyboard_report();
731     }
732
733     else if (KC_LOCKING_SCROLL == code) {
734 #ifdef LOCKING_RESYNC_ENABLE
735         if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
736 #endif
737         add_key(KC_SCROLLLOCK);
738         send_keyboard_report();
739         wait_ms(100);
740         del_key(KC_SCROLLLOCK);
741         send_keyboard_report();
742     }
743 #endif
744
745     else if IS_KEY(code) {
746         // TODO: should push command_proc out of this block?
747         if (command_proc(code)) return;
748
749 #ifndef NO_ACTION_ONESHOT
750 /* TODO: remove
751         if (oneshot_state.mods && !oneshot_state.disabled) {
752             uint8_t tmp_mods = get_mods();
753             add_mods(oneshot_state.mods);
754
755             add_key(code);
756             send_keyboard_report();
757
758             set_mods(tmp_mods);
759             send_keyboard_report();
760             oneshot_cancel();
761         } else
762 */
763 #endif
764         {
765             add_key(code);
766             send_keyboard_report();
767         }
768     }
769     else if IS_MOD(code) {
770         add_mods(MOD_BIT(code));
771         send_keyboard_report();
772     }
773     else if IS_SYSTEM(code) {
774         host_system_send(KEYCODE2SYSTEM(code));
775     }
776     else if IS_CONSUMER(code) {
777         host_consumer_send(KEYCODE2CONSUMER(code));
778     }
779
780     #ifdef MOUSEKEY_ENABLE
781       else if IS_MOUSEKEY(code) {
782         mousekey_on(code);
783         mousekey_send();
784       }
785     #endif
786 }
787
788 /** \brief Utilities for actions. (FIXME: Needs better description)
789  *
790  * FIXME: Needs documentation.
791  */
792 void unregister_code(uint8_t code)
793 {
794     if (code == KC_NO) {
795         return;
796     }
797
798 #ifdef LOCKING_SUPPORT_ENABLE
799     else if (KC_LOCKING_CAPS == code) {
800 #ifdef LOCKING_RESYNC_ENABLE
801         // Resync: ignore if caps lock already is off
802         if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
803 #endif
804         add_key(KC_CAPSLOCK);
805         send_keyboard_report();
806         del_key(KC_CAPSLOCK);
807         send_keyboard_report();
808     }
809
810     else if (KC_LOCKING_NUM == code) {
811 #ifdef LOCKING_RESYNC_ENABLE
812         if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
813 #endif
814         add_key(KC_NUMLOCK);
815         send_keyboard_report();
816         del_key(KC_NUMLOCK);
817         send_keyboard_report();
818     }
819
820     else if (KC_LOCKING_SCROLL == code) {
821 #ifdef LOCKING_RESYNC_ENABLE
822         if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
823 #endif
824         add_key(KC_SCROLLLOCK);
825         send_keyboard_report();
826         del_key(KC_SCROLLLOCK);
827         send_keyboard_report();
828     }
829 #endif
830
831     else if IS_KEY(code) {
832         del_key(code);
833         send_keyboard_report();
834     }
835     else if IS_MOD(code) {
836         del_mods(MOD_BIT(code));
837         send_keyboard_report();
838     }
839     else if IS_SYSTEM(code) {
840         host_system_send(0);
841     }
842     else if IS_CONSUMER(code) {
843         host_consumer_send(0);
844     }
845     #ifdef MOUSEKEY_ENABLE
846       else if IS_MOUSEKEY(code) {
847         mousekey_off(code);
848         mousekey_send();
849       }
850     #endif
851 }
852
853 /** \brief Utilities for actions. (FIXME: Needs better description)
854  *
855  * FIXME: Needs documentation.
856  */
857 void tap_code(uint8_t code) {
858   register_code(code);
859   if (code == KC_CAPS) {
860     wait_ms(TAP_HOLD_CAPS_DELAY);
861   }
862   #if TAP_CODE_DELAY > 0
863   else {
864     wait_ms(TAP_CODE_DELAY);
865   }
866   #endif
867   unregister_code(code);
868 }
869
870 /** \brief Utilities for actions. (FIXME: Needs better description)
871  *
872  * FIXME: Needs documentation.
873  */
874 void register_mods(uint8_t mods)
875 {
876     if (mods) {
877         add_mods(mods);
878         send_keyboard_report();
879     }
880 }
881
882 /** \brief Utilities for actions. (FIXME: Needs better description)
883  *
884  * FIXME: Needs documentation.
885  */
886 void unregister_mods(uint8_t mods)
887 {
888     if (mods) {
889         del_mods(mods);
890         send_keyboard_report();
891     }
892 }
893
894 /** \brief Utilities for actions. (FIXME: Needs better description)
895  *
896  * FIXME: Needs documentation.
897  */
898 void clear_keyboard(void)
899 {
900     clear_mods();
901     clear_keyboard_but_mods();
902 }
903
904 /** \brief Utilities for actions. (FIXME: Needs better description)
905  *
906  * FIXME: Needs documentation.
907  */
908 void clear_keyboard_but_mods(void)
909 {
910     clear_keys();
911     clear_keyboard_but_mods_and_keys();
912 }
913
914 /** \brief Utilities for actions. (FIXME: Needs better description)
915  *
916  * FIXME: Needs documentation.
917  */
918 void clear_keyboard_but_mods_and_keys()
919 {
920     clear_weak_mods();
921     clear_macro_mods();
922     send_keyboard_report();
923 #ifdef MOUSEKEY_ENABLE
924     mousekey_clear();
925     mousekey_send();
926 #endif
927 #ifdef EXTRAKEY_ENABLE
928     host_system_send(0);
929     host_consumer_send(0);
930 #endif
931 }
932
933 /** \brief Utilities for actions. (FIXME: Needs better description)
934  *
935  * FIXME: Needs documentation.
936  */
937 bool is_tap_key(keypos_t key)
938 {
939     action_t action = layer_switch_get_action(key);
940     return is_tap_action(action);
941 }
942
943 /** \brief Utilities for actions. (FIXME: Needs better description)
944  *
945  * FIXME: Needs documentation.
946  */
947 bool is_tap_action(action_t action)
948 {
949     switch (action.kind.id) {
950         case ACT_LMODS_TAP:
951         case ACT_RMODS_TAP:
952         case ACT_LAYER_TAP:
953         case ACT_LAYER_TAP_EXT:
954             switch (action.layer_tap.code) {
955                 case 0x00 ... 0xdf:
956                 case OP_TAP_TOGGLE:
957                 case OP_ONESHOT:
958                     return true;
959             }
960             return false;
961         case ACT_SWAP_HANDS:
962             switch (action.swap.code) {
963                 case 0x00 ... 0xdf:
964                 case OP_SH_TAP_TOGGLE:
965                     return true;
966             }
967             return false;
968         case ACT_MACRO:
969         case ACT_FUNCTION:
970             if (action.func.opt & FUNC_TAP) { return true; }
971             return false;
972     }
973     return false;
974 }
975
976
977 /** \brief Debug print (FIXME: Needs better description)
978  *
979  * FIXME: Needs documentation.
980  */
981 void debug_event(keyevent_t event)
982 {
983     dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
984 }
985
986 /** \brief Debug print (FIXME: Needs better description)
987  *
988  * FIXME: Needs documentation.
989  */
990 void debug_record(keyrecord_t record)
991 {
992     debug_event(record.event);
993 #ifndef NO_ACTION_TAPPING
994     dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
995 #endif
996 }
997
998 /** \brief Debug print (FIXME: Needs better description)
999  *
1000  * FIXME: Needs documentation.
1001  */
1002 void debug_action(action_t action)
1003 {
1004     switch (action.kind.id) {
1005         case ACT_LMODS:             dprint("ACT_LMODS");             break;
1006         case ACT_RMODS:             dprint("ACT_RMODS");             break;
1007         case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
1008         case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
1009         case ACT_USAGE:             dprint("ACT_USAGE");             break;
1010         case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
1011         case ACT_LAYER:             dprint("ACT_LAYER");             break;
1012         case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
1013         case ACT_LAYER_TAP_EXT:     dprint("ACT_LAYER_TAP_EXT");     break;
1014         case ACT_MACRO:             dprint("ACT_MACRO");             break;
1015         case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
1016         case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
1017         case ACT_SWAP_HANDS:        dprint("ACT_SWAP_HANDS");        break;
1018         default:                    dprint("UNKNOWN");               break;
1019     }
1020     dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
1021 }