[Keymap] Jonavin userspace encoder alt tab scrolling (#14979) Co-authored-by: Jonavin <=>
8 files changed, 271 insertions(+), 165 deletions(-) M keyboards/mechwild/obe/keymaps/jonavin/keymap.c M keyboards/mechwild/obe/keymaps/jonavin/readme.md M keyboards/mechwild/obe/keymaps/jonavin/rules.mk M users/jonavin/jonavin.c M users/jonavin/jonavin.h A users/jonavin/jonavin_encoder.c M users/jonavin/readme.md M users/jonavin/rules.mk
M keyboards/mechwild/obe/keymaps/jonavin/keymap.c => keyboards/mechwild/obe/keymaps/jonavin/keymap.c +2 -2
@@ 25,14 25,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Base */ [_BASE] = LAYOUT( KC_MUTE, KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_DEL, KC_TSTOG,KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_DEL, KC_PGUP, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, KC_PGDN, TT(_RAISE), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_LSFTCAPSWIN,KC_Z, KC_X, KC_C, KC_V, KC_B, LT(_LOWER,KC_B), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_SFTUP,KC_RSFT, KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, MO(_FN1), KC_RAISESPC, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ), [_FN1] = LAYOUT( KC_NO, KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_INS, KC_MUTE, KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_INS, KC_HOME, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_NO, KC_NO, RESET, KC_END, KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NLCK, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_TRNS,
M keyboards/mechwild/obe/keymaps/jonavin/readme.md => keyboards/mechwild/obe/keymaps/jonavin/readme.md +4 -0
@@ 18,6 18,7 @@ Features - left spacebar Backspace - add double tap of Left Shift to toggle Caps Lock - Up arrow is also Shift when held - Pushing the encoder switches the default encoder scroll between volume control and Alt-Tab @@ rules.mk OPTIONS - Active features from userspace 46,5 47,8 @@ EMOTICON_ENABLE INVERT_NUMLOCK_INDICATOR - inverts the Num lock indicator, LED is on when num lokc is off ALTTAB_SCROLL_ENABLE - bind KS_TSTOG to a different key to change how this toggle happens ## All layers diagram 
M keyboards/mechwild/obe/keymaps/jonavin/rules.mk => keyboards/mechwild/obe/keymaps/jonavin/rules.mk +2 -0
@@ 10,3 10,5 @@ STARTUP_NUMLOCK_ON = yes ENCODER_DEFAULTACTIONS_ENABLE = yes EMOTICON_ENABLE = yes INVERT_NUMLOCK_INDICATOR = yes ALTTAB_SCROLL_ENABLE = yes
M users/jonavin/jonavin.c => users/jonavin/jonavin.c +17 -160
@@ 95,171 95,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. } // timeout_threshold = 0 will disable timeout } #endif // IDLE_TIMEOUT_ENABLE #if defined(ALTTAB_SCROLL_ENABLE) || defined(IDLE_TIMEOUT_ENABLE) // timer features __attribute__((weak)) void matrix_scan_keymap(void) {} void matrix_scan_user(void) { timeout_tick_timer(); #ifdef ALTTAB_SCROLL_ENABLE encoder_tick_alttabscroll(); #endif #ifdef IDLE_TIMEOUT_ENABLE timeout_tick_timer(); #endif matrix_scan_keymap(); } #endif // IDLE_TIMEOUT_ENABLE #ifdef ENCODER_ENABLE #ifndef DYNAMIC_KEYMAP_LAYER_COUNT #define DYNAMIC_KEYMAP_LAYER_COUNT 4 //default in case this is not already defined elsewhere #endif #ifndef ENCODER_DEFAULTACTIONS_INDEX #define ENCODER_DEFAULTACTIONS_INDEX 0 // can select encoder index if there are multiple encoders #endif void encoder_action_volume(bool clockwise) { if (clockwise) tap_code(KC_VOLU); else tap_code(KC_VOLD); } void encoder_action_mediatrack(bool clockwise) { if (clockwise) tap_code(KC_MEDIA_NEXT_TRACK); else tap_code(KC_MEDIA_PREV_TRACK); } void encoder_action_navword(bool clockwise) { if (clockwise) tap_code16(LCTL(KC_RGHT)); else tap_code16(LCTL(KC_LEFT)); } void encoder_action_navpage(bool clockwise) { if (clockwise) tap_code16(KC_PGUP); else tap_code16(KC_PGDN); } // LAYER HANDLING uint8_t selected_layer = 0; uint8_t get_selected_layer(void) { return selected_layer; } void encoder_action_layerchange(bool clockwise) { if (clockwise) { if(selected_layer < (DYNAMIC_KEYMAP_LAYER_COUNT - 1)) { selected_layer ++; layer_move(selected_layer); } } else { if (selected_layer > 0) { selected_layer --; layer_move(selected_layer); } } } #ifdef RGB_MATRIX_ENABLE void encoder_action_rgb_speed(bool clockwise) { if (clockwise) rgb_matrix_increase_speed_noeeprom(); else rgb_matrix_decrease_speed_noeeprom(); } void encoder_action_rgb_hue(bool clockwise) { if (clockwise) rgb_matrix_increase_hue_noeeprom(); else rgb_matrix_decrease_hue_noeeprom(); } void encoder_action_rgb_saturation(bool clockwise) { if (clockwise) rgb_matrix_increase_sat_noeeprom(); else rgb_matrix_decrease_sat_noeeprom(); } void encoder_action_rgb_brightness(bool clockwise) { if (clockwise) rgb_matrix_increase_val_noeeprom(); else rgb_matrix_decrease_val_noeeprom(); } void encoder_action_rgb_mode(bool clockwise) { if (clockwise) rgb_matrix_step_noeeprom(); else rgb_matrix_step_reverse_noeeprom(); } #elif defined(RGBLIGHT_ENABLE) void encoder_action_rgb_speed(bool clockwise) { if (clockwise) rgblight_increase_speed_noeeprom(); else rgblight_decrease_speed_noeeprom(); } void encoder_action_rgb_hue(bool clockwise) { if (clockwise) rgblight_increase_hue_noeeprom(); else rgblight_decrease_hue_noeeprom(); } void encoder_action_rgb_saturation(bool clockwise) { if (clockwise) rgblight_increase_sat_noeeprom(); else rgblight_decrease_sat_noeeprom(); } void encoder_action_rgb_brightness(bool clockwise) { if (clockwise) rgblight_increase_val_noeeprom(); else rgblight_decrease_val_noeeprom(); } void encoder_action_rgb_mode(bool clockwise) { if (clockwise) rgblight_step_noeeprom(); else rgblight_step_reverse_noeeprom(); } #endif // RGB_MATRIX_ENABLE || RGBLIGHT_ENABLE #endif // ENCODER_ENABLE #if defined(ENCODER_ENABLE) && defined(ENCODER_DEFAULTACTIONS_ENABLE) // Encoder Functionality __attribute__((weak)) bool encoder_update_keymap(uint8_t index, bool clockwise) { return true; } bool encoder_update_user(uint8_t index, bool clockwise) { if (!encoder_update_keymap(index, clockwise)) { return false; } if (index != ENCODER_DEFAULTACTIONS_INDEX) {return true;} // exit if the index doesn't match uint8_t mods_state = get_mods(); if (mods_state & MOD_BIT(KC_LSFT) ) { // If you are holding L shift, encoder changes layers encoder_action_layerchange(clockwise); } else if (mods_state & MOD_BIT(KC_RSFT) ) { // If you are holding R shift, Page up/dn unregister_mods(MOD_BIT(KC_RSFT)); encoder_action_navpage(clockwise); register_mods(MOD_BIT(KC_RSFT)); } else if (mods_state & MOD_BIT(KC_LCTL)) { // if holding Left Ctrl, navigate next/prev word encoder_action_navword(clockwise); } else if (mods_state & MOD_BIT(KC_LALT)) { // if holding Left Alt, change media next/prev track encoder_action_mediatrack(clockwise); } else { switch(get_highest_layer(layer_state)) { case _FN1: #ifdef IDLE_TIMEOUT_ENABLE timeout_update_threshold(clockwise); #endif break; default: encoder_action_volume(clockwise); // Otherwise it just changes volume break; } } return false; } #endif // ENCODER_ENABLE #endif // ALTTAB_SCROLL_ENABLE or IDLE_TIMEOUT_ENABLE // PROCESS KEY CODES @@ __attribute__ ((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; } 326,6 176,13 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { break; #endif // EMOTICON_ENABLE #ifdef ALTTAB_SCROLL_ENABLE case KC_TSTOG: if (record->event.pressed) encoder_toggle_alttabscroll(); else unregister_code16(keycode); break; #endif // ALTTAB_SCROLL_ENABLE default: if (record->event.pressed) { #ifdef RGB_MATRIX_ENABLE
M users/jonavin/jonavin.h => users/jonavin/jonavin.h +8 -0
@@ 45,6 45,8 @@ enum custom_user_keycodes { EMO_JOY, // (^o^) EMO_TEARS, // (T_T) KC_TSTOG, // Tab Scroll Toggle NEW_SAFE_RANGE // new safe range for keymap level custom keycodes }; @@ 91,6 93,12 @@ enum custom_user_keycodes { void encoder_action_rgb_brightness(bool clockwise); void encoder_action_rgb_mode(bool clockwise); #endif // RGB_MATRIX_ENABLE / RGBLIGHT_ENABLE #ifdef ALTTAB_SCROLL_ENABLE void encoder_action_alttabscroll(bool clockwise); void encoder_toggle_alttabscroll(void); void encoder_tick_alttabscroll(void); #endif // ALTTAB_SCROLL_ENABLE #endif // ENCODER_ENABLE
A users/jonavin/jonavin_encoder.c => users/jonavin/jonavin_encoder.c +219 -0
@@ 0,0 1,219 @@ /* Copyright 2021 Jonavin Eng @Jonavin 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 <http://www.gnu.org/licenses/>. */ #include QMK_KEYBOARD_H #include "jonavin.h" #ifdef ENCODER_ENABLE #ifndef DYNAMIC_KEYMAP_LAYER_COUNT #define DYNAMIC_KEYMAP_LAYER_COUNT 4 //default in case this is not already defined elsewhere #endif #ifndef ENCODER_DEFAULTACTIONS_INDEX #define ENCODER_DEFAULTACTIONS_INDEX 0 // can select encoder index if there are multiple encoders #endif void encoder_action_volume(bool clockwise) { if (clockwise) tap_code(KC_VOLU); else tap_code(KC_VOLD); } void encoder_action_mediatrack(bool clockwise) { if (clockwise) tap_code(KC_MEDIA_NEXT_TRACK); else tap_code(KC_MEDIA_PREV_TRACK); } void encoder_action_navword(bool clockwise) { if (clockwise) tap_code16(LCTL(KC_RGHT)); else tap_code16(LCTL(KC_LEFT)); } void encoder_action_navpage(bool clockwise) { if (clockwise) tap_code16(KC_PGUP); else tap_code16(KC_PGDN); } // LAYER HANDLING uint8_t selected_layer = 0; uint8_t get_selected_layer(void) { return selected_layer; } void encoder_action_layerchange(bool clockwise) { if (clockwise) { if(selected_layer < (DYNAMIC_KEYMAP_LAYER_COUNT - 1)) { selected_layer ++; layer_move(selected_layer); } } else { if (selected_layer > 0) { selected_layer --; layer_move(selected_layer); } } } #ifdef RGB_MATRIX_ENABLE void encoder_action_rgb_speed(bool clockwise) { if (clockwise) rgb_matrix_increase_speed_noeeprom(); else rgb_matrix_decrease_speed_noeeprom(); } void encoder_action_rgb_hue(bool clockwise) { if (clockwise) rgb_matrix_increase_hue_noeeprom(); else rgb_matrix_decrease_hue_noeeprom(); } void encoder_action_rgb_saturation(bool clockwise) { if (clockwise) rgb_matrix_increase_sat_noeeprom(); else rgb_matrix_decrease_sat_noeeprom(); } void encoder_action_rgb_brightness(bool clockwise) { if (clockwise) rgb_matrix_increase_val_noeeprom(); else rgb_matrix_decrease_val_noeeprom(); } void encoder_action_rgb_mode(bool clockwise) { if (clockwise) rgb_matrix_step_noeeprom(); else rgb_matrix_step_reverse_noeeprom(); } #elif defined(RGBLIGHT_ENABLE) void encoder_action_rgb_speed(bool clockwise) { if (clockwise) rgblight_increase_speed_noeeprom(); else rgblight_decrease_speed_noeeprom(); } void encoder_action_rgb_hue(bool clockwise) { if (clockwise) rgblight_increase_hue_noeeprom(); else rgblight_decrease_hue_noeeprom(); } void encoder_action_rgb_saturation(bool clockwise) { if (clockwise) rgblight_increase_sat_noeeprom(); else rgblight_decrease_sat_noeeprom(); } void encoder_action_rgb_brightness(bool clockwise) { if (clockwise) rgblight_increase_val_noeeprom(); else rgblight_decrease_val_noeeprom(); } void encoder_action_rgb_mode(bool clockwise) { if (clockwise) rgblight_step_noeeprom(); else rgblight_step_reverse_noeeprom(); } #endif // RGB_MATRIX_ENABLE || RGBLIGHT_ENABLE #ifdef ALTTAB_SCROLL_ENABLE bool is_tab_scrolling = false; bool is_alt_tab_active = false; uint16_t alt_tab_timer = 0; void encoder_toggle_alttabscroll(void) { is_tab_scrolling = !is_tab_scrolling; } void encoder_action_alttabscroll(bool clockwise) { if (clockwise) { if (!is_alt_tab_active) { is_alt_tab_active = true; register_mods(MOD_RALT); } tap_code16(KC_TAB); } else { tap_code16(S(KC_TAB)); } alt_tab_timer = timer_read(); } void encoder_tick_alttabscroll(void) { if (is_alt_tab_active) { if (timer_elapsed(alt_tab_timer) > 600) { unregister_mods(MOD_RALT); is_alt_tab_active = false; } } } #endif // ALTTAB_SCROLL_ENABLE #endif // ENCODER_ENABLE #if defined(ENCODER_ENABLE) && defined(ENCODER_DEFAULTACTIONS_ENABLE) // Encoder Functionality __attribute__((weak)) bool encoder_update_keymap(uint8_t index, bool clockwise) { return true; } bool encoder_update_user(uint8_t index, bool clockwise) { if (!encoder_update_keymap(index, clockwise)) { return false; } if (index != ENCODER_DEFAULTACTIONS_INDEX) {return true;} // exit if the index doesn't match uint8_t mods_state = get_mods(); if (mods_state & MOD_BIT(KC_LSFT) ) { // If you are holding L shift, encoder changes layers encoder_action_layerchange(clockwise); } else if (mods_state & MOD_BIT(KC_RSFT) ) { // If you are holding R shift, Page up/dn unregister_mods(MOD_BIT(KC_RSFT)); encoder_action_navpage(clockwise); register_mods(MOD_BIT(KC_RSFT)); } else if (mods_state & MOD_BIT(KC_LCTL)) { // if holding Left Ctrl, navigate next/prev word encoder_action_navword(clockwise); } else if (mods_state & MOD_BIT(KC_LALT)) { // if holding Left Alt, change media next/prev track encoder_action_mediatrack(clockwise); } else { switch(get_highest_layer(layer_state)) { case _FN1: #ifdef IDLE_TIMEOUT_ENABLE timeout_update_threshold(clockwise); #endif break; default: #ifdef ALTTAB_SCROLL_ENABLE if (is_tab_scrolling) encoder_action_alttabscroll(clockwise); else encoder_action_volume(clockwise); // Otherwise it just changes volume #else encoder_action_volume(clockwise); // Otherwise it just changes volume #endif // ALTTAB_SCROLL_ENABLE break; } } return false; } #endif // ENCODER_ENABLE
M users/jonavin/readme.md => users/jonavin/readme.md +10 -1
@@ 35,6 35,7 @@ KEYCODES: - KC_SFTUP RShift when held, Up arrow when tapped - KC_RAISESPC _RAISE layer mod when held, space when tapped - KC_LOWERSPC _LOWER layer mod when held, space when tapped - KC_TSTOG toggles between volume and Alt-Tab encoder control - When EMOTICON_ENABLE = yes @@ - EMO_SHRUG `\_("/)_/` 59,7 60,9 @@ AVAILABLE ENCODER ACTIONS: - void encoder_action_rgb_saturation(bool clockwise); - void encoder_action_rgb_brightness(bool clockwise); - void encoder_action_rgb_mode(bool clockwise); - - void encoder_action_alttabscroll(bool clockwise) - void encoder_toggle_alttabscroll(void); ENABLE FEATURES your keymap rules.mk @@ --------------------------------------- 89,6 92,12 @@ EMOTICON_ENABLE INVERT_NUMLOCK_INDICATOR - inverts the Num lock indicator, LED is on when num lock is off ALTTAB_SCROLL_ENABLE - When ENCODER_DEFAULTACTIONS_ENABLE = yes, Enables Alt-Tab scrolling functions in default encoder, bind KS_TSTOG to a key to enable/disable Alt-Tab vs Volume control - When defining your own encoder functions use encoder_action_alttabscroll(bool clockwise) to assign the encodr action FUNCTIONS ------------------------
M users/jonavin/rules.mk => users/jonavin/rules.mk +9 -2
@@ 1,6 1,13 @@ SRC += jonavin.c ifeq ($(strip $(ENCODER_DEFAULTACTIONS_ENABLE)), yes) OPT_DEFS += -DENCODER_DEFAULTACTIONS_ENABLE ifdef ENCODER_ENABLE # include encoder related code when enabled ifeq ($(strip $(ENCODER_DEFAULTACTIONS_ENABLE)), yes) OPT_DEFS += -DENCODER_DEFAULTACTIONS_ENABLE endif ifeq ($(strip $(ALTTAB_SCROLL_ENABLE)), yes) OPT_DEFS += -DALTTAB_SCROLL_ENABLE endif SRC += jonavin_encoder.c endif ifeq ($(strip $(TD_LSFT_CAPSLOCK_ENABLE)), yes) OPT_DEFS += -DTD_LSFT_CAPSLOCK_ENABLE