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