diff options
| author | Morton Jonuschat <mjonuschat@gmail.com> | 2020-02-13 19:30:32 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-14 03:30:32 +0000 |
| commit | 806cd392e70b81bbefdc06f111d2562ead4094ba (patch) | |
| tree | cb049878003333b7eba63b01ce7d95810f672e3e | |
| parent | 9241d11dc5f98a862fb58cb0c125d14451568e78 (diff) | |
| download | qmk_firmware-806cd392e70b81bbefdc06f111d2562ead4094ba.tar.gz qmk_firmware-806cd392e70b81bbefdc06f111d2562ead4094ba.zip | |
[osx_neo2] Bugfixes and improvements to Ergodox macOS Neo2 keymap (#8154)
* Use TAPPING_TERM constant (and redefine value to 200ms)
* change TAPPING_TOGGLE to 2 to require two taps to lock in layer 4
* add support for Shift-Command 3/4/5 key combinations that are used in
macOS Catalina
* avoid false positive tap detecion for RMOD3 when the whole sequence of
pressing RMOD3, tapping another key and releasing RMOD3 took less than
TAPPING_TERM milliseconds.
* replace SEND_STRING with tap_code()/tap_code16(), saving ~860 bytes in
compiled firmware size.
| -rw-r--r-- | layouts/community/ergodox/osx_neo2/config.h | 7 | ||||
| -rw-r--r-- | layouts/community/ergodox/osx_neo2/keymap.c | 113 |
2 files changed, 79 insertions, 41 deletions
diff --git a/layouts/community/ergodox/osx_neo2/config.h b/layouts/community/ergodox/osx_neo2/config.h new file mode 100644 index 000000000..faa79da02 --- /dev/null +++ b/layouts/community/ergodox/osx_neo2/config.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #undef TAPPING_TERM | ||
| 4 | #define TAPPING_TERM 200 | ||
| 5 | |||
| 6 | #undef TAPPING_TOGGLE | ||
| 7 | #define TAPPING_TOGGLE 2 | ||
diff --git a/layouts/community/ergodox/osx_neo2/keymap.c b/layouts/community/ergodox/osx_neo2/keymap.c index 9e379c73f..3dbfceabc 100644 --- a/layouts/community/ergodox/osx_neo2/keymap.c +++ b/layouts/community/ergodox/osx_neo2/keymap.c | |||
| @@ -5,6 +5,9 @@ | |||
| 5 | // Timer to detect tap/hold on NEO_RMOD3 key | 5 | // Timer to detect tap/hold on NEO_RMOD3 key |
| 6 | static uint16_t neo3_timer; | 6 | static uint16_t neo3_timer; |
| 7 | // State bitmap to track which key(s) enabled NEO_3 layer | 7 | // State bitmap to track which key(s) enabled NEO_3 layer |
| 8 | // Bit 1 = LMOD state | ||
| 9 | // Bit 2 = RMOD state | ||
| 10 | // Bit 3 = Seen other keypress | ||
| 8 | static uint8_t neo3_state = 0; | 11 | static uint8_t neo3_state = 0; |
| 9 | // State bitmap to track key combo for CAPSLOCK | 12 | // State bitmap to track key combo for CAPSLOCK |
| 10 | static uint8_t capslock_state = 0; | 13 | static uint8_t capslock_state = 0; |
| @@ -453,6 +456,7 @@ void tap_with_modifiers(uint16_t keycode, uint8_t force_modifiers) { | |||
| 453 | bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) { | 456 | bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) { |
| 454 | uint8_t active_modifiers = get_mods(); | 457 | uint8_t active_modifiers = get_mods(); |
| 455 | uint8_t shifted = active_modifiers & MOD_MASK_SHIFT; | 458 | uint8_t shifted = active_modifiers & MOD_MASK_SHIFT; |
| 459 | uint8_t command = active_modifiers & MOD_MASK_GUI; | ||
| 456 | 460 | ||
| 457 | // Early return on key release | 461 | // Early return on key release |
| 458 | if (!record->event.pressed) { | 462 | if (!record->event.pressed) { |
| @@ -465,67 +469,81 @@ bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) { | |||
| 465 | switch (keycode) { | 469 | switch (keycode) { |
| 466 | case NEO2_1: | 470 | case NEO2_1: |
| 467 | // degree symbol | 471 | // degree symbol |
| 468 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_8) SS_UP(X_LSHIFT) SS_UP(X_LALT)); | 472 | tap_code16(S(A(KC_8))); |
| 469 | break; | 473 | break; |
| 470 | case NEO2_2: | 474 | case NEO2_2: |
| 471 | // section symbol | 475 | // section symbol |
| 472 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_6) SS_UP(X_LALT)); | 476 | tap_code16(A(KC_6)); |
| 473 | break; | 477 | break; |
| 474 | case NEO2_3: | 478 | case NEO2_3: |
| 475 | // There is no OSX key combination for the script small l character | 479 | if (command) { |
| 480 | tap_code16(S(G(KC_3))); | ||
| 481 | } else { | ||
| 482 | // There is no OSX key combination for the script small l character | ||
| 483 | } | ||
| 476 | break; | 484 | break; |
| 477 | case NEO2_4: | 485 | case NEO2_4: |
| 478 | // right angled quote | 486 | if (command) { |
| 479 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_BSLASH) SS_UP(X_LSHIFT) SS_UP(X_LALT)); | 487 | tap_code16(S(G(KC_4))); |
| 488 | } else { | ||
| 489 | tap_code16(S(A(KC_BSLASH))); | ||
| 490 | } | ||
| 480 | break; | 491 | break; |
| 481 | case NEO2_5: | 492 | case NEO2_5: |
| 482 | // left angled quote | 493 | if (command) { |
| 483 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_BSLASH) SS_UP(X_LALT)); | 494 | tap_code16(S(G(KC_5))); |
| 495 | } else { | ||
| 496 | // left angled quote | ||
| 497 | tap_code16(A(KC_BSLASH)); | ||
| 498 | } | ||
| 484 | break; | 499 | break; |
| 485 | case NEO2_6: | 500 | case NEO2_6: |
| 486 | // dollar sign | 501 | // dollar sign |
| 487 | SEND_STRING(SS_DOWN(X_LSHIFT) SS_TAP(X_4) SS_UP(X_LSHIFT)); | 502 | tap_code16(S(KC_4)); |
| 488 | break; | 503 | break; |
| 489 | case NEO2_7: | 504 | case NEO2_7: |
| 490 | // euro sign | 505 | // euro sign |
| 491 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_2) SS_UP(X_LSHIFT) SS_UP(X_LALT)); | 506 | tap_code16(S(A(KC_2))); |
| 492 | break; | 507 | break; |
| 493 | case NEO2_8: | 508 | case NEO2_8: |
| 494 | // low9 double quote | 509 | // low9 double quote |
| 495 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_W) SS_UP(X_LSHIFT) SS_UP(X_LALT)); | 510 | tap_code16(S(A(KC_W))); |
| 496 | break; | 511 | break; |
| 497 | case NEO2_9: | 512 | case NEO2_9: |
| 498 | // left double quote | 513 | // left double quote |
| 499 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_LBRACKET) SS_UP(X_LALT)); | 514 | tap_code16(A(KC_LBRACKET)); |
| 500 | break; | 515 | break; |
| 501 | case NEO2_0: | 516 | case NEO2_0: |
| 502 | // right double quote | 517 | // right double quote |
| 503 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_LBRACKET) SS_UP(X_LSHIFT) SS_UP(X_LALT)); | 518 | tap_code16(S(A(KC_LBRACKET))); |
| 504 | break; | 519 | break; |
| 505 | case NEO2_MINUS: | 520 | case NEO2_MINUS: |
| 506 | // em dash | 521 | // em dash |
| 507 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_MINUS) SS_UP(X_LSHIFT) SS_UP(X_LALT)); | 522 | tap_code16(S(A(KC_MINUS))); |
| 508 | break; | 523 | break; |
| 509 | case NEO2_COMMA: | 524 | case NEO2_COMMA: |
| 510 | // en dash | 525 | // en dash |
| 511 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_MINUS) SS_UP(X_LALT)); | 526 | tap_code16(A(KC_MINUS)); |
| 512 | break; | 527 | break; |
| 513 | case NEO2_DOT: | 528 | case NEO2_DOT: |
| 514 | // bullet | 529 | // bullet |
| 515 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_8) SS_UP(X_LALT)); | 530 | tap_code16(A(KC_8)); |
| 516 | break; | 531 | break; |
| 517 | case NEO2_SHARP_S: | 532 | case NEO2_SHARP_S: |
| 518 | // german sharp s | 533 | // german sharp s |
| 519 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_S) SS_UP(X_LALT)); | 534 | tap_code16(S(KC_S)); |
| 520 | break; | 535 | break; |
| 521 | case NEO2_UE: | 536 | case NEO2_UE: |
| 522 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_U) SS_UP(X_LSHIFT)); | 537 | tap_code16(A(KC_U)); |
| 538 | tap_code16(S(KC_U)); | ||
| 523 | break; | 539 | break; |
| 524 | case NEO2_OE: | 540 | case NEO2_OE: |
| 525 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_O) SS_UP(X_LSHIFT)); | 541 | tap_code16(A(KC_U)); |
| 542 | tap_code16(S(KC_O)); | ||
| 526 | break; | 543 | break; |
| 527 | case NEO2_AE: | 544 | case NEO2_AE: |
| 528 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_A) SS_UP(X_LSHIFT)); | 545 | tap_code16(A(KC_U)); |
| 546 | tap_code16(S(KC_A)); | ||
| 529 | break; | 547 | break; |
| 530 | default: | 548 | default: |
| 531 | set_mods(active_modifiers); | 549 | set_mods(active_modifiers); |
| @@ -537,56 +555,59 @@ bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) { | |||
| 537 | } else { | 555 | } else { |
| 538 | switch (keycode) { | 556 | switch (keycode) { |
| 539 | case NEO2_1: | 557 | case NEO2_1: |
| 540 | SEND_STRING(SS_TAP(X_1)); | 558 | tap_code(KC_1); |
| 541 | break; | 559 | break; |
| 542 | case NEO2_2: | 560 | case NEO2_2: |
| 543 | SEND_STRING(SS_TAP(X_2)); | 561 | tap_code(KC_2); |
| 544 | break; | 562 | break; |
| 545 | case NEO2_3: | 563 | case NEO2_3: |
| 546 | SEND_STRING(SS_TAP(X_3)); | 564 | tap_code(KC_3); |
| 547 | break; | 565 | break; |
| 548 | case NEO2_4: | 566 | case NEO2_4: |
| 549 | SEND_STRING(SS_TAP(X_4)); | 567 | tap_code(KC_4); |
| 550 | break; | 568 | break; |
| 551 | case NEO2_5: | 569 | case NEO2_5: |
| 552 | SEND_STRING(SS_TAP(X_5)); | 570 | tap_code(KC_5); |
| 553 | break; | 571 | break; |
| 554 | case NEO2_6: | 572 | case NEO2_6: |
| 555 | SEND_STRING(SS_TAP(X_6)); | 573 | tap_code(KC_6); |
| 556 | break; | 574 | break; |
| 557 | case NEO2_7: | 575 | case NEO2_7: |
| 558 | SEND_STRING(SS_TAP(X_7)); | 576 | tap_code(KC_7); |
| 559 | break; | 577 | break; |
| 560 | case NEO2_8: | 578 | case NEO2_8: |
| 561 | SEND_STRING(SS_TAP(X_8)); | 579 | tap_code(KC_8); |
| 562 | break; | 580 | break; |
| 563 | case NEO2_9: | 581 | case NEO2_9: |
| 564 | SEND_STRING(SS_TAP(X_9)); | 582 | tap_code(KC_9); |
| 565 | break; | 583 | break; |
| 566 | case NEO2_0: | 584 | case NEO2_0: |
| 567 | SEND_STRING(SS_TAP(X_0)); | 585 | tap_code(KC_0); |
| 568 | break; | 586 | break; |
| 569 | case NEO2_MINUS: | 587 | case NEO2_MINUS: |
| 570 | SEND_STRING(SS_TAP(X_MINUS)); | 588 | tap_code(KC_MINUS); |
| 571 | break; | 589 | break; |
| 572 | case NEO2_COMMA: | 590 | case NEO2_COMMA: |
| 573 | SEND_STRING(SS_TAP(X_COMMA)); | 591 | tap_code(KC_COMMA); |
| 574 | break; | 592 | break; |
| 575 | case NEO2_DOT: | 593 | case NEO2_DOT: |
| 576 | SEND_STRING(SS_TAP(X_DOT)); | 594 | tap_code(KC_DOT); |
| 577 | break; | 595 | break; |
| 578 | case NEO2_SHARP_S: | 596 | case NEO2_SHARP_S: |
| 579 | // german sharp s | 597 | // german sharp s |
| 580 | SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_S) SS_UP(X_LALT)); | 598 | tap_code16(A(KC_S)); |
| 581 | break; | 599 | break; |
| 582 | case NEO2_UE: | 600 | case NEO2_UE: |
| 583 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_U)); | 601 | tap_code16(A(KC_U)); |
| 602 | tap_code(KC_U); | ||
| 584 | break; | 603 | break; |
| 585 | case NEO2_OE: | 604 | case NEO2_OE: |
| 586 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_O)); | 605 | tap_code16(A(KC_U)); |
| 606 | tap_code(KC_O); | ||
| 587 | break; | 607 | break; |
| 588 | case NEO2_AE: | 608 | case NEO2_AE: |
| 589 | SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_A)); | 609 | tap_code16(A(KC_U)); |
| 610 | tap_code(KC_A); | ||
| 590 | break; | 611 | break; |
| 591 | default: | 612 | default: |
| 592 | return true; | 613 | return true; |
| @@ -619,7 +640,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||
| 619 | neo3_state |= (1 << 1); | 640 | neo3_state |= (1 << 1); |
| 620 | } else { | 641 | } else { |
| 621 | // Turn off NEO_3 layer unless it's enabled through NEO2_RMOD3 as well. | 642 | // Turn off NEO_3 layer unless it's enabled through NEO2_RMOD3 as well. |
| 622 | if ((neo3_state & ~(1 << 1)) == 0) { | 643 | if ((neo3_state & (1 << 2)) == 0) { |
| 623 | layer_off(NEO_3); | 644 | layer_off(NEO_3); |
| 624 | } | 645 | } |
| 625 | neo3_state &= ~(1 << 1); | 646 | neo3_state &= ~(1 << 1); |
| @@ -629,28 +650,38 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||
| 629 | if (record->event.pressed) { | 650 | if (record->event.pressed) { |
| 630 | neo3_timer = timer_read(); | 651 | neo3_timer = timer_read(); |
| 631 | neo3_state |= (1 << 2); | 652 | neo3_state |= (1 << 2); |
| 653 | // Reset tap detection state | ||
| 654 | neo3_state &= ~(1 << 3); | ||
| 632 | layer_on(NEO_3); | 655 | layer_on(NEO_3); |
| 633 | } else { | 656 | } else { |
| 634 | // Turn off NEO_3 layer unless it's enabled through NEO2_LMOD3 as well. | 657 | // Turn off NEO_3 layer unless it's enabled through NEO2_LMOD3 as well. |
| 635 | if ((neo3_state & ~(1 << 2)) == 0) { | 658 | if ((neo3_state & (1 << 1)) == 0) { |
| 636 | layer_off(NEO_3); | 659 | layer_off(NEO_3); |
| 637 | } | 660 | } |
| 638 | neo3_state &= ~(1 << 2); | 661 | neo3_state &= ~(1 << 2); |
| 639 | 662 | ||
| 640 | // Was the NEO2_RMOD3 key TAPPED? | 663 | // Was the NEO2_RMOD3 key TAPPED? |
| 641 | if (timer_elapsed(neo3_timer) <= 150) { | 664 | if (timer_elapsed(neo3_timer) <= TAPPING_TERM) { |
| 642 | if (neo3_state > 0) { | 665 | if ((neo3_state & ~(1 << 3)) > 0) { |
| 643 | // We are still in NEO_3 layer, send keycode and modifiers for @ | 666 | // We are still in NEO_3 layer, send keycode and modifiers for @ |
| 644 | tap_with_modifiers(KC_2, MOD_MASK_SHIFT); | 667 | tap_with_modifiers(KC_2, MOD_MASK_SHIFT); |
| 645 | return false; | 668 | return false; |
| 646 | } else { | 669 | } else { |
| 647 | // Do the normal key processing, send y | 670 | // Do the normal key processing, send y |
| 648 | tap_with_modifiers(KC_Y, MOD_MASK_NONE); | 671 | if ((neo3_state & (1 << 3)) == 0) { |
| 672 | tap_with_modifiers(KC_Y, MOD_MASK_NONE); | ||
| 673 | } | ||
| 649 | return false; | 674 | return false; |
| 650 | } | 675 | } |
| 651 | } | 676 | } |
| 652 | } | 677 | } |
| 653 | break; | 678 | break; |
| 679 | default: | ||
| 680 | if (record->event.pressed && neo3_state > 0) { | ||
| 681 | // Track that we've seen a separate keypress event | ||
| 682 | neo3_state |= (1 << 3); | ||
| 683 | } | ||
| 684 | break; | ||
| 654 | } | 685 | } |
| 655 | 686 | ||
| 656 | if ((capslock_state & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) { | 687 | if ((capslock_state & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) { |
