/**
* Copyright 2021 Charly Delay <charly@codesink.dev> (@0xcharly)
*
* 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
#ifdef CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
# include "timer.h"
#endif // CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
enum charybdis_keymap_layers {
LAYER_BASE = 0,
LAYER_TRANSPARENT,
LAYER_GAMING,
LAYER_POINTER,
LAYER_SYMBOL,
LAYER_SETTINGS,
};
/** \brief Automatically enable sniping-mode on the pointer layer. */
#define CHARYBDIS_AUTO_SNIPING_ON_LAYER LAYER_POINTER
#ifdef CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
static uint16_t auto_pointer_layer_timer = 0;
# ifndef CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_TIMEOUT_MS
# define CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_TIMEOUT_MS 1000
# endif // CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_TIMEOUT_MS
# ifndef CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_THRESHOLD
# define CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_THRESHOLD 8
# endif // CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_THRESHOLD
#endif // CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
#define LOWER MO(LAYER_POINTER)
#define RAISE MO(LAYER_SYMBOL)
#define MO_SET MO(LAYER_SETTINGS)
#define PT_Z LT(LAYER_SETTINGS, KC_Z)
#define PT_SLSH LT(LAYER_SETTINGS, KC_SLSH)
#ifndef POINTING_DEVICE_ENABLE
# define DRGSCRL KC_NO
# define DRG_TOG KC_NO
# define DPI_MOD KC_NO
# define DPI_RMOD KC_NO
# define S_D_MOD KC_NO
# define S_D_RMOD KC_NO
# define SNIPING KC_NO
#endif // !POINTING_DEVICE_ENABLE
#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
#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),
};
#define TD_U TD(TD_UNDO)
#define LT_TAB LT(LAYER_POINTER, KC_TAB)
#define LT_BSPC LT(LAYER_SYMBOL, KC_BSPC)
#define MT_ENT MT(MOD_RGUI, KC_ENT)
#define LT_SPC LT(LAYER_SYMBOL, KC_SPC)
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[LAYER_BASE] = LAYOUT(
// ╭──────────────────────────────────────────────────────╮ ╭──────────────────────────────────────────────────────╮
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, TD_U, KC_I, KC_O, KC_P, KC_BSLS,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
KC_LSFT, HR_A, HR_S, HR_D, HR_F, KC_G, KC_H, HR_J, HR_K, HR_L, HR_SCLN, KC_QUOT,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
MO_SET, PT_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, PT_SLSH, MO_SET,
// ╰──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────╯
LT_TAB, LT_BSPC, KC_LGUI, MT_ENT, LT_SPC,
KC_LALT, KC_BSPC, KC_DEL
// ╰───────────────────────────╯ ╰──────────────────╯
),
[LAYER_TRANSPARENT] = LAYOUT(
// ╭──────────────────────────────────────────────────────╮ ╭──────────────────────────────────────────────────────╮
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ╰──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────╯
_______, _______, _______, _______, _______,
_______, _______, _______
// ╰───────────────────────────╯ ╰──────────────────╯
),
[LAYER_GAMING] = LAYOUT(
// ╭──────────────────────────────────────────────────────╮ ╭──────────────────────────────────────────────────────╮
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, KC_E, _______, _______, _______, KC_U, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, KC_A, KC_S, KC_D, KC_F, _______, _______, KC_J, KC_K, KC_L, KC_SCLN, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, _______, _______, KC_B, _______, _______, _______, _______, _______, _______,
// ╰──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────╯
_______, _______, _______, _______, _______,
_______, _______, _______
// ╰───────────────────────────╯ ╰──────────────────╯
),
[LAYER_POINTER] = LAYOUT(
// ╭──────────────────────────────────────────────────────╮ ╭──────────────────────────────────────────────────────╮
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, _______, _______, _______, KC_SLSH, KC_7, KC_8, KC_9, KC_ASTR, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, _______, _______, _______, _______, _______, KC_MINS, KC_4, KC_5, KC_6, KC_PLUS, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, DRG_TOG, DRGSCRL, MS_BTN2, MS_BTN1, _______, KC_0, KC_1, KC_2, KC_3, KC_DOT, _______,
// ╰──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────╯
_______, _______, _______, _______, _______,
_______, _______, _______
// ╰───────────────────────────╯ ╰──────────────────╯
),
[LAYER_SYMBOL] = LAYOUT(
// ╭──────────────────────────────────────────────────────╮ ╭──────────────────────────────────────────────────────╮
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
_______, 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_MINS, KC_LT, KC_GT, KC_DQT, _______,
// ╰──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────╯
_______, _______, _______, _______, _______,
_______, _______, _______
// ╰───────────────────────────╯ ╰──────────────────╯
),
[LAYER_SETTINGS] = LAYOUT(
// ╭──────────────────────────────────────────────────────╮ ╭──────────────────────────────────────────────────────╮
RM_TOGG, XXXXXXX, XXXXXXX, XXXXXXX, DRG_TOG, TG(LAYER_TRANSPARENT), DRGSCRL, _______, KC_UP, _______, QK_BOOT, EE_CLR,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
WAYHALF, WAYFULL, KC_CAD, KC_AENTER, S_D_MOD, XXXXXXX, DPI_MOD, KC_LEFT, KC_DOWN, KC_RGHT, XXXXXXX, XXXXXXX,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
RM_NEXT, RM_PREV, RM_VALU, RM_VALD, S_D_RMOD, XXXXXXX, DPI_RMOD, _______, _______, _______, _______, XXXXXXX,
// ├──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────┤
QK_BOOT, EE_CLR, _______, _______, _______, _______, SNIPING, _______, _______, _______, KC_PGDN, EE_CLR,
// ╰──────────────────────────────────────────────────────┤ ├──────────────────────────────────────────────────────╯
_______, _______, _______, _______, _______,
_______, _______, _______
// ╰───────────────────────────╯ ╰──────────────────╯
),
};
// clang-format on
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(LAYER_TRANSPARENT)) {
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.
}
}
#ifdef POINTING_DEVICE_ENABLE
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
# ifdef CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
if (abs(mouse_report.x) > CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_THRESHOLD || abs(mouse_report.y) > CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_THRESHOLD) {
if (auto_pointer_layer_timer == 0) {
layer_on(LAYER_SETTINGS);
# ifdef RGB_MATRIX_ENABLE
rgb_matrix_mode_noeeprom(RGB_MATRIX_NONE);
rgb_matrix_sethsv_noeeprom(HSV_GREEN);
# endif // RGB_MATRIX_ENABLE
}
auto_pointer_layer_timer = timer_read();
}
# endif // CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
mouse_report.v = -mouse_report.v;
return mouse_report;
}
# ifdef CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
void matrix_scan_user(void) {
if (auto_pointer_layer_timer != 0 && TIMER_DIFF_16(timer_read(), auto_pointer_layer_timer) >= CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_TIMEOUT_MS) {
auto_pointer_layer_timer = 0;
layer_off(LAYER_SETTINGS);
# ifdef RGB_MATRIX_ENABLE
rgb_matrix_mode_noeeprom(RGB_MATRIX_DEFAULT_MODE);
# endif // RGB_MATRIX_ENABLE
}
}
# endif // CHARYBDIS_AUTO_POINTER_LAYER_TRIGGER_ENABLE
# ifdef CHARYBDIS_AUTO_SNIPING_ON_LAYER
layer_state_t layer_state_set_user(layer_state_t state) {
charybdis_set_pointer_sniping_enabled(layer_state_cmp(state, CHARYBDIS_AUTO_SNIPING_ON_LAYER));
return state;
}
# endif // CHARYBDIS_AUTO_SNIPING_ON_LAYER
#endif // POINTING_DEVICE_ENABLE
#ifdef RGB_MATRIX_ENABLE
// Forward-declare this helper function since it is defined in rgb_matrix.c.
void rgb_matrix_update_pwm_buffers(void);
#endif