[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.
This commit is contained in:
parent
9241d11dc5
commit
806cd392e7
2 changed files with 79 additions and 41 deletions
7
layouts/community/ergodox/osx_neo2/config.h
Normal file
7
layouts/community/ergodox/osx_neo2/config.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#undef TAPPING_TERM
|
||||||
|
#define TAPPING_TERM 200
|
||||||
|
|
||||||
|
#undef TAPPING_TOGGLE
|
||||||
|
#define TAPPING_TOGGLE 2
|
|
@ -5,6 +5,9 @@
|
||||||
// Timer to detect tap/hold on NEO_RMOD3 key
|
// Timer to detect tap/hold on NEO_RMOD3 key
|
||||||
static uint16_t neo3_timer;
|
static uint16_t neo3_timer;
|
||||||
// State bitmap to track which key(s) enabled NEO_3 layer
|
// State bitmap to track which key(s) enabled NEO_3 layer
|
||||||
|
// Bit 1 = LMOD state
|
||||||
|
// Bit 2 = RMOD state
|
||||||
|
// Bit 3 = Seen other keypress
|
||||||
static uint8_t neo3_state = 0;
|
static uint8_t neo3_state = 0;
|
||||||
// State bitmap to track key combo for CAPSLOCK
|
// State bitmap to track key combo for CAPSLOCK
|
||||||
static uint8_t capslock_state = 0;
|
static uint8_t capslock_state = 0;
|
||||||
|
@ -453,6 +456,7 @@ void tap_with_modifiers(uint16_t keycode, uint8_t force_modifiers) {
|
||||||
bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
|
bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
|
||||||
uint8_t active_modifiers = get_mods();
|
uint8_t active_modifiers = get_mods();
|
||||||
uint8_t shifted = active_modifiers & MOD_MASK_SHIFT;
|
uint8_t shifted = active_modifiers & MOD_MASK_SHIFT;
|
||||||
|
uint8_t command = active_modifiers & MOD_MASK_GUI;
|
||||||
|
|
||||||
// Early return on key release
|
// Early return on key release
|
||||||
if (!record->event.pressed) {
|
if (!record->event.pressed) {
|
||||||
|
@ -465,67 +469,81 @@ bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
case NEO2_1:
|
case NEO2_1:
|
||||||
// degree symbol
|
// degree symbol
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_8) SS_UP(X_LSHIFT) SS_UP(X_LALT));
|
tap_code16(S(A(KC_8)));
|
||||||
break;
|
break;
|
||||||
case NEO2_2:
|
case NEO2_2:
|
||||||
// section symbol
|
// section symbol
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_6) SS_UP(X_LALT));
|
tap_code16(A(KC_6));
|
||||||
break;
|
break;
|
||||||
case NEO2_3:
|
case NEO2_3:
|
||||||
|
if (command) {
|
||||||
|
tap_code16(S(G(KC_3)));
|
||||||
|
} else {
|
||||||
// There is no OSX key combination for the script small l character
|
// There is no OSX key combination for the script small l character
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NEO2_4:
|
case NEO2_4:
|
||||||
// right angled quote
|
if (command) {
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_BSLASH) SS_UP(X_LSHIFT) SS_UP(X_LALT));
|
tap_code16(S(G(KC_4)));
|
||||||
|
} else {
|
||||||
|
tap_code16(S(A(KC_BSLASH)));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NEO2_5:
|
case NEO2_5:
|
||||||
|
if (command) {
|
||||||
|
tap_code16(S(G(KC_5)));
|
||||||
|
} else {
|
||||||
// left angled quote
|
// left angled quote
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_BSLASH) SS_UP(X_LALT));
|
tap_code16(A(KC_BSLASH));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NEO2_6:
|
case NEO2_6:
|
||||||
// dollar sign
|
// dollar sign
|
||||||
SEND_STRING(SS_DOWN(X_LSHIFT) SS_TAP(X_4) SS_UP(X_LSHIFT));
|
tap_code16(S(KC_4));
|
||||||
break;
|
break;
|
||||||
case NEO2_7:
|
case NEO2_7:
|
||||||
// euro sign
|
// euro sign
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_2) SS_UP(X_LSHIFT) SS_UP(X_LALT));
|
tap_code16(S(A(KC_2)));
|
||||||
break;
|
break;
|
||||||
case NEO2_8:
|
case NEO2_8:
|
||||||
// low9 double quote
|
// low9 double quote
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_W) SS_UP(X_LSHIFT) SS_UP(X_LALT));
|
tap_code16(S(A(KC_W)));
|
||||||
break;
|
break;
|
||||||
case NEO2_9:
|
case NEO2_9:
|
||||||
// left double quote
|
// left double quote
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_LBRACKET) SS_UP(X_LALT));
|
tap_code16(A(KC_LBRACKET));
|
||||||
break;
|
break;
|
||||||
case NEO2_0:
|
case NEO2_0:
|
||||||
// right double quote
|
// right double quote
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_LBRACKET) SS_UP(X_LSHIFT) SS_UP(X_LALT));
|
tap_code16(S(A(KC_LBRACKET)));
|
||||||
break;
|
break;
|
||||||
case NEO2_MINUS:
|
case NEO2_MINUS:
|
||||||
// em dash
|
// em dash
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_MINUS) SS_UP(X_LSHIFT) SS_UP(X_LALT));
|
tap_code16(S(A(KC_MINUS)));
|
||||||
break;
|
break;
|
||||||
case NEO2_COMMA:
|
case NEO2_COMMA:
|
||||||
// en dash
|
// en dash
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_MINUS) SS_UP(X_LALT));
|
tap_code16(A(KC_MINUS));
|
||||||
break;
|
break;
|
||||||
case NEO2_DOT:
|
case NEO2_DOT:
|
||||||
// bullet
|
// bullet
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_8) SS_UP(X_LALT));
|
tap_code16(A(KC_8));
|
||||||
break;
|
break;
|
||||||
case NEO2_SHARP_S:
|
case NEO2_SHARP_S:
|
||||||
// german sharp s
|
// german sharp s
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_S) SS_UP(X_LALT));
|
tap_code16(S(KC_S));
|
||||||
break;
|
break;
|
||||||
case NEO2_UE:
|
case NEO2_UE:
|
||||||
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));
|
tap_code16(A(KC_U));
|
||||||
|
tap_code16(S(KC_U));
|
||||||
break;
|
break;
|
||||||
case NEO2_OE:
|
case NEO2_OE:
|
||||||
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));
|
tap_code16(A(KC_U));
|
||||||
|
tap_code16(S(KC_O));
|
||||||
break;
|
break;
|
||||||
case NEO2_AE:
|
case NEO2_AE:
|
||||||
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));
|
tap_code16(A(KC_U));
|
||||||
|
tap_code16(S(KC_A));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
set_mods(active_modifiers);
|
set_mods(active_modifiers);
|
||||||
|
@ -537,56 +555,59 @@ bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
|
||||||
} else {
|
} else {
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
case NEO2_1:
|
case NEO2_1:
|
||||||
SEND_STRING(SS_TAP(X_1));
|
tap_code(KC_1);
|
||||||
break;
|
break;
|
||||||
case NEO2_2:
|
case NEO2_2:
|
||||||
SEND_STRING(SS_TAP(X_2));
|
tap_code(KC_2);
|
||||||
break;
|
break;
|
||||||
case NEO2_3:
|
case NEO2_3:
|
||||||
SEND_STRING(SS_TAP(X_3));
|
tap_code(KC_3);
|
||||||
break;
|
break;
|
||||||
case NEO2_4:
|
case NEO2_4:
|
||||||
SEND_STRING(SS_TAP(X_4));
|
tap_code(KC_4);
|
||||||
break;
|
break;
|
||||||
case NEO2_5:
|
case NEO2_5:
|
||||||
SEND_STRING(SS_TAP(X_5));
|
tap_code(KC_5);
|
||||||
break;
|
break;
|
||||||
case NEO2_6:
|
case NEO2_6:
|
||||||
SEND_STRING(SS_TAP(X_6));
|
tap_code(KC_6);
|
||||||
break;
|
break;
|
||||||
case NEO2_7:
|
case NEO2_7:
|
||||||
SEND_STRING(SS_TAP(X_7));
|
tap_code(KC_7);
|
||||||
break;
|
break;
|
||||||
case NEO2_8:
|
case NEO2_8:
|
||||||
SEND_STRING(SS_TAP(X_8));
|
tap_code(KC_8);
|
||||||
break;
|
break;
|
||||||
case NEO2_9:
|
case NEO2_9:
|
||||||
SEND_STRING(SS_TAP(X_9));
|
tap_code(KC_9);
|
||||||
break;
|
break;
|
||||||
case NEO2_0:
|
case NEO2_0:
|
||||||
SEND_STRING(SS_TAP(X_0));
|
tap_code(KC_0);
|
||||||
break;
|
break;
|
||||||
case NEO2_MINUS:
|
case NEO2_MINUS:
|
||||||
SEND_STRING(SS_TAP(X_MINUS));
|
tap_code(KC_MINUS);
|
||||||
break;
|
break;
|
||||||
case NEO2_COMMA:
|
case NEO2_COMMA:
|
||||||
SEND_STRING(SS_TAP(X_COMMA));
|
tap_code(KC_COMMA);
|
||||||
break;
|
break;
|
||||||
case NEO2_DOT:
|
case NEO2_DOT:
|
||||||
SEND_STRING(SS_TAP(X_DOT));
|
tap_code(KC_DOT);
|
||||||
break;
|
break;
|
||||||
case NEO2_SHARP_S:
|
case NEO2_SHARP_S:
|
||||||
// german sharp s
|
// german sharp s
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_S) SS_UP(X_LALT));
|
tap_code16(A(KC_S));
|
||||||
break;
|
break;
|
||||||
case NEO2_UE:
|
case NEO2_UE:
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_U));
|
tap_code16(A(KC_U));
|
||||||
|
tap_code(KC_U);
|
||||||
break;
|
break;
|
||||||
case NEO2_OE:
|
case NEO2_OE:
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_O));
|
tap_code16(A(KC_U));
|
||||||
|
tap_code(KC_O);
|
||||||
break;
|
break;
|
||||||
case NEO2_AE:
|
case NEO2_AE:
|
||||||
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_A));
|
tap_code16(A(KC_U));
|
||||||
|
tap_code(KC_A);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
@ -619,7 +640,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
neo3_state |= (1 << 1);
|
neo3_state |= (1 << 1);
|
||||||
} else {
|
} else {
|
||||||
// Turn off NEO_3 layer unless it's enabled through NEO2_RMOD3 as well.
|
// Turn off NEO_3 layer unless it's enabled through NEO2_RMOD3 as well.
|
||||||
if ((neo3_state & ~(1 << 1)) == 0) {
|
if ((neo3_state & (1 << 2)) == 0) {
|
||||||
layer_off(NEO_3);
|
layer_off(NEO_3);
|
||||||
}
|
}
|
||||||
neo3_state &= ~(1 << 1);
|
neo3_state &= ~(1 << 1);
|
||||||
|
@ -629,28 +650,38 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
if (record->event.pressed) {
|
if (record->event.pressed) {
|
||||||
neo3_timer = timer_read();
|
neo3_timer = timer_read();
|
||||||
neo3_state |= (1 << 2);
|
neo3_state |= (1 << 2);
|
||||||
|
// Reset tap detection state
|
||||||
|
neo3_state &= ~(1 << 3);
|
||||||
layer_on(NEO_3);
|
layer_on(NEO_3);
|
||||||
} else {
|
} else {
|
||||||
// Turn off NEO_3 layer unless it's enabled through NEO2_LMOD3 as well.
|
// Turn off NEO_3 layer unless it's enabled through NEO2_LMOD3 as well.
|
||||||
if ((neo3_state & ~(1 << 2)) == 0) {
|
if ((neo3_state & (1 << 1)) == 0) {
|
||||||
layer_off(NEO_3);
|
layer_off(NEO_3);
|
||||||
}
|
}
|
||||||
neo3_state &= ~(1 << 2);
|
neo3_state &= ~(1 << 2);
|
||||||
|
|
||||||
// Was the NEO2_RMOD3 key TAPPED?
|
// Was the NEO2_RMOD3 key TAPPED?
|
||||||
if (timer_elapsed(neo3_timer) <= 150) {
|
if (timer_elapsed(neo3_timer) <= TAPPING_TERM) {
|
||||||
if (neo3_state > 0) {
|
if ((neo3_state & ~(1 << 3)) > 0) {
|
||||||
// We are still in NEO_3 layer, send keycode and modifiers for @
|
// We are still in NEO_3 layer, send keycode and modifiers for @
|
||||||
tap_with_modifiers(KC_2, MOD_MASK_SHIFT);
|
tap_with_modifiers(KC_2, MOD_MASK_SHIFT);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// Do the normal key processing, send y
|
// Do the normal key processing, send y
|
||||||
|
if ((neo3_state & (1 << 3)) == 0) {
|
||||||
tap_with_modifiers(KC_Y, MOD_MASK_NONE);
|
tap_with_modifiers(KC_Y, MOD_MASK_NONE);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
if (record->event.pressed && neo3_state > 0) {
|
||||||
|
// Track that we've seen a separate keypress event
|
||||||
|
neo3_state |= (1 << 3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((capslock_state & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {
|
if ((capslock_state & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {
|
||||||
|
|
Loading…
Reference in a new issue