Files
keyboard/keymaps/custom/keymap.c
2026-03-15 16:14:14 -07:00

301 lines
17 KiB
C

#include QMK_KEYBOARD_H
#include "keymap_introspection.h"
#include "dynamic_keymap.h"
#include "mac_mode.h"
enum custom_keycodes {
CK_MCMD = SAFE_RANGE, // toggle mac-command mode
};
typedef struct {
uint8_t from;
uint8_t to;
} mod_rewrite_t;
static const mod_rewrite_t CTRL_TO_SUPER = { MOD_MASK_CTRL, MOD_MASK_GUI };
static const mod_rewrite_t CTRL_SHIFT_TO_SUPER = { MOD_MASK_CTRL | MOD_MASK_SHIFT, MOD_MASK_GUI };
static const mod_rewrite_t CTRL_SHIFT_TO_CMD_SHIFT = { MOD_MASK_CTRL | MOD_MASK_SHIFT, MOD_MASK_GUI | MOD_MASK_SHIFT };
static const mod_rewrite_t CTRL_ALT_TO_CTRL = { MOD_MASK_CTRL | MOD_MASK_ALT, MOD_MASK_CTRL };
static const mod_rewrite_t CTRL_TO_ALT = { MOD_MASK_CTRL, MOD_MASK_ALT };
static const mod_rewrite_t ALT_TO_SUPER = { MOD_MASK_ALT, MOD_MASK_GUI };
static const mod_rewrite_t SUPER_TO_SUPER = { MOD_MASK_GUI, MOD_MASK_GUI };
static const mod_rewrite_t SUPER_TO_CTRL = { MOD_MASK_GUI, MOD_MASK_CTRL };
static const mod_rewrite_t NONE_TO_SUPER = { 0, MOD_MASK_GUI };
// Collapse left/right mods into modifier types for comparison.
// e.g. either LCTL (0x01) or RCTL (0x10) both become 0x01.
static uint8_t normalize_mods(uint8_t mods) {
return (mods | (mods >> 4)) & 0x0F;
}
// Check if current mods exactly match a rule's `from` mods.
// Returns false if FN layer is active (skip rewrites when FN is held).
static bool mods_match(uint8_t mods, mod_rewrite_t rule) {
if (layer_state_is(1)) return false;
return normalize_mods(mods) == normalize_mods(rule.from);
}
// Rewrite modifier combos: swap exact `from` mod types to `to` mods, tap keycode, restore.
// Left/right variants of the same modifier are treated as equivalent.
// Returns true if rewrite occurred.
static bool rewrite_mods(uint16_t keycode, mod_rewrite_t rule) {
uint8_t mods = get_mods();
if (mods_match(mods, rule)) {
set_mods(normalize_mods(rule.to));
tap_code(keycode);
set_mods(mods);
return true;
}
return false;
}
// Rewrite modifier combo AND change the keycode sent.
// Returns true if rewrite occurred.
static bool rewrite_mods_and_key(mod_rewrite_t rule, uint16_t keycode_out) {
uint8_t mods = get_mods();
if (mods_match(mods, rule)) {
set_mods(normalize_mods(rule.to));
tap_code(keycode_out);
set_mods(mods);
return true;
}
return false;
}
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Layer 0, default layer
__________________________________________________________________________________________________________________________________ ________
| | | | | | | | | | | | | | || |
| ESC | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | DELETE || HOME |
|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________|
| | | | | | | | | | | | | | || |
| ~` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | _ - | = + | BACKSPACE || PGUP |
|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________|
| | | | | | | | | | | | [ | ] | || |
| TAB | Q | W | E | R | T | Y | U | I | O | P | { | } | | \ || PGDN |
|____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________|
| | | | | | | | | | | ; | ' | | | |
| CAPS | A | S | D | F | G | H | J | K | L | : | " | ENTER | | END |
|____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________|
| | | | | | | | | , | . | / | | |
| SHIFT | Z | X | C | V | B | N | M | < | > | ? | SHIFT | UP |
|________________|________|________|________|________|________|________|________|________|________|________|____________|________|_________
| | | | | | | | | | | | | |
| CTRL | FN | LGUI | LALT | SPACE | SPACE | RALT | RCTRL | FN | | LEFT | DOWN | RIGHT |
|____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________|
*/
[0] = LAYOUT(
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_DEL, KC_HOME,
KC_GRV, 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_BSPC, 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_BSLS, KC_PGDN,
KC_CAPS, 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_END,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, MO(1), KC_LGUI, KC_LALT, KC_SPC, KC_SPC, KC_RALT, KC_RCTL, MO(1), KC_LEFT, KC_DOWN, KC_RGHT
),
/* Layer 1, function layer
__________________________________________________________________________________________________________________________________ ________
| | | | | | | | | | | | | | || PLAY/ |
|QK_BOOT | | | | | | | | | | | | | || PAUSE |
|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________|
| | | | | | | | | | | LED | LED | LED | || VOLUME |
| | | | | | | | | | | TOGGLE | DOWN | UP | || UP |
|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________|
| | | | | | | | | | | | | | || VOLUME |
|PRINT SCREEN| | | | | | HOME | PGDN | PGUP | END | | | | || DOWN |
|____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________|
| | | | | | | | | | | | | | | |
| | | | | | | LEFT | DOWN | UP | RIGHT | | | | | MUTE |
|____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________|
| | | | | | | | | | | | | |
| | | | | | | | | | | | | PGUP |
|________________|________|________|________|________|________|________|________|________|________|________|____________|________|_________
| | | | | | | | | | | | | |
| | | | | | | | | | | HOME | PGDN | END |
|____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________|
* 'QK_BOOT' resets the controller and puts the board into firmware flashing mode. If this key is hit accidentally, just unplug the board
* and plug it back in.
*/
[1] = LAYOUT(
QK_BOOT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, CK_MCMD, KC_MPLY,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_VAD, RGB_VAI, KC_TRNS, KC_VOLU,
KC_PSCR, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_PGUP, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLD,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_MUTE,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_END
),
[2] = LAYOUT(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[3] = LAYOUT(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
};
// Override layer resolution: in mac mode, any modifier forces layer 0 (ignores FN)
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) {
if (mac_mode && (get_mods() & (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI))) {
layer = 0;
}
if (key.row < MATRIX_ROWS && key.col < MATRIX_COLS) {
return keycode_at_keymap_location(layer, key.row, key.col);
}
return KC_NO;
}
static bool gui_tapped = false;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Any other key pressed while GUI held means it's being used as a modifier
if (record->event.pressed && keycode != KC_LGUI) {
gui_tapped = false;
}
switch (keycode) {
// Mac mode: tap Super -> Cmd+Space (Spotlight)
// Linux: tap Super passes through normally (KDE app menu)
case KC_LGUI:
if (mac_mode) {
if (record->event.pressed) {
gui_tapped = true;
register_mods(MOD_BIT(KC_LGUI));
} else {
if (gui_tapped) {
tap_code(KC_SPC); // GUI still held, sends Super+Space
gui_tapped = false;
}
unregister_mods(MOD_BIT(KC_LGUI));
}
return false;
}
break;
case CK_MCMD:
if (record->event.pressed) {
mac_mode = !mac_mode;
mac_mode_manual = true;
// Flash LEDs to indicate mode: green = mac, red = normal
rgb_matrix_mode_noeeprom(RGB_MATRIX_SOLID_COLOR);
if (mac_mode) {
rgb_matrix_sethsv_noeeprom(HSV_GREEN);
} else {
rgb_matrix_sethsv_noeeprom(HSV_BLUE);
}
}
return false;
// Mac mode rewrites:
// Ctrl+C/V -> Super+C/V (copy/paste)
// Ctrl+Shift+C/V -> Super+C/V (terminal copy/paste)
case KC_C:
case KC_V:
if (mac_mode && record->event.pressed) {
if (rewrite_mods(keycode, CTRL_TO_SUPER)) return false;
if (rewrite_mods(keycode, CTRL_SHIFT_TO_SUPER)) return false;
}
break;
// Mac mode rewrites:
// Ctrl+X/A/S/F -> Super+X/A/S/F (cut, select all, save, find)
// Ctrl+W/L/R -> Super+W/L/R (close tab, address bar, reload)
case KC_X:
case KC_A:
case KC_S:
case KC_F:
case KC_W:
case KC_L:
case KC_R:
if (mac_mode && record->event.pressed) {
if (rewrite_mods(keycode, CTRL_TO_SUPER)) return false;
}
break;
// Mac mode rewrites:
// Ctrl+Z/T/N -> Super+Z/T/N (undo, new tab, new window)
// Ctrl+Shift+Z/T/N -> Super+Shift+Z/T/N (redo, reopen tab, incognito)
case KC_Z:
case KC_T:
case KC_N:
if (mac_mode && record->event.pressed) {
if (rewrite_mods(keycode, CTRL_TO_SUPER)) return false;
if (rewrite_mods(keycode, CTRL_SHIFT_TO_CMD_SHIFT)) return false;
}
break;
// Mac mode rewrites:
// Ctrl+Alt+Left/Right -> Ctrl+Left/Right (switch workspace)
// Ctrl+Left/Right -> Alt+Left/Right (word navigation)
case KC_LEFT:
case KC_RGHT:
if (mac_mode && record->event.pressed) {
if (rewrite_mods(keycode, CTRL_ALT_TO_CTRL)) return false;
if (rewrite_mods(keycode, CTRL_TO_ALT)) return false;
}
break;
// Mac mode rewrites:
// Ctrl+Backspace -> Alt+Backspace (delete word backward)
case KC_BSPC:
if (mac_mode && record->event.pressed) {
if (rewrite_mods(keycode, CTRL_TO_ALT)) return false;
}
break;
// Mac mode rewrites:
// Home -> Super+Left (line start)
// End -> Super+Right (line end)
case KC_HOME:
if (mac_mode && record->event.pressed) {
if (rewrite_mods_and_key(NONE_TO_SUPER, KC_LEFT)) return false;
}
break;
case KC_END:
if (mac_mode && record->event.pressed) {
if (rewrite_mods_and_key(NONE_TO_SUPER, KC_RGHT)) return false;
}
break;
// Mac mode rewrites:
// Alt+F4 -> Super+Q (quit app)
case KC_F4:
if (mac_mode && record->event.pressed) {
if (rewrite_mods_and_key(ALT_TO_SUPER, KC_Q)) return false;
}
break;
// Mac mode rewrites:
// Alt+Tab -> Super+Tab (app switcher)
case KC_TAB:
if (mac_mode && record->event.pressed) {
if (rewrite_mods(keycode, ALT_TO_SUPER)) return false;
}
break;
// Workspace overview (both modes):
// Super+Up -> Super+W (KDE overview, linux)
// Super+Up -> Ctrl+Up (Mission Control, mac)
case KC_UP:
if (record->event.pressed) {
if (mac_mode) {
if (rewrite_mods(keycode, SUPER_TO_CTRL)) return false;
} else {
if (rewrite_mods_and_key(SUPER_TO_SUPER, KC_W)) return false;
}
}
break;
}
return true;
}
void matrix_init_user(void) {
// Force dynamic keymap reset so PROGMEM keymaps always take effect
dynamic_keymap_reset();
}