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