#include QMK_KEYBOARD_H #include "keymap_introspection.h" #include "dynamic_keymap.h" #include "os_mode.h" #include "app_focus.h" // System76 per-layer RGB state (defined in system76_ec.c, declared in launch_3.c) extern rgb_config_t layer_rgb[]; void system76_ec_rgb_eeprom(bool write); enum custom_keycodes { CK_OSMODE = SAFE_RANGE, // cycle OS mode CK_RGBMOD, // cycle RGB animation CK_NOREMAP, // hold to bypass all remaps }; 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 }; static const mod_rewrite_t NONE_TO_CTRL = { 0, MOD_MASK_CTRL }; // 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. static bool mods_match(uint8_t mods, mod_rewrite_t rule) { 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 | NOREMAP | | 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, CK_NOREMAP, KC_LEFT, KC_DOWN, KC_RGHT ), /* Layer 1, function layer __________________________________________________________________________________________________________________________________ ________ | PRINT | | | | | | | | | | | | | || | | SCREEN | MUTE | VOL DN | VOL UP | | | | | | | | | | OS MODE || | |________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| | | PLAY/ | | | | | | | | | LED | LED | LED | LED || | | | PAUSE | PREV | NEXT | | | | | | | TOGGLE | DOWN | UP | MODE || | |________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| | | | | | | | | | | | | | | || | | | | | | | | | | | | | | | || | |____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________| | | | | | | | | | | | | | | | x | | | | | | | | | | | | PGUP | |________________|________|________|________|________|________|________|________|________|________|________|____________|________|_________ | | | | | | | | | | | | | | | x | | x | x | | | x | x | x | | HOME | PGDN | END | |____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________| */ [1] = LAYOUT( KC_PSCR, KC_MUTE, KC_VOLD, KC_VOLU, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, CK_OSMODE, KC_NO, KC_NO, KC_MPLY, KC_MPRV, KC_MNXT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_TOG, RGB_VAD, RGB_VAI, CK_RGBMOD, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, 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 ), }; static bool super_tapped = false; static bool no_remap = false; bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Cycle OS mode (FN+Del) if (keycode == CK_OSMODE) { if (record->event.pressed) { os_mode = (os_mode + 1) % 4; os_mode_manual = true; rgb_matrix_mode_noeeprom(RGB_MATRIX_SOLID_COLOR); switch (os_mode) { case OS_MODE_NONE: rgb_matrix_sethsv_noeeprom(HSV_RED); break; case OS_MODE_LINUX: rgb_matrix_sethsv_noeeprom(HSV_GREEN); break; case OS_MODE_MAC: rgb_matrix_sethsv_noeeprom(HSV_YELLOW); break; case OS_MODE_WINDOWS: rgb_matrix_sethsv_noeeprom(HSV_BLUE); break; } } return false; } // Cycle RGB animation (FN+Backspace) // Must update layer_rgb for all layers because system76_ec_rgb_layer() // resets rgb_matrix_config from layer_rgb on every layer change. if (keycode == CK_RGBMOD) { if (record->event.pressed) { uint8_t mode = layer_rgb[0].mode + 1; if (mode >= RGB_MATRIX_EFFECT_MAX) mode = 1; layer_rgb[0].mode = mode; rgb_matrix_mode_noeeprom(mode); system76_ec_rgb_eeprom(true); } return false; } // Hold CK_NOREMAP to bypass all remaps if (keycode == CK_NOREMAP) { no_remap = record->event.pressed; return false; } // No rewrites in none mode or when noremap held if (os_mode == OS_MODE_NONE || no_remap) return true; // Any other key pressed while GUI held means it's being used as a modifier if (record->event.pressed && keycode != KC_LGUI) { super_tapped = false; } switch (keycode) { // Mac mode: tap Super -> Cmd+Space (Spotlight) // Linux/Windows: tap Super passes through normally (KDE app menu) case KC_LGUI: if (os_mode == OS_MODE_MAC) { if (record->event.pressed) { super_tapped = true; register_mods(MOD_BIT(KC_LGUI)); } else { if (super_tapped) { tap_code(KC_SPC); // GUI still held, sends Super+Space super_tapped = false; } unregister_mods(MOD_BIT(KC_LGUI)); } return false; } break; // 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 (os_mode == OS_MODE_MAC && record->event.pressed) { if (rewrite_mods(keycode, CTRL_SHIFT_TO_SUPER)) return false; // Terminal: plain Ctrl+C/V passes through (SIGINT, etc.) if (focused_app != APP_TERMINAL) { if (rewrite_mods(keycode, CTRL_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 (os_mode == OS_MODE_MAC && 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 (os_mode == OS_MODE_MAC && 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 (os_mode == OS_MODE_MAC && 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 (os_mode == OS_MODE_MAC && 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 (os_mode == OS_MODE_MAC && record->event.pressed) { // Terminal: Home -> Ctrl+A (line start) if (focused_app == APP_TERMINAL) { if (rewrite_mods_and_key(NONE_TO_CTRL, KC_A)) return false; } if (rewrite_mods_and_key(NONE_TO_SUPER, KC_LEFT)) return false; } break; case KC_END: if (os_mode == OS_MODE_MAC && record->event.pressed) { // Terminal: End -> Ctrl+E (line end) if (focused_app == APP_TERMINAL) { if (rewrite_mods_and_key(NONE_TO_CTRL, KC_E)) return false; } 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 (os_mode == OS_MODE_MAC && 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 (os_mode == OS_MODE_MAC && record->event.pressed) { if (rewrite_mods(keycode, ALT_TO_SUPER)) return false; } break; // Workspace overview: // Super+Up -> Super+W (KDE overview, linux) // Super+Up -> Ctrl+Up (Mission Control, mac) // Super+Up -> Super+Tab (Task View, windows) case KC_UP: if (record->event.pressed) { if (os_mode == OS_MODE_MAC) { if (rewrite_mods(keycode, SUPER_TO_CTRL)) return false; } else if (os_mode == OS_MODE_LINUX) { if (rewrite_mods_and_key(SUPER_TO_SUPER, KC_W)) return false; } else if (os_mode == OS_MODE_WINDOWS) { if (rewrite_mods_and_key(SUPER_TO_SUPER, KC_TAB)) return false; } } break; } return true; } void matrix_init_user(void) { // Force dynamic keymap reset so PROGMEM keymaps always take effect dynamic_keymap_reset(); }