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