]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/action.c
Merge branch 'fix_print'
[tmk_firmware.git] / 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 "action_layer.h"
24 #include "action_tapping.h"
25 #include "action_oneshot.h"
26 #include "action_macro.h"
27 #include "action.h"
28
29 #ifdef DEBUG_ACTION
30 #include "debug.h"
31 #else
32 #include "nodebug.h"
33 #endif
34
35
36 void action_exec(keyevent_t event)
37 {
38     if (!IS_NOEVENT(event)) {
39         dprint("\n---- action_exec: start -----\n");
40         dprint("EVENT: "); debug_event(event); dprintln();
41     }
42
43     keyrecord_t record = { .event = event };
44
45 #ifndef NO_ACTION_TAPPING
46     action_tapping_process(record);
47 #else
48     process_action(&record);
49     if (!IS_NOEVENT(record.event)) {
50         dprint("processed: "); debug_record(record); dprintln();
51     }
52 #endif
53 }
54
55 void process_action(keyrecord_t *record)
56 {
57     keyevent_t event = record->event;
58 #ifndef NO_ACTION_TAPPING
59     uint8_t tap_count = record->tap.count;
60 #endif
61
62     if (IS_NOEVENT(event)) { return; }
63
64     action_t action = layer_switch_get_action(event.key);
65     dprint("ACTION: "); debug_action(action);
66 #ifndef NO_ACTION_LAYER
67     dprint(" layer_state: "); layer_debug();
68     dprint(" default_layer_state: "); default_layer_debug();
69 #endif
70     dprintln();
71
72     switch (action.kind.id) {
73         /* Key and Mods */
74         case ACT_LMODS:
75         case ACT_RMODS:
76             {
77                 uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
78                                                                 action.key.mods<<4;
79                 if (event.pressed) {
80                     if (mods) {
81                         host_add_mods(mods);
82                         host_send_keyboard_report();
83                     }
84                     register_code(action.key.code);
85                 } else {
86                     unregister_code(action.key.code);
87                     if (mods) {
88                         host_del_mods(mods);
89                         host_send_keyboard_report();
90                     }
91                 }
92             }
93             break;
94 #ifndef NO_ACTION_TAPPING
95         case ACT_LMODS_TAP:
96         case ACT_RMODS_TAP:
97             {
98                 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
99                                                                     action.key.mods<<4;
100                 switch (action.layer_tap.code) {
101     #ifndef NO_ACTION_ONESHOT
102                     case 0x00:
103                         // Oneshot modifier
104                         if (event.pressed) {
105                             if (tap_count == 0) {
106                                 dprint("MODS_TAP: Oneshot: add_mods\n");
107                                 add_mods(mods);
108                             }
109                             else if (tap_count == 1) {
110                                 dprint("MODS_TAP: Oneshot: start\n");
111                                 oneshot_start(mods);
112                             }
113                             else if (tap_count == TAPPING_TOGGLE) {
114                                 dprint("MODS_TAP: Oneshot: toggle\n");
115                                 oneshot_toggle();
116                             }
117                             else {
118                                 dprint("MODS_TAP: Oneshot: cancel&add_mods\n");
119                                 // double tap cancels oneshot and works as normal modifier.
120                                 oneshot_cancel();
121                                 add_mods(mods);
122                             }
123                         } else {
124                             if (tap_count == 0) {
125                                 dprint("MODS_TAP: Oneshot: cancel/del_mods\n");
126                                 // cancel oneshot on hold
127                                 oneshot_cancel();
128                                 del_mods(mods);
129                             }
130                             else if (tap_count == 1) {
131                                 dprint("MODS_TAP: Oneshot: del_mods\n");
132                                 // retain Oneshot
133                                 del_mods(mods);
134                             }
135                             else {
136                                 dprint("MODS_TAP: Oneshot: del_mods\n");
137                                 // cancel Mods
138                                 del_mods(mods);
139                             }
140                         }
141                         break;
142     #endif
143                     default:
144                         if (event.pressed) {
145                             if (tap_count > 0) {
146                                 if (record->tap.interrupted) {
147                                     dprint("MODS_TAP: Tap: Cancel: add_mods\n");
148                                     // ad hoc: set 0 to cancel tap
149                                     record->tap.count = 0;
150                                     add_mods(mods);
151                                 } else {
152                                     dprint("MODS_TAP: Tap: register_code\n");
153                                     register_code(action.key.code);
154                                 }
155                             } else {
156                                 dprint("MODS_TAP: No tap: add_mods\n");
157                                 add_mods(mods);
158                             }
159                         } else {
160                             if (tap_count > 0) {
161                                 dprint("MODS_TAP: Tap: unregister_code\n");
162                                 unregister_code(action.key.code);
163                             } else {
164                                 dprint("MODS_TAP: No tap: add_mods\n");
165                                 del_mods(mods);
166                             }
167                         }
168                         break;
169                 }
170             }
171             break;
172 #endif
173 #ifdef EXTRAKEY_ENABLE
174         /* other HID usage */
175         case ACT_USAGE:
176             switch (action.usage.page) {
177                 case PAGE_SYSTEM:
178                     if (event.pressed) {
179                         host_system_send(action.usage.code);
180                     } else {
181                         host_system_send(0);
182                     }
183                     break;
184                 case PAGE_CONSUMER:
185                     if (event.pressed) {
186                         host_consumer_send(action.usage.code);
187                     } else {
188                         host_consumer_send(0);
189                     }
190                     break;
191             }
192             break;
193 #endif
194 #ifdef MOUSEKEY_ENABLE
195         /* Mouse key */
196         case ACT_MOUSEKEY:
197             if (event.pressed) {
198                 mousekey_on(action.key.code);
199                 mousekey_send();
200             } else {
201                 mousekey_off(action.key.code);
202                 mousekey_send();
203             }
204             break;
205 #endif
206 #ifndef NO_ACTION_LAYER
207         case ACT_LAYER:
208             if (action.layer_bitop.on == 0) {
209                 /* Default Layer Bitwise Operation */
210                 if (!event.pressed) {
211                     uint8_t shift = action.layer_bitop.part*4;
212                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
213                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
214                     switch (action.layer_bitop.op) {
215                         case OP_BIT_AND: default_layer_and(bits | mask); break;
216                         case OP_BIT_OR:  default_layer_or(bits | mask);  break;
217                         case OP_BIT_XOR: default_layer_xor(bits | mask); break;
218                         case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
219                     }
220                 }
221             } else {
222                 /* Layer Bitwise Operation */
223                 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
224                                     (action.layer_bitop.on & ON_RELEASE)) {
225                     uint8_t shift = action.layer_bitop.part*4;
226                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
227                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
228                     switch (action.layer_bitop.op) {
229                         case OP_BIT_AND: layer_and(bits | mask); break;
230                         case OP_BIT_OR:  layer_or(bits | mask);  break;
231                         case OP_BIT_XOR: layer_xor(bits | mask); break;
232                         case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
233                     }
234                 }
235             }
236             break;
237     #ifndef NO_ACTION_TAPPING
238         case ACT_LAYER_TAP:
239         case ACT_LAYER_TAP1:
240             switch (action.layer_tap.code) {
241                 case OP_TAP_TOGGLE:
242                     /* tap toggle */
243                     if (event.pressed) {
244                         if (tap_count < TAPPING_TOGGLE) {
245                             layer_invert(action.layer_tap.val);
246                         }
247                     } else {
248                         if (tap_count <= TAPPING_TOGGLE) {
249                             layer_invert(action.layer_tap.val);
250                         }
251                     }
252                     break;
253                 case OP_ON_OFF:
254                     event.pressed ? layer_on(action.layer_tap.val) :
255                                     layer_off(action.layer_tap.val);
256                     break;
257                 case OP_OFF_ON:
258                     event.pressed ? layer_off(action.layer_tap.val) :
259                                     layer_on(action.layer_tap.val);
260                     break;
261                 case OP_SET_CLEAR:
262                     event.pressed ? layer_move(action.layer_tap.val) :
263                                     layer_clear();
264                     break;
265                 default:
266                     /* tap key */
267                     if (event.pressed) {
268                         if (tap_count > 0) {
269                             dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
270                             register_code(action.layer_tap.code);
271                         } else {
272                             dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
273                             layer_on(action.layer_tap.val);
274                         }
275                     } else {
276                         if (tap_count > 0) {
277                             dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
278                             unregister_code(action.layer_tap.code);
279                         } else {
280                             dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
281                             layer_off(action.layer_tap.val);
282                         }
283                     }
284                     break;
285             }
286             break;
287     #endif
288 #endif
289         /* Extentions */
290 #ifndef NO_ACTION_MACRO
291         case ACT_MACRO:
292             action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
293             break;
294 #endif
295         case ACT_COMMAND:
296             break;
297 #ifndef NO_ACTION_FUNCTION
298         case ACT_FUNCTION:
299             action_function(record, action.func.id, action.func.opt);
300             break;
301 #endif
302         default:
303             break;
304     }
305 }
306
307
308
309
310 /*
311  * Utilities for actions.
312  */
313 void register_code(uint8_t code)
314 {
315     if (code == KC_NO) {
316         return;
317     }
318 #ifdef CAPSLOCK_LOCKING_ENABLE
319     else if (KC_LOCKING_CAPS == code) {
320 #ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
321         // Resync: ignore if caps lock already is on
322         if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
323 #endif
324         host_add_key(KC_CAPSLOCK);
325         host_send_keyboard_report();
326         host_del_key(KC_CAPSLOCK);
327         host_send_keyboard_report();
328     }
329 #endif
330     else if IS_KEY(code) {
331         // TODO: should push command_proc out of this block?
332         if (command_proc(code)) return;
333
334 #ifndef NO_ACTION_ONESHOT
335         if (oneshot_state.mods && !oneshot_state.disabled) {
336             uint8_t tmp_mods = host_get_mods();
337             host_add_mods(oneshot_state.mods);
338
339             host_add_key(code);
340             host_send_keyboard_report();
341
342             host_set_mods(tmp_mods);
343             oneshot_cancel();
344         } else 
345 #endif
346         {
347             host_add_key(code);
348             host_send_keyboard_report();
349         }
350     }
351     else if IS_MOD(code) {
352         host_add_mods(MOD_BIT(code));
353         host_send_keyboard_report();
354     }
355 }
356
357 void unregister_code(uint8_t code)
358 {
359     if (code == KC_NO) {
360         return;
361     }
362 #ifdef CAPSLOCK_LOCKING_ENABLE
363     else if (KC_LOCKING_CAPS == code) {
364 #ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
365         // Resync: ignore if caps lock already is off
366         if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
367 #endif
368         host_add_key(KC_CAPSLOCK);
369         host_send_keyboard_report();
370         host_del_key(KC_CAPSLOCK);
371         host_send_keyboard_report();
372     }
373 #endif
374     else if IS_KEY(code) {
375         host_del_key(code);
376         host_send_keyboard_report();
377     }
378     else if IS_MOD(code) {
379         host_del_mods(MOD_BIT(code));
380         host_send_keyboard_report();
381     }
382 }
383
384 void add_mods(uint8_t mods)
385 {
386     if (mods) {
387         host_add_mods(mods);
388         host_send_keyboard_report();
389     }
390 }
391
392 void del_mods(uint8_t mods)
393 {
394     if (mods) {
395         host_del_mods(mods);
396         host_send_keyboard_report();
397     }
398 }
399
400 void set_mods(uint8_t mods)
401 {
402     host_set_mods(mods);
403     host_send_keyboard_report();
404 }
405
406 void clear_keyboard(void)
407 {
408     host_clear_mods();
409     clear_keyboard_but_mods();
410 }
411
412 void clear_keyboard_but_mods(void)
413 {
414     host_clear_keys();
415     host_send_keyboard_report();
416 #ifdef MOUSEKEY_ENABLE
417     mousekey_clear();
418     mousekey_send();
419 #endif
420 #ifdef EXTRAKEY_ENABLE
421     host_system_send(0);
422     host_consumer_send(0);
423 #endif
424 }
425
426 bool sending_anykey(void)
427 {
428     return (host_has_anykey() || host_mouse_in_use() ||
429             host_last_sysytem_report() || host_last_consumer_report());
430 }
431
432 bool is_tap_key(key_t key)
433 {
434     action_t action = layer_switch_get_action(key);
435
436     switch (action.kind.id) {
437         case ACT_LMODS_TAP:
438         case ACT_RMODS_TAP:
439         case ACT_LAYER_TAP:
440         case ACT_LAYER_TAP1:
441             return true;
442         case ACT_MACRO:
443         case ACT_FUNCTION:
444             if (action.func.opt & FUNC_TAP) { return true; }
445             return false;
446     }
447     return false;
448 }
449
450
451 /*
452  * debug print
453  */
454 void debug_event(keyevent_t event)
455 {
456     dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
457 }
458
459 void debug_record(keyrecord_t record)
460 {
461     debug_event(record.event);
462 #ifndef NO_ACTION_TAPPING
463     dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
464 #endif
465 }
466
467 void debug_action(action_t action)
468 {
469     switch (action.kind.id) {
470         case ACT_LMODS:             dprint("ACT_LMODS");             break;
471         case ACT_RMODS:             dprint("ACT_RMODS");             break;
472         case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
473         case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
474         case ACT_USAGE:             dprint("ACT_USAGE");             break;
475         case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
476         case ACT_LAYER:             dprint("ACT_LAYER");             break;
477         case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
478         case ACT_LAYER_TAP1:        dprint("ACT_LAYER_TAP1");        break;
479         case ACT_MACRO:             dprint("ACT_MACRO");             break;
480         case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
481         case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
482         default:                    dprint("UNKNOWN");               break;
483     }
484     dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
485 }