/* Copyright 2022 @Yowkees Copyright 2022 MURAOKA Taro (aka KoRoN, @kaoriya) 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 QMK_KEYBOARD_H #include "quantum.h" // Home row mods #define HR_A KC_A #define HR_S MT(MOD_LALT, KC_S) #define HR_D MT(MOD_LSFT, KC_D) #define HR_F MT(MOD_LCTL, KC_F) #define HR_J MT(MOD_RCTL, KC_J) #define HR_K MT(MOD_RSFT, KC_K) #define HR_L MT(MOD_RALT, KC_L) #define HR_SCLN KC_SCLN // Custom shortcuts #define KC_EUNDO LCTL(LSFT(KC_MINUS)) #define KC_AENTER LCTL(LALT(KC_ENT)) #define WAYFULL LGUI(LSFT(KC_F)) #define WAYHALF LGUI(LSFT(KC_D)) #define KC_CAD LCTL(LALT(KC_DEL)) enum { TD_UNDO, }; // Combo for caps word const uint16_t PROGMEM capsword_combo[] = {HR_D, HR_K, COMBO_END}; combo_t key_combos[] = { COMBO(capsword_combo, QK_CAPS_WORD_TOGGLE), }; tap_dance_action_t tap_dance_actions[] = { [TD_UNDO] = ACTION_TAP_DANCE_DOUBLE(KC_U, KC_EUNDO), }; // clang-format off const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { // Base layer [0] = LAYOUT_universal( KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , TD(TD_UNDO), KC_I , KC_O , KC_P , HR_A , HR_S , HR_D , HR_F , KC_G , KC_H , HR_J , HR_K , HR_L , HR_SCLN , KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM , KC_DOT , KC_SLSH , MO(5) , KC_TAB , KC_ESC , LT(3,KC_TAB), LT(4,KC_BSPC), KC_LGUI, MT(MOD_RGUI, KC_ENT), LT(4,KC_SPC), _______, _______, _______, KC_QUOT ), // Transparent layer for HR_L GUI+N behavior [1] = LAYOUT_universal( _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ), // Gaming layer (removes home row mods via layer toggle) [2] = LAYOUT_universal( _______ , _______ , KC_E , _______ , _______ , _______ , KC_U , _______ , _______ , _______ , KC_A , KC_S , KC_D , KC_F , _______ , _______ , KC_J , KC_K , KC_L , KC_SCLN , _______ , _______ , _______ , _______ , KC_B , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ), // Mouse + Numpad layer (via left thumb) [3] = LAYOUT_universal( _______ , _______ , _______ , _______ , _______ , KC_SLSH , KC_7 , KC_8 , KC_9 , KC_ASTR , _______ , _______ , _______ , _______ , _______ , KC_MINS , KC_4 , KC_5 , KC_6 , KC_PLUS , SCRL_TO , SCRL_MO , KC_BTN2 , KC_BTN1 , _______ , KC_0 , KC_1 , KC_2 , KC_3 , KC_DOT , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ), // Symbols layer (via thumb keys) [4] = LAYOUT_universal( KC_GRV , KC_TILDE , KC_HASH , KC_AMPR , KC_PIPE, KC_CIRC , KC_LCBR , KC_RCBR , KC_LBRC , KC_RBRC , KC_EXLM , KC_UNDS , KC_COLN , KC_EQL , KC_DLR , KC_AT , KC_LPRN , KC_RPRN , KC_UNDS , KC_SCLN , KC_PERC , KC_QUES , KC_ASTR , KC_PLUS , KC_BSLS , KC_SLSH , KC_MINUS , KC_LT , KC_GT , KC_DQT , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ), // Nav/Settings layer [5] = LAYOUT_universal( RGB_TOG , AML_TO , AML_I50 , AML_D50 , TG(1) , _______ , SSNP_VRT , KC_UP , SSNP_FRE , QK_BOOT , WAYHALF , WAYFULL , KC_CAD , KC_AENTER, SCRL_DVI, CPI_I100, KC_LEFT , KC_DOWN , KC_RGHT , _______ , RGB_MOD , RGB_RMOD , RGB_VAI , RGB_VAD , SCRL_DVD, CPI_D100, _______ , _______ , _______ , _______ , QK_BOOT , KBC_RST , _______ , _______ , _______ , _______ , _______ , SSNP_VRT, SSNP_HOR , SSNP_FRE , KC_PGDN , KBC_SAVE ), }; // clang-format on layer_state_t layer_state_set_user(layer_state_t state) { // Auto enable scroll mode on layer 5 (nav layer) // Only force scroll ON for layer 5; let SCRL_TO handle toggling otherwise if (get_highest_layer(state) == 5) { keyball_set_scroll_mode(true); } return state; } bool process_record_user(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case HR_L: if (record->event.pressed && record->tap.count && layer_state_is(1)) { uint8_t mods = get_mods(); uint8_t weak = get_weak_mods(); uint8_t oneshot = get_oneshot_mods(); if ((mods | weak | oneshot) & MOD_MASK_GUI) { // GUI is already held; just tap N so the host sees GUI+N. tap_code(KC_N); return false; } } break; } return true; } bool caps_word_press_user(uint16_t keycode) { switch (keycode) { // Keycodes that continue Caps Word, with shift applied. case KC_A ... KC_Z: case TD(TD_UNDO): // Treat tap dance U like a letter add_weak_mods(MOD_BIT(KC_LSFT)); return true; // Keycodes that continue Caps Word, without shifting. case KC_1 ... KC_0: case KC_BSPC: case KC_DEL: case KC_UNDS: case KC_MINS: return true; default: return false; // Deactivate Caps Word. } } // Override scroll direction (invert vertical scroll) with accumulator // Adjust SCROLL_DIVISOR to control speed (higher = slower) #define SCROLL_DIVISOR 4 void keyball_on_apply_motion_to_mouse_scroll(report_mouse_t *report, report_mouse_t *output, bool is_left) { static int16_t acc_h = 0; static int16_t acc_v = 0; // Accumulate movement acc_h += report->x; acc_v += report->y; // Consume input report->x = 0; report->y = 0; // Calculate scroll output int8_t h = acc_h / SCROLL_DIVISOR; int8_t v = acc_v / SCROLL_DIVISOR; // Keep remainder for next time acc_h -= h * SCROLL_DIVISOR; acc_v -= v * SCROLL_DIVISOR; // Apply to output (inverted) output->h = is_left ? h : -h; output->v = is_left ? v : -v; // scroll snapping switch (keyball_get_scrollsnap_mode()) { case KEYBALL_SCROLLSNAP_MODE_VERTICAL: output->h = 0; break; case KEYBALL_SCROLLSNAP_MODE_HORIZONTAL: output->v = 0; break; default: // pass by without doing anything break; } } uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case LT(4, KC_BSPC): return TAPPING_TERM; // Enable quick-tap for backspace case HR_F: return TAPPING_TERM; // Enable quick-tap for Ctrl+F repeating default: return 0; // Disabled for everything else (home row mods) } } #ifdef OLED_ENABLE # include "lib/oledkit/oledkit.h" void oledkit_render_info_user(void) { keyball_oled_render_keyinfo(); keyball_oled_render_ballinfo(); keyball_oled_render_layerinfo(); } #endif