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