]> git.gir.st - tmk_keyboard.git/blob - common/action.c
Add support partly for modifier with tap key.
[tmk_keyboard.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 }
Imprint / Impressum