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