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