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