diff options
Diffstat (limited to 'common/action.c')
| -rw-r--r-- | common/action.c | 201 |
1 files changed, 132 insertions, 69 deletions
diff --git a/common/action.c b/common/action.c index db31613bf..22f0bf0a0 100644 --- a/common/action.c +++ b/common/action.c | |||
| @@ -97,6 +97,40 @@ static void waiting_buffer_process(void) | |||
| 97 | { | 97 | { |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | /* Oneshot modifier | ||
| 101 | * | ||
| 102 | * Problem: Want to capitalize like 'The' but the result tends to be 'THe'. | ||
| 103 | * Solution: Oneshot modifier have its effect on only one key coming next. | ||
| 104 | * Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key. | ||
| 105 | * | ||
| 106 | * Hold: works as normal modifier. | ||
| 107 | * Tap: one shot modifier. | ||
| 108 | * 2 Tap: cancel one shot modifier. | ||
| 109 | * 5-Tap: toggles enable/disable oneshot feature. | ||
| 110 | */ | ||
| 111 | static struct { | ||
| 112 | uint8_t mods; | ||
| 113 | uint8_t time; | ||
| 114 | bool ready; | ||
| 115 | bool disabled; | ||
| 116 | } oneshot_state; | ||
| 117 | static void oneshot_start(uint8_t mods, uint16_t time) | ||
| 118 | { | ||
| 119 | oneshot_state.mods = mods; | ||
| 120 | oneshot_state.time = time; | ||
| 121 | oneshot_state.ready = true; | ||
| 122 | } | ||
| 123 | static void oneshot_cancel(void) | ||
| 124 | { | ||
| 125 | oneshot_state.mods = 0; | ||
| 126 | oneshot_state.time = 0; | ||
| 127 | oneshot_state.ready = false; | ||
| 128 | } | ||
| 129 | static void oneshot_toggle(void) | ||
| 130 | { | ||
| 131 | oneshot_state.disabled = !oneshot_state.disabled; | ||
| 132 | } | ||
| 133 | |||
| 100 | 134 | ||
| 101 | /* | 135 | /* |
| 102 | * Rule to judge tap: | 136 | * Rule to judge tap: |
| @@ -271,83 +305,102 @@ static void process(keyrecord_t *record) | |||
| 271 | switch (action.kind.id) { | 305 | switch (action.kind.id) { |
| 272 | /* Key and Mods */ | 306 | /* Key and Mods */ |
| 273 | case ACT_LMODS: | 307 | case ACT_LMODS: |
| 274 | // |pressed |released | ||
| 275 | // --------------+---------------------------------+------------ | ||
| 276 | // key |down(key) |up(key) | ||
| 277 | // mods |add(mods) |del(mods) | ||
| 278 | // key with mods |add(mods), down(key), unset(mods)|up(key) | ||
| 279 | if (event.pressed) { | ||
| 280 | uint8_t tmp_mods = host_get_mods(); | ||
| 281 | if (action.key.mods) { | ||
| 282 | host_add_mods(action.key.mods); | ||
| 283 | host_send_keyboard_report(); | ||
| 284 | } | ||
| 285 | register_code(action.key.code); | ||
| 286 | if (action.key.mods && action.key.code) { | ||
| 287 | host_set_mods(tmp_mods); | ||
| 288 | host_send_keyboard_report(); | ||
| 289 | } | ||
| 290 | } else { | ||
| 291 | if (action.key.mods && !action.key.code) { | ||
| 292 | host_del_mods(action.key.mods); | ||
| 293 | host_send_keyboard_report(); | ||
| 294 | } | ||
| 295 | unregister_code(action.key.code); | ||
| 296 | } | ||
| 297 | break; | ||
| 298 | case ACT_RMODS: | 308 | case ACT_RMODS: |
| 299 | // |pressed |released | 309 | { |
| 300 | // --------------+---------------------------------+------------ | 310 | uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : |
| 301 | // key |down(key) |up(key) | 311 | action.key.mods<<4; |
| 302 | // mods |add(mods) |del(mods) | 312 | if (event.pressed) { |
| 303 | // key with mods |add(mods), down(key), unset(mods)|up(key) | 313 | uint8_t tmp_mods = host_get_mods(); |
| 304 | if (event.pressed) { | 314 | if (mods) { |
| 305 | uint8_t tmp_mods = host_get_mods(); | 315 | host_add_mods(mods); |
| 306 | if (action.key.mods) { | 316 | host_send_keyboard_report(); |
| 307 | host_add_mods(action.key.mods<<4); | 317 | } |
| 308 | host_send_keyboard_report(); | 318 | register_code(action.key.code); |
| 309 | } | 319 | if (mods && action.key.code) { |
| 310 | register_code(action.key.code); | 320 | host_set_mods(tmp_mods); |
| 311 | if (action.key.mods && action.key.code) { | 321 | host_send_keyboard_report(); |
| 312 | host_set_mods(tmp_mods); | 322 | } |
| 313 | host_send_keyboard_report(); | 323 | } else { |
| 314 | } | 324 | if (mods && !action.key.code) { |
| 315 | } else { | 325 | host_del_mods(mods); |
| 316 | if (action.key.mods && !action.key.code) { | 326 | host_send_keyboard_report(); |
| 317 | host_del_mods(action.key.mods<<4); | 327 | } |
| 318 | host_send_keyboard_report(); | 328 | unregister_code(action.key.code); |
| 319 | } | 329 | } |
| 320 | unregister_code(action.key.code); | ||
| 321 | } | 330 | } |
| 322 | break; | 331 | break; |
| 323 | case ACT_LMODS_TAP: | 332 | case ACT_LMODS_TAP: |
| 324 | case ACT_RMODS_TAP: | 333 | case ACT_RMODS_TAP: |
| 325 | { | 334 | { |
| 326 | uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : | 335 | uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : |
| 327 | action.key.mods<<4; | 336 | action.key.mods<<4; |
| 328 | if (event.pressed) { | 337 | switch (action.layer.code) { |
| 329 | if (IS_TAPPING_KEY(event.key) && tap_count > 0) { | 338 | case 0x00: |
| 330 | if (waiting_buffer_has_anykey_pressed()) { | 339 | // Oneshot modifier |
| 331 | debug("MODS_TAP: Tap: Cancel: add_mods\n"); | 340 | if (event.pressed) { |
| 332 | // ad hoc: set 0 to cancel tap | 341 | if (tap_count == 0) { |
| 333 | record->tap_count = 0; | 342 | debug("MODS_TAP: Oneshot: add_mods\n"); |
| 334 | add_mods(tmp_mods); | 343 | add_mods(mods); |
| 344 | } | ||
| 345 | else if (tap_count == 1) { | ||
| 346 | debug("MODS_TAP: Oneshot: start\n"); | ||
| 347 | oneshot_start(mods, event.time); | ||
| 348 | } | ||
| 349 | else if (tap_count == 5) { | ||
| 350 | debug("MODS_TAP: Oneshot: toggle\n"); | ||
| 351 | oneshot_toggle(); | ||
| 352 | } | ||
| 353 | else { | ||
| 354 | debug("MODS_TAP: Oneshot: cancel&add_mods\n"); | ||
| 355 | // double tap cancels oneshot and works as normal modifier. | ||
| 356 | oneshot_cancel(); | ||
| 357 | add_mods(mods); | ||
| 358 | } | ||
| 335 | } else { | 359 | } else { |
| 336 | debug("MODS_TAP: Tap: register_code\n"); | 360 | if (tap_count == 0) { |
| 337 | register_code(action.key.code); | 361 | debug("MODS_TAP: Oneshot: cancel/del_mods\n"); |
| 362 | // cancel oneshot by holding. | ||
| 363 | oneshot_cancel(); | ||
| 364 | del_mods(mods); | ||
| 365 | } | ||
| 366 | else if (tap_count == 1) { | ||
| 367 | debug("MODS_TAP: Oneshot: del_mods\n"); | ||
| 368 | // retain Oneshot | ||
| 369 | del_mods(mods); | ||
| 370 | } | ||
| 371 | else { | ||
| 372 | debug("MODS_TAP: Oneshot: del_mods\n"); | ||
| 373 | // cancel Mods | ||
| 374 | del_mods(mods); | ||
| 375 | } | ||
| 338 | } | 376 | } |
| 339 | } else { | 377 | break; |
| 340 | debug("MODS_TAP: No tap: add_mods\n"); | 378 | default: |
| 341 | add_mods(tmp_mods); | 379 | if (event.pressed) { |
| 342 | } | 380 | if (tap_count > 0) { |
| 343 | } else { | 381 | if (waiting_buffer_has_anykey_pressed()) { |
| 344 | if (IS_TAPPING_KEY(event.key) && tap_count > 0) { | 382 | debug("MODS_TAP: Tap: Cancel: add_mods\n"); |
| 345 | debug("MODS_TAP: Tap: unregister_code\n"); | 383 | // ad hoc: set 0 to cancel tap |
| 346 | unregister_code(action.key.code); | 384 | record->tap_count = 0; |
| 347 | } else { | 385 | add_mods(mods); |
| 348 | debug("MODS_TAP: No tap: add_mods\n"); | 386 | } else { |
| 349 | del_mods(tmp_mods); | 387 | debug("MODS_TAP: Tap: register_code\n"); |
| 350 | } | 388 | register_code(action.key.code); |
| 389 | } | ||
| 390 | } else { | ||
| 391 | debug("MODS_TAP: No tap: add_mods\n"); | ||
| 392 | add_mods(mods); | ||
| 393 | } | ||
| 394 | } else { | ||
| 395 | if (tap_count > 0) { | ||
| 396 | debug("MODS_TAP: Tap: unregister_code\n"); | ||
| 397 | unregister_code(action.key.code); | ||
| 398 | } else { | ||
| 399 | debug("MODS_TAP: No tap: add_mods\n"); | ||
| 400 | del_mods(mods); | ||
| 401 | } | ||
| 402 | } | ||
| 403 | break; | ||
| 351 | } | 404 | } |
| 352 | } | 405 | } |
| 353 | break; | 406 | break; |
| @@ -579,7 +632,17 @@ void register_code(uint8_t code) | |||
| 579 | } | 632 | } |
| 580 | else if IS_KEY(code) { | 633 | else if IS_KEY(code) { |
| 581 | // TODO: should push command_proc out of this block? | 634 | // TODO: should push command_proc out of this block? |
| 582 | if (!command_proc(code)) { | 635 | if (command_proc(code)) return; |
| 636 | |||
| 637 | if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) { | ||
| 638 | uint8_t tmp_mods = host_get_mods(); | ||
| 639 | host_add_mods(oneshot_state.mods); | ||
| 640 | host_add_key(code); | ||
| 641 | host_send_keyboard_report(); | ||
| 642 | |||
| 643 | host_set_mods(tmp_mods); | ||
| 644 | oneshot_state.ready = false; | ||
| 645 | } else { | ||
| 583 | host_add_key(code); | 646 | host_add_key(code); |
| 584 | host_send_keyboard_report(); | 647 | host_send_keyboard_report(); |
| 585 | } | 648 | } |
