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