* Refactor edvorakjp user library * add tap dance support * update keymaps * edvorakjp: add SWAP_SCLN option * fix behavior of SWAP_SCLNpull/4489/head
@ -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 |