From f100de88e524633d4f7b35602b37ad6a76044f1d Mon Sep 17 00:00:00 2001 From: Dalius Dobravolskas Date: Tue, 25 Oct 2022 09:23:35 +0300 Subject: Callum style layout improvements and my layout changes (#16174) --- keyboards/a_dux/keymaps/daliusd/config.h | 5 +- keyboards/a_dux/keymaps/daliusd/flow.c | 336 ++++++++++++++++++++++++++++++ keyboards/a_dux/keymaps/daliusd/flow.h | 27 +++ keyboards/a_dux/keymaps/daliusd/keymap.c | 219 +++++++++---------- keyboards/a_dux/keymaps/daliusd/oneshot.c | 195 ----------------- keyboards/a_dux/keymaps/daliusd/oneshot.h | 65 ------ keyboards/a_dux/keymaps/daliusd/readme.md | 299 +++++++++++++++++++++++++- keyboards/a_dux/keymaps/daliusd/rules.mk | 2 +- 8 files changed, 762 insertions(+), 386 deletions(-) create mode 100644 keyboards/a_dux/keymaps/daliusd/flow.c create mode 100644 keyboards/a_dux/keymaps/daliusd/flow.h delete mode 100644 keyboards/a_dux/keymaps/daliusd/oneshot.c delete mode 100644 keyboards/a_dux/keymaps/daliusd/oneshot.h (limited to 'keyboards') diff --git a/keyboards/a_dux/keymaps/daliusd/config.h b/keyboards/a_dux/keymaps/daliusd/config.h index 42e88a687f..786451768a 100644 --- a/keyboards/a_dux/keymaps/daliusd/config.h +++ b/keyboards/a_dux/keymaps/daliusd/config.h @@ -17,7 +17,7 @@ along with this program. If not, see . #pragma once -#define UNICODE_SELECTED_MODES UC_MAC, UC_LNX +#define UNICODE_SELECTED_MODES UC_LNX #define MOUSEKEY_INTERVAL 12 #define MOUSEKEY_MAX_SPEED 6 @@ -30,3 +30,6 @@ along with this program. If not, see . #define MOUSEKEY_WHEEL_INTERVAL 50 // The default is 40 #define MOUSEKEY_WHEEL_TIME_TO_MAX 100 + +#define FLOW_COUNT 6 +#define FLOW_LAYERS_COUNT 5 diff --git a/keyboards/a_dux/keymaps/daliusd/flow.c b/keyboards/a_dux/keymaps/daliusd/flow.c new file mode 100644 index 0000000000..6e4db873fe --- /dev/null +++ b/keyboards/a_dux/keymaps/daliusd/flow.c @@ -0,0 +1,336 @@ +/* Copyright 2022 @daliusd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "flow.h" + +extern const uint16_t flow_config[FLOW_COUNT][2]; +extern const uint16_t flow_layers_config[FLOW_LAYERS_COUNT][2]; + +// Represents the states a flow key can be in +typedef enum { + flow_up_unqueued, + flow_up_queued, + flow_up_queued_used, + flow_down_unused, + flow_down_used, +} flow_state_t; + +#ifdef FLOW_ONESHOT_TERM +const int g_flow_oneshot_term = FLOW_ONESHOT_TERM; +#else +const int g_flow_oneshot_term = 500; +#endif + +#ifdef FLOW_ONESHOT_WAIT_TERM +const int g_flow_oneshot_wait_term = FLOW_ONESHOT_WAIT_TERM; +#else +const int g_flow_oneshot_wait_term = 500; +#endif + +flow_state_t flow_state[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = flow_up_unqueued }; +bool flow_pressed[FLOW_COUNT][2] = { [0 ... FLOW_COUNT - 1] = {false, false} }; +uint16_t flow_timers[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = 0 }; +bool flow_timeout_timers_active[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = false }; +uint16_t flow_timeout_timers_value[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = 0 }; +uint16_t flow_timeout_wait_timers_value[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = 0 }; + +flow_state_t flow_layers_state[FLOW_LAYERS_COUNT] = { + [0 ... FLOW_LAYERS_COUNT - 1] = flow_up_unqueued +}; +bool flow_layer_timeout_timers_active[FLOW_LAYERS_COUNT] = { [0 ... FLOW_LAYERS_COUNT - 1] = false }; +uint16_t flow_layer_timeout_timers_value[FLOW_LAYERS_COUNT] = { [0 ... FLOW_LAYERS_COUNT - 1] = 0 }; +uint16_t flow_layer_timeout_wait_timers_value[FLOW_LAYERS_COUNT] = { [0 ... FLOW_LAYERS_COUNT - 1] = 0 }; + +bool is_flow_ignored_key(uint16_t keycode) { + for (int i = 0; i < FLOW_COUNT; i++) { + if (flow_config[i][0] == keycode) { + return true; + } + } + + for (int i = 0; i < FLOW_LAYERS_COUNT; i++) { + if (flow_layers_config[i][0] == keycode) { + return true; + } + } + + if (keycode == KC_LSFT || keycode == KC_RSFT + || keycode == KC_LCTL || keycode == KC_RCTL + || keycode == KC_LALT || keycode == KC_RALT + || keycode == KC_LGUI || keycode == KC_RGUI) { + return true; + } + + return false; +} + +bool update_flow_mods( + uint16_t keycode, + bool pressed +) { + bool pass = true; + bool flow_key_list_triggered[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = false }; + bool flow_key_list_pressed[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = false }; + + bool flow_triggered = false; + + for (uint8_t i = 0; i < FLOW_COUNT; i++) { + // Layer key + if (keycode == flow_config[i][0]) { + if (pressed) { + flow_pressed[i][0] = true; + } else { + flow_pressed[i][0] = false; + } + // KC mod key + } else if (keycode == flow_config[i][1]) { + if (pressed) { + if (flow_pressed[i][0]) { + flow_pressed[i][1] = true; + flow_key_list_triggered[i] = true; + flow_triggered = true; + flow_key_list_pressed[i] = true; + pass = false; + } + } else if (flow_pressed[i][1]) { + flow_pressed[i][1] = false; + if (flow_pressed[i][0]) { + flow_key_list_triggered[i] = true; + flow_triggered = true; + pass = false; + } else if ((flow_state[i] == flow_down_unused) + || (flow_state[i] == flow_down_used)) { + flow_key_list_triggered[i] = true; + flow_triggered = true; + pass = false; + } + } + } + } + + for (uint8_t i = 0; i < FLOW_COUNT; i++) { + if (flow_key_list_triggered[i]) { + if (flow_key_list_pressed[i]) { + if (flow_state[i] == flow_up_unqueued) { + register_code(flow_config[i][1]); + } + flow_timeout_wait_timers_value[i] = timer_read(); + flow_state[i] = flow_down_unused; + } else { + // Trigger keyup + switch (flow_state[i]) { + case flow_down_unused: + if (!flow_pressed[i][1]) { + if (timer_elapsed(flow_timeout_wait_timers_value[i]) > g_flow_oneshot_wait_term) { + flow_state[i] = flow_up_unqueued; + unregister_code(flow_config[i][1]); + } else { + // If we didn't use the mod while trigger was held, queue it. + flow_state[i] = flow_up_queued; + flow_timeout_timers_active[i] = true; + flow_timeout_timers_value[i] = timer_read(); + } + } + break; + case flow_down_used: + // If we did use the mod while trigger was held, unregister it. + if (!flow_pressed[i][1]) { + flow_state[i] = flow_up_unqueued; + unregister_code(flow_config[i][1]); + } + break; + default: + break; + } + } + } else if (!flow_triggered) { + if (pressed) { + if (!is_flow_ignored_key(keycode)) { + switch (flow_state[i]) { + case flow_up_queued: + flow_state[i] = flow_up_queued_used; + flow_timeout_timers_active[i] = false; + break; + case flow_up_queued_used: + flow_state[i] = flow_up_unqueued; + unregister_code(flow_config[i][1]); + break; + default: + break; + } + } + } else { + if (!is_flow_ignored_key(keycode)) { + // On non-ignored keyup, consider the oneshot used. + switch (flow_state[i]) { + case flow_down_unused: + flow_state[i] = flow_down_used; + break; + case flow_up_queued: + flow_state[i] = flow_up_unqueued; + unregister_code(flow_config[i][1]); + break; + case flow_up_queued_used: + flow_state[i] = flow_up_unqueued; + unregister_code(flow_config[i][1]); + break; + default: + break; + } + } + } + } + } + + return pass; +} + +void change_pressed_status(uint16_t keycode, bool pressed) { + for (int i = 0; i < FLOW_COUNT; i++) { + if (flow_config[i][0] == keycode) { + flow_pressed[i][0] = pressed; + } + } +} + +bool update_flow_layers( + uint16_t keycode, + bool pressed, + keypos_t key_position +) { + uint8_t key_layer = read_source_layers_cache(key_position); + bool pass = true; + + for (int i = 0; i < FLOW_LAYERS_COUNT; i++) { + uint16_t trigger = flow_layers_config[i][0]; + uint16_t layer = flow_layers_config[i][1]; + + if (keycode == trigger) { + if (pressed) { + // Trigger keydown + if (flow_layers_state[i] == flow_up_unqueued) { + layer_on(layer); + change_pressed_status(trigger, true); + } + flow_layer_timeout_wait_timers_value[i] = timer_read(); + flow_layers_state[i] = flow_down_unused; + pass = false; + } else { + // Trigger keyup + switch (flow_layers_state[i]) { + case flow_down_unused: + if (timer_elapsed(flow_layer_timeout_wait_timers_value[i]) > g_flow_oneshot_wait_term) { + flow_layers_state[i] = flow_up_unqueued; + layer_off(layer); + change_pressed_status(trigger, false); + pass = false; + } else { + // If we didn't use the layer while trigger was held, queue it. + flow_layers_state[i] = flow_up_queued; + flow_layer_timeout_timers_active[i] = true; + flow_layer_timeout_timers_value[i] = timer_read(); + pass = false; + change_pressed_status(trigger, true); + } + break; + case flow_down_used: + // If we did use the layer while trigger was held, turn off it. + flow_layers_state[i] = flow_up_unqueued; + layer_off(layer); + change_pressed_status(trigger, false); + pass = false; + break; + default: + break; + } + } + } else { + if (pressed) { + if (key_layer == layer) { + // On non-ignored keyup, consider the oneshot used. + switch (flow_layers_state[i]) { + case flow_down_unused: + flow_layers_state[i] = flow_down_used; + break; + case flow_up_queued: + flow_layers_state[i] = flow_up_queued_used; + flow_layer_timeout_timers_active[i] = false; + break; + case flow_up_queued_used: + flow_layers_state[i] = flow_up_unqueued; + layer_off(layer); + change_pressed_status(trigger, false); + pass = false; + break; + default: + break; + } + } + } else { + // Ignore key ups from other layers + if (key_layer == layer) { + // On non-ignored keyup, consider the oneshot used. + switch (flow_layers_state[i]) { + case flow_up_queued: + flow_layers_state[i] = flow_up_unqueued; + layer_off(layer); + change_pressed_status(trigger, false); + break; + case flow_up_queued_used: + flow_layers_state[i] = flow_up_unqueued; + layer_off(layer); + change_pressed_status(trigger, false); + break; + default: + break; + } + } + } + } + } + + return pass; +} + +bool update_flow( + uint16_t keycode, + bool pressed, + keypos_t key_position +) { + bool pass = update_flow_mods(keycode, pressed); + pass = update_flow_layers(keycode, pressed, key_position) & pass; + return pass; +} + +void flow_matrix_scan(void) { + for (int i = 0; i < FLOW_COUNT; i++) { + if (flow_timeout_timers_active[i] + && timer_elapsed(flow_timeout_timers_value[i]) > g_flow_oneshot_term) { + flow_timeout_timers_active[i] = false; + flow_state[i] = flow_up_unqueued; + unregister_code(flow_config[i][1]); + } + } + + for (int i = 0; i < FLOW_LAYERS_COUNT; i++) { + if (flow_layer_timeout_timers_active[i] + && timer_elapsed(flow_layer_timeout_timers_value[i]) > g_flow_oneshot_term) { + flow_layer_timeout_timers_active[i] = false; + flow_layers_state[i] = flow_up_unqueued; + layer_off(flow_layers_config[i][1]); + change_pressed_status(flow_layers_config[i][0], false); + } + } +} diff --git a/keyboards/a_dux/keymaps/daliusd/flow.h b/keyboards/a_dux/keymaps/daliusd/flow.h new file mode 100644 index 0000000000..e9ac32c8ed --- /dev/null +++ b/keyboards/a_dux/keymaps/daliusd/flow.h @@ -0,0 +1,27 @@ +/* +Copyright 2022 Dalius Dobravolskas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#pragma once + +#include QMK_KEYBOARD_H + +bool update_flow( + uint16_t keycode, + bool pressed, + keypos_t key_position +); + +void flow_matrix_scan(void); diff --git a/keyboards/a_dux/keymaps/daliusd/keymap.c b/keyboards/a_dux/keymaps/daliusd/keymap.c index aa45d10449..3da9b76057 100644 --- a/keyboards/a_dux/keymaps/daliusd/keymap.c +++ b/keyboards/a_dux/keymaps/daliusd/keymap.c @@ -15,7 +15,7 @@ */ #include QMK_KEYBOARD_H -#include "oneshot.h" +#include "flow.h" // Each layer gets a name for readability, which is then used in the keymap matrix below. // The underscores don't mean anything - you can have a layer called STUFF or any other name. @@ -25,11 +25,12 @@ enum layers { _QWERTY, _SYM, _NAV, - _NUMB, + _MISC, _TMUX, _MOUSE, - _MISC, _FUNC, + _LT_MAC, + _LT_LINUX, }; enum custom_keycodes { @@ -41,22 +42,40 @@ enum custom_keycodes { TM_SLCT, TM_SRCH, TM_URL, - OS_CTRL, - OS_ALT, - OS_GUI, - OS_TMUX, OS_MISC, + OS_TMUX, OS_FUNC, + LT_OSLNX, }; // Shortcut to make keymap more readable #define L_NAV MO(_NAV) #define L_SYM MO(_SYM) -#define L_MOUSE TG(_MOUSE) +#define L_MOUSE MO(_MOUSE) #define K_PRINT (QK_LCTL | QK_LSFT | QK_LGUI | KC_4) +#define K_VIDEO (QK_LSFT | QK_LGUI | KC_5) + +// flow_config should correspond to following format: +// * layer keycode +// * modifier keycode +const uint16_t flow_config[FLOW_COUNT][2] = { + {L_NAV, KC_LALT}, + {L_NAV, KC_LGUI}, + {L_NAV, KC_LCTL}, + {L_SYM, KC_RCTL}, + {L_SYM, KC_RGUI}, + {L_SYM, KC_RALT}, +}; +const uint16_t flow_layers_config[FLOW_LAYERS_COUNT][2] = { + {OS_MISC, _MISC}, + {OS_TMUX, _TMUX}, + {OS_FUNC, _FUNC}, +}; + +// Unicode characters enum unicode_names { SNEK, EURO, @@ -96,7 +115,7 @@ const uint32_t PROGMEM unicode_map[] = { [LT_S_I] = 0x12f, // į [LT_L_I] = 0x12e, // Į [LT_S_S] = 0x161, // š - [LT_L_S] = 0x160, // Š' + [LT_L_S] = 0x160, // Š [LT_S_U1] = 0x173, // ų [LT_L_U1] = 0x172, // Ų [LT_S_U2] = 0x16b, // ū @@ -110,14 +129,23 @@ const uint32_t PROGMEM unicode_map[] = { #define K_SNEK X(SNEK) #define K_EURO X(EURO) #define K_LT_A XP(LT_S_A, LT_L_A) +#define K_LT_AU X(LT_L_A) #define K_LT_C XP(LT_S_C, LT_L_C) +#define K_LT_CU X(LT_L_C) #define K_LT_E1 XP(LT_S_E1, LT_L_E1) +#define K_LT_E1U X(LT_L_E1) #define K_LT_E2 XP(LT_S_E2, LT_L_E2) +#define K_LT_E2U X(LT_L_E2) #define K_LT_I XP(LT_S_I, LT_L_I) +#define K_LT_IU X(LT_L_I) #define K_LT_S XP(LT_S_S, LT_L_S) +#define K_LT_SU X(LT_L_S) #define K_LT_U1 XP(LT_S_U1, LT_L_U1) +#define K_LT_U1U X(LT_L_U1) #define K_LT_U2 XP(LT_S_U2, LT_L_U2) +#define K_LT_U2U X(LT_L_U2) #define K_LT_Z XP(LT_S_Z, LT_L_Z) +#define K_LT_ZU X(LT_L_Z) #define K_LT_OB X(LT_OB) #define K_LT_CB X(LT_CB) @@ -139,35 +167,35 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ KC_EXLM ,KC_AT ,KC_HASH ,KC_DLR ,KC_PERC , KC_CIRC ,KC_AMPR ,KC_ASTR ,KC_LPRN ,KC_RPRN , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - KC_GRV ,KC_PLUS ,KC_LBRC ,KC_RBRC ,K_LT_OB , KC_MINS ,OS_ALT ,OS_CTRL ,OS_GUI ,KC_PIPE , + XXXXXXX ,KC_GRV ,KC_LBRC ,KC_RBRC ,KC_PLUS , KC_MINS ,KC_PIPE ,KC_RCTL ,KC_RGUI ,KC_RALT , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - K_SNEK ,KC_EQL ,KC_LCBR ,KC_RCBR ,K_LT_CB , KC_UNDS ,KC_QUOT ,KC_DQT ,K_EURO ,KC_BSLS , + KC_DEL ,KC_BSPC ,KC_LCBR ,KC_RCBR ,KC_EQL , KC_UNDS ,KC_QUOT ,KC_DQT ,OS_MISC ,KC_BSLS , //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ - _______ , _______ , _______ , _______ + _______ , _______ , _______ , XXXXXXX // └────────┘ └────────┘ └────────┘ └────────┘ ), [_NAV] = LAYOUT( //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ - KC_TILDE,L_MOUSE ,OS_FUNC ,OS_MISC ,OS_TMUX , K_LT_A ,K_LT_C ,K_LT_E1 ,K_LT_E2 ,K_LT_I , + KC_1 ,KC_2 ,KC_3 ,KC_4 ,KC_5 , KC_6 ,KC_7 ,KC_8 ,KC_9 ,KC_0 , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - KC_TAB ,OS_GUI ,OS_CTRL ,OS_ALT ,KC_ENT , KC_LEFT ,KC_DOWN ,KC_UP ,KC_RIGHT,KC_END , + KC_LALT ,KC_LGUI ,KC_LCTL ,KC_TAB ,KC_ENT , KC_LEFT ,KC_DOWN ,KC_UP ,KC_RIGHT,KC_PGUP , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - KC_DELT ,KC_BSPC ,KC_ESC ,KC_PGDN ,KC_PGUP , KC_HOME ,K_LT_S ,K_LT_U1 ,K_LT_U2 ,K_LT_Z , + KC_LSFT ,KC_BSPC ,KC_ESC ,KC_TILDE,OS_TMUX , OS_FUNC ,L_MOUSE ,KC_COMM ,KC_DOT ,KC_PGDN , //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ - _______ , _______ , _______ , _______ + XXXXXXX , _______ , _______ , _______ // └────────┘ └────────┘ └────────┘ └────────┘ ), - [_NUMB] = LAYOUT( + [_MISC] = LAYOUT( //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ - KC_1 ,KC_2 ,KC_3 ,KC_4 ,KC_5 , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , + RESET ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_BRID ,KC_BRIU ,KC_PSCR ,XXXXXXX ,K_PRINT , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - KC_6 ,KC_7 ,KC_8 ,KC_9 ,KC_0 , XXXXXXX ,OS_ALT ,OS_CTRL ,OS_GUI ,XXXXXXX , + XXXXXXX ,XXXXXXX ,DEBUG ,LT_OSLNX,XXXXXXX , KC_MPRV ,KC_MPLY ,KC_MNXT ,XXXXXXX ,K_VIDEO , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - KC_DELT ,KC_BSPC ,XXXXXXX ,XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , + XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_VOLD ,KC_VOLU ,XXXXXXX ,XXXXXXX ,XXXXXXX , //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ - _______ , _______ , _______ , _______ + XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX // └────────┘ └────────┘ └────────┘ └────────┘ ), @@ -185,127 +213,59 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_MOUSE] = LAYOUT( //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ - XXXXXXX ,L_MOUSE ,KC_MS_U ,KC_BTN3 ,KC_WH_U , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , + XXXXXXX ,XXXXXXX ,KC_MS_U ,KC_BTN3 ,KC_WH_U , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - XXXXXXX ,KC_MS_L ,KC_MS_D ,KC_MS_R ,KC_WH_D , XXXXXXX ,KC_LALT ,KC_LCTL ,KC_LGUI ,XXXXXXX , + XXXXXXX ,KC_MS_L ,KC_MS_D ,KC_MS_R ,KC_WH_D , XXXXXXX ,XXXXXXX ,KC_RCTL ,KC_RGUI ,KC_RALT , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - XXXXXXX ,XXXXXXX ,KC_ESC ,XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , + XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ - KC_BTN1 , KC_BTN2 , XXXXXXX , XXXXXXX + KC_BTN1 , KC_BTN2 , _______ , XXXXXXX // └────────┘ └────────┘ └────────┘ └────────┘ ), - [_MISC] = LAYOUT( + [_FUNC] = LAYOUT( //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ - QK_BOOT,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_BRID ,KC_BRIU ,XXXXXXX ,KC_PSCR ,K_PRINT , + KC_F1 ,KC_F2 ,KC_F3 ,KC_F4 ,KC_F5 , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - XXXXXXX ,XXXXXXX ,DEBUG ,XXXXXXX ,XXXXXXX , KC_MPRV ,KC_MPLY ,XXXXXXX ,KC_MNXT ,XXXXXXX , + KC_F6 ,KC_F7 ,KC_F8 ,KC_F9 ,KC_F10 , XXXXXXX ,XXXXXXX ,KC_RCTL ,KC_RGUI ,KC_RALT , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_VOLD ,KC_VOLU ,XXXXXXX ,XXXXXXX ,UC_MOD , + KC_F11 ,KC_F12 ,XXXXXXX ,XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX // └────────┘ └────────┘ └────────┘ └────────┘ ), - [_FUNC] = LAYOUT( + [_LT_MAC] = LAYOUT( //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ - XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_F1 ,KC_F2 ,KC_F3 ,KC_F4 ,KC_F5 , + KC_EXLM ,KC_AT ,KC_HASH ,KC_DLR ,KC_PERC , KC_CIRC ,KC_AMPR ,KC_ASTR ,KC_PLUS ,XXXXXXX , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_F6 ,KC_F7 ,KC_F8 ,KC_F9 ,KC_F10 , + KC_1 ,KC_2 ,KC_3 ,KC_4 ,KC_5 , KC_6 ,KC_7 ,KC_8 ,KC_EQL ,XXXXXXX , //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ - XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_F11 ,KC_F12 ,XXXXXXX ,XXXXXXX ,XXXXXXX , + XXXXXXX ,KC_BSPC ,XXXXXXX ,XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ - XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX + XXXXXXX , XXXXXXX , _______ , XXXXXXX + // └────────┘ └────────┘ └────────┘ └────────┘ + ), + + [_LT_LINUX] = LAYOUT( + //┌────────┬────────┬────────┬────────┬────────┐ ┌────────┬────────┬────────┬────────┬────────┐ + K_LT_AU ,K_LT_CU ,K_LT_E1U,K_LT_E2U,K_LT_IU , K_LT_SU ,K_LT_U1U,K_LT_U2U,K_LT_ZU ,XXXXXXX , + //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ + K_LT_A ,K_LT_C ,K_LT_E1 ,K_LT_E2 ,K_LT_I , K_LT_S ,K_LT_U1 ,K_LT_U2 ,K_LT_Z ,XXXXXXX , + //├────────┼────────┼────────┼────────┼────────┤ ├────────┼────────┼────────┼────────┼────────┤ + XXXXXXX ,KC_BSPC ,XXXXXXX ,K_SNEK ,K_LT_OB , K_LT_CB ,K_EURO ,XXXXXXX ,XXXXXXX ,XXXXXXX , + //└────────┴────────┴────────┴────┬───┴────┬───┼────────┐ ┌────────┼───┬────┴───┬────┴────────┴────────┴────────┘ + XXXXXXX , XXXXXXX , _______ , XXXXXXX // └────────┘ └────────┘ └────────┘ └────────┘ ), }; #define TMUX_PREFIX SS_DOWN(X_LCTL) "b" SS_UP(X_LCTL) -bool is_oneshot_cancel_key(uint16_t keycode) { - switch (keycode) { - case L_SYM: - case L_NAV: - return true; - default: - return false; - } -} - -bool is_oneshot_layer_cancel_key(uint16_t keycode) { - switch (keycode) { - case L_SYM: - case L_NAV: - return true; - default: - return false; - } -} - -bool is_oneshot_ignored_key(uint16_t keycode) { - switch (keycode) { - case L_SYM: - case L_NAV: - case OS_CTRL: - case OS_ALT: - case OS_GUI: - case OS_TMUX: - case OS_MISC: - case KC_LSFT: - return true; - default: - return false; - } -} - -bool is_oneshot_mod_key(uint16_t keycode) { - switch (keycode) { - case OS_CTRL: - case OS_ALT: - case OS_GUI: - return true; - default: - return false; - } -} - -oneshot_state os_ctrl_state = os_up_unqueued; -oneshot_state os_alt_state = os_up_unqueued; -oneshot_state os_cmd_state = os_up_unqueued; -oneshot_state os_tmux_state = os_up_unqueued; -oneshot_state os_misc_state = os_up_unqueued; -oneshot_state os_func_state = os_up_unqueued; +bool lt_os_is_linux = false; bool process_record_user(uint16_t keycode, keyrecord_t *record) { - update_oneshot( - &os_ctrl_state, KC_LCTL, OS_CTRL, - keycode, record - ); - update_oneshot( - &os_alt_state, KC_LALT, OS_ALT, - keycode, record - ); - update_oneshot( - &os_cmd_state, KC_LGUI, OS_GUI, - keycode, record - ); - - bool handled = true; - handled = update_oneshot_layer( - &os_tmux_state, _TMUX, OS_TMUX, - keycode, record - ) & handled; - - handled = update_oneshot_layer( - &os_misc_state, _MISC, OS_MISC, - keycode, record - ) & handled; - - handled = update_oneshot_layer( - &os_func_state, _FUNC, OS_FUNC, - keycode, record - ) & handled; - if (!handled) return false; + if (!update_flow(keycode, record->event.pressed, record->event.key)) return false; switch (keycode) { case TM_LEFT: @@ -340,10 +300,35 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (!record->event.pressed) return true; SEND_STRING(TMUX_PREFIX SS_LCTL("u")); return false; + case LT_OSLNX: + if (!record->event.pressed) return true; + lt_os_is_linux = !lt_os_is_linux; + return false; } return true; } +void matrix_scan_user(void) { + flow_matrix_scan(); +} + +bool lang_layer_on = false; + layer_state_t layer_state_set_user(layer_state_t state) { - return update_tri_layer_state(state, _SYM, _NAV, _NUMB); + state = update_tri_layer_state(state, _SYM, _NAV, lt_os_is_linux ? _LT_LINUX : _LT_MAC); + + uint8_t hl = get_highest_layer(state); + if (hl == _LT_MAC) { + if (!lang_layer_on) { + tap_code16(LCTL(KC_SPC)); + lang_layer_on = true; + } + } else { + if (lang_layer_on) { + tap_code16(LCTL(KC_SPC)); + lang_layer_on = false; + } + } + + return state; } diff --git a/keyboards/a_dux/keymaps/daliusd/oneshot.c b/keyboards/a_dux/keymaps/daliusd/oneshot.c deleted file mode 100644 index 1e7b4d9650..0000000000 --- a/keyboards/a_dux/keymaps/daliusd/oneshot.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright 2021 @daliusd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "print.h" -#include "oneshot.h" - -void update_oneshot( - oneshot_state *state, - uint16_t mod, - uint16_t trigger, - uint16_t keycode, - keyrecord_t *record -) { - if (keycode == trigger) { - if (record->event.pressed) { - // Trigger keydown - if (*state == os_up_unqueued) { - register_code(mod); - } - *state = os_down_unused; - dprintf("trigger down (on?), mod: %d, ? -> os_down_unused\n", mod); - } else { - // Trigger keyup - switch (*state) { - case os_down_unused: - // If we didn't use the mod while trigger was held, queue it. - *state = os_up_queued; - dprintf("trigger up, mod: %d, os_down_unused -> os_up_queued\n", mod); - break; - case os_down_used: - // If we did use the mod while trigger was held, unregister it. - *state = os_up_unqueued; - unregister_code(mod); - dprintf("trigger up (off), mod: %d, os_down_used -> os_up_unqueued\n", mod); - break; - default: - break; - } - } - } else { - if (record->event.pressed) { - if (is_oneshot_cancel_key(keycode) && *state != os_up_unqueued) { - // Cancel oneshot on designated cancel keydown. - *state = os_up_unqueued; - unregister_code(mod); - dprintf("cancel (off), mod: %d, ? -> os_up_unqueued\n", mod); - } - if (!is_oneshot_ignored_key(keycode)) { - switch (*state) { - case os_up_queued: - *state = os_up_queued_used; - dprintf("key up (off), mod: %d, os_up_queued -> os_up_queued_used\n", mod); - break; - case os_up_queued_used: - *state = os_up_unqueued; - unregister_code(mod); - dprintf("key up (off), mod: %d, os_up_queued_used -> os_up_unqueued\n", mod); - break; - default: - break; - } - } - } else { - if (!is_oneshot_ignored_key(keycode)) { - // On non-ignored keyup, consider the oneshot used. - switch (*state) { - case os_down_unused: - *state = os_down_used; - dprintf("key up, mod: %d, os_down_unused -> os_down_used\n", mod); - break; - case os_up_queued: - *state = os_up_unqueued; - unregister_code(mod); - dprintf("key up (off), mod: %d, os_up_queued -> os_up_unqueued\n", mod); - break; - case os_up_queued_used: - *state = os_up_unqueued; - unregister_code(mod); - dprintf("key up (off), mod: %d, os_up_queued_used -> os_up_unqueued\n", mod); - break; - default: - break; - } - } - } - } -} - -bool update_oneshot_layer( - oneshot_state *state, - uint16_t layer, - uint16_t trigger, - uint16_t keycode, - keyrecord_t *record -) { - if (keycode == trigger) { - if (record->event.pressed) { - // Trigger keydown - if (*state == os_up_unqueued) { - layer_on(layer); - } - *state = os_down_unused; - dprintf("trigger down (on?), layer: %d, ? -> os_down_unused\n", layer); - return false; - } else { - // Trigger keyup - switch (*state) { - case os_down_unused: - // If we didn't use the layer while trigger was held, queue it. - *state = os_up_queued; - dprintf("trigger up, layer: %d, os_down_unused -> os_up_queued\n", layer); - return false; - case os_down_used: - // If we did use the layer while trigger was held, turn off it. - *state = os_up_unqueued; - layer_off(layer); - dprintf("trigger up (off), layer: %d, os_down_used -> os_up_unqueued\n", layer); - return false; - default: - break; - } - } - } else { - if (record->event.pressed) { - if (is_oneshot_layer_cancel_key(keycode) && *state != os_up_unqueued) { - // Cancel oneshot layer on designated cancel keydown. - *state = os_up_unqueued; - layer_off(layer); - dprintf("cancel (off), layer: %d, ? -> os_up_unqueued\n", layer); - return false; - } - uint8_t key_layer = read_source_layers_cache(record->event.key); - if (key_layer == layer) { - // On non-ignored keyup, consider the oneshot used. - switch (*state) { - case os_down_unused: - *state = os_down_used; - dprintf("key down, layer: %d, os_down_unused -> os_down_used\n", layer); - return true; - case os_up_queued: - if (is_oneshot_mod_key(keycode)) { - *state = os_up_unqueued; - layer_off(layer); - dprintf("key down, layer: %d, os_up_queued -> os_up_unqueued\n", layer); - return false; - } else { - *state = os_up_queued_used; - dprintf("key down, layer: %d, os_up_queued -> os_up_queued_used\n", layer); - } - return true; - case os_up_queued_used: - *state = os_up_unqueued; - layer_off(layer); - dprintf("key down (off), layer: %d, os_up_queued_used -> os_up_unqueued\n", layer); - return false; - default: - break; - } - } - } else { - // Ignore key ups from other layers - uint8_t key_layer = read_source_layers_cache(record->event.key); - if (key_layer == layer) { - // On non-ignored keyup, consider the oneshot used. - switch (*state) { - case os_up_queued: - *state = os_up_unqueued; - layer_off(layer); - dprintf("key up (off), layer: %d, os_up_queued -> os_up_unqueued\n", layer); - return true; - case os_up_queued_used: - *state = os_up_unqueued; - layer_off(layer); - dprintf("key up (off), layer: %d, os_up_queued_used -> os_up_unqueued\n", layer); - return true; - default: - break; - } - } - } - } - return true; -} diff --git a/keyboards/a_dux/keymaps/daliusd/oneshot.h b/keyboards/a_dux/keymaps/daliusd/oneshot.h deleted file mode 100644 index a4ea71b8a7..0000000000 --- a/keyboards/a_dux/keymaps/daliusd/oneshot.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2021 @daliusd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include QMK_KEYBOARD_H - -// Represents the four states a oneshot key can be in -typedef enum { - os_up_unqueued, - os_up_queued, - os_up_queued_used, - os_down_unused, - os_down_used, -} oneshot_state; - -// Custom oneshot mod implementation that doesn't rely on timers. If a mod is -// used while it is held it will be unregistered on keyup as normal, otherwise -// it will be queued and only released after the next non-mod keyup. -void update_oneshot( - oneshot_state *state, - uint16_t mod, - uint16_t trigger, - uint16_t keycode, - keyrecord_t *record -); - -// Oneshot implementation for layers -bool update_oneshot_layer( - oneshot_state *state, - uint16_t layer, - uint16_t trigger, - uint16_t keycode, - keyrecord_t *record -); - -// To be implemented by the consumer. Layers one shot implementation needs to -// know which keys are used as oneshot mods -bool is_oneshot_mod_key( - uint16_t keycode -); - -// To be implemented by the consumer. Defines keys to cancel oneshot mods. -bool is_oneshot_cancel_key(uint16_t keycode); - -// To be implemented by the consumer. Defines keys to cancel oneshot layers. -bool is_oneshot_layer_cancel_key(uint16_t keycode); - -// To be implemented by the consumer. Defines keys to ignore when determining -// whether a oneshot mod has been used. Setting this to modifiers and layer -// change keys allows stacking multiple oneshot modifiers, and carrying them -// between layers. -bool is_oneshot_ignored_key(uint16_t keycode); diff --git a/keyboards/a_dux/keymaps/daliusd/readme.md b/keyboards/a_dux/keymaps/daliusd/readme.md index f6e0efd0e8..fde19ee630 100644 --- a/keyboards/a_dux/keymaps/daliusd/readme.md +++ b/keyboards/a_dux/keymaps/daliusd/readme.md @@ -1,21 +1,306 @@ # My 34 keys layout -This are my principles for layout: +This is my principles for layout: * I am using Callum style layout. Here you can read explanation by Callum himself and his reasoning for not using mod-tap: [here](../../../../users/callum/readme.md) * There should be only one way to type key. Key can be on - different layer but it must maintain its physical location. + different layer but it must maintain its physical location. I + broke this rule for Shift key only. * The less features are used the better. -* trilayer is cool. +* There is simple TMUX layer. -* There is 🐍 key for no reason. +* Common keys must be accessible using two keys if possible. -As well I have added one shot layers compatible with Callum's one -shot keys. +* It should be possible to work with left keyboard side and mouse + in right hand without lifting hands for some scenarios (that's + why I had to duplicate Shift key). -There is simple TMUX layer as well. +## Improvements over Callum + +* I have added one shot layers compatible with Callum's one shot + keys. + +* There is one issue with accidental uppercase characters fixed + that exists in original Callum layout's implementation. + +* Another annoying feature of Callum layer is one shot keys are + frozen until you cancel them. This is problem when you use one + hand for keyboard and another for mouse. E.g. you click Ctrl and + mouse to get some menu (on Mac OS X), and then you want to click + some item in that menu. You have to remember to cancel one shot in such + situation. I have added two settings two handle situations like + this: + + * `FLOW_ONESHOT_WAIT_TERM` - if hold one shot key longer than + `FLOW_ONESHOT_WAIT_TERM` ms then mod key / layer key is not + treated as one shot key (defaults to 500ms). + + * `FLOW_ONESHOT_TERM` - if you do not click another key in + `FLOW_ONESHOT_TERM` ms then one shot key / layer key is treated + as normal key. Therefore if you lift it after `FLOW_ONESHOT_TERM` + it will not be treated as one shot (defaults to 500ms). + + After adding those two settings I have found out that I don't + need one shot cancel key anymore so I have removed it. + +Since differences are significant I named this layout `flow`. + +## Using flow with your keyboard + +Copy `flow.c` and `flow.h` to keyboard folder. + +Add following line to `rules.mk`: + +```make +SRC += flow.c +``` + +Define following in `config.h` for modifiers and layers: + +```c +#define FLOW_COUNT 7 +#define FLOW_LAYERS_COUNT 3 +``` + +In your `keymap.c` add and configure like this: + +```c +#include "flow.h" + +... + +// flow_config should correspond to following format: +// * layer keycode +// * modifier keycode +const uint16_t flow_config[FLOW_COUNT][2] = { + {L_NAV, KC_LALT}, + {L_NAV, KC_LGUI}, + {L_NAV, KC_LCTL}, + {L_NAV, KC_LSFT}, + {L_SYM, KC_LCTL}, + {L_SYM, KC_LGUI}, + {L_SYM, KC_LALT}, +}; + + +// for layers configuration follow this format: +// * custom layer key +// * layer name +const uint16_t flow_layers_config[FLOW_LAYERS_COUNT][2] = { + {OS_TMUX, _TMUX}, + {OS_MISC, _MISC}, + {OS_FUNC, _FUNC}, +}; + +... + +// Add following to handle flow + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (!update_flow(keycode, record->event.pressed, record->event.key)) return false; + return true; +} + +void matrix_scan_user(void) { + flow_matrix_scan(); +} + +``` + +## Lithuanian letters + +There are at least two ways how to enter Lithuanian letters: to +use Unicode support from QMK or to switch OS language when +necessary. Unicode support has some problems: + +* it is OS specific (you need to change Unicode input mode based + on your OS and I sometimes switch between Mac OS X and Ubuntu). + This is minor issue but it is still issue. + +* There is bug in Mac OS X and I can't enter `Š` using unicode + input method. + +* Unicode Hex Input in Mac OS X is not perfect and there are some + minor issue while using it. + +On Linux Unicode support meanwhile works perfectly. + +This leaves us with other option to use OS language switching as +you most probably have done before. Still there is space for +improvement. E.g. I have added Lithuanian letters to trilayer and +trilayer activation toggles OS language (this works because I use +only two languages). Check `layer_state_set_user` implementation +for details. + +# Rejected ideas + +## Mods as combos + +Sometimes when I press `NAV (layer key) + S + Tab` to get `Command ++ Tab` I ended up with `S + Nav + Tab`. This happened because I +did that really fast and sometimes clicked S slightly earlier than +NAV layer key. Initially I have solved this problem using Combo +keys, but that's additional dependency and combo keys are not +ideal for Callum layer. You need to release both keys to trigger +Combo key release. Therefore I have written custom code that +allows pressing S some milliseconds earlier. This is controlled by +FLOW_TERM and defaults to 10. I do not recommend setting this to +higher than 30. + +This idea was rejected because it looks like 10ms did not made +that big difference. + +## Swapper + +Idea of swapper is to have key that registers Mode key (e.g. +Command while layer and some key is pressed) to simulate two key +combo, e.g. Command + Tab. Overall I found that 3 keys combo that +I have currently for swapping windows is equally good as 2 keys +swapper. Another problem with swapper is that it is OS specific. +Still if you want here is swapper implementation I have used: + +```c +bool active; + +void update_swapper( + uint16_t trigger, + uint16_t keycode, + bool pressed +) { + if (keycode == trigger) { + if (pressed) { + if (!active) { + active = true; + register_code(KC_LGUI); + } + register_code(KC_TAB); + } else { + unregister_code(KC_TAB); + } + } else if (active && keycode != KC_LSFT && keycode != KC_LEFT && keycode != KC_RIGHT) { + unregister_code(KC_LGUI); + active = false; + } +} +``` + +## Combos + +I have seen that some people use two letter horizontal combos for +some actions, e.g. XC for Command+C, CV for Command+V, JK for ESC +and etc. I found that this kind of kicks me out of the flow when +working as it requires different kind of action and I need to +pause to make that action. + +## Comma-space + +I have noticed that I put space after comma `,` usually. That +means I can use comma + letter for something else with backspace, +e.g. for Lithuanian letters. Performance wise that works OK, but +practically that does not feel really good. Trilayer with language +layer switch works better. + +Still if you are interested here is comma-space implementation: + +```c +void swap_layout(void) { + uint8_t saved_mods = get_mods(); + clear_mods(); + tap_code16(LCTL(KC_SPC)); + set_mods(saved_mods); +} + +void press_with_layout_swap(uint16_t keycode) { + tap_code16(KC_BSPC); + swap_layout(); + tap_code16(keycode); + swap_layout(); +} + +bool comma_pressed = false; + +bool update_commaspace( + uint16_t keycode, + bool pressed +) { + if (keycode == KC_COMM) { + if (!(get_mods() & MOD_MASK_SHIFT)) { + comma_pressed = true; + } + } else if (comma_pressed) { + if (keycode != KC_LSFT) { + comma_pressed = false; + } + + switch(keycode) { + case KC_Q: + if (pressed) { + press_with_layout_swap(KC_1); + return false; + } + break; + case KC_W: + if (pressed) { + press_with_layout_swap(KC_2); + return false; + } + break; + case KC_E: + if (pressed) { + press_with_layout_swap(KC_3); + return false; + } + break; + case KC_R: + if (pressed) { + press_with_layout_swap(KC_4); + return false; + } + break; + case KC_T: + if (pressed) { + press_with_layout_swap(KC_5); + return false; + } + break; + case KC_Y: + if (pressed) { + press_with_layout_swap(KC_6); + return false; + } + break; + case KC_U: + if (pressed) { + press_with_layout_swap(KC_7); + return false; + } + break; + case KC_I: + if (pressed) { + press_with_layout_swap(KC_8); + return false; + } + break; + case KC_O: + if (pressed) { + press_with_layout_swap(KC_EQL); + return false; + } + break; + } + } + + return true; +}; +``` + +## Using one shot layers on top layer keys (NAV and SYM) + +While this looked promising and fun it was really easy to get lost +in which layer you actually are. You can still use it as `flow` +supports this scenario, but I do not recommend it. diff --git a/keyboards/a_dux/keymaps/daliusd/rules.mk b/keyboards/a_dux/keymaps/daliusd/rules.mk index 0f203f004c..dda50a4f78 100644 --- a/keyboards/a_dux/keymaps/daliusd/rules.mk +++ b/keyboards/a_dux/keymaps/daliusd/rules.mk @@ -2,4 +2,4 @@ UNICODE_ENABLE = no UNICODEMAP_ENABLE = yes #CONSOLE_ENABLE = yes -SRC += oneshot.c +SRC += flow.c -- cgit v1.2.3