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