]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/action.c
Merge pull request #311 from adiabatic/ergodox-zweihander-osx
[qmk_firmware.git] / tmk_core / common / action.c
1 /*
2 Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "host.h"
18 #include "keycode.h"
19 #include "keyboard.h"
20 #include "mousekey.h"
21 #include "command.h"
22 #include "led.h"
23 #include "backlight.h"
24 #include "action_layer.h"
25 #include "action_tapping.h"
26 #include "action_macro.h"
27 #include "action_util.h"
28 #include "action.h"
29
30 #ifdef DEBUG_ACTION
31 #include "debug.h"
32 #else
33 #include "nodebug.h"
34 #endif
35
36
37 void action_exec(keyevent_t event)
38 {
39     if (!IS_NOEVENT(event)) {
40         dprint("\n---- action_exec: start -----\n");
41         dprint("EVENT: "); debug_event(event); dprintln();
42     }
43
44     keyrecord_t record = { .event = event };
45
46 #ifndef NO_ACTION_TAPPING
47     action_tapping_process(record);
48 #else
49     process_action(&record);
50     if (!IS_NOEVENT(record.event)) {
51         dprint("processed: "); debug_record(record); dprintln();
52     }
53 #endif
54 }
55
56 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
57 bool disable_action_cache = false;
58
59 void process_action_nocache(keyrecord_t *record)
60 {
61     disable_action_cache = true;
62     process_action(record);
63     disable_action_cache = false;
64 }
65 #else
66 void process_action_nocache(keyrecord_t *record)
67 {
68     process_action(record);
69 }
70 #endif
71
72 __attribute__ ((weak))
73 void process_action_kb(keyrecord_t *record) {}
74
75 void process_action(keyrecord_t *record)
76 {
77     bool do_release_oneshot = false;
78     keyevent_t event = record->event;
79 #ifndef NO_ACTION_TAPPING
80     uint8_t tap_count = record->tap.count;
81 #endif
82
83     if (IS_NOEVENT(event)) { return; }
84
85 #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
86     if (has_oneshot_layer_timed_out()) {
87         dprintf("Oneshot layer: timeout\n");
88         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
89     }
90 #endif
91
92     process_action_kb(record);
93
94     action_t action = store_or_get_action(event.pressed, event.key);
95     dprint("ACTION: "); debug_action(action);
96 #ifndef NO_ACTION_LAYER
97     dprint(" layer_state: "); layer_debug();
98     dprint(" default_layer_state: "); default_layer_debug();
99 #endif
100     dprintln();
101
102     if (event.pressed) {
103         // clear the potential weak mods left by previously pressed keys
104         clear_weak_mods();
105     }
106
107 #ifndef NO_ACTION_ONESHOT
108     // notice we only clear the one shot layer if the pressed key is not a modifier.
109     if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
110         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
111         do_release_oneshot = !is_oneshot_layer_active();
112     }
113 #endif
114
115     switch (action.kind.id) {
116         /* Key and Mods */
117         case ACT_LMODS:
118         case ACT_RMODS:
119             {
120                 uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
121                                                                 action.key.mods<<4;
122                 if (event.pressed) {
123                     if (mods) {
124                         if (IS_MOD(action.key.code)) {
125                             // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
126                             // this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT)
127                             add_mods(mods);
128                         } else {
129                             add_weak_mods(mods);
130                         }
131                         send_keyboard_report();
132                     }
133                     register_code(action.key.code);
134                 } else {
135                     unregister_code(action.key.code);
136                     if (mods) {
137                         if (IS_MOD(action.key.code)) {
138                             del_mods(mods);
139                         } else {
140                             del_weak_mods(mods);
141                         }
142                         send_keyboard_report();
143                     }
144                 }
145             }
146             break;
147 #ifndef NO_ACTION_TAPPING
148         case ACT_LMODS_TAP:
149         case ACT_RMODS_TAP:
150             {
151                 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
152                                                                     action.key.mods<<4;
153                 switch (action.layer_tap.code) {
154     #ifndef NO_ACTION_ONESHOT
155                     case MODS_ONESHOT:
156                         // Oneshot modifier
157                         if (event.pressed) {
158                             if (tap_count == 0) {
159                                 dprint("MODS_TAP: Oneshot: 0\n");
160                                 register_mods(mods);
161                             } else if (tap_count == 1) {
162                                 dprint("MODS_TAP: Oneshot: start\n");
163                                 set_oneshot_mods(mods);
164                     #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
165                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
166                                 dprint("MODS_TAP: Toggling oneshot");
167                                 clear_oneshot_mods();
168                                 set_oneshot_locked_mods(mods);
169                                 register_mods(mods);
170                     #endif
171                             } else {
172                                 register_mods(mods);
173                             }
174                         } else {
175                             if (tap_count == 0) {
176                                 clear_oneshot_mods();
177                                 unregister_mods(mods);
178                             } else if (tap_count == 1) {
179                                 // Retain Oneshot mods
180                     #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
181                                 if (mods & get_mods()) {
182                                     clear_oneshot_locked_mods();
183                                     clear_oneshot_mods();
184                                     unregister_mods(mods);
185                                 }
186                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
187                                 // Toggle Oneshot Layer
188                     #endif
189                             } else {
190                                 clear_oneshot_mods();
191                                 unregister_mods(mods);
192                             }
193                         }
194                         break;
195     #endif
196                     case MODS_TAP_TOGGLE:
197                         if (event.pressed) {
198                             if (tap_count <= TAPPING_TOGGLE) {
199                                 register_mods(mods);
200                             }
201                         } else {
202                             if (tap_count < TAPPING_TOGGLE) {
203                                 unregister_mods(mods);
204                             }
205                         }
206                         break;
207                     default:
208                         if (event.pressed) {
209                             if (tap_count > 0) {
210 #ifndef IGNORE_MOD_TAP_INTERRUPT
211                                 if (record->tap.interrupted) {
212                                     dprint("mods_tap: tap: cancel: add_mods\n");
213                                     // ad hoc: set 0 to cancel tap
214                                     record->tap.count = 0;
215                                     register_mods(mods);
216                                 } else
217 #endif
218                                 {
219                                     dprint("MODS_TAP: Tap: register_code\n");
220                                     register_code(action.key.code);
221                                 }
222                             } else {
223                                 dprint("MODS_TAP: No tap: add_mods\n");
224                                 register_mods(mods);
225                             }
226                         } else {
227                             if (tap_count > 0) {
228                                 dprint("MODS_TAP: Tap: unregister_code\n");
229                                 unregister_code(action.key.code);
230                             } else {
231                                 dprint("MODS_TAP: No tap: add_mods\n");
232                                 unregister_mods(mods);
233                             }
234                         }
235                         break;
236                 }
237             }
238             break;
239 #endif
240 #ifdef EXTRAKEY_ENABLE
241         /* other HID usage */
242         case ACT_USAGE:
243             switch (action.usage.page) {
244                 case PAGE_SYSTEM:
245                     if (event.pressed) {
246                         host_system_send(action.usage.code);
247                     } else {
248                         host_system_send(0);
249                     }
250                     break;
251                 case PAGE_CONSUMER:
252                     if (event.pressed) {
253                         host_consumer_send(action.usage.code);
254                     } else {
255                         host_consumer_send(0);
256                     }
257                     break;
258             }
259             break;
260 #endif
261 #ifdef MOUSEKEY_ENABLE
262         /* Mouse key */
263         case ACT_MOUSEKEY:
264             if (event.pressed) {
265                 mousekey_on(action.key.code);
266                 mousekey_send();
267             } else {
268                 mousekey_off(action.key.code);
269                 mousekey_send();
270             }
271             break;
272 #endif
273 #ifndef NO_ACTION_LAYER
274         case ACT_LAYER:
275             if (action.layer_bitop.on == 0) {
276                 /* Default Layer Bitwise Operation */
277                 if (!event.pressed) {
278                     uint8_t shift = action.layer_bitop.part*4;
279                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
280                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
281                     switch (action.layer_bitop.op) {
282                         case OP_BIT_AND: default_layer_and(bits | mask); break;
283                         case OP_BIT_OR:  default_layer_or(bits | mask);  break;
284                         case OP_BIT_XOR: default_layer_xor(bits | mask); break;
285                         case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
286                     }
287                 }
288             } else {
289                 /* Layer Bitwise Operation */
290                 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
291                                     (action.layer_bitop.on & ON_RELEASE)) {
292                     uint8_t shift = action.layer_bitop.part*4;
293                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
294                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
295                     switch (action.layer_bitop.op) {
296                         case OP_BIT_AND: layer_and(bits | mask); break;
297                         case OP_BIT_OR:  layer_or(bits | mask);  break;
298                         case OP_BIT_XOR: layer_xor(bits | mask); break;
299                         case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
300                     }
301                 }
302             }
303             break;
304     #ifndef NO_ACTION_TAPPING
305         case ACT_LAYER_TAP:
306         case ACT_LAYER_TAP_EXT:
307             switch (action.layer_tap.code) {
308                 case 0xe0 ... 0xef:
309                     /* layer On/Off with modifiers(left only) */
310                     if (event.pressed) {
311                         layer_on(action.layer_tap.val);
312                         register_mods(action.layer_tap.code & 0x0f);
313                     } else {
314                         layer_off(action.layer_tap.val);
315                         unregister_mods(action.layer_tap.code & 0x0f);
316                     }
317                     break;
318                 case OP_TAP_TOGGLE:
319                     /* tap toggle */
320                     if (event.pressed) {
321                         if (tap_count < TAPPING_TOGGLE) {
322                             layer_invert(action.layer_tap.val);
323                         }
324                     } else {
325                         if (tap_count <= TAPPING_TOGGLE) {
326                             layer_invert(action.layer_tap.val);
327                         }
328                     }
329                     break;
330                 case OP_ON_OFF:
331                     event.pressed ? layer_on(action.layer_tap.val) :
332                                     layer_off(action.layer_tap.val);
333                     break;
334                 case OP_OFF_ON:
335                     event.pressed ? layer_off(action.layer_tap.val) :
336                                     layer_on(action.layer_tap.val);
337                     break;
338                 case OP_SET_CLEAR:
339                     event.pressed ? layer_move(action.layer_tap.val) :
340                                     layer_clear();
341                     break;
342             #ifndef NO_ACTION_ONESHOT
343                 case OP_ONESHOT:
344                     // Oneshot modifier
345                 #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
346                     do_release_oneshot = false;
347                     if (event.pressed) {
348                         del_mods(get_oneshot_locked_mods());
349                         if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
350                             reset_oneshot_layer();
351                             layer_off(action.layer_tap.val);
352                             break;
353                         } else if (tap_count < ONESHOT_TAP_TOGGLE) {
354                             layer_on(action.layer_tap.val);
355                             set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
356                         }
357                     } else {
358                         add_mods(get_oneshot_locked_mods());
359                         if (tap_count >= ONESHOT_TAP_TOGGLE) {
360                             reset_oneshot_layer();
361                             clear_oneshot_locked_mods();
362                             set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
363                         } else {
364                             clear_oneshot_layer_state(ONESHOT_PRESSED);
365                         }
366                     }
367                 #else
368                     if (event.pressed) {
369                         layer_on(action.layer_tap.val);
370                         set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
371                     } else {
372                         clear_oneshot_layer_state(ONESHOT_PRESSED);
373                         if (tap_count > 1) {
374                             clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
375                         }
376                     }
377                 #endif
378                     break;
379             #endif
380                 default:
381                     /* tap key */
382                     if (event.pressed) {
383                         if (tap_count > 0) {
384                             dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
385                             register_code(action.layer_tap.code);
386                         } else {
387                             dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
388                             layer_on(action.layer_tap.val);
389                         }
390                     } else {
391                         if (tap_count > 0) {
392                             dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
393                             unregister_code(action.layer_tap.code);
394                         } else {
395                             dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
396                             layer_off(action.layer_tap.val);
397                         }
398                     }
399                     break;
400             }
401             break;
402     #endif
403 #endif
404         /* Extentions */
405 #ifndef NO_ACTION_MACRO
406         case ACT_MACRO:
407             action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
408             break;
409 #endif
410 #ifdef BACKLIGHT_ENABLE
411         case ACT_BACKLIGHT:
412             if (!event.pressed) {
413                 switch (action.backlight.opt) {
414                     case BACKLIGHT_INCREASE:
415                         backlight_increase();
416                         break;
417                     case BACKLIGHT_DECREASE:
418                         backlight_decrease();
419                         break;
420                     case BACKLIGHT_TOGGLE:
421                         backlight_toggle();
422                         break;
423                     case BACKLIGHT_STEP:
424                         backlight_step();
425                         break;
426                     case BACKLIGHT_LEVEL:
427                         backlight_level(action.backlight.level);
428                         break;
429                 }
430             }
431             break;
432 #endif
433         case ACT_COMMAND:
434             break;
435 #ifndef NO_ACTION_FUNCTION
436         case ACT_FUNCTION:
437             action_function(record, action.func.id, action.func.opt);
438             break;
439 #endif
440         default:
441             break;
442     }
443
444 #ifndef NO_ACTION_ONESHOT
445     /* Because we switch layers after a oneshot event, we need to release the
446      * key before we leave the layer or no key up event will be generated.
447      */
448     if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED )   ) {
449         record->event.pressed = false;
450         layer_on(get_oneshot_layer());
451         process_action(record);
452         layer_off(get_oneshot_layer());
453     }
454 #endif
455 }
456
457
458
459
460 /*
461  * Utilities for actions.
462  */
463 void register_code(uint8_t code)
464 {
465     if (code == KC_NO) {
466         return;
467     }
468
469 #ifdef LOCKING_SUPPORT_ENABLE
470     else if (KC_LOCKING_CAPS == code) {
471 #ifdef LOCKING_RESYNC_ENABLE
472         // Resync: ignore if caps lock already is on
473         if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
474 #endif
475         add_key(KC_CAPSLOCK);
476         send_keyboard_report();
477         del_key(KC_CAPSLOCK);
478         send_keyboard_report();
479     }
480
481     else if (KC_LOCKING_NUM == code) {
482 #ifdef LOCKING_RESYNC_ENABLE
483         if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
484 #endif
485         add_key(KC_NUMLOCK);
486         send_keyboard_report();
487         del_key(KC_NUMLOCK);
488         send_keyboard_report();
489     }
490
491     else if (KC_LOCKING_SCROLL == code) {
492 #ifdef LOCKING_RESYNC_ENABLE
493         if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
494 #endif
495         add_key(KC_SCROLLLOCK);
496         send_keyboard_report();
497         del_key(KC_SCROLLLOCK);
498         send_keyboard_report();
499     }
500 #endif
501
502     else if IS_KEY(code) {
503         // TODO: should push command_proc out of this block?
504         if (command_proc(code)) return;
505
506 #ifndef NO_ACTION_ONESHOT
507 /* TODO: remove
508         if (oneshot_state.mods && !oneshot_state.disabled) {
509             uint8_t tmp_mods = get_mods();
510             add_mods(oneshot_state.mods);
511
512             add_key(code);
513             send_keyboard_report();
514
515             set_mods(tmp_mods);
516             send_keyboard_report();
517             oneshot_cancel();
518         } else
519 */
520 #endif
521         {
522             add_key(code);
523             send_keyboard_report();
524         }
525     }
526     else if IS_MOD(code) {
527         add_mods(MOD_BIT(code));
528         send_keyboard_report();
529     }
530     else if IS_SYSTEM(code) {
531         host_system_send(KEYCODE2SYSTEM(code));
532     }
533     else if IS_CONSUMER(code) {
534         host_consumer_send(KEYCODE2CONSUMER(code));
535     }
536 }
537
538 void unregister_code(uint8_t code)
539 {
540     if (code == KC_NO) {
541         return;
542     }
543
544 #ifdef LOCKING_SUPPORT_ENABLE
545     else if (KC_LOCKING_CAPS == code) {
546 #ifdef LOCKING_RESYNC_ENABLE
547         // Resync: ignore if caps lock already is off
548         if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
549 #endif
550         add_key(KC_CAPSLOCK);
551         send_keyboard_report();
552         del_key(KC_CAPSLOCK);
553         send_keyboard_report();
554     }
555
556     else if (KC_LOCKING_NUM == code) {
557 #ifdef LOCKING_RESYNC_ENABLE
558         if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
559 #endif
560         add_key(KC_NUMLOCK);
561         send_keyboard_report();
562         del_key(KC_NUMLOCK);
563         send_keyboard_report();
564     }
565
566     else if (KC_LOCKING_SCROLL == code) {
567 #ifdef LOCKING_RESYNC_ENABLE
568         if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
569 #endif
570         add_key(KC_SCROLLLOCK);
571         send_keyboard_report();
572         del_key(KC_SCROLLLOCK);
573         send_keyboard_report();
574     }
575 #endif
576
577     else if IS_KEY(code) {
578         del_key(code);
579         send_keyboard_report();
580     }
581     else if IS_MOD(code) {
582         del_mods(MOD_BIT(code));
583         send_keyboard_report();
584     }
585     else if IS_SYSTEM(code) {
586         host_system_send(0);
587     }
588     else if IS_CONSUMER(code) {
589         host_consumer_send(0);
590     }
591 }
592
593 void register_mods(uint8_t mods)
594 {
595     if (mods) {
596         add_mods(mods);
597         send_keyboard_report();
598     }
599 }
600
601 void unregister_mods(uint8_t mods)
602 {
603     if (mods) {
604         del_mods(mods);
605         send_keyboard_report();
606     }
607 }
608
609 void clear_keyboard(void)
610 {
611     clear_mods();
612     clear_keyboard_but_mods();
613 }
614
615 void clear_keyboard_but_mods(void)
616 {
617     clear_weak_mods();
618     clear_macro_mods();
619     clear_keys();
620     send_keyboard_report();
621 #ifdef MOUSEKEY_ENABLE
622     mousekey_clear();
623     mousekey_send();
624 #endif
625 #ifdef EXTRAKEY_ENABLE
626     host_system_send(0);
627     host_consumer_send(0);
628 #endif
629 }
630
631 bool is_tap_key(keypos_t key)
632 {
633     action_t action = layer_switch_get_action(key);
634
635     switch (action.kind.id) {
636         case ACT_LMODS_TAP:
637         case ACT_RMODS_TAP:
638         case ACT_LAYER_TAP:
639         case ACT_LAYER_TAP_EXT:
640             switch (action.layer_tap.code) {
641                 case 0x00 ... 0xdf:
642                 case OP_TAP_TOGGLE:
643                 case OP_ONESHOT:
644                     return true;
645             }
646             return false;
647         case ACT_MACRO:
648         case ACT_FUNCTION:
649             if (action.func.opt & FUNC_TAP) { return true; }
650             return false;
651     }
652     return false;
653 }
654
655
656 /*
657  * debug print
658  */
659 void debug_event(keyevent_t event)
660 {
661     dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
662 }
663
664 void debug_record(keyrecord_t record)
665 {
666     debug_event(record.event);
667 #ifndef NO_ACTION_TAPPING
668     dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
669 #endif
670 }
671
672 void debug_action(action_t action)
673 {
674     switch (action.kind.id) {
675         case ACT_LMODS:             dprint("ACT_LMODS");             break;
676         case ACT_RMODS:             dprint("ACT_RMODS");             break;
677         case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
678         case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
679         case ACT_USAGE:             dprint("ACT_USAGE");             break;
680         case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
681         case ACT_LAYER:             dprint("ACT_LAYER");             break;
682         case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
683         case ACT_LAYER_TAP_EXT:     dprint("ACT_LAYER_TAP_EXT");     break;
684         case ACT_MACRO:             dprint("ACT_MACRO");             break;
685         case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
686         case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
687         default:                    dprint("UNKNOWN");               break;
688     }
689     dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
690 }