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