]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/action.c
Add support partly for modifier with tap key.
[tmk_firmware.git] / common / action.c
1 #include "host.h"
2 #include "timer.h"
3 #include "keymap.h"
4 #include "keycode.h"
5 #include "keyboard.h"
6 #include "mousekey.h"
7 #include "command.h"
8 #include "util.h"
9 #include "debug.h"
10 #include "action.h"
11
12
13 static void process(keyevent_t event, action_t action);
14 static void register_code(uint8_t code);
15 static void unregister_code(uint8_t code);
16 static void add_mods(uint8_t mods);
17 static void del_mods(uint8_t mods);
18 static void set_mods(uint8_t mods);
19 static void clear_keyboard(void);
20 static void clear_keyboard_but_mods(void);
21 static bool sending_anykey(void);
22 static void layer_switch(uint8_t new_layer);
23
24
25 /* tap */
26 #define TAP_TIME    200
27 static keyevent_t last_event = {};
28 static uint8_t tap_count = 0;
29
30 /* layer */
31 uint8_t default_layer = 0;
32 uint8_t current_layer = 0;
33 keyrecord_t delaying_layer = {};
34
35 /* waiting keys buffer */
36 #define WAITING_KEYS_BUFFER 3
37 static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {};
38 static uint8_t waiting_keys_head = 0;
39 static bool waiting_keys_enqueue(keyevent_t event, action_t action)
40 {
41     debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = ");
42     debug_hex16(action.code); debug("\n");
43     if (waiting_keys_head < WAITING_KEYS_BUFFER) {
44         waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event,
45                                                            .action = action,
46                                                            .mods = host_get_mods() };
47     } else {
48         return true;
49     }
50 }
51 static void waiting_keys_clear(void)
52 {
53     waiting_keys_head = 0;
54 }
55 static bool waiting_keys_has(keypos_t key)
56 {
57     for (uint8_t i = 0; i < waiting_keys_head; i++) {
58         if KEYEQ(key, waiting_keys[i].event.key) return true;
59     }
60     return false;
61 }
62 static void waiting_keys_process_in_current_layer(void)
63 {
64     // TODO: in case of including layer key in waiting keys
65     uint8_t tmp_mods = host_get_mods();
66     for (uint8_t i = 0; i < waiting_keys_head; i++) {
67         /* revive status of mods */
68         host_set_mods(waiting_keys[i].mods);
69         process(waiting_keys[i].event, keymap_get_action(current_layer,
70                                                          waiting_keys[i].event.key.row,
71                                                          waiting_keys[i].event.key.col));
72         debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n");
73     }
74     host_set_mods(tmp_mods);
75     waiting_keys_clear();
76 }
77
78
79 void action_exec(keyevent_t event)
80 {
81     /* When delaying layer switch */
82     if (delaying_layer.action.code) {
83         /* Layer switch when tap time elapses or waiting key is released */
84         if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) ||
85             (!event.pressed && waiting_keys_has(event.key))) {
86             /* layer switch */
87             switch (delaying_layer.action.kind.id) {
88                 case ACT_LAYER_PRESSED:
89                     layer_switch(delaying_layer.action.layer.opt);
90                     break;
91                 case ACT_LAYER_BIT:
92                     layer_switch(current_layer | delaying_layer.action.layer.opt);
93                     break;
94             }
95             delaying_layer = (keyrecord_t){};
96
97             /* Process waiting keys in new layer */
98             waiting_keys_process_in_current_layer();
99         }
100         /* when delaying layer key is released within delay term */
101         else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) {
102             /* tap key down */
103             debug("tap[delaying_layer](register): fist\n");
104             uint8_t tmp_mods = host_get_mods();
105             host_set_mods(delaying_layer.mods);
106             register_code(delaying_layer.action.layer.code);
107             delaying_layer = (keyrecord_t){};
108             host_set_mods(tmp_mods);
109
110             /* process waiting keys */
111             waiting_keys_process_in_current_layer();
112         }
113     }
114
115     // not real event. event just to update delaying layer.
116     if (IS_NOEVENT(event)) {
117         return;
118     }
119
120     /* count tap when key is up */
121     if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) {
122         if (!event.pressed) tap_count++;
123     } else {
124         tap_count = 0;
125     }
126
127     action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
128
129     // TODO: all key events(pressed, released) should be recorded?
130     /* postpone key-down events while delaying layer */
131     if (delaying_layer.action.code) {
132         if (event.pressed) {
133             waiting_keys_enqueue(event, action);
134         } else {
135             process(event, action);
136         }
137     } else {
138         process(event, action);
139     }
140
141     /* last event */
142     last_event = event;
143 }
144
145
146 static void process(keyevent_t event, action_t action)
147 {
148     //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
149     debug("action: "); debug_hex16(action.code);
150     if (event.pressed) debug("[down]\n"); else debug("[up]\n");
151
152     switch (action.kind.id) {
153         /* Key and Mods */
154         case ACT_LMODS:
155             //               |pressed                          |released
156             // --------------+---------------------------------+------------
157             // key           |down(key)                        |up(key)
158             // mods          |add(mods)                        |del(mods)
159             // key with mods |add(mods), down(key), unset(mods)|up(key)
160             if (event.pressed) {
161                 uint8_t tmp_mods = host_get_mods();
162                 if (action.key.mods) {
163                     host_add_mods(action.key.mods);
164                     host_send_keyboard_report();
165                 }
166                 register_code(action.key.code);
167                 if (action.key.mods && action.key.code) {
168                     host_set_mods(tmp_mods);
169                     host_send_keyboard_report();
170                 }
171             } else {
172                 if (action.key.mods && !action.key.code) {
173                     host_del_mods(action.key.mods);
174                     host_send_keyboard_report();
175                 }
176                 unregister_code(action.key.code);
177             }
178             break;
179         case ACT_RMODS:
180             //               |pressed                          |released
181             // --------------+---------------------------------+------------
182             // key           |down(key)                        |up(key)
183             // mods          |add(mods)                        |del(mods)
184             // key with mods |add(mods), down(key), unset(mods)|up(key)
185             if (event.pressed) {
186                 uint8_t tmp_mods = host_get_mods();
187                 if (action.key.mods) {
188                     host_add_mods(action.key.mods<<4);
189                     host_send_keyboard_report();
190                 }
191                 register_code(action.key.code);
192                 if (action.key.mods && action.key.code) {
193                     host_set_mods(tmp_mods);
194                     host_send_keyboard_report();
195                 }
196             } else {
197                 if (action.key.mods && !action.key.code) {
198                     host_del_mods(action.key.mods<<4);
199                     host_send_keyboard_report();
200                 }
201                 unregister_code(action.key.code);
202             }
203             break;
204         case ACT_LMODS_TAP:
205             if (event.pressed) {
206                 if (tap_count == 0) {
207                     add_mods(action.key.mods);
208                 } else {
209                     debug("tap[lmods](register): "); debug_hex(tap_count); debug("\n");
210                     register_code(action.key.code);
211                 }
212             } else {
213                 if (tap_count == 0) {
214                     del_mods(action.key.mods);
215                 } else if (tap_count == 1) {
216                     debug("tap[lmods](register/unregister): "); debug_hex(tap_count); debug("\n");
217                     del_mods(action.key.mods);
218                     register_code(action.key.code);
219                     unregister_code(action.key.code);
220                 } else {
221                     debug("tap[lmods](unregister): "); debug_hex(tap_count); debug("\n");
222                     unregister_code(action.key.code);
223                 }
224             }
225             break;
226         case ACT_RMODS_TAP:
227             if (event.pressed) {
228                 if (tap_count == 0) {
229                     add_mods(action.key.mods<<4);
230                 } else {
231                     debug("tap[rmods](register): "); debug_hex(tap_count); debug("\n");
232                     register_code(action.key.code);
233                 }
234             } else {
235                 if (tap_count == 0) {
236                     del_mods(action.key.mods<<4);
237                 } else if (tap_count == 1) {
238                     debug("tap[rmods](register/unregister): "); debug_hex(tap_count); debug("\n");
239                     del_mods(action.key.mods<<4);
240                     register_code(action.key.code);
241                     unregister_code(action.key.code);
242                 } else {
243                     debug("tap[rmods](unregister): "); debug_hex(tap_count); debug("\n");
244                     unregister_code(action.key.code);
245                 }
246             }
247             break;
248
249         /* other HID usage */
250         case ACT_USAGE:
251 #ifdef EXTRAKEY_ENABLE
252             switch (action.usage.page) {
253                 case ACTION_USAGE_PAGE_SYSTEM:
254                     if (event.pressed) {
255                         host_system_send(action.usage.code);
256                     } else {
257                         host_system_send(0);
258                     }
259                     break;
260                 case ACTION_USAGE_PAGE_CONSUMER:
261                     if (event.pressed) {
262                         host_consumer_send(action.usage.code);
263                     } else {
264                         host_consumer_send(0);
265                     }
266                     break;
267             }
268 #endif
269             break;
270
271         /* Mouse key */
272         case ACT_MOUSEKEY:
273 #ifdef MOUSEKEY_ENABLE
274             if (event.pressed) {
275                 mousekey_on(action.key.code);
276                 mousekey_send();
277             } else {
278                 mousekey_off(action.key.code);
279                 mousekey_send();
280             }
281 #endif
282             break;
283
284         /* Layer key */
285         case ACT_LAYER_PRESSED:
286             // layer action when pressed
287             switch (action.layer.code) {
288                 case 0x00:
289                     if (event.pressed) {
290                         layer_switch(action.layer.opt);
291                     }
292                     break;
293                 case 0xF0:
294                     // TODO: tap toggle
295                     break;
296                 case 0xFF:
297                     if (event.pressed) {
298                         default_layer = action.layer.opt;
299                         layer_switch(default_layer);
300                     }
301                     break;
302                 default:
303                     // with tap key
304                     if (event.pressed) {
305                         if (tap_count == 0) {
306                             // not tapping yet
307                             if (host_has_anykey()) {
308                                 register_code(action.layer.code);
309                             } else {
310                                 debug("Delay switching layer("); debug_hex8(action.layer.opt); debug(")\n");
311                                 delaying_layer = (keyrecord_t){
312                                     .event = event,
313                                     .action = action,
314                                     .mods = host_get_mods()
315                                 };
316                             }
317                         } else if (tap_count > 0) {
318                             // pressed after tapping
319                             debug("tap[layer](register): "); debug_hex(tap_count); debug("\n");
320                             register_code(action.layer.code);
321                         }
322                     } else {
323                         // released after tapping
324                         debug("tap[layer](unregister): "); debug_hex(tap_count); debug("\n");
325                         unregister_code(action.layer.code);
326                     }
327                     break;
328             }
329             break;
330         case ACT_LAYER_RELEASED:
331             switch (action.layer.code) {
332                 case 0x00:
333                     if (!event.pressed) {
334                         layer_switch(action.layer.opt);
335                     }
336                     break;
337                 case 0xF0:
338                     // Ignored. LAYER_RELEASED with tap toggle is invalid action.
339                     break;
340                 case 0xFF:
341                     if (!event.pressed) {
342                         default_layer = action.layer.opt;
343                         layer_switch(default_layer);
344                     }
345                     break;
346                 default:
347                     // Ignored. LAYER_RELEASED with tap key is invalid action.
348                     break;
349             }
350             break;
351         case ACT_LAYER_BIT:
352             switch (action.layer.code) {
353                 case 0x00:
354                     if (event.pressed) {
355                         layer_switch(current_layer | action.layer.opt);
356                     } else {
357                         layer_switch(current_layer & ~action.layer.opt);
358                     }
359                     break;
360                 case 0xF0:
361                     // TODO: tap toggle
362                     break;
363                 case 0xFF:
364                     // change default layer
365                     if (event.pressed) {
366                         default_layer = current_layer | action.layer.opt;
367                         layer_switch(default_layer);
368                     } else {
369                         default_layer = current_layer & ~action.layer.opt;
370                         layer_switch(default_layer);
371                     }
372                     break;
373                 default:
374                     // with tap key
375                     if (event.pressed) {
376                         if (tap_count == 0) {
377                             if (host_has_anykey()) {
378                                 register_code(action.layer.code);
379                             } else {
380                                 delaying_layer = (keyrecord_t){
381                                     .event = event,
382                                     .action = action,
383                                     .mods = keyboard_report->mods
384                                 };
385                             }
386                         } else if (tap_count > 0) {
387                             debug("tap[layer_bit](register): "); debug_hex(tap_count); debug("\n");
388                             register_code(action.layer.code);
389                         }
390                     } else {
391                         if (tap_count == 0) {
392                             // no tap
393                             layer_switch(current_layer & ~action.layer.opt);
394                         } else if (tap_count == 1) {
395                             // tap
396                             register_code(action.layer.code);
397                         }
398                         unregister_code(action.layer.code);
399                     }
400                     break;
401             }
402         case ACT_LAYER_EXT:
403             switch (action.layer.opt) {
404                 case 0x00:
405                     // set default layer when pressed
406                     switch (action.layer.code) {
407                         case 0x00:
408                             if (event.pressed) {
409                                 layer_switch(default_layer);
410                             }
411                             break;
412                         case 0xF0:
413                             // TODO: tap toggle
414                             break;
415                         case 0xFF:
416                             if (event.pressed) {
417                                 default_layer = current_layer;
418                                 layer_switch(default_layer);
419                             }
420                             break;
421                         default:
422                             // TODO: tap key
423                             break;
424                     }
425                     break;
426                 case 0x01:
427                     // set default layer when released
428                     switch (action.layer.code) {
429                         case 0x00:
430                             if (!event.pressed) {
431                                 layer_switch(default_layer);
432                             }
433                             break;
434                         case 0xFF:
435                             if (!event.pressed) {
436                                 default_layer = current_layer;
437                                 layer_switch(default_layer);
438                             }
439                             break;
440                         case 0xF0:
441                         default:
442                             // Ignore tap.
443                             if (!event.pressed) {
444                                 layer_switch(default_layer);
445                             }
446                             break;
447                     }
448                     break;
449             }
450             break;
451
452         /* Extentions */
453         case ACT_MACRO:
454         case ACT_COMMAND:
455         case ACT_FUNCTION:
456         default:
457             break;
458     }
459 }
460
461 static void register_code(uint8_t code)
462 {
463     if (code == KC_NO) {
464         return;
465     }
466     else if IS_KEY(code) {
467         // TODO: should push command_proc out of this block?
468         if (!command_proc(code)) {
469             host_add_key(code);
470             host_send_keyboard_report();
471         }
472     }
473     else if IS_MOD(code) {
474         host_add_mods(MOD_BIT(code));
475         host_send_keyboard_report();
476     }
477 }
478
479 static void unregister_code(uint8_t code)
480 {
481     if IS_KEY(code) {
482         host_del_key(code);
483         host_send_keyboard_report();
484     }
485     else if IS_MOD(code) {
486         host_del_mods(MOD_BIT(code));
487         host_send_keyboard_report();
488     }
489 }
490
491 static void add_mods(uint8_t mods)
492 {
493     if (mods) {
494         host_add_mods(mods);
495         host_send_keyboard_report();
496     }
497 }
498
499 static void del_mods(uint8_t mods)
500 {
501     if (mods) {
502         host_del_mods(mods);
503         host_send_keyboard_report();
504     }
505 }
506
507 static void set_mods(uint8_t mods)
508 {
509     host_set_mods(mods);
510     host_send_keyboard_report();
511 }
512
513 static void clear_keyboard(void)
514 {
515     host_clear_mods();
516     clear_keyboard_but_mods();
517 }
518
519 static void clear_keyboard_but_mods(void)
520 {
521     host_clear_keys();
522     host_send_keyboard_report();
523 #ifdef MOUSEKEY_ENABLE
524     mousekey_clear();
525     mousekey_send();
526 #endif
527 #ifdef EXTRAKEY_ENABLE
528     host_system_send(0);
529     host_consumer_send(0);
530 #endif
531 }
532
533 static bool sending_anykey(void)
534 {
535     return (host_has_anykey() || host_mouse_in_use() ||
536             host_last_sysytem_report() || host_last_consumer_report());
537 }
538
539 static void layer_switch(uint8_t new_layer)
540 {
541     if (current_layer != new_layer) {
542         debug("Layer Switch: "); debug_hex(current_layer);
543         debug(" -> "); debug_hex(new_layer); debug("\n");
544
545         current_layer = new_layer;
546         clear_keyboard_but_mods(); // To avoid stuck keys
547         // TODO: update mods with full scan of matrix? if modifier changes between layers
548     }
549 }