]> git.gir.st - tmk_keyboard.git/blob - common/action.c
Add action_tapping.[ch] for refactoring
[tmk_keyboard.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 "keycode.h"
19 #include "keyboard.h"
20 #include "mousekey.h"
21 #include "command.h"
22 #include "debug.h"
23 #include "led.h"
24 #include "layer_switch.h"
25 #include "action_tapping.h"
26 #include "action_oneshot.h"
27 #include "action_macro.h"
28 #include "action.h"
29
30
31 void action_exec(keyevent_t event)
32 {
33 if (!IS_NOEVENT(event)) {
34 debug("\n---- action_exec: start -----\n");
35 debug("EVENT: "); debug_event(event); debug("\n");
36 }
37
38 keyrecord_t record = { .event = event };
39
40 #ifndef NO_ACTION_TAPPING
41 action_tapping_process(record);
42 #else
43 process_action(&record);
44 if (!IS_NOEVENT(record.event)) {
45 debug("processed: "); debug_record(record); debug("\n");
46 }
47 #endif
48 }
49
50 void process_action(keyrecord_t *record)
51 {
52 keyevent_t event = record->event;
53 uint8_t tap_count = record->tap.count;
54
55 if (IS_NOEVENT(event)) { return; }
56
57 action_t action = layer_switch_get_action(event.key);
58 debug("ACTION: "); debug_action(action);
59 debug(" overlays: "); overlay_debug();
60 debug(" keymaps: "); keymap_debug();
61 debug(" default_layer: "); debug_dec(default_layer); debug("\n");
62
63 switch (action.kind.id) {
64 /* Key and Mods */
65 case ACT_LMODS:
66 case ACT_RMODS:
67 {
68 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
69 action.key.mods<<4;
70 if (event.pressed) {
71 uint8_t tmp_mods = host_get_mods();
72 if (mods) {
73 host_add_mods(mods);
74 host_send_keyboard_report();
75 }
76 register_code(action.key.code);
77 if (mods && action.key.code) {
78 host_set_mods(tmp_mods);
79 host_send_keyboard_report();
80 }
81 } else {
82 if (mods && !action.key.code) {
83 host_del_mods(mods);
84 host_send_keyboard_report();
85 }
86 unregister_code(action.key.code);
87 }
88 }
89 break;
90 #ifndef NO_ACTION_TAPPING
91 case ACT_LMODS_TAP:
92 case ACT_RMODS_TAP:
93 {
94 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
95 action.key.mods<<4;
96 switch (action.layer.code) {
97 #ifndef NO_ACTION_ONESHOT
98 case 0x00:
99 // Oneshot modifier
100 if (event.pressed) {
101 if (tap_count == 0) {
102 debug("MODS_TAP: Oneshot: add_mods\n");
103 add_mods(mods);
104 }
105 else if (tap_count == 1) {
106 debug("MODS_TAP: Oneshot: start\n");
107 oneshot_start(mods);
108 }
109 else if (tap_count == TAPPING_TOGGLE) {
110 debug("MODS_TAP: Oneshot: toggle\n");
111 oneshot_toggle();
112 }
113 else {
114 debug("MODS_TAP: Oneshot: cancel&add_mods\n");
115 // double tap cancels oneshot and works as normal modifier.
116 oneshot_cancel();
117 add_mods(mods);
118 }
119 } else {
120 if (tap_count == 0) {
121 debug("MODS_TAP: Oneshot: cancel/del_mods\n");
122 // cancel oneshot on hold
123 oneshot_cancel();
124 del_mods(mods);
125 }
126 else if (tap_count == 1) {
127 debug("MODS_TAP: Oneshot: del_mods\n");
128 // retain Oneshot
129 del_mods(mods);
130 }
131 else {
132 debug("MODS_TAP: Oneshot: del_mods\n");
133 // cancel Mods
134 del_mods(mods);
135 }
136 }
137 break;
138 #endif
139 default:
140 if (event.pressed) {
141 if (tap_count > 0) {
142 if (record->tap.interrupted) {
143 debug("MODS_TAP: Tap: Cancel: add_mods\n");
144 // ad hoc: set 0 to cancel tap
145 record->tap.count = 0;
146 add_mods(mods);
147 } else {
148 debug("MODS_TAP: Tap: register_code\n");
149 register_code(action.key.code);
150 }
151 } else {
152 debug("MODS_TAP: No tap: add_mods\n");
153 add_mods(mods);
154 }
155 } else {
156 if (tap_count > 0) {
157 debug("MODS_TAP: Tap: unregister_code\n");
158 unregister_code(action.key.code);
159 } else {
160 debug("MODS_TAP: No tap: add_mods\n");
161 del_mods(mods);
162 }
163 }
164 break;
165 }
166 }
167 break;
168 #endif
169 #ifdef EXTRAKEY_ENABLE
170 /* other HID usage */
171 case ACT_USAGE:
172 switch (action.usage.page) {
173 case PAGE_SYSTEM:
174 if (event.pressed) {
175 host_system_send(action.usage.code);
176 } else {
177 host_system_send(0);
178 }
179 break;
180 case PAGE_CONSUMER:
181 if (event.pressed) {
182 host_consumer_send(action.usage.code);
183 } else {
184 host_consumer_send(0);
185 }
186 break;
187 }
188 break;
189 #endif
190 #ifdef MOUSEKEY_ENABLE
191 /* Mouse key */
192 case ACT_MOUSEKEY:
193 if (event.pressed) {
194 mousekey_on(action.key.code);
195 mousekey_send();
196 } else {
197 mousekey_off(action.key.code);
198 mousekey_send();
199 }
200 break;
201 #endif
202 #ifndef NO_ACTION_KEYMAP
203 case ACT_KEYMAP:
204 switch (action.layer.code) {
205 /* Keymap clear */
206 case OP_RESET:
207 switch (action.layer.val & 0x03) {
208 case 0:
209 // NOTE: reserved
210 overlay_clear();
211 keymap_clear();
212 break;
213 case ON_PRESS:
214 if (event.pressed) {
215 overlay_clear();
216 keymap_clear();
217 }
218 break;
219 case ON_RELEASE:
220 if (!event.pressed) {
221 overlay_clear();
222 keymap_clear();
223 }
224 break;
225 case ON_BOTH:
226 overlay_clear();
227 keymap_clear();
228 break;
229 /* NOTE: 4-7 rserved */
230 }
231 break;
232 /* Keymap Reset default layer */
233 case (OP_RESET | ON_PRESS):
234 if (event.pressed) {
235 default_layer_set(action.layer.val);
236 }
237 break;
238 case (OP_RESET | ON_RELEASE):
239 if (!event.pressed) {
240 default_layer_set(action.layer.val);
241 }
242 break;
243 case (OP_RESET | ON_BOTH):
244 default_layer_set(action.layer.val);
245 break;
246
247 /* Keymap Bit invert */
248 case OP_INV:
249 /* with tap toggle */
250 if (event.pressed) {
251 if (tap_count < TAPPING_TOGGLE) {
252 debug("KEYMAP_INV: tap toggle(press).\n");
253 keymap_invert(action.layer.val);
254 }
255 } else {
256 if (tap_count <= TAPPING_TOGGLE) {
257 debug("KEYMAP_INV: tap toggle(release).\n");
258 keymap_invert(action.layer.val);
259 }
260 }
261 break;
262 case (OP_INV | ON_PRESS):
263 if (event.pressed) {
264 keymap_invert(action.layer.val);
265 }
266 break;
267 case (OP_INV | ON_RELEASE):
268 if (!event.pressed) {
269 keymap_invert(action.layer.val);
270 }
271 break;
272 case (OP_INV | ON_BOTH):
273 keymap_invert(action.layer.val);
274 break;
275
276 /* Keymap Bit on */
277 case OP_ON:
278 if (event.pressed) {
279 keymap_on(action.layer.val);
280 } else {
281 keymap_off(action.layer.val);
282 }
283 break;
284 case (OP_ON | ON_PRESS):
285 if (event.pressed) {
286 keymap_on(action.layer.val);
287 }
288 break;
289 case (OP_ON | ON_RELEASE):
290 if (!event.pressed) {
291 keymap_on(action.layer.val);
292 }
293 break;
294 case (OP_ON | ON_BOTH):
295 keymap_on(action.layer.val);
296 break;
297
298 /* Keymap Bit off */
299 case OP_OFF:
300 if (event.pressed) {
301 keymap_off(action.layer.val);
302 } else {
303 keymap_on(action.layer.val);
304 }
305 break;
306 case (OP_OFF | ON_PRESS):
307 if (event.pressed) {
308 keymap_off(action.layer.val);
309 }
310 break;
311 case (OP_OFF | ON_RELEASE):
312 if (!event.pressed) {
313 keymap_off(action.layer.val);
314 }
315 break;
316 case (OP_OFF | ON_BOTH):
317 keymap_off(action.layer.val);
318 break;
319
320 /* Keymap Bit set */
321 case OP_SET:
322 if (event.pressed) {
323 keymap_set(action.layer.val);
324 } else {
325 keymap_clear();
326 }
327 break;
328 case (OP_SET | ON_PRESS):
329 if (event.pressed) {
330 keymap_set(action.layer.val);
331 }
332 break;
333 case (OP_SET | ON_RELEASE):
334 if (!event.pressed) {
335 keymap_set(action.layer.val);
336 }
337 break;
338 case (OP_SET | ON_BOTH):
339 keymap_set(action.layer.val);
340 break;
341
342 /* Keymap Bit invert with tap key */
343 default:
344 if (event.pressed) {
345 if (tap_count > 0) {
346 debug("KEYMAP_TAP_KEY: Tap: register_code\n");
347 register_code(action.layer.code);
348 } else {
349 debug("KEYMAP_TAP_KEY: No tap: On on press\n");
350 keymap_on(action.layer.val);
351 }
352 } else {
353 if (tap_count > 0) {
354 debug("KEYMAP_TAP_KEY: Tap: unregister_code\n");
355 unregister_code(action.layer.code);
356 } else {
357 debug("KEYMAP_TAP_KEY: No tap: Off on release\n");
358 keymap_off(action.layer.val);
359 }
360 }
361 break;
362 }
363 break;
364 #endif
365 #ifndef NO_ACTION_OVERLAY
366 case ACT_OVERLAY:
367 switch (action.layer.code) {
368 // Overlay Invert bit4
369 case OP_INV4 | 0:
370 if (action.layer.val == 0) {
371 // NOTE: reserved for future use
372 overlay_clear();
373 } else {
374 overlay_set(overlay_stat ^ action.layer.val);
375 }
376 break;
377 case OP_INV4 | 1:
378 if (action.layer.val == 0) {
379 // on pressed
380 if (event.pressed) overlay_clear();
381 } else {
382 overlay_set(overlay_stat ^ action.layer.val<<4);
383 }
384 break;
385 case OP_INV4 | 2:
386 if (action.layer.val == 0) {
387 // on released
388 if (!event.pressed) overlay_clear();
389 } else {
390 overlay_set(overlay_stat ^ action.layer.val<<8);
391 }
392 break;
393 case OP_INV4 | 3:
394 if (action.layer.val == 0) {
395 // on both
396 overlay_clear();
397 } else {
398 overlay_set(overlay_stat ^ action.layer.val<<12);
399 }
400 break;
401
402 /* Overlay Bit invert */
403 case OP_INV:
404 /* with tap toggle */
405 if (event.pressed) {
406 if (tap_count < TAPPING_TOGGLE) {
407 debug("OVERLAY_INV: tap toggle(press).\n");
408 overlay_invert(action.layer.val);
409 }
410 } else {
411 if (tap_count <= TAPPING_TOGGLE) {
412 debug("OVERLAY_INV: tap toggle(release).\n");
413 overlay_invert(action.layer.val);
414 }
415 }
416 break;
417 case (OP_INV | ON_PRESS):
418 if (event.pressed) {
419 overlay_invert(action.layer.val);
420 }
421 break;
422 case (OP_INV | ON_RELEASE):
423 if (!event.pressed) {
424 overlay_invert(action.layer.val);
425 }
426 break;
427 case (OP_INV | ON_BOTH):
428 overlay_invert(action.layer.val);
429 break;
430
431 /* Overlay Bit on */
432 case OP_ON:
433 if (event.pressed) {
434 overlay_on(action.layer.val);
435 } else {
436 overlay_off(action.layer.val);
437 }
438 break;
439 case (OP_ON | ON_PRESS):
440 if (event.pressed) {
441 overlay_on(action.layer.val);
442 }
443 break;
444 case (OP_ON | ON_RELEASE):
445 if (!event.pressed) {
446 overlay_on(action.layer.val);
447 }
448 break;
449 case (OP_ON | ON_BOTH):
450 overlay_on(action.layer.val);
451 break;
452
453 /* Overlay Bit off */
454 case OP_OFF:
455 if (event.pressed) {
456 overlay_off(action.layer.val);
457 } else {
458 overlay_on(action.layer.val);
459 }
460 break;
461 case (OP_OFF | ON_PRESS):
462 if (event.pressed) {
463 overlay_off(action.layer.val);
464 }
465 break;
466 case (OP_OFF | ON_RELEASE):
467 if (!event.pressed) {
468 overlay_off(action.layer.val);
469 }
470 break;
471 case (OP_OFF | ON_BOTH):
472 overlay_off(action.layer.val);
473 break;
474
475 /* Overlay Bit set */
476 case OP_SET:
477 if (event.pressed) {
478 overlay_move(action.layer.val);
479 } else {
480 overlay_clear();
481 }
482 break;
483 case (OP_SET | ON_PRESS):
484 if (event.pressed) {
485 overlay_move(action.layer.val);
486 }
487 break;
488 case (OP_SET | ON_RELEASE):
489 if (!event.pressed) {
490 overlay_move(action.layer.val);
491 }
492 break;
493 case (OP_SET | ON_BOTH):
494 overlay_move(action.layer.val);
495 break;
496
497 /* Overlay Bit invert with tap key */
498 default:
499 if (event.pressed) {
500 if (tap_count > 0) {
501 debug("OVERLAY_TAP_KEY: Tap: register_code\n");
502 register_code(action.layer.code);
503 } else {
504 debug("OVERLAY_TAP_KEY: No tap: On on press\n");
505 overlay_on(action.layer.val);
506 }
507 } else {
508 if (tap_count > 0) {
509 debug("OVERLAY_TAP_KEY: Tap: unregister_code\n");
510 unregister_code(action.layer.code);
511 } else {
512 debug("OVERLAY_TAP_KEY: No tap: Off on release\n");
513 overlay_off(action.layer.val);
514 }
515 }
516 break;
517 }
518 break;
519 #endif
520 /* Extentions */
521 #ifndef NO_ACTION_MACRO
522 case ACT_MACRO:
523 action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
524 break;
525 #endif
526 case ACT_COMMAND:
527 break;
528 #ifndef NO_ACTION_FUNCTION
529 case ACT_FUNCTION:
530 action_function(record, action.func.id, action.func.opt);
531 break;
532 #endif
533 default:
534 break;
535 }
536 }
537
538
539
540
541 /*
542 * Utilities for actions.
543 */
544 void register_code(uint8_t code)
545 {
546 if (code == KC_NO) {
547 return;
548 }
549 #ifdef CAPSLOCK_LOCKING_ENABLE
550 else if (KC_LOCKING_CAPS == code) {
551 #ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
552 // Resync: ignore if caps lock already is on
553 if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
554 #endif
555 host_add_key(KC_CAPSLOCK);
556 host_send_keyboard_report();
557 host_del_key(KC_CAPSLOCK);
558 host_send_keyboard_report();
559 }
560 #endif
561 else if IS_KEY(code) {
562 // TODO: should push command_proc out of this block?
563 if (command_proc(code)) return;
564
565 #ifndef NO_ACTION_ONESHOT
566 if (oneshot_state.mods && !oneshot_state.disabled) {
567 uint8_t tmp_mods = host_get_mods();
568 host_add_mods(oneshot_state.mods);
569
570 host_add_key(code);
571 host_send_keyboard_report();
572
573 host_set_mods(tmp_mods);
574 oneshot_cancel();
575 } else
576 #endif
577 {
578 host_add_key(code);
579 host_send_keyboard_report();
580 }
581 }
582 else if IS_MOD(code) {
583 host_add_mods(MOD_BIT(code));
584 host_send_keyboard_report();
585 }
586 }
587
588 void unregister_code(uint8_t code)
589 {
590 if (code == KC_NO) {
591 return;
592 }
593 #ifdef CAPSLOCK_LOCKING_ENABLE
594 else if (KC_LOCKING_CAPS == code) {
595 #ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
596 // Resync: ignore if caps lock already is off
597 if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
598 #endif
599 host_add_key(KC_CAPSLOCK);
600 host_send_keyboard_report();
601 host_del_key(KC_CAPSLOCK);
602 host_send_keyboard_report();
603 }
604 #endif
605 else if IS_KEY(code) {
606 host_del_key(code);
607 host_send_keyboard_report();
608 }
609 else if IS_MOD(code) {
610 host_del_mods(MOD_BIT(code));
611 host_send_keyboard_report();
612 }
613 }
614
615 void add_mods(uint8_t mods)
616 {
617 if (mods) {
618 host_add_mods(mods);
619 host_send_keyboard_report();
620 }
621 }
622
623 void del_mods(uint8_t mods)
624 {
625 if (mods) {
626 host_del_mods(mods);
627 host_send_keyboard_report();
628 }
629 }
630
631 void set_mods(uint8_t mods)
632 {
633 host_set_mods(mods);
634 host_send_keyboard_report();
635 }
636
637 void clear_keyboard(void)
638 {
639 host_clear_mods();
640 clear_keyboard_but_mods();
641 }
642
643 void clear_keyboard_but_mods(void)
644 {
645 host_clear_keys();
646 host_send_keyboard_report();
647 #ifdef MOUSEKEY_ENABLE
648 mousekey_clear();
649 mousekey_send();
650 #endif
651 #ifdef EXTRAKEY_ENABLE
652 host_system_send(0);
653 host_consumer_send(0);
654 #endif
655 }
656
657 bool sending_anykey(void)
658 {
659 return (host_has_anykey() || host_mouse_in_use() ||
660 host_last_sysytem_report() || host_last_consumer_report());
661 }
662
663 bool is_tap_key(key_t key)
664 {
665 action_t action = layer_switch_get_action(key);
666
667 switch (action.kind.id) {
668 case ACT_LMODS_TAP:
669 case ACT_RMODS_TAP:
670 return true;
671 case ACT_KEYMAP:
672 case ACT_OVERLAY:
673 switch (action.layer.code) {
674 case 0x04 ... 0xEF: /* tap key */
675 case OP_INV:
676 return true;
677 default:
678 return false;
679 }
680 case ACT_MACRO:
681 case ACT_FUNCTION:
682 if (action.func.opt & FUNC_TAP) { return true; }
683 return false;
684 }
685 return false;
686 }
687
688
689 /*
690 * debug print
691 */
692 void debug_event(keyevent_t event)
693 {
694 debug_hex16((event.key.row<<8) | event.key.col);
695 if (event.pressed) debug("d("); else debug("u(");
696 debug_dec(event.time); debug(")");
697 }
698
699 void debug_record(keyrecord_t record)
700 {
701 debug_event(record.event);
702 #ifndef NO_ACTION_TAPPING
703 debug(":"); debug_dec(record.tap.count);
704 if (record.tap.interrupted) debug("-");
705 #endif
706 }
707
708 void debug_action(action_t action)
709 {
710 switch (action.kind.id) {
711 case ACT_LMODS: debug("ACT_LMODS"); break;
712 case ACT_RMODS: debug("ACT_RMODS"); break;
713 case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break;
714 case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break;
715 case ACT_USAGE: debug("ACT_USAGE"); break;
716 case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break;
717 case ACT_KEYMAP: debug("ACT_KEYMAP"); break;
718 case ACT_OVERLAY: debug("ACT_OVERLAY"); break;
719 case ACT_MACRO: debug("ACT_MACRO"); break;
720 case ACT_COMMAND: debug("ACT_COMMAND"); break;
721 case ACT_FUNCTION: debug("ACT_FUNCTION"); break;
722 default: debug("UNKNOWN"); break;
723 }
724 debug("[");
725 debug_hex4(action.kind.param>>8);
726 debug(":");
727 debug_hex8(action.kind.param & 0xff);
728 debug("]");
729 }
Imprint / Impressum