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