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