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