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