]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/action.c
Make Transparent feature available to new keymaps.
[tmk_firmware.git] / 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 "timer.h"
19 #include "keymap.h"
20 #include "keycode.h"
21 #include "keyboard.h"
22 #include "mousekey.h"
23 #include "command.h"
24 #include "util.h"
25 #include "debug.h"
26 #include "action.h"
27
28
29 static void process_action(keyrecord_t *record);
30 static bool process_tapping(keyrecord_t *record);
31 static void waiting_buffer_scan_tap(void);
32
33 static void debug_event(keyevent_t event);
34 static void debug_record(keyrecord_t record);
35 static void debug_action(action_t action);
36 static void debug_tapping_key(void);
37 static void debug_waiting_buffer(void);
38
39
40 /*
41  * Tapping
42  */
43 /* period of tapping(ms) */
44 #ifndef TAPPING_TERM
45 #define TAPPING_TERM    200
46 #endif
47
48 /* tap count needed for toggling a feature */
49 #ifndef TAPPING_TOGGLE
50 #define TAPPING_TOGGLE  5
51 #endif
52
53 /* stores a key event of current tap. */
54 static keyrecord_t tapping_key = {};
55
56 #define IS_TAPPING()            !IS_NOEVENT(tapping_key.event)
57 #define IS_TAPPING_PRESSED()    (IS_TAPPING() && tapping_key.event.pressed)
58 #define IS_TAPPING_RELEASED()   (IS_TAPPING() && !tapping_key.event.pressed)
59 #define IS_TAPPING_KEY(k)       (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
60 #define WITHIN_TAPPING_TERM(e)  (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
61
62
63 /*
64  * Waiting buffer
65  *
66  * stores key events waiting for settling current tap.
67  */
68 #define WAITING_BUFFER_SIZE 8
69 static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
70
71 /* point to empty cell to enq */
72 static uint8_t waiting_buffer_head = 0;
73
74 /* point to the oldest data cell to deq */
75 static uint8_t waiting_buffer_tail = 0;
76
77 static bool waiting_buffer_enq(keyrecord_t record)
78 {
79     if (IS_NOEVENT(record.event)) {
80         return true;
81     }
82
83     if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
84         debug("waiting_buffer_enq: Over flow.\n");
85         return false;
86     }
87
88     waiting_buffer[waiting_buffer_head] = record;
89     waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
90
91     debug("waiting_buffer_enq: "); debug_waiting_buffer();
92     return true;
93 }
94
95 static void waiting_buffer_clear(void)
96 {
97     waiting_buffer_head = 0;
98     waiting_buffer_tail = 0;
99 }
100
101 #if TAPPING_TERM >= 500
102 static bool waiting_buffer_typed(keyevent_t event)
103 {
104     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
105         if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed !=  waiting_buffer[i].event.pressed) {
106             return true;
107         }
108     }
109     return false;
110 }
111 #endif
112
113 bool waiting_buffer_has_anykey_pressed(void)
114 {
115     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
116         if (waiting_buffer[i].event.pressed) return true;
117     }
118     return false;
119 }
120
121
122 /* Oneshot modifier
123  *
124  * Problem: Want to capitalize like 'The' but the result tends to be 'THe'.
125  * Solution: Oneshot modifier have its effect on only one key coming next.
126  *           Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key.
127  *
128  *  Hold:       works as normal modifier.
129  *  Tap:        one shot modifier.
130  *  2 Tap:      cancel one shot modifier.
131  *  5-Tap:      toggles enable/disable oneshot feature.
132  */
133 static struct {
134     uint8_t mods;
135     uint8_t time;
136     bool    ready;
137     bool    disabled;
138 }   oneshot_state;
139
140 static void oneshot_start(uint8_t mods, uint16_t time)
141 {
142     oneshot_state.mods = mods;
143     oneshot_state.time = time;
144     oneshot_state.ready = true;
145 }
146
147 static void oneshot_cancel(void)
148 {
149     oneshot_state.mods = 0;
150     oneshot_state.time = 0;
151     oneshot_state.ready = false;
152 }
153
154 static void oneshot_toggle(void)
155 {
156     oneshot_state.disabled = !oneshot_state.disabled;
157 }
158
159
160
161 void action_exec(keyevent_t event)
162 {
163     if (!IS_NOEVENT(event)) {
164         debug("\n---- action_exec: start -----\n");
165         debug("EVENT: "); debug_event(event); debug("\n");
166     }
167
168     keyrecord_t record = { .event = event };
169
170     // pre-process on tapping
171     if (process_tapping(&record)) {
172         if (!IS_NOEVENT(record.event)) {
173             debug("processed: "); debug_record(record); debug("\n");
174         }
175     } else {
176         // enqueue
177         if (!waiting_buffer_enq(record)) {
178             // clear all in case of overflow.
179             debug("OVERFLOW: CLEAR ALL STATES\n");
180             clear_keyboard();
181             waiting_buffer_clear();
182             tapping_key = (keyrecord_t){};
183         }
184     }
185
186     // process waiting_buffer
187     if (!IS_NOEVENT(event) && waiting_buffer_head != waiting_buffer_tail) {
188         debug("---- action_exec: process waiting_buffer -----\n");
189     }
190
191     for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
192         if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
193             debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
194             debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
195         } else {
196             break;
197         }
198     }
199     if (!IS_NOEVENT(event)) {
200         debug("\n");
201     }
202 }
203
204 static action_t get_action(key_t key)
205 {
206     action_t action = keymap_get_action(current_layer, key.pos.row, key.pos.col);
207
208     /* Transparently use default layer */
209     if (action.code == ACTION_TRANSPARENT) {
210         // TODO: layer stacking
211         action = keymap_get_action(default_layer, key.pos.row, key.pos.col);
212         debug("TRNASPARENT: "); debug_hex16(action.code); debug("\n");
213     }
214     return action;
215 }
216
217 static void process_action(keyrecord_t *record)
218 {
219     keyevent_t event = record->event;
220     uint8_t tap_count = record->tap_count;
221
222     if (IS_NOEVENT(event)) { return; }
223
224     action_t action = get_action(event.key);
225     debug("ACTION: "); debug_action(action); debug("\n");
226
227     switch (action.kind.id) {
228         /* Key and Mods */
229         case ACT_LMODS:
230         case ACT_RMODS:
231             {
232                 uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
233                                                                 action.key.mods<<4;
234                 if (event.pressed) {
235                     uint8_t tmp_mods = host_get_mods();
236                     if (mods) {
237                         host_add_mods(mods);
238                         host_send_keyboard_report();
239                     }
240                     register_code(action.key.code);
241                     if (mods && action.key.code) {
242                         host_set_mods(tmp_mods);
243                         host_send_keyboard_report();
244                     }
245                 } else {
246                     if (mods && !action.key.code) {
247                         host_del_mods(mods);
248                         host_send_keyboard_report();
249                     }
250                     unregister_code(action.key.code);
251                 }
252             }
253             break;
254         case ACT_LMODS_TAP:
255         case ACT_RMODS_TAP:
256             {
257                 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
258                                                                     action.key.mods<<4;
259                 switch (action.layer.code) {
260                     case 0x00:
261                         // Oneshot modifier
262                         if (event.pressed) {
263                             if (tap_count == 0) {
264                                 debug("MODS_TAP: Oneshot: add_mods\n");
265                                 add_mods(mods);
266                             }
267                             else if (tap_count == 1) {
268                                 debug("MODS_TAP: Oneshot: start\n");
269                                 oneshot_start(mods, event.time);
270                             }
271                             else if (tap_count == TAPPING_TOGGLE) {
272                                 debug("MODS_TAP: Oneshot: toggle\n");
273                                 oneshot_toggle();
274                             }
275                             else {
276                                 debug("MODS_TAP: Oneshot: cancel&add_mods\n");
277                                 // double tap cancels oneshot and works as normal modifier.
278                                 oneshot_cancel();
279                                 add_mods(mods);
280                             }
281                         } else {
282                             if (tap_count == 0) {
283                                 debug("MODS_TAP: Oneshot: cancel/del_mods\n");
284                                 // cancel oneshot by holding.
285                                 oneshot_cancel();
286                                 del_mods(mods);
287                             }
288                             else if (tap_count == 1) {
289                                 debug("MODS_TAP: Oneshot: del_mods\n");
290                                 // retain Oneshot
291                                 del_mods(mods);
292                             }
293                             else {
294                                 debug("MODS_TAP: Oneshot: del_mods\n");
295                                 // cancel Mods
296                                 del_mods(mods);
297                             }
298                         }
299                         break;
300                     default:
301                         if (event.pressed) {
302                             if (tap_count > 0) {
303                                 if (waiting_buffer_has_anykey_pressed()) {
304                                     debug("MODS_TAP: Tap: Cancel: add_mods\n");
305                                     // ad hoc: set 0 to cancel tap
306                                     record->tap_count = 0;
307                                     add_mods(mods);
308                                 } else {
309                                     debug("MODS_TAP: Tap: register_code\n");
310                                     register_code(action.key.code);
311                                 }
312                             } else {
313                                 debug("MODS_TAP: No tap: add_mods\n");
314                                 add_mods(mods);
315                             }
316                         } else {
317                             if (tap_count > 0) {
318                                 debug("MODS_TAP: Tap: unregister_code\n");
319                                 unregister_code(action.key.code);
320                             } else {
321                                 debug("MODS_TAP: No tap: add_mods\n");
322                                 del_mods(mods);
323                             }
324                         }
325                         break;
326                 }
327             }
328             break;
329
330         /* other HID usage */
331         case ACT_USAGE:
332 #ifdef EXTRAKEY_ENABLE
333             switch (action.usage.page) {
334                 case PAGE_SYSTEM:
335                     if (event.pressed) {
336                         host_system_send(action.usage.code);
337                     } else {
338                         host_system_send(0);
339                     }
340                     break;
341                 case PAGE_CONSUMER:
342                     if (event.pressed) {
343                         host_consumer_send(action.usage.code);
344                     } else {
345                         host_consumer_send(0);
346                     }
347                     break;
348             }
349 #endif
350             break;
351
352         /* Mouse key */
353         case ACT_MOUSEKEY:
354 #ifdef MOUSEKEY_ENABLE
355             if (event.pressed) {
356                 mousekey_on(action.key.code);
357                 mousekey_send();
358             } else {
359                 mousekey_off(action.key.code);
360                 mousekey_send();
361             }
362 #endif
363             break;
364
365         /* Layer key */
366         case ACT_LAYER:
367             switch (action.layer.code) {
368                 case LAYER_MOMENTARY:  /* momentary */
369                     if (event.pressed) {
370                         layer_switch(action.layer.val);
371                     }
372                     else {
373                         // NOTE: This is needed by legacy keymap support
374                         layer_switch(default_layer);
375                     }
376                     break;
377                 case LAYER_ON_PRESS:
378                     if (event.pressed) {
379                         layer_switch(action.layer.val);
380                     }
381                     break;
382                 case LAYER_ON_RELEASE:
383                     if (!event.pressed) {
384                         layer_switch(action.layer.val);
385                     }
386                     break;
387                 case LAYER_DEFAULT:  /* default layer */
388                     switch (action.layer.val) {
389                         case DEFAULT_ON_BOTH:
390                             layer_switch(default_layer);
391                             break;
392                         case DEFAULT_ON_PRESS:
393                             if (event.pressed) {
394                                 layer_switch(default_layer);
395                             }
396                             break;
397                         case DEFAULT_ON_RELEASE:
398                             if (!event.pressed) {
399                                 layer_switch(default_layer);
400                             }
401                             break;
402                     }
403                     break;
404                 case LAYER_TAP_TOGGLE:  /* switch on hold and toggle on several taps */
405                     if (event.pressed) {
406                         if (tap_count < TAPPING_TOGGLE) {
407                             layer_switch(action.layer.val);
408                         }
409                     } else {
410                         if (tap_count >= TAPPING_TOGGLE) {
411                             debug("LAYER_PRESSED: tap toggle.\n");
412                             layer_switch(action.layer.val);
413                         }
414                     }
415                     break;
416                 case LAYER_CHANGE_DEFAULT:  /* change default layer */
417                     if (event.pressed) {
418                         default_layer = action.layer.val;
419                         layer_switch(default_layer);
420                     }
421                     break;
422                 default:    /* switch layer on hold and key on tap*/
423                     if (event.pressed) {
424                        if (tap_count > 0) {
425                             debug("LAYER_PRESSED: Tap: register_code\n");
426                             register_code(action.layer.code);
427                        } else {
428                             debug("LAYER_PRESSED: No tap: layer_switch\n");
429                             layer_switch(action.layer.val);
430                        }
431                     } else {
432                         if (tap_count > 0) {
433                             debug("LAYER_PRESSED: Tap: unregister_code\n");
434                             unregister_code(action.layer.code);
435                         } else {
436                             //debug("LAYER_PRESSED: No tap: NO ACTION\n");
437                             // NOTE: This is needed by legacy keymap support
438                             debug("LAYER_PRESSED: No tap: return to default layer\n");
439                             layer_switch(default_layer);
440                         }
441                     }
442                     break;
443             }
444             break;
445         case ACT_LAYER_BIT:
446             switch (action.layer.code) {
447                 case LAYER_MOMENTARY:  /* momentary */
448                     if (event.pressed) {
449                         layer_switch(current_layer ^ action.layer.val);
450                     } else {
451                         layer_switch(current_layer ^ action.layer.val);
452                     }
453                     break;
454                 case LAYER_ON_PRESS:
455                     if (event.pressed) {
456                         layer_switch(current_layer ^ action.layer.val);
457                     }
458                     break;
459                 case LAYER_ON_RELEASE:
460                     if (!event.pressed) {
461                         layer_switch(current_layer ^ action.layer.val);
462                     }
463                     break;
464                 case LAYER_TAP_TOGGLE:  /* switch on hold and toggle on several taps */
465                     if (event.pressed) {
466                         if (tap_count < TAPPING_TOGGLE) {
467                             debug("LAYER_BIT: tap toggle(press).\n");
468                             layer_switch(current_layer ^ action.layer.val);
469                         }
470                     } else {
471                         if (tap_count <= TAPPING_TOGGLE) {
472                             debug("LAYER_BIT: tap toggle(release).\n");
473                             layer_switch(current_layer ^ action.layer.val);
474                         }
475                     }
476                     break;
477                 case 0xFF:
478                     // change default layer
479                     if (event.pressed) {
480                         default_layer = current_layer ^ action.layer.val;
481                         layer_switch(default_layer);
482                     } else {
483                         default_layer = current_layer ^ action.layer.val;
484                         layer_switch(default_layer);
485                     }
486                     break;
487                 default:
488                     // with tap key
489                     if (event.pressed) {
490                         if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
491                             debug("LAYER_BIT: Tap: register_code\n");
492                             register_code(action.layer.code);
493                         } else {
494                             debug("LAYER_BIT: No tap: layer_switch(bit on)\n");
495                             layer_switch(current_layer ^ action.layer.val);
496                         }
497                     } else {
498                         if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
499                             debug("LAYER_BIT: Tap: unregister_code\n");
500                             unregister_code(action.layer.code);
501                         } else {
502                             debug("LAYER_BIT: No tap: layer_switch(bit off)\n");
503                             layer_switch(current_layer ^ action.layer.val);
504                         }
505                     }
506                     break;
507             }
508             break;
509
510         /* Extentions */
511         case ACT_MACRO:
512             break;
513         case ACT_COMMAND:
514             break;
515         case ACT_FUNCTION:
516             // TODO
517             keymap_call_function(record, action.func.id, action.func.opt);
518             break;
519         default:
520             break;
521     }
522 }
523
524 /* Tapping
525  *
526  * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
527  *       (without interfering by typing other key)
528  */
529 /* return true when key event is processed or consumed. */
530 static bool process_tapping(keyrecord_t *keyp)
531 {
532     keyevent_t event = keyp->event;
533
534     // if tapping
535     if (IS_TAPPING_PRESSED()) {
536         if (WITHIN_TAPPING_TERM(event)) {
537             if (tapping_key.tap_count == 0) {
538                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
539                     // first tap!
540                     debug("Tapping: First tap(0->1).\n");
541                     tapping_key.tap_count = 1;
542                     debug_tapping_key();
543                     process_action(&tapping_key);
544
545                     // enqueue
546                     keyp->tap_count = tapping_key.tap_count;
547                     return false;
548                 }
549 #if TAPPING_TERM >= 500
550                 /* This can prevent from typing some tap keys in a row at a time. */
551                 else if (!event.pressed && waiting_buffer_typed(event)) {
552                     // other key typed. not tap.
553                     debug("Tapping: End. No tap. Interfered by typing key\n");
554                     process_action(&tapping_key);
555                     tapping_key = (keyrecord_t){};
556                     debug_tapping_key();
557
558                     // enqueue
559                     return false;
560                 }
561 #endif
562                 else {
563                     // other key events shall be enq'd till tapping state settles.
564                     return false;
565                 }
566             }
567             // tap_count > 0
568             else {
569                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
570                     debug("Tapping: Tap release("); debug_dec(tapping_key.tap_count); debug(")\n");
571                     keyp->tap_count = tapping_key.tap_count;
572                     process_action(keyp);
573                     tapping_key = *keyp;
574                     debug_tapping_key();
575                     return true;
576                 }
577                 else if (is_tap_key(keyp->event.key) && event.pressed) {
578                     if (tapping_key.tap_count > 1) {
579                         debug("Tapping: Start new tap with releasing last tap(>1).\n");
580                         // unregister key
581                         process_action(&(keyrecord_t){
582                                 .tap_count = tapping_key.tap_count,
583                                 .event.key = tapping_key.event.key,
584                                 .event.time = event.time,
585                                 .event.pressed = false
586                         });
587                     } else {
588                         debug("Tapping: Start while last tap(1).\n");
589                     }
590                     tapping_key = *keyp;
591                     waiting_buffer_scan_tap();
592                     debug_tapping_key();
593                     return true;
594                 }
595                 else {
596                     if (!IS_NOEVENT(keyp->event)) {
597                         debug("Tapping: key event while last tap(>0).\n");
598                     }
599                     process_action(keyp);
600                     return true;
601                 }
602             }
603         }
604         // after TAPPING_TERM
605         else {
606             if (tapping_key.tap_count == 0) {
607                 debug("Tapping: End. Timeout. Not tap(0): ");
608                 debug_event(event); debug("\n");
609                 process_action(&tapping_key);
610                 tapping_key = (keyrecord_t){};
611                 debug_tapping_key();
612                 return false;
613             }  else {
614                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
615                     debug("Tapping: End. last timeout tap release(>0).");
616                     keyp->tap_count = tapping_key.tap_count;
617                     process_action(keyp);
618                     tapping_key = (keyrecord_t){};
619                     return true;
620                 }
621                 else if (is_tap_key(keyp->event.key) && event.pressed) {
622                     if (tapping_key.tap_count > 1) {
623                         debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
624                         // unregister key
625                         process_action(&(keyrecord_t){
626                                 .tap_count = tapping_key.tap_count,
627                                 .event.key = tapping_key.event.key,
628                                 .event.time = event.time,
629                                 .event.pressed = false
630                         });
631                     } else {
632                         debug("Tapping: Start while last timeout tap(1).\n");
633                     }
634                     tapping_key = *keyp;
635                     waiting_buffer_scan_tap();
636                     debug_tapping_key();
637                     return true;
638                 }
639                 else {
640                     if (!IS_NOEVENT(keyp->event)) {
641                         debug("Tapping: key event while last timeout tap(>0).\n");
642                     }
643                     process_action(keyp);
644                     return true;
645                 }
646             }
647         }
648     } else if (IS_TAPPING_RELEASED()) {
649         if (WITHIN_TAPPING_TERM(event)) {
650             if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
651                 // sequential tap.
652                 keyp->tap_count = tapping_key.tap_count + 1;
653                 debug("Tapping: Tap press("); debug_dec(keyp->tap_count); debug(")\n");
654                 process_action(keyp);
655                 tapping_key = *keyp;
656                 debug_tapping_key();
657                 return true;
658             } else if (event.pressed && is_tap_key(event.key)) {
659                 // Sequential tap can be interfered with other tap key.
660                 debug("Tapping: Start with interfering other tap.\n");
661                 tapping_key = *keyp;
662                 waiting_buffer_scan_tap();
663                 debug_tapping_key();
664                 return true;
665             } else {
666                 if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
667                 process_action(keyp);
668                 return true;
669             }
670         } else {
671             // timeout. no sequential tap.
672             debug("Tapping: End(Timeout after releasing last tap): ");
673             debug_event(event); debug("\n");
674             tapping_key = (keyrecord_t){};
675             debug_tapping_key();
676             return false;
677         }
678     }
679     // not tapping satate
680     else {
681         if (event.pressed && is_tap_key(event.key)) {
682             debug("Tapping: Start(Press tap key).\n");
683             tapping_key = *keyp;
684             waiting_buffer_scan_tap();
685             debug_tapping_key();
686             return true;
687         } else {
688             process_action(keyp);
689             return true;
690         }
691     }
692 }
693
694 /* scan buffer for tapping */
695 static void waiting_buffer_scan_tap(void)
696 {
697     // tapping already is settled
698     if (tapping_key.tap_count > 0) return;
699     // invalid state: tapping_key released && tap_count == 0
700     if (!tapping_key.event.pressed) return;
701
702     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
703         if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
704                 !waiting_buffer[i].event.pressed &&
705                 WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
706             tapping_key.tap_count = 1;
707             waiting_buffer[i].tap_count = 1;
708             process_action(&tapping_key);
709
710             debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
711             debug_waiting_buffer();
712             return;
713         }
714     }
715 }
716
717
718
719 /*
720  * Utilities for actions.
721  */
722 void register_code(uint8_t code)
723 {
724     if (code == KC_NO) {
725         return;
726     }
727     else if IS_KEY(code) {
728         // TODO: should push command_proc out of this block?
729         if (command_proc(code)) return;
730
731         if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) {
732             uint8_t tmp_mods = host_get_mods();
733             host_add_mods(oneshot_state.mods);
734             host_add_key(code);
735             host_send_keyboard_report();
736
737             host_set_mods(tmp_mods);
738             oneshot_state.ready = false;
739         } else {
740             host_add_key(code);
741             host_send_keyboard_report();
742         }
743     }
744     else if IS_MOD(code) {
745         host_add_mods(MOD_BIT(code));
746         host_send_keyboard_report();
747     }
748 }
749
750 void unregister_code(uint8_t code)
751 {
752     if IS_KEY(code) {
753         host_del_key(code);
754         host_send_keyboard_report();
755     }
756     else if IS_MOD(code) {
757         host_del_mods(MOD_BIT(code));
758         host_send_keyboard_report();
759     }
760 }
761
762 void add_mods(uint8_t mods)
763 {
764     if (mods) {
765         host_add_mods(mods);
766         host_send_keyboard_report();
767     }
768 }
769
770 void del_mods(uint8_t mods)
771 {
772     if (mods) {
773         host_del_mods(mods);
774         host_send_keyboard_report();
775     }
776 }
777
778 void set_mods(uint8_t mods)
779 {
780     host_set_mods(mods);
781     host_send_keyboard_report();
782 }
783
784 void clear_keyboard(void)
785 {
786     host_clear_mods();
787     clear_keyboard_but_mods();
788 }
789
790 void clear_keyboard_but_mods(void)
791 {
792     host_clear_keys();
793     host_send_keyboard_report();
794 #ifdef MOUSEKEY_ENABLE
795     mousekey_clear();
796     mousekey_send();
797 #endif
798 #ifdef EXTRAKEY_ENABLE
799     host_system_send(0);
800     host_consumer_send(0);
801 #endif
802 }
803
804 bool sending_anykey(void)
805 {
806     return (host_has_anykey() || host_mouse_in_use() ||
807             host_last_sysytem_report() || host_last_consumer_report());
808 }
809
810 void layer_switch(uint8_t new_layer)
811 {
812     if (current_layer != new_layer) {
813         debug("Layer Switch: "); debug_hex(current_layer);
814         debug(" -> "); debug_hex(new_layer); debug("\n");
815
816         current_layer = new_layer;
817         clear_keyboard_but_mods(); // To avoid stuck keys
818         // NOTE: update mods with full scan of matrix? if modifier changes between layers
819     }
820 }
821
822 bool is_tap_key(key_t key)
823 {
824     action_t action = get_action(key);
825
826     switch (action.kind.id) {
827         case ACT_LMODS_TAP:
828         case ACT_RMODS_TAP:
829             return true;
830         case ACT_LAYER:
831         case ACT_LAYER_BIT:
832             switch (action.layer.code) {
833                 case LAYER_MOMENTARY:
834                 case LAYER_ON_PRESS:
835                 case LAYER_ON_RELEASE:
836                 case LAYER_DEFAULT:
837                     return false;
838                 case LAYER_TAP_TOGGLE:
839                 default:    /* tap key */
840                     return true;
841             }
842             return false;
843         case ACT_FUNCTION:
844             if (action.func.opt & FUNC_TAP) { return true; }
845             return false;
846     }
847     return false;
848 }
849
850
851 /*
852  * debug print
853  */
854 static void debug_event(keyevent_t event)
855 {
856     debug_hex16(event.key.raw);
857     if (event.pressed) debug("d("); else debug("u(");
858     debug_dec(event.time); debug(")");
859 }
860 static void debug_record(keyrecord_t record)
861 {
862     debug_event(record.event); debug(":"); debug_dec(record.tap_count);
863 }
864 static void debug_action(action_t action)
865 {
866     switch (action.kind.id) {
867         case ACT_LMODS:             debug("ACT_LMODS");             break;
868         case ACT_RMODS:             debug("ACT_RMODS");             break;
869         case ACT_LMODS_TAP:         debug("ACT_LMODS_TAP");         break;
870         case ACT_RMODS_TAP:         debug("ACT_RMODS_TAP");         break;
871         case ACT_USAGE:             debug("ACT_USAGE");             break;
872         case ACT_MOUSEKEY:          debug("ACT_MOUSEKEY");          break;
873         case ACT_LAYER:             debug("ACT_LAYER");     break;
874         case ACT_LAYER_BIT:         debug("ACT_LAYER_BIT");         break;
875         case ACT_MACRO:             debug("ACT_MACRO");             break;
876         case ACT_COMMAND:           debug("ACT_COMMAND");           break;
877         case ACT_FUNCTION:          debug("ACT_FUNCTION");          break;
878         default:                    debug("UNKNOWN");               break;
879     }
880     debug("[");
881     debug_hex4(action.kind.param>>8);
882     debug(":");
883     debug_hex8(action.kind.param & 0xff);
884     debug("]");
885 }
886 static void debug_tapping_key(void)
887 {
888     debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
889 }
890 static void debug_waiting_buffer(void)
891 {
892     debug("{ ");
893     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
894         debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
895     }
896     debug("}\n");
897 }