Keymap: Refactor edvorakjp user library (#4480)
* Refactor edvorakjp user library * add tap dance support * update keymaps * edvorakjp: add SWAP_SCLN option * fix behavior of SWAP_SCLNpull/4489/head
parent
0031e46191
commit
f3ffd6ad50
@ -0,0 +1,206 @@
|
|||||||
|
#include "edvorakjp.h"
|
||||||
|
|
||||||
|
#if TAP_DANCE_ENABLE != yes
|
||||||
|
static uint16_t time_on_pressed;
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Each process_record_* methods defined here are
|
||||||
|
* return false if handle edvorak_keycodes, or return true others.
|
||||||
|
*/
|
||||||
|
bool process_record_edvorakjp_ext(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
if (!(default_layer_state == 1UL<<_EDVORAK &&
|
||||||
|
get_enable_jp_extra_layer() && get_japanese_mode())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// consonant keys
|
||||||
|
// layer_on(J1) or layer_on(J2) are defined based on key positions.
|
||||||
|
switch (keycode) {
|
||||||
|
// right hand's left side w/o N
|
||||||
|
case KC_F:
|
||||||
|
case KC_G:
|
||||||
|
case KC_R:
|
||||||
|
case KC_D:
|
||||||
|
case KC_T:
|
||||||
|
case KC_B:
|
||||||
|
case KC_H:
|
||||||
|
case KC_J:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
layer_on(_EDVORAKJ1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// N: toggle layer
|
||||||
|
case KC_N:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
biton32(layer_state) == _EDVORAK ? layer_on(_EDVORAKJ1) : dvorakj_layer_off();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// left hand and right hand's right side
|
||||||
|
case KC_X:
|
||||||
|
case KC_C:
|
||||||
|
case KC_V:
|
||||||
|
case KC_Z:
|
||||||
|
case KC_Y:
|
||||||
|
case KC_P:
|
||||||
|
case KC_W:
|
||||||
|
case KC_Q:
|
||||||
|
case KC_S:
|
||||||
|
case KC_M:
|
||||||
|
case KC_K:
|
||||||
|
case KC_L:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
layer_on(_EDVORAKJ2);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vowel keys, symbol keys and modifier keys
|
||||||
|
if (record->event.pressed) {
|
||||||
|
dvorakj_layer_off();
|
||||||
|
}
|
||||||
|
switch (keycode) {
|
||||||
|
// combination vowel keys
|
||||||
|
case KC_AI:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("ai");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_OU:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("ou");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_EI:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("ei");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_ANN:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("ann");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_ONN:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("onn");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_ENN:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("enn");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_INN:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("inn");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_UNN:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("unn");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// AOEIU and other (symbol, modifier) keys
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_record_edvorakjp_swap_scln(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
#ifdef SWAP_SCLN
|
||||||
|
static const uint8_t shift_bits = MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT);
|
||||||
|
static uint8_t last_mods_status;
|
||||||
|
if (keycode == KC_SCLN) {
|
||||||
|
if (record->event.pressed) {
|
||||||
|
last_mods_status = get_mods();
|
||||||
|
|
||||||
|
// invert shift_bits
|
||||||
|
if (last_mods_status & shift_bits) {
|
||||||
|
set_mods(last_mods_status & ~shift_bits);
|
||||||
|
} else {
|
||||||
|
set_mods(last_mods_status | MOD_BIT(KC_LSFT));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set_mods(last_mods_status);
|
||||||
|
last_mods_status = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_record_edvorakjp_config(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
switch (keycode) {
|
||||||
|
case KC_MAC:
|
||||||
|
case KC_WIN:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
set_enable_kc_lang(keycode == KC_MAC);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KC_EXTON:
|
||||||
|
case KC_EXTOFF:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
set_enable_jp_extra_layer(keycode == KC_EXTON);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_record_layer(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
switch (keycode) {
|
||||||
|
case EDVORAK:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
set_single_persistent_default_layer(_EDVORAK);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case QWERTY:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
dvorakj_layer_off();
|
||||||
|
set_single_persistent_default_layer(_QWERTY);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#if TAP_DANCE_ENABLE != yes
|
||||||
|
case LOWER:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
layer_on(_LOWER);
|
||||||
|
time_on_pressed = record->event.time;
|
||||||
|
} else {
|
||||||
|
layer_off(_LOWER);
|
||||||
|
|
||||||
|
if (TIMER_DIFF_16(record->event.time, time_on_pressed) < TAPPING_TERM) {
|
||||||
|
set_japanese_mode(false);
|
||||||
|
}
|
||||||
|
time_on_pressed = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case RAISE:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
layer_on(_RAISE);
|
||||||
|
time_on_pressed = record->event.time;
|
||||||
|
} else {
|
||||||
|
layer_off(_RAISE);
|
||||||
|
|
||||||
|
if (TIMER_DIFF_16(record->event.time, time_on_pressed) < TAPPING_TERM) {
|
||||||
|
set_japanese_mode(true);
|
||||||
|
}
|
||||||
|
time_on_pressed = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_record_ime(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
switch (keycode) {
|
||||||
|
case KC_JPN:
|
||||||
|
case KC_ENG:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
set_japanese_mode(keycode == KC_JPN);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
#include "eeprom.h"
|
||||||
|
#include "edvorakjp.h"
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint8_t raw;
|
||||||
|
struct {
|
||||||
|
bool enable_jp_extra_layer : 1;
|
||||||
|
bool enable_kc_lang : 1; // for macOS
|
||||||
|
};
|
||||||
|
} edvorakjp_config_t;
|
||||||
|
static edvorakjp_config_t edvorakjp_config;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool japanese_mode;
|
||||||
|
} edvorakjp_state_t;
|
||||||
|
static edvorakjp_state_t edvorakjp_state;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* private methods
|
||||||
|
*/
|
||||||
|
uint8_t eeconfig_read_edvorakjp(void) {
|
||||||
|
return eeprom_read_byte(EECONFIG_EDVORAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eeconfig_update_edvorakjp(uint8_t val) {
|
||||||
|
eeprom_update_byte(EECONFIG_EDVORAK, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* public methods
|
||||||
|
*/
|
||||||
|
void edvorakjp_status_init(void) {
|
||||||
|
edvorakjp_state.japanese_mode = false;
|
||||||
|
edvorakjp_config.raw = eeconfig_read_edvorakjp();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_enable_jp_extra_layer(void) {
|
||||||
|
return edvorakjp_config.enable_jp_extra_layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_enable_jp_extra_layer(bool new_state) {
|
||||||
|
edvorakjp_config.enable_jp_extra_layer = new_state;
|
||||||
|
eeconfig_update_edvorakjp(edvorakjp_config.raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_enable_kc_lang(void) {
|
||||||
|
return edvorakjp_config.enable_kc_lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_enable_kc_lang(bool new_state) {
|
||||||
|
edvorakjp_config.enable_kc_lang = new_state;
|
||||||
|
eeconfig_update_edvorakjp(edvorakjp_config.raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_japanese_mode(void) {
|
||||||
|
return edvorakjp_state.japanese_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_japanese_mode(bool new_state) {
|
||||||
|
edvorakjp_state.japanese_mode = new_state;
|
||||||
|
if (edvorakjp_state.japanese_mode) {
|
||||||
|
if (edvorakjp_config.enable_kc_lang) {
|
||||||
|
SEND_STRING(SS_TAP(X_LANG1));
|
||||||
|
} else {
|
||||||
|
SEND_STRING(SS_LALT("`"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dvorakj_layer_off();
|
||||||
|
if (edvorakjp_config.enable_kc_lang) {
|
||||||
|
SEND_STRING(SS_TAP(X_LANG2));
|
||||||
|
} else {
|
||||||
|
SEND_STRING(SS_LALT("`"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
#include "edvorakjp.h"
|
||||||
|
#include "process_keycode/process_tap_dance.h"
|
||||||
|
|
||||||
|
enum tap_state {
|
||||||
|
NONE = 0,
|
||||||
|
SINGLE_TAP = 1,
|
||||||
|
DOUBLE_TAP = 2,
|
||||||
|
HOLD
|
||||||
|
};
|
||||||
|
|
||||||
|
static int td_status_lower = NONE;
|
||||||
|
static int td_status_raise = NONE;
|
||||||
|
|
||||||
|
int cur_dance(qk_tap_dance_state_t *state) {
|
||||||
|
if (state->interrupted || !state->pressed) {
|
||||||
|
return state->count == 1 ? SINGLE_TAP : DOUBLE_TAP;
|
||||||
|
} else {
|
||||||
|
return HOLD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void td_lower_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||||
|
td_status_lower = cur_dance(state);
|
||||||
|
switch(td_status_lower) {
|
||||||
|
case SINGLE_TAP:
|
||||||
|
set_japanese_mode(false);
|
||||||
|
register_code(KC_ESC);
|
||||||
|
break;
|
||||||
|
case DOUBLE_TAP:
|
||||||
|
set_japanese_mode(false);
|
||||||
|
break;
|
||||||
|
case HOLD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
layer_on(_LOWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void td_lower_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||||
|
if (td_status_lower == SINGLE_TAP) {
|
||||||
|
unregister_code(KC_ESC);
|
||||||
|
}
|
||||||
|
layer_off(_LOWER);
|
||||||
|
td_status_lower = NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void td_raise_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||||
|
td_status_raise = cur_dance(state);
|
||||||
|
switch(td_status_raise) {
|
||||||
|
case SINGLE_TAP:
|
||||||
|
case DOUBLE_TAP:
|
||||||
|
set_japanese_mode(true);
|
||||||
|
break;
|
||||||
|
case HOLD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
layer_on(_RAISE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void td_raise_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||||
|
layer_off(_RAISE);
|
||||||
|
td_status_raise = NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||||
|
[TD_LOWER] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(
|
||||||
|
NULL, td_lower_finished, td_lower_reset, TAPPING_TERM * 1.5
|
||||||
|
),
|
||||||
|
[TD_RAISE] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(
|
||||||
|
NULL, td_raise_finished, td_raise_reset, TAPPING_TERM * 1.5
|
||||||
|
)
|
||||||
|
};
|
@ -1 +1,7 @@
|
|||||||
SRC += edvorakjp.c
|
SRC += edvorakjp.c \
|
||||||
|
edvorakjp_process_record.c \
|
||||||
|
edvorakjp_status.c
|
||||||
|
|
||||||
|
ifeq ($(TAP_DANCE_ENABLE), yes)
|
||||||
|
SRC += edvorakjp_tap_dance.c
|
||||||
|
endif
|
||||||
|
Loading…
Reference in new issue