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