diff options
Diffstat (limited to 'quantum/action.c')
-rw-r--r-- | quantum/action.c | 1126 |
1 files changed, 1126 insertions, 0 deletions
diff --git a/quantum/action.c b/quantum/action.c new file mode 100644 index 000000000..d19fd2a04 --- /dev/null +++ b/quantum/action.c | |||
@@ -0,0 +1,1126 @@ | |||
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 "action_layer.h" | ||
24 | #include "action_tapping.h" | ||
25 | #include "action_macro.h" | ||
26 | #include "action_util.h" | ||
27 | #include "action.h" | ||
28 | #include "wait.h" | ||
29 | |||
30 | #ifdef BACKLIGHT_ENABLE | ||
31 | # include "backlight.h" | ||
32 | #endif | ||
33 | |||
34 | #ifdef DEBUG_ACTION | ||
35 | # include "debug.h" | ||
36 | #else | ||
37 | # include "nodebug.h" | ||
38 | #endif | ||
39 | |||
40 | #ifdef POINTING_DEVICE_ENABLE | ||
41 | # include "pointing_device.h" | ||
42 | #endif | ||
43 | |||
44 | int tp_buttons; | ||
45 | |||
46 | #if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) | ||
47 | int retro_tapping_counter = 0; | ||
48 | #endif | ||
49 | |||
50 | #ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY | ||
51 | __attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } | ||
52 | #endif | ||
53 | |||
54 | #ifdef RETRO_TAPPING_PER_KEY | ||
55 | __attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } | ||
56 | #endif | ||
57 | |||
58 | __attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; } | ||
59 | |||
60 | #ifndef TAP_CODE_DELAY | ||
61 | # define TAP_CODE_DELAY 0 | ||
62 | #endif | ||
63 | #ifndef TAP_HOLD_CAPS_DELAY | ||
64 | # define TAP_HOLD_CAPS_DELAY 80 | ||
65 | #endif | ||
66 | /** \brief Called to execute an action. | ||
67 | * | ||
68 | * FIXME: Needs documentation. | ||
69 | */ | ||
70 | void action_exec(keyevent_t event) { | ||
71 | if (!IS_NOEVENT(event)) { | ||
72 | dprint("\n---- action_exec: start -----\n"); | ||
73 | dprint("EVENT: "); | ||
74 | debug_event(event); | ||
75 | dprintln(); | ||
76 | #if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) | ||
77 | retro_tapping_counter++; | ||
78 | #endif | ||
79 | } | ||
80 | |||
81 | if (event.pressed) { | ||
82 | // clear the potential weak mods left by previously pressed keys | ||
83 | clear_weak_mods(); | ||
84 | } | ||
85 | |||
86 | #ifdef SWAP_HANDS_ENABLE | ||
87 | if (!IS_NOEVENT(event)) { | ||
88 | process_hand_swap(&event); | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | keyrecord_t record = {.event = event}; | ||
93 | |||
94 | #ifndef NO_ACTION_ONESHOT | ||
95 | # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) | ||
96 | if (has_oneshot_layer_timed_out()) { | ||
97 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
98 | } | ||
99 | if (has_oneshot_mods_timed_out()) { | ||
100 | clear_oneshot_mods(); | ||
101 | } | ||
102 | # ifdef SWAP_HANDS_ENABLE | ||
103 | if (has_oneshot_swaphands_timed_out()) { | ||
104 | clear_oneshot_swaphands(); | ||
105 | } | ||
106 | # endif | ||
107 | # endif | ||
108 | #endif | ||
109 | |||
110 | #ifndef NO_ACTION_TAPPING | ||
111 | if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { | ||
112 | action_tapping_process(record); | ||
113 | } | ||
114 | #else | ||
115 | if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { | ||
116 | process_record(&record); | ||
117 | } | ||
118 | if (!IS_NOEVENT(record.event)) { | ||
119 | dprint("processed: "); | ||
120 | debug_record(record); | ||
121 | dprintln(); | ||
122 | } | ||
123 | #endif | ||
124 | } | ||
125 | |||
126 | #ifdef SWAP_HANDS_ENABLE | ||
127 | bool swap_hands = false; | ||
128 | bool swap_held = false; | ||
129 | |||
130 | /** \brief Process Hand Swap | ||
131 | * | ||
132 | * FIXME: Needs documentation. | ||
133 | */ | ||
134 | void process_hand_swap(keyevent_t *event) { | ||
135 | static swap_state_row_t swap_state[MATRIX_ROWS]; | ||
136 | |||
137 | keypos_t pos = event->key; | ||
138 | swap_state_row_t col_bit = (swap_state_row_t)1 << pos.col; | ||
139 | bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); | ||
140 | |||
141 | if (do_swap) { | ||
142 | event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); | ||
143 | event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); | ||
144 | swap_state[pos.row] |= col_bit; | ||
145 | } else { | ||
146 | swap_state[pos.row] &= ~(col_bit); | ||
147 | } | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) | ||
152 | bool disable_action_cache = false; | ||
153 | |||
154 | void process_record_nocache(keyrecord_t *record) { | ||
155 | disable_action_cache = true; | ||
156 | process_record(record); | ||
157 | disable_action_cache = false; | ||
158 | } | ||
159 | #else | ||
160 | void process_record_nocache(keyrecord_t *record) { process_record(record); } | ||
161 | #endif | ||
162 | |||
163 | __attribute__((weak)) bool process_record_quantum(keyrecord_t *record) { return true; } | ||
164 | |||
165 | __attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {} | ||
166 | |||
167 | #ifndef NO_ACTION_TAPPING | ||
168 | /** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. | ||
169 | * | ||
170 | * FIXME: Needs documentation. | ||
171 | */ | ||
172 | void process_record_tap_hint(keyrecord_t *record) { | ||
173 | action_t action = layer_switch_get_action(record->event.key); | ||
174 | |||
175 | switch (action.kind.id) { | ||
176 | # ifdef SWAP_HANDS_ENABLE | ||
177 | case ACT_SWAP_HANDS: | ||
178 | switch (action.swap.code) { | ||
179 | case OP_SH_ONESHOT: | ||
180 | break; | ||
181 | case OP_SH_TAP_TOGGLE: | ||
182 | default: | ||
183 | swap_hands = !swap_hands; | ||
184 | swap_held = true; | ||
185 | } | ||
186 | break; | ||
187 | # endif | ||
188 | } | ||
189 | } | ||
190 | #endif | ||
191 | |||
192 | /** \brief Take a key event (key press or key release) and processes it. | ||
193 | * | ||
194 | * FIXME: Needs documentation. | ||
195 | */ | ||
196 | void process_record(keyrecord_t *record) { | ||
197 | if (IS_NOEVENT(record->event)) { | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | if (!process_record_quantum(record)) { | ||
202 | #ifndef NO_ACTION_ONESHOT | ||
203 | if (is_oneshot_layer_active() && record->event.pressed) { | ||
204 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
205 | } | ||
206 | #endif | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | process_record_handler(record); | ||
211 | post_process_record_quantum(record); | ||
212 | } | ||
213 | |||
214 | void process_record_handler(keyrecord_t *record) { | ||
215 | #ifdef COMBO_ENABLE | ||
216 | action_t action; | ||
217 | if (record->keycode) { | ||
218 | action = action_for_keycode(record->keycode); | ||
219 | } else { | ||
220 | action = store_or_get_action(record->event.pressed, record->event.key); | ||
221 | } | ||
222 | #else | ||
223 | action_t action = store_or_get_action(record->event.pressed, record->event.key); | ||
224 | #endif | ||
225 | dprint("ACTION: "); | ||
226 | debug_action(action); | ||
227 | #ifndef NO_ACTION_LAYER | ||
228 | dprint(" layer_state: "); | ||
229 | layer_debug(); | ||
230 | dprint(" default_layer_state: "); | ||
231 | default_layer_debug(); | ||
232 | #endif | ||
233 | dprintln(); | ||
234 | |||
235 | process_action(record, action); | ||
236 | } | ||
237 | |||
238 | #if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) | ||
239 | void register_button(bool pressed, enum mouse_buttons button) { | ||
240 | # ifdef PS2_MOUSE_ENABLE | ||
241 | tp_buttons = pressed ? tp_buttons | button : tp_buttons & ~button; | ||
242 | # endif | ||
243 | # ifdef POINTING_DEVICE_ENABLE | ||
244 | report_mouse_t currentReport = pointing_device_get_report(); | ||
245 | currentReport.buttons = pressed ? currentReport.buttons | button : currentReport.buttons & ~button; | ||
246 | pointing_device_set_report(currentReport); | ||
247 | # endif | ||
248 | } | ||
249 | #endif | ||
250 | |||
251 | /** \brief Take an action and processes it. | ||
252 | * | ||
253 | * FIXME: Needs documentation. | ||
254 | */ | ||
255 | void process_action(keyrecord_t *record, action_t action) { | ||
256 | keyevent_t event = record->event; | ||
257 | #ifndef NO_ACTION_TAPPING | ||
258 | uint8_t tap_count = record->tap.count; | ||
259 | #endif | ||
260 | |||
261 | #ifndef NO_ACTION_ONESHOT | ||
262 | bool do_release_oneshot = false; | ||
263 | // notice we only clear the one shot layer if the pressed key is not a modifier. | ||
264 | if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) | ||
265 | # ifdef SWAP_HANDS_ENABLE | ||
266 | && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT) | ||
267 | # endif | ||
268 | ) { | ||
269 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
270 | do_release_oneshot = !is_oneshot_layer_active(); | ||
271 | } | ||
272 | #endif | ||
273 | |||
274 | switch (action.kind.id) { | ||
275 | /* Key and Mods */ | ||
276 | case ACT_LMODS: | ||
277 | case ACT_RMODS: { | ||
278 | uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods << 4; | ||
279 | if (event.pressed) { | ||
280 | if (mods) { | ||
281 | if (IS_MOD(action.key.code) || action.key.code == KC_NO) { | ||
282 | // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. | ||
283 | // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). | ||
284 | // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). | ||
285 | add_mods(mods); | ||
286 | } else { | ||
287 | add_weak_mods(mods); | ||
288 | } | ||
289 | send_keyboard_report(); | ||
290 | } | ||
291 | register_code(action.key.code); | ||
292 | } else { | ||
293 | unregister_code(action.key.code); | ||
294 | if (mods) { | ||
295 | if (IS_MOD(action.key.code) || action.key.code == KC_NO) { | ||
296 | del_mods(mods); | ||
297 | } else { | ||
298 | del_weak_mods(mods); | ||
299 | } | ||
300 | send_keyboard_report(); | ||
301 | } | ||
302 | } | ||
303 | } break; | ||
304 | #ifndef NO_ACTION_TAPPING | ||
305 | case ACT_LMODS_TAP: | ||
306 | case ACT_RMODS_TAP: { | ||
307 | uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4; | ||
308 | switch (action.layer_tap.code) { | ||
309 | # ifndef NO_ACTION_ONESHOT | ||
310 | case MODS_ONESHOT: | ||
311 | // Oneshot modifier | ||
312 | if (event.pressed) { | ||
313 | if (tap_count == 0) { | ||
314 | dprint("MODS_TAP: Oneshot: 0\n"); | ||
315 | register_mods(mods | get_oneshot_mods()); | ||
316 | } else if (tap_count == 1) { | ||
317 | dprint("MODS_TAP: Oneshot: start\n"); | ||
318 | set_oneshot_mods(mods | get_oneshot_mods()); | ||
319 | # if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 | ||
320 | } else if (tap_count == ONESHOT_TAP_TOGGLE) { | ||
321 | dprint("MODS_TAP: Toggling oneshot"); | ||
322 | clear_oneshot_mods(); | ||
323 | set_oneshot_locked_mods(mods); | ||
324 | register_mods(mods); | ||
325 | # endif | ||
326 | } else { | ||
327 | register_mods(mods | get_oneshot_mods()); | ||
328 | } | ||
329 | } else { | ||
330 | if (tap_count == 0) { | ||
331 | clear_oneshot_mods(); | ||
332 | unregister_mods(mods); | ||
333 | } else if (tap_count == 1) { | ||
334 | // Retain Oneshot mods | ||
335 | # if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 | ||
336 | if (mods & get_mods()) { | ||
337 | clear_oneshot_locked_mods(); | ||
338 | clear_oneshot_mods(); | ||
339 | unregister_mods(mods); | ||
340 | } | ||
341 | } else if (tap_count == ONESHOT_TAP_TOGGLE) { | ||
342 | // Toggle Oneshot Layer | ||
343 | # endif | ||
344 | } else { | ||
345 | clear_oneshot_mods(); | ||
346 | unregister_mods(mods); | ||
347 | } | ||
348 | } | ||
349 | break; | ||
350 | # endif | ||
351 | case MODS_TAP_TOGGLE: | ||
352 | if (event.pressed) { | ||
353 | if (tap_count <= TAPPING_TOGGLE) { | ||
354 | register_mods(mods); | ||
355 | } | ||
356 | } else { | ||
357 | if (tap_count < TAPPING_TOGGLE) { | ||
358 | unregister_mods(mods); | ||
359 | } | ||
360 | } | ||
361 | break; | ||
362 | default: | ||
363 | if (event.pressed) { | ||
364 | if (tap_count > 0) { | ||
365 | # if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY) | ||
366 | if ( | ||
367 | # ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY | ||
368 | !get_ignore_mod_tap_interrupt(get_event_keycode(record->event, false), record) && | ||
369 | # endif | ||
370 | record->tap.interrupted) { | ||
371 | dprint("mods_tap: tap: cancel: add_mods\n"); | ||
372 | // ad hoc: set 0 to cancel tap | ||
373 | record->tap.count = 0; | ||
374 | register_mods(mods); | ||
375 | } else | ||
376 | # endif | ||
377 | { | ||
378 | dprint("MODS_TAP: Tap: register_code\n"); | ||
379 | register_code(action.key.code); | ||
380 | } | ||
381 | } else { | ||
382 | dprint("MODS_TAP: No tap: add_mods\n"); | ||
383 | register_mods(mods); | ||
384 | } | ||
385 | } else { | ||
386 | if (tap_count > 0) { | ||
387 | dprint("MODS_TAP: Tap: unregister_code\n"); | ||
388 | if (action.layer_tap.code == KC_CAPS) { | ||
389 | wait_ms(TAP_HOLD_CAPS_DELAY); | ||
390 | } else { | ||
391 | wait_ms(TAP_CODE_DELAY); | ||
392 | } | ||
393 | unregister_code(action.key.code); | ||
394 | } else { | ||
395 | dprint("MODS_TAP: No tap: add_mods\n"); | ||
396 | unregister_mods(mods); | ||
397 | } | ||
398 | } | ||
399 | break; | ||
400 | } | ||
401 | } break; | ||
402 | #endif | ||
403 | #ifdef EXTRAKEY_ENABLE | ||
404 | /* other HID usage */ | ||
405 | case ACT_USAGE: | ||
406 | switch (action.usage.page) { | ||
407 | case PAGE_SYSTEM: | ||
408 | if (event.pressed) { | ||
409 | host_system_send(action.usage.code); | ||
410 | } else { | ||
411 | host_system_send(0); | ||
412 | } | ||
413 | break; | ||
414 | case PAGE_CONSUMER: | ||
415 | if (event.pressed) { | ||
416 | host_consumer_send(action.usage.code); | ||
417 | } else { | ||
418 | host_consumer_send(0); | ||
419 | } | ||
420 | break; | ||
421 | } | ||
422 | break; | ||
423 | #endif | ||
424 | #ifdef MOUSEKEY_ENABLE | ||
425 | /* Mouse key */ | ||
426 | case ACT_MOUSEKEY: | ||
427 | if (event.pressed) { | ||
428 | mousekey_on(action.key.code); | ||
429 | } else { | ||
430 | mousekey_off(action.key.code); | ||
431 | } | ||
432 | switch (action.key.code) { | ||
433 | # if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) | ||
434 | # ifdef POINTING_DEVICE_ENABLE | ||
435 | case KC_MS_BTN1 ... KC_MS_BTN8: | ||
436 | # else | ||
437 | case KC_MS_BTN1 ... KC_MS_BTN3: | ||
438 | # endif | ||
439 | register_button(event.pressed, MOUSE_BTN_MASK(action.key.code - KC_MS_BTN1)); | ||
440 | break; | ||
441 | # endif | ||
442 | default: | ||
443 | mousekey_send(); | ||
444 | break; | ||
445 | } | ||
446 | break; | ||
447 | #endif | ||
448 | #ifndef NO_ACTION_LAYER | ||
449 | case ACT_LAYER: | ||
450 | if (action.layer_bitop.on == 0) { | ||
451 | /* Default Layer Bitwise Operation */ | ||
452 | if (!event.pressed) { | ||
453 | uint8_t shift = action.layer_bitop.part * 4; | ||
454 | layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; | ||
455 | layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; | ||
456 | switch (action.layer_bitop.op) { | ||
457 | case OP_BIT_AND: | ||
458 | default_layer_and(bits | mask); | ||
459 | break; | ||
460 | case OP_BIT_OR: | ||
461 | default_layer_or(bits | mask); | ||
462 | break; | ||
463 | case OP_BIT_XOR: | ||
464 | default_layer_xor(bits | mask); | ||
465 | break; | ||
466 | case OP_BIT_SET: | ||
467 | default_layer_set(bits | mask); | ||
468 | break; | ||
469 | } | ||
470 | } | ||
471 | } else { | ||
472 | /* Layer Bitwise Operation */ | ||
473 | if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { | ||
474 | uint8_t shift = action.layer_bitop.part * 4; | ||
475 | layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; | ||
476 | layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; | ||
477 | switch (action.layer_bitop.op) { | ||
478 | case OP_BIT_AND: | ||
479 | layer_and(bits | mask); | ||
480 | break; | ||
481 | case OP_BIT_OR: | ||
482 | layer_or(bits | mask); | ||
483 | break; | ||
484 | case OP_BIT_XOR: | ||
485 | layer_xor(bits | mask); | ||
486 | break; | ||
487 | case OP_BIT_SET: | ||
488 | layer_state_set(bits | mask); | ||
489 | break; | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | break; | ||
494 | case ACT_LAYER_MODS: | ||
495 | if (event.pressed) { | ||
496 | layer_on(action.layer_mods.layer); | ||
497 | register_mods(action.layer_mods.mods); | ||
498 | } else { | ||
499 | unregister_mods(action.layer_mods.mods); | ||
500 | layer_off(action.layer_mods.layer); | ||
501 | } | ||
502 | break; | ||
503 | # ifndef NO_ACTION_TAPPING | ||
504 | case ACT_LAYER_TAP: | ||
505 | case ACT_LAYER_TAP_EXT: | ||
506 | switch (action.layer_tap.code) { | ||
507 | case OP_TAP_TOGGLE: | ||
508 | /* tap toggle */ | ||
509 | if (event.pressed) { | ||
510 | if (tap_count < TAPPING_TOGGLE) { | ||
511 | layer_invert(action.layer_tap.val); | ||
512 | } | ||
513 | } else { | ||
514 | if (tap_count <= TAPPING_TOGGLE) { | ||
515 | layer_invert(action.layer_tap.val); | ||
516 | } | ||
517 | } | ||
518 | break; | ||
519 | case OP_ON_OFF: | ||
520 | event.pressed ? layer_on(action.layer_tap.val) : layer_off(action.layer_tap.val); | ||
521 | break; | ||
522 | case OP_OFF_ON: | ||
523 | event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val); | ||
524 | break; | ||
525 | case OP_SET_CLEAR: | ||
526 | event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); | ||
527 | break; | ||
528 | # ifndef NO_ACTION_ONESHOT | ||
529 | case OP_ONESHOT: | ||
530 | // Oneshot modifier | ||
531 | # if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 | ||
532 | do_release_oneshot = false; | ||
533 | if (event.pressed) { | ||
534 | del_mods(get_oneshot_locked_mods()); | ||
535 | if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { | ||
536 | reset_oneshot_layer(); | ||
537 | layer_off(action.layer_tap.val); | ||
538 | break; | ||
539 | } else if (tap_count < ONESHOT_TAP_TOGGLE) { | ||
540 | layer_on(action.layer_tap.val); | ||
541 | set_oneshot_layer(action.layer_tap.val, ONESHOT_START); | ||
542 | } | ||
543 | } else { | ||
544 | add_mods(get_oneshot_locked_mods()); | ||
545 | if (tap_count >= ONESHOT_TAP_TOGGLE) { | ||
546 | reset_oneshot_layer(); | ||
547 | clear_oneshot_locked_mods(); | ||
548 | set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); | ||
549 | } else { | ||
550 | clear_oneshot_layer_state(ONESHOT_PRESSED); | ||
551 | } | ||
552 | } | ||
553 | # else | ||
554 | if (event.pressed) { | ||
555 | layer_on(action.layer_tap.val); | ||
556 | set_oneshot_layer(action.layer_tap.val, ONESHOT_START); | ||
557 | } else { | ||
558 | clear_oneshot_layer_state(ONESHOT_PRESSED); | ||
559 | if (tap_count > 1) { | ||
560 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
561 | } | ||
562 | } | ||
563 | # endif | ||
564 | break; | ||
565 | # endif | ||
566 | default: | ||
567 | /* tap key */ | ||
568 | if (event.pressed) { | ||
569 | if (tap_count > 0) { | ||
570 | dprint("KEYMAP_TAP_KEY: Tap: register_code\n"); | ||
571 | register_code(action.layer_tap.code); | ||
572 | } else { | ||
573 | dprint("KEYMAP_TAP_KEY: No tap: On on press\n"); | ||
574 | layer_on(action.layer_tap.val); | ||
575 | } | ||
576 | } else { | ||
577 | if (tap_count > 0) { | ||
578 | dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); | ||
579 | if (action.layer_tap.code == KC_CAPS) { | ||
580 | wait_ms(TAP_HOLD_CAPS_DELAY); | ||
581 | } else { | ||
582 | wait_ms(TAP_CODE_DELAY); | ||
583 | } | ||
584 | unregister_code(action.layer_tap.code); | ||
585 | } else { | ||
586 | dprint("KEYMAP_TAP_KEY: No tap: Off on release\n"); | ||
587 | layer_off(action.layer_tap.val); | ||
588 | } | ||
589 | } | ||
590 | break; | ||
591 | } | ||
592 | break; | ||
593 | # endif | ||
594 | #endif | ||
595 | /* Extentions */ | ||
596 | #ifndef NO_ACTION_MACRO | ||
597 | case ACT_MACRO: | ||
598 | action_macro_play(action_get_macro(record, action.func.id, action.func.opt)); | ||
599 | break; | ||
600 | #endif | ||
601 | #ifdef SWAP_HANDS_ENABLE | ||
602 | case ACT_SWAP_HANDS: | ||
603 | switch (action.swap.code) { | ||
604 | case OP_SH_TOGGLE: | ||
605 | if (event.pressed) { | ||
606 | swap_hands = !swap_hands; | ||
607 | } | ||
608 | break; | ||
609 | case OP_SH_ON_OFF: | ||
610 | swap_hands = event.pressed; | ||
611 | break; | ||
612 | case OP_SH_OFF_ON: | ||
613 | swap_hands = !event.pressed; | ||
614 | break; | ||
615 | case OP_SH_ON: | ||
616 | if (!event.pressed) { | ||
617 | swap_hands = true; | ||
618 | } | ||
619 | break; | ||
620 | case OP_SH_OFF: | ||
621 | if (!event.pressed) { | ||
622 | swap_hands = false; | ||
623 | } | ||
624 | break; | ||
625 | # ifndef NO_ACTION_ONESHOT | ||
626 | case OP_SH_ONESHOT: | ||
627 | if (event.pressed) { | ||
628 | set_oneshot_swaphands(); | ||
629 | } else { | ||
630 | release_oneshot_swaphands(); | ||
631 | } | ||
632 | break; | ||
633 | # endif | ||
634 | |||
635 | # ifndef NO_ACTION_TAPPING | ||
636 | case OP_SH_TAP_TOGGLE: | ||
637 | /* tap toggle */ | ||
638 | |||
639 | if (event.pressed) { | ||
640 | if (swap_held) { | ||
641 | swap_held = false; | ||
642 | } else { | ||
643 | swap_hands = !swap_hands; | ||
644 | } | ||
645 | } else { | ||
646 | if (tap_count < TAPPING_TOGGLE) { | ||
647 | swap_hands = !swap_hands; | ||
648 | } | ||
649 | } | ||
650 | break; | ||
651 | default: | ||
652 | /* tap key */ | ||
653 | if (tap_count > 0) { | ||
654 | if (swap_held) { | ||
655 | swap_hands = !swap_hands; // undo hold set up in _tap_hint | ||
656 | swap_held = false; | ||
657 | } | ||
658 | if (event.pressed) { | ||
659 | register_code(action.swap.code); | ||
660 | } else { | ||
661 | wait_ms(TAP_CODE_DELAY); | ||
662 | unregister_code(action.swap.code); | ||
663 | *record = (keyrecord_t){}; // hack: reset tap mode | ||
664 | } | ||
665 | } else { | ||
666 | if (swap_held && !event.pressed) { | ||
667 | swap_hands = !swap_hands; // undo hold set up in _tap_hint | ||
668 | swap_held = false; | ||
669 | } | ||
670 | } | ||
671 | # endif | ||
672 | } | ||
673 | #endif | ||
674 | #ifndef NO_ACTION_FUNCTION | ||
675 | case ACT_FUNCTION: | ||
676 | action_function(record, action.func.id, action.func.opt); | ||
677 | break; | ||
678 | #endif | ||
679 | default: | ||
680 | break; | ||
681 | } | ||
682 | |||
683 | #ifndef NO_ACTION_LAYER | ||
684 | // if this event is a layer action, update the leds | ||
685 | switch (action.kind.id) { | ||
686 | case ACT_LAYER: | ||
687 | case ACT_LAYER_MODS: | ||
688 | # ifndef NO_ACTION_TAPPING | ||
689 | case ACT_LAYER_TAP: | ||
690 | case ACT_LAYER_TAP_EXT: | ||
691 | # endif | ||
692 | led_set(host_keyboard_leds()); | ||
693 | break; | ||
694 | default: | ||
695 | break; | ||
696 | } | ||
697 | #endif | ||
698 | |||
699 | #ifndef NO_ACTION_TAPPING | ||
700 | # if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) | ||
701 | if (!is_tap_action(action)) { | ||
702 | retro_tapping_counter = 0; | ||
703 | } else { | ||
704 | if (event.pressed) { | ||
705 | if (tap_count > 0) { | ||
706 | retro_tapping_counter = 0; | ||
707 | } | ||
708 | } else { | ||
709 | if (tap_count > 0) { | ||
710 | retro_tapping_counter = 0; | ||
711 | } else { | ||
712 | if ( | ||
713 | # ifdef RETRO_TAPPING_PER_KEY | ||
714 | get_retro_tapping(get_event_keycode(record->event, false), record) && | ||
715 | # endif | ||
716 | retro_tapping_counter == 2) { | ||
717 | tap_code(action.layer_tap.code); | ||
718 | } | ||
719 | retro_tapping_counter = 0; | ||
720 | } | ||
721 | } | ||
722 | } | ||
723 | # endif | ||
724 | #endif | ||
725 | |||
726 | #ifdef SWAP_HANDS_ENABLE | ||
727 | # ifndef NO_ACTION_ONESHOT | ||
728 | if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) { | ||
729 | use_oneshot_swaphands(); | ||
730 | } | ||
731 | # endif | ||
732 | #endif | ||
733 | |||
734 | #ifndef NO_ACTION_ONESHOT | ||
735 | /* Because we switch layers after a oneshot event, we need to release the | ||
736 | * key before we leave the layer or no key up event will be generated. | ||
737 | */ | ||
738 | if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED)) { | ||
739 | record->event.pressed = false; | ||
740 | layer_on(get_oneshot_layer()); | ||
741 | process_record(record); | ||
742 | layer_off(get_oneshot_layer()); | ||
743 | } | ||
744 | #endif | ||
745 | } | ||
746 | |||
747 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
748 | * | ||
749 | * FIXME: Needs documentation. | ||
750 | */ | ||
751 | void register_code(uint8_t code) { | ||
752 | if (code == KC_NO) { | ||
753 | return; | ||
754 | } | ||
755 | #ifdef LOCKING_SUPPORT_ENABLE | ||
756 | else if (KC_LOCKING_CAPS == code) { | ||
757 | # ifdef LOCKING_RESYNC_ENABLE | ||
758 | // Resync: ignore if caps lock already is on | ||
759 | if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return; | ||
760 | # endif | ||
761 | add_key(KC_CAPSLOCK); | ||
762 | send_keyboard_report(); | ||
763 | wait_ms(100); | ||
764 | del_key(KC_CAPSLOCK); | ||
765 | send_keyboard_report(); | ||
766 | } | ||
767 | |||
768 | else if (KC_LOCKING_NUM == code) { | ||
769 | # ifdef LOCKING_RESYNC_ENABLE | ||
770 | if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return; | ||
771 | # endif | ||
772 | add_key(KC_NUMLOCK); | ||
773 | send_keyboard_report(); | ||
774 | wait_ms(100); | ||
775 | del_key(KC_NUMLOCK); | ||
776 | send_keyboard_report(); | ||
777 | } | ||
778 | |||
779 | else if (KC_LOCKING_SCROLL == code) { | ||
780 | # ifdef LOCKING_RESYNC_ENABLE | ||
781 | if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return; | ||
782 | # endif | ||
783 | add_key(KC_SCROLLLOCK); | ||
784 | send_keyboard_report(); | ||
785 | wait_ms(100); | ||
786 | del_key(KC_SCROLLLOCK); | ||
787 | send_keyboard_report(); | ||
788 | } | ||
789 | #endif | ||
790 | |||
791 | else if IS_KEY (code) { | ||
792 | // TODO: should push command_proc out of this block? | ||
793 | if (command_proc(code)) return; | ||
794 | |||
795 | #ifndef NO_ACTION_ONESHOT | ||
796 | /* TODO: remove | ||
797 | if (oneshot_state.mods && !oneshot_state.disabled) { | ||
798 | uint8_t tmp_mods = get_mods(); | ||
799 | add_mods(oneshot_state.mods); | ||
800 | |||
801 | add_key(code); | ||
802 | send_keyboard_report(); | ||
803 | |||
804 | set_mods(tmp_mods); | ||
805 | send_keyboard_report(); | ||
806 | oneshot_cancel(); | ||
807 | } else | ||
808 | */ | ||
809 | #endif | ||
810 | { | ||
811 | // Force a new key press if the key is already pressed | ||
812 | // without this, keys with the same keycode, but different | ||
813 | // modifiers will be reported incorrectly, see issue #1708 | ||
814 | if (is_key_pressed(keyboard_report, code)) { | ||
815 | del_key(code); | ||
816 | send_keyboard_report(); | ||
817 | } | ||
818 | add_key(code); | ||
819 | send_keyboard_report(); | ||
820 | } | ||
821 | } else if IS_MOD (code) { | ||
822 | add_mods(MOD_BIT(code)); | ||
823 | send_keyboard_report(); | ||
824 | } | ||
825 | #ifdef EXTRAKEY_ENABLE | ||
826 | else if IS_SYSTEM (code) { | ||
827 | host_system_send(KEYCODE2SYSTEM(code)); | ||
828 | } else if IS_CONSUMER (code) { | ||
829 | host_consumer_send(KEYCODE2CONSUMER(code)); | ||
830 | } | ||
831 | #endif | ||
832 | #ifdef MOUSEKEY_ENABLE | ||
833 | else if IS_MOUSEKEY (code) { | ||
834 | mousekey_on(code); | ||
835 | mousekey_send(); | ||
836 | } | ||
837 | #endif | ||
838 | } | ||
839 | |||
840 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
841 | * | ||
842 | * FIXME: Needs documentation. | ||
843 | */ | ||
844 | void unregister_code(uint8_t code) { | ||
845 | if (code == KC_NO) { | ||
846 | return; | ||
847 | } | ||
848 | #ifdef LOCKING_SUPPORT_ENABLE | ||
849 | else if (KC_LOCKING_CAPS == code) { | ||
850 | # ifdef LOCKING_RESYNC_ENABLE | ||
851 | // Resync: ignore if caps lock already is off | ||
852 | if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return; | ||
853 | # endif | ||
854 | add_key(KC_CAPSLOCK); | ||
855 | send_keyboard_report(); | ||
856 | del_key(KC_CAPSLOCK); | ||
857 | send_keyboard_report(); | ||
858 | } | ||
859 | |||
860 | else if (KC_LOCKING_NUM == code) { | ||
861 | # ifdef LOCKING_RESYNC_ENABLE | ||
862 | if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return; | ||
863 | # endif | ||
864 | add_key(KC_NUMLOCK); | ||
865 | send_keyboard_report(); | ||
866 | del_key(KC_NUMLOCK); | ||
867 | send_keyboard_report(); | ||
868 | } | ||
869 | |||
870 | else if (KC_LOCKING_SCROLL == code) { | ||
871 | # ifdef LOCKING_RESYNC_ENABLE | ||
872 | if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return; | ||
873 | # endif | ||
874 | add_key(KC_SCROLLLOCK); | ||
875 | send_keyboard_report(); | ||
876 | del_key(KC_SCROLLLOCK); | ||
877 | send_keyboard_report(); | ||
878 | } | ||
879 | #endif | ||
880 | |||
881 | else if IS_KEY (code) { | ||
882 | del_key(code); | ||
883 | send_keyboard_report(); | ||
884 | } else if IS_MOD (code) { | ||
885 | del_mods(MOD_BIT(code)); | ||
886 | send_keyboard_report(); | ||
887 | } else if IS_SYSTEM (code) { | ||
888 | host_system_send(0); | ||
889 | } else if IS_CONSUMER (code) { | ||
890 | host_consumer_send(0); | ||
891 | } | ||
892 | #ifdef MOUSEKEY_ENABLE | ||
893 | else if IS_MOUSEKEY (code) { | ||
894 | mousekey_off(code); | ||
895 | mousekey_send(); | ||
896 | } | ||
897 | #endif | ||
898 | } | ||
899 | |||
900 | /** \brief Tap a keycode with a delay. | ||
901 | * | ||
902 | * \param code The basic keycode to tap. | ||
903 | * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it. | ||
904 | */ | ||
905 | void tap_code_delay(uint8_t code, uint16_t delay) { | ||
906 | register_code(code); | ||
907 | for (uint16_t i = delay; i > 0; i--) { | ||
908 | wait_ms(1); | ||
909 | } | ||
910 | unregister_code(code); | ||
911 | } | ||
912 | |||
913 | /** \brief Tap a keycode with the default delay. | ||
914 | * | ||
915 | * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. | ||
916 | */ | ||
917 | void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } | ||
918 | |||
919 | /** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately. | ||
920 | * | ||
921 | * \param mods A bitfield of modifiers to register. | ||
922 | */ | ||
923 | void register_mods(uint8_t mods) { | ||
924 | if (mods) { | ||
925 | add_mods(mods); | ||
926 | send_keyboard_report(); | ||
927 | } | ||
928 | } | ||
929 | |||
930 | /** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately. | ||
931 | * | ||
932 | * \param mods A bitfield of modifiers to unregister. | ||
933 | */ | ||
934 | void unregister_mods(uint8_t mods) { | ||
935 | if (mods) { | ||
936 | del_mods(mods); | ||
937 | send_keyboard_report(); | ||
938 | } | ||
939 | } | ||
940 | |||
941 | /** \brief Adds the given weak modifiers and sends a keyboard report immediately. | ||
942 | * | ||
943 | * \param mods A bitfield of modifiers to register. | ||
944 | */ | ||
945 | void register_weak_mods(uint8_t mods) { | ||
946 | if (mods) { | ||
947 | add_weak_mods(mods); | ||
948 | send_keyboard_report(); | ||
949 | } | ||
950 | } | ||
951 | |||
952 | /** \brief Removes the given weak modifiers and sends a keyboard report immediately. | ||
953 | * | ||
954 | * \param mods A bitfield of modifiers to unregister. | ||
955 | */ | ||
956 | void unregister_weak_mods(uint8_t mods) { | ||
957 | if (mods) { | ||
958 | del_weak_mods(mods); | ||
959 | send_keyboard_report(); | ||
960 | } | ||
961 | } | ||
962 | |||
963 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
964 | * | ||
965 | * FIXME: Needs documentation. | ||
966 | */ | ||
967 | void clear_keyboard(void) { | ||
968 | clear_mods(); | ||
969 | clear_keyboard_but_mods(); | ||
970 | } | ||
971 | |||
972 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
973 | * | ||
974 | * FIXME: Needs documentation. | ||
975 | */ | ||
976 | void clear_keyboard_but_mods(void) { | ||
977 | clear_keys(); | ||
978 | clear_keyboard_but_mods_and_keys(); | ||
979 | } | ||
980 | |||
981 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
982 | * | ||
983 | * FIXME: Needs documentation. | ||
984 | */ | ||
985 | void clear_keyboard_but_mods_and_keys() { | ||
986 | #ifdef EXTRAKEY_ENABLE | ||
987 | host_system_send(0); | ||
988 | host_consumer_send(0); | ||
989 | #endif | ||
990 | clear_weak_mods(); | ||
991 | clear_macro_mods(); | ||
992 | send_keyboard_report(); | ||
993 | #ifdef MOUSEKEY_ENABLE | ||
994 | mousekey_clear(); | ||
995 | mousekey_send(); | ||
996 | #endif | ||
997 | } | ||
998 | |||
999 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
1000 | * | ||
1001 | * FIXME: Needs documentation. | ||
1002 | */ | ||
1003 | bool is_tap_key(keypos_t key) { | ||
1004 | action_t action = layer_switch_get_action(key); | ||
1005 | return is_tap_action(action); | ||
1006 | } | ||
1007 | |||
1008 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
1009 | * | ||
1010 | * FIXME: Needs documentation. | ||
1011 | */ | ||
1012 | bool is_tap_record(keyrecord_t *record) { | ||
1013 | #ifdef COMBO_ENABLE | ||
1014 | action_t action; | ||
1015 | if (record->keycode) { | ||
1016 | action = action_for_keycode(record->keycode); | ||
1017 | } else { | ||
1018 | action = layer_switch_get_action(record->event.key); | ||
1019 | } | ||
1020 | #else | ||
1021 | action_t action = layer_switch_get_action(record->event.key); | ||
1022 | #endif | ||
1023 | return is_tap_action(action); | ||
1024 | } | ||
1025 | |||
1026 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
1027 | * | ||
1028 | * FIXME: Needs documentation. | ||
1029 | */ | ||
1030 | bool is_tap_action(action_t action) { | ||
1031 | switch (action.kind.id) { | ||
1032 | case ACT_LMODS_TAP: | ||
1033 | case ACT_RMODS_TAP: | ||
1034 | case ACT_LAYER_TAP: | ||
1035 | case ACT_LAYER_TAP_EXT: | ||
1036 | switch (action.layer_tap.code) { | ||
1037 | case KC_NO ... KC_RGUI: | ||
1038 | case OP_TAP_TOGGLE: | ||
1039 | case OP_ONESHOT: | ||
1040 | return true; | ||
1041 | } | ||
1042 | return false; | ||
1043 | case ACT_SWAP_HANDS: | ||
1044 | switch (action.swap.code) { | ||
1045 | case KC_NO ... KC_RGUI: | ||
1046 | case OP_SH_TAP_TOGGLE: | ||
1047 | return true; | ||
1048 | } | ||
1049 | return false; | ||
1050 | case ACT_MACRO: | ||
1051 | case ACT_FUNCTION: | ||
1052 | if (action.func.opt & FUNC_TAP) { | ||
1053 | return true; | ||
1054 | } | ||
1055 | return false; | ||
1056 | } | ||
1057 | return false; | ||
1058 | } | ||
1059 | |||
1060 | /** \brief Debug print (FIXME: Needs better description) | ||
1061 | * | ||
1062 | * FIXME: Needs documentation. | ||
1063 | */ | ||
1064 | void debug_event(keyevent_t event) { dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); } | ||
1065 | /** \brief Debug print (FIXME: Needs better description) | ||
1066 | * | ||
1067 | * FIXME: Needs documentation. | ||
1068 | */ | ||
1069 | void debug_record(keyrecord_t record) { | ||
1070 | debug_event(record.event); | ||
1071 | #ifndef NO_ACTION_TAPPING | ||
1072 | dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' ')); | ||
1073 | #endif | ||
1074 | } | ||
1075 | |||
1076 | /** \brief Debug print (FIXME: Needs better description) | ||
1077 | * | ||
1078 | * FIXME: Needs documentation. | ||
1079 | */ | ||
1080 | void debug_action(action_t action) { | ||
1081 | switch (action.kind.id) { | ||
1082 | case ACT_LMODS: | ||
1083 | dprint("ACT_LMODS"); | ||
1084 | break; | ||
1085 | case ACT_RMODS: | ||
1086 | dprint("ACT_RMODS"); | ||
1087 | break; | ||
1088 | case ACT_LMODS_TAP: | ||
1089 | dprint("ACT_LMODS_TAP"); | ||
1090 | break; | ||
1091 | case ACT_RMODS_TAP: | ||
1092 | dprint("ACT_RMODS_TAP"); | ||
1093 | break; | ||
1094 | case ACT_USAGE: | ||
1095 | dprint("ACT_USAGE"); | ||
1096 | break; | ||
1097 | case ACT_MOUSEKEY: | ||
1098 | dprint("ACT_MOUSEKEY"); | ||
1099 | break; | ||
1100 | case ACT_LAYER: | ||
1101 | dprint("ACT_LAYER"); | ||
1102 | break; | ||
1103 | case ACT_LAYER_MODS: | ||
1104 | dprint("ACT_LAYER_MODS"); | ||
1105 | break; | ||
1106 | case ACT_LAYER_TAP: | ||
1107 | dprint("ACT_LAYER_TAP"); | ||
1108 | break; | ||
1109 | case ACT_LAYER_TAP_EXT: | ||
1110 | dprint("ACT_LAYER_TAP_EXT"); | ||
1111 | break; | ||
1112 | case ACT_MACRO: | ||
1113 | dprint("ACT_MACRO"); | ||
1114 | break; | ||
1115 | case ACT_FUNCTION: | ||
1116 | dprint("ACT_FUNCTION"); | ||
1117 | break; | ||
1118 | case ACT_SWAP_HANDS: | ||
1119 | dprint("ACT_SWAP_HANDS"); | ||
1120 | break; | ||
1121 | default: | ||
1122 | dprint("UNKNOWN"); | ||
1123 | break; | ||
1124 | } | ||
1125 | dprintf("[%X:%02X]", action.kind.param >> 8, action.kind.param & 0xff); | ||
1126 | } | ||