]> git.gir.st - tmk_keyboard.git/blob - tmk_core/common/action.c
remove experimental return, cleanup slash_question key
[tmk_keyboard.git] / tmk_core / 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 "backlight.h"
24 #include "action_layer.h"
25 #include "action_tapping.h"
26 #include "action_macro.h"
27 #include "action_util.h"
28 #include "action.h"
29 #include "hook.h"
30 #include "wait.h"
31
32 #ifdef DEBUG_ACTION
33 #include "debug.h"
34 #else
35 #include "nodebug.h"
36 #endif
37
38
39 void action_exec(keyevent_t event)
40 {
41 if (!IS_NOEVENT(event)) {
42 dprint("\n---- action_exec: start -----\n");
43 dprint("EVENT: "); debug_event(event); dprintln();
44 hook_matrix_change(event);
45 }
46
47 keyrecord_t record = { .event = event };
48
49 #ifndef NO_ACTION_TAPPING
50 action_tapping_process(record);
51 #else
52 process_action(&record);
53 if (!IS_NOEVENT(record.event)) {
54 dprint("processed: "); debug_record(record); dprintln();
55 }
56 #endif
57 }
58
59 void process_action(keyrecord_t *record)
60 {
61 keyevent_t event = record->event;
62 #ifndef NO_ACTION_TAPPING
63 uint8_t tap_count = record->tap.count;
64 #endif
65
66 if (IS_NOEVENT(event)) { return; }
67
68 action_t action = layer_switch_get_action(event);
69 dprint("ACTION: "); debug_action(action);
70 #ifndef NO_ACTION_LAYER
71 dprint(" layer_state: "); layer_debug();
72 dprint(" default_layer_state: "); default_layer_debug();
73 #endif
74 dprintln();
75
76 switch (action.kind.id) {
77 /* Key and Mods */
78 case ACT_LMODS:
79 case ACT_RMODS:
80 {
81 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
82 action.key.mods<<4;
83 if (event.pressed) {
84 if (mods) {
85 add_weak_mods(mods);
86 send_keyboard_report();
87 }
88 register_code(action.key.code);
89 } else {
90 unregister_code(action.key.code);
91 if (mods) {
92 del_weak_mods(mods);
93 send_keyboard_report();
94 }
95 }
96 }
97 break;
98 #ifndef NO_ACTION_TAPPING
99 case ACT_LMODS_TAP:
100 case ACT_RMODS_TAP:
101 {
102 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
103 action.key.mods<<4;
104 switch (action.key.code) {
105 #ifndef NO_ACTION_ONESHOT
106 case MODS_ONESHOT:
107 // Oneshot modifier
108 if (event.pressed) {
109 if (tap_count == 0) {
110 register_mods(mods);
111 }
112 else if (tap_count == 1) {
113 dprint("MODS_TAP: Oneshot: start\n");
114 set_oneshot_mods(mods);
115 }
116 else {
117 register_mods(mods);
118 }
119 } else {
120 if (tap_count == 0) {
121 clear_oneshot_mods();
122 unregister_mods(mods);
123 }
124 else if (tap_count == 1) {
125 // Retain Oneshot mods
126 }
127 else {
128 clear_oneshot_mods();
129 unregister_mods(mods);
130 }
131 }
132 break;
133 #endif
134 case MODS_TAP_TOGGLE:
135 if (event.pressed) {
136 if (tap_count <= TAPPING_TOGGLE) {
137 if (mods & get_mods()) {
138 dprint("MODS_TAP_TOGGLE: toggle mods off\n");
139 unregister_mods(mods);
140 } else {
141 dprint("MODS_TAP_TOGGLE: toggle mods on\n");
142 register_mods(mods);
143 }
144 }
145 } else {
146 if (tap_count < TAPPING_TOGGLE) {
147 dprint("MODS_TAP_TOGGLE: release : unregister_mods\n");
148 unregister_mods(mods);
149 }
150 }
151 break;
152 default:
153 if (event.pressed) {
154 if (tap_count > 0) {
155 if (record->tap.interrupted) {
156 dprint("MODS_TAP: Tap: Cancel: add_mods\n");
157 // ad hoc: set 0 to cancel tap
158 record->tap.count = 0;
159 register_mods(mods);
160 } else {
161 dprint("MODS_TAP: Tap: register_code\n");
162 register_code(action.key.code);
163 }
164 } else {
165 dprint("MODS_TAP: No tap: add_mods\n");
166 register_mods(mods);
167 }
168 } else {
169 if (tap_count > 0) {
170 dprint("MODS_TAP: Tap: unregister_code\n");
171 unregister_code(action.key.code);
172 } else {
173 dprint("MODS_TAP: No tap: add_mods\n");
174 unregister_mods(mods);
175 }
176 }
177 break;
178 }
179 }
180 break;
181 #endif
182 #ifdef EXTRAKEY_ENABLE
183 /* other HID usage */
184 case ACT_USAGE:
185 switch (action.usage.page) {
186 case PAGE_SYSTEM:
187 if (event.pressed) {
188 host_system_send(action.usage.code);
189 } else {
190 host_system_send(0);
191 }
192 break;
193 case PAGE_CONSUMER:
194 if (event.pressed) {
195 host_consumer_send(action.usage.code);
196 } else {
197 host_consumer_send(0);
198 }
199 break;
200 }
201 break;
202 #endif
203 #ifdef MOUSEKEY_ENABLE
204 /* Mouse key */
205 case ACT_MOUSEKEY:
206 if (event.pressed) {
207 mousekey_on(action.key.code);
208 mousekey_send();
209 } else {
210 mousekey_off(action.key.code);
211 mousekey_send();
212 }
213 break;
214 #endif
215 #ifndef NO_ACTION_LAYER
216 case ACT_LAYER:
217 if (action.layer_bitop.on == 0) {
218 /* Default Layer Bitwise Operation */
219 if (!event.pressed) {
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: default_layer_and(bits | mask); break;
225 case OP_BIT_OR: default_layer_or(bits | mask); break;
226 case OP_BIT_XOR: default_layer_xor(bits | mask); break;
227 case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
228 }
229 }
230 } else {
231 /* Layer Bitwise Operation */
232 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
233 (action.layer_bitop.on & ON_RELEASE)) {
234 uint8_t shift = action.layer_bitop.part*4;
235 uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
236 uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
237 switch (action.layer_bitop.op) {
238 case OP_BIT_AND: layer_and(bits | mask); break;
239 case OP_BIT_OR: layer_or(bits | mask); break;
240 case OP_BIT_XOR: layer_xor(bits | mask); break;
241 case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
242 }
243 }
244 }
245 break;
246 #ifndef NO_ACTION_TAPPING
247 case ACT_LAYER_TAP:
248 case ACT_LAYER_TAP_EXT:
249 switch (action.layer_tap.code) {
250 case 0xc0 ... 0xdf:
251 /* layer On/Off with modifiers */
252 if (event.pressed) {
253 layer_on(action.layer_tap.val);
254 register_mods((action.layer_tap.code & 0x10) ?
255 (action.layer_tap.code & 0x0f) << 4 :
256 (action.layer_tap.code & 0x0f));
257 } else {
258 layer_off(action.layer_tap.val);
259 unregister_mods((action.layer_tap.code & 0x10) ?
260 (action.layer_tap.code & 0x0f) << 4 :
261 (action.layer_tap.code & 0x0f));
262 }
263 break;
264 case OP_TAP_TOGGLE:
265 /* tap toggle */
266 if (event.pressed) {
267 if (tap_count < TAPPING_TOGGLE) {
268 layer_invert(action.layer_tap.val);
269 }
270 } else {
271 if (tap_count <= TAPPING_TOGGLE) {
272 layer_invert(action.layer_tap.val);
273 }
274 }
275 break;
276 case OP_ON_OFF:
277 event.pressed ? layer_on(action.layer_tap.val) :
278 layer_off(action.layer_tap.val);
279 break;
280 case OP_OFF_ON:
281 event.pressed ? layer_off(action.layer_tap.val) :
282 layer_on(action.layer_tap.val);
283 break;
284 case OP_SET_CLEAR:
285 event.pressed ? layer_move(action.layer_tap.val) :
286 layer_clear();
287 break;
288 default:
289 /* tap key */
290 if (event.pressed) {
291 if (tap_count > 0) {
292 dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
293 register_code(action.layer_tap.code);
294 } else {
295 dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
296 layer_on(action.layer_tap.val);
297 }
298 } else {
299 if (tap_count > 0) {
300 dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
301 unregister_code(action.layer_tap.code);
302 } else {
303 dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
304 layer_off(action.layer_tap.val);
305 }
306 }
307 break;
308 }
309 break;
310 #endif
311 #endif
312 /* Extentions */
313 #ifndef NO_ACTION_MACRO
314 case ACT_MACRO:
315 action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
316 break;
317 #endif
318 #ifdef BACKLIGHT_ENABLE
319 case ACT_BACKLIGHT:
320 if (!event.pressed) {
321 switch (action.backlight.opt) {
322 case BACKLIGHT_INCREASE:
323 backlight_increase();
324 break;
325 case BACKLIGHT_DECREASE:
326 backlight_decrease();
327 break;
328 case BACKLIGHT_TOGGLE:
329 backlight_toggle();
330 break;
331 case BACKLIGHT_STEP:
332 backlight_step();
333 break;
334 case BACKLIGHT_LEVEL:
335 backlight_level(action.backlight.level);
336 break;
337 }
338 }
339 break;
340 #endif
341 case ACT_COMMAND:
342 break;
343 #ifndef NO_ACTION_FUNCTION
344 case ACT_FUNCTION:
345 action_function(record, action.func.id, action.func.opt);
346 break;
347 #endif
348 default:
349 break;
350 }
351 }
352
353
354
355
356 /*
357 * Utilities for actions.
358 */
359 void register_code(uint8_t code)
360 {
361 if (code == KC_NO) {
362 return;
363 }
364
365 #ifdef LOCKING_SUPPORT_ENABLE
366 else if (KC_LOCKING_CAPS == code) {
367 #ifdef LOCKING_RESYNC_ENABLE
368 // Resync: ignore if caps lock already is on
369 if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
370 #endif
371 add_key(KC_CAPSLOCK);
372 send_keyboard_report();
373 wait_ms(100);
374 del_key(KC_CAPSLOCK);
375 send_keyboard_report();
376 }
377
378 else if (KC_LOCKING_NUM == code) {
379 #ifdef LOCKING_RESYNC_ENABLE
380 if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
381 #endif
382 add_key(KC_NUMLOCK);
383 send_keyboard_report();
384 wait_ms(100);
385 del_key(KC_NUMLOCK);
386 send_keyboard_report();
387 }
388
389 else if (KC_LOCKING_SCROLL == code) {
390 #ifdef LOCKING_RESYNC_ENABLE
391 if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
392 #endif
393 add_key(KC_SCROLLLOCK);
394 send_keyboard_report();
395 wait_ms(100);
396 del_key(KC_SCROLLLOCK);
397 send_keyboard_report();
398 }
399 #endif
400
401 else if IS_KEY(code) {
402 // TODO: should push command_proc out of this block?
403 if (command_proc(code)) return;
404
405 #ifndef NO_ACTION_ONESHOT
406 /* TODO: remove
407 if (oneshot_state.mods && !oneshot_state.disabled) {
408 uint8_t tmp_mods = get_mods();
409 add_mods(oneshot_state.mods);
410
411 add_key(code);
412 send_keyboard_report();
413
414 set_mods(tmp_mods);
415 send_keyboard_report();
416 oneshot_cancel();
417 } else
418 */
419 #endif
420 {
421 add_key(code);
422 send_keyboard_report();
423 }
424 }
425 else if IS_MOD(code) {
426 add_mods(MOD_BIT(code));
427 send_keyboard_report();
428 }
429 else if IS_SYSTEM(code) {
430 host_system_send(KEYCODE2SYSTEM(code));
431 }
432 else if IS_CONSUMER(code) {
433 host_consumer_send(KEYCODE2CONSUMER(code));
434 }
435 }
436
437 void unregister_code(uint8_t code)
438 {
439 if (code == KC_NO) {
440 return;
441 }
442
443 #ifdef LOCKING_SUPPORT_ENABLE
444 else if (KC_LOCKING_CAPS == code) {
445 #ifdef LOCKING_RESYNC_ENABLE
446 // Resync: ignore if caps lock already is off
447 if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
448 #endif
449 add_key(KC_CAPSLOCK);
450 send_keyboard_report();
451 wait_ms(100);
452 del_key(KC_CAPSLOCK);
453 send_keyboard_report();
454 }
455
456 else if (KC_LOCKING_NUM == code) {
457 #ifdef LOCKING_RESYNC_ENABLE
458 if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
459 #endif
460 add_key(KC_NUMLOCK);
461 send_keyboard_report();
462 wait_ms(100);
463 del_key(KC_NUMLOCK);
464 send_keyboard_report();
465 }
466
467 else if (KC_LOCKING_SCROLL == code) {
468 #ifdef LOCKING_RESYNC_ENABLE
469 if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
470 #endif
471 add_key(KC_SCROLLLOCK);
472 send_keyboard_report();
473 wait_ms(100);
474 del_key(KC_SCROLLLOCK);
475 send_keyboard_report();
476 }
477 #endif
478
479 else if IS_KEY(code) {
480 del_key(code);
481 send_keyboard_report();
482 }
483 else if IS_MOD(code) {
484 del_mods(MOD_BIT(code));
485 send_keyboard_report();
486 }
487 else if IS_SYSTEM(code) {
488 host_system_send(0);
489 }
490 else if IS_CONSUMER(code) {
491 host_consumer_send(0);
492 }
493 }
494
495 void register_mods(uint8_t mods)
496 {
497 if (mods) {
498 add_mods(mods);
499 send_keyboard_report();
500 }
501 }
502
503 void unregister_mods(uint8_t mods)
504 {
505 if (mods) {
506 del_mods(mods);
507 send_keyboard_report();
508 }
509 }
510
511 void clear_keyboard(void)
512 {
513 clear_mods();
514 clear_keyboard_but_mods();
515 }
516
517 void clear_keyboard_but_mods(void)
518 {
519 clear_weak_mods();
520 clear_keys();
521 send_keyboard_report();
522 #ifdef MOUSEKEY_ENABLE
523 mousekey_clear();
524 mousekey_send();
525 #endif
526 #ifdef EXTRAKEY_ENABLE
527 host_system_send(0);
528 host_consumer_send(0);
529 #endif
530 }
531
532 bool is_tap_key(keyevent_t event)
533 {
534 if (IS_NOEVENT(event)) { return false; }
535
536 action_t action = layer_switch_get_action(event);
537
538 switch (action.kind.id) {
539 case ACT_LMODS_TAP:
540 case ACT_RMODS_TAP:
541 switch (action.key.code) {
542 case MODS_ONESHOT:
543 case MODS_TAP_TOGGLE:
544 case KC_A ... KC_EXSEL: // tap key
545 case KC_LCTRL ... KC_RGUI: // tap key
546 return true;
547 }
548 case ACT_LAYER_TAP:
549 case ACT_LAYER_TAP_EXT:
550 switch (action.layer_tap.code) {
551 case 0xc0 ... 0xdf: // with modifiers
552 return false;
553 case KC_A ... KC_EXSEL: // tap key
554 case KC_LCTRL ... KC_RGUI: // tap key
555 case OP_TAP_TOGGLE:
556 return true;
557 }
558 return false;
559 case ACT_MACRO:
560 case ACT_FUNCTION:
561 if (action.func.opt & FUNC_TAP) { return true; }
562 return false;
563 }
564 return false;
565 }
566
567
568 /*
569 * debug print
570 */
571 void debug_event(keyevent_t event)
572 {
573 dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
574 }
575
576 void debug_record(keyrecord_t record)
577 {
578 debug_event(record.event);
579 #ifndef NO_ACTION_TAPPING
580 dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
581 #endif
582 }
583
584 void debug_action(action_t action)
585 {
586 switch (action.kind.id) {
587 case ACT_LMODS: dprint("ACT_LMODS"); break;
588 case ACT_RMODS: dprint("ACT_RMODS"); break;
589 case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break;
590 case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break;
591 case ACT_USAGE: dprint("ACT_USAGE"); break;
592 case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break;
593 case ACT_LAYER: dprint("ACT_LAYER"); break;
594 case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break;
595 case ACT_LAYER_TAP_EXT: dprint("ACT_LAYER_TAP_EXT"); break;
596 case ACT_MACRO: dprint("ACT_MACRO"); break;
597 case ACT_COMMAND: dprint("ACT_COMMAND"); break;
598 case ACT_FUNCTION: dprint("ACT_FUNCTION"); break;
599 default: dprint("UNKNOWN"); break;
600 }
601 dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
602 }
Imprint / Impressum