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