bindings, Ctrl+Shift word selection, and Ctrl-as-Cmd for mouse clicks in Xcode/VSCode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
369 lines
21 KiB
C
369 lines
21 KiB
C
#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
|
|
};
|
|
|
|
// --- Remap rules engine -------------------------------------------------
|
|
//
|
|
// Each rule defines a single key remap: when the trigger key is pressed with
|
|
// exactly the specified modifiers, on a matching OS and focused app, the
|
|
// modifiers are swapped and (optionally) the keycode is changed.
|
|
//
|
|
// Rules are evaluated in order; the first match wins.
|
|
|
|
// OS match bitmasks
|
|
#define OS_ANY 0xFF
|
|
#define OS_LINUX (1 << OS_MODE_LINUX)
|
|
#define OS_MAC (1 << OS_MODE_MAC)
|
|
#define OS_WIN (1 << OS_MODE_WINDOWS)
|
|
|
|
// App match bitmasks
|
|
#define APP_ANY 0xFF
|
|
#define APP(a) (1 << (a))
|
|
#define APP_NOT(a) (APP_ANY & ~APP(a))
|
|
|
|
// Rule flags
|
|
#define RULE_CANCEL_ON_KEYPRESS (1 << 0) // teardown rewrite if any other key is pressed
|
|
|
|
typedef struct {
|
|
uint8_t os_mask; // bitmask of OS modes that match
|
|
uint8_t app_mask; // bitmask of focused apps that match
|
|
uint8_t mods_from; // required modifiers (exact match after normalization)
|
|
uint16_t key_from; // trigger keycode
|
|
uint8_t mods_to; // replacement modifiers
|
|
uint16_t key_to; // output keycode (0 = same as trigger key)
|
|
uint8_t flags; // RULE_* flags (0 for most rules via partial init)
|
|
} remap_rule_t;
|
|
|
|
static const remap_rule_t remap_rules[] = {
|
|
// --- Ctrl -> Cmd for mouse clicks (Xcode/VSCode on Mac) ---
|
|
// Registers Cmd while Ctrl is held alone; any keyboard key cancels it.
|
|
// Enables Cmd+click (jump to symbol) via the Ctrl key.
|
|
{ OS_MAC, APP(APP_XCODE) | APP(APP_VSCODE), 0, KC_LCTL, 0, KC_LGUI, RULE_CANCEL_ON_KEYPRESS },
|
|
{ OS_MAC, APP(APP_XCODE) | APP(APP_VSCODE), 0, KC_RCTL, 0, KC_LGUI, RULE_CANCEL_ON_KEYPRESS },
|
|
|
|
// --- Text editing (Mac) ---
|
|
// Ctrl+Shift+C/V -> copy/paste (Cmd on Mac, Ctrl on Linux/Windows)
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_C, MOD_MASK_GUI, 0 },
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_V, MOD_MASK_GUI, 0 },
|
|
// Ctrl+C/V -> Cmd+C/V (not in terminal — let Ctrl+C = SIGINT through)
|
|
{ OS_MAC, APP_NOT(APP_TERMINAL), MOD_MASK_CTRL, KC_C, MOD_MASK_GUI, 0 },
|
|
{ OS_MAC, APP_NOT(APP_TERMINAL), MOD_MASK_CTRL, KC_V, MOD_MASK_GUI, 0 },
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_X, MOD_MASK_GUI, 0 }, // cut
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_A, MOD_MASK_GUI, 0 }, // select all
|
|
{ OS_MAC, APP_NOT(APP_TERMINAL), MOD_MASK_CTRL, KC_D, MOD_MASK_GUI, 0 }, // bookmark / select next occurrence
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_F, MOD_MASK_GUI, 0 }, // find
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_F, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // find in files
|
|
// Word navigation: Ctrl(+Shift)+Left/Right -> Alt(+Shift)+Left/Right
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_LEFT, MOD_MASK_ALT | MOD_MASK_SHIFT, 0 }, // select word left
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_RGHT, MOD_MASK_ALT | MOD_MASK_SHIFT, 0 }, // select word right
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_LEFT, MOD_MASK_ALT, 0 }, // word left
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_RGHT, MOD_MASK_ALT, 0 }, // word right
|
|
// Delete word: Ctrl+Backspace -> Alt+Backspace
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_BSPC, MOD_MASK_ALT, 0 },
|
|
// Home/End: terminal -> Ctrl+A/E, general -> Cmd+Left/Right
|
|
{ OS_MAC, APP(APP_TERMINAL), 0, KC_HOME, MOD_MASK_CTRL, KC_A },
|
|
{ OS_MAC, APP(APP_TERMINAL), 0, KC_END, MOD_MASK_CTRL, KC_E },
|
|
{ OS_MAC, APP_ANY, 0, KC_HOME, MOD_MASK_GUI, KC_LEFT },
|
|
{ OS_MAC, APP_ANY, 0, KC_END, MOD_MASK_GUI, KC_RGHT },
|
|
|
|
// --- Common Ctrl -> Cmd shortcuts (Mac) ---
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_S, MOD_MASK_GUI, 0 }, // save
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_W, MOD_MASK_GUI, 0 }, // close tab
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_L, MOD_MASK_GUI, 0 }, // address bar
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_R, MOD_MASK_GUI, 0 }, // reload
|
|
{ OS_MAC, APP(APP_XCODE), MOD_MASK_CTRL, KC_P, MOD_MASK_GUI | MOD_MASK_SHIFT, KC_O }, // Xcode: Open Quickly
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_P, MOD_MASK_GUI, 0 }, // print / quick open
|
|
{ OS_MAC, APP(APP_XCODE), MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_P, MOD_MASK_GUI | MOD_MASK_SHIFT, KC_A }, // Xcode: Quick Actions
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_P, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // command palette
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_Z, MOD_MASK_GUI, 0 }, // undo
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_Z, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // redo
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_T, MOD_MASK_GUI, 0 }, // new tab
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_T, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // reopen tab
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_N, MOD_MASK_GUI, 0 }, // new window
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_N, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // incognito
|
|
|
|
// --- Workspace switching (Mac) ---
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_ALT, KC_LEFT, MOD_MASK_CTRL, 0 }, // switch workspace left
|
|
{ OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_ALT, KC_RGHT, MOD_MASK_CTRL, 0 }, // switch workspace right
|
|
|
|
// --- Alt+F4 -> Cmd+Q (Mac) ---
|
|
{ OS_MAC, APP_ANY, MOD_MASK_ALT, KC_F4, MOD_MASK_GUI, KC_Q },
|
|
|
|
// --- Alt+Tab -> Cmd+Tab (Mac) ---
|
|
{ OS_MAC, APP_ANY, MOD_MASK_ALT, KC_TAB, MOD_MASK_GUI, 0 },
|
|
|
|
// --- Workspace overview (all OS) ---
|
|
{ OS_MAC, APP_ANY, MOD_MASK_GUI, KC_UP, MOD_MASK_CTRL, 0 }, // Mission Control
|
|
{ OS_LINUX, APP_ANY, MOD_MASK_GUI, KC_UP, MOD_MASK_GUI, KC_W }, // KDE overview
|
|
{ OS_WIN, APP_ANY, MOD_MASK_GUI, KC_UP, MOD_MASK_GUI, KC_TAB }, // Task View
|
|
};
|
|
|
|
// --- Modifier normalization ----------------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
// --- Active rewrite tracking (hold-to-repeat support) --------------------
|
|
//
|
|
// register_code() keeps the key held for auto-repeat. This struct tracks the
|
|
// state needed to clean up correctly on release. Only one rewrite can be
|
|
// active at a time (only one key auto-repeats).
|
|
typedef struct {
|
|
uint16_t trigger_keycode; // physical key (e.g. KC_LEFT) -- 0 when inactive
|
|
uint8_t output_keycode; // key registered with host (may differ from trigger)
|
|
uint8_t from_mods; // normalized mods that were removed
|
|
uint8_t to_mods; // normalized mods that were added
|
|
uint8_t saved_mods; // exact get_mods() at press time, for restoration
|
|
// updated as from-mods are released during hold
|
|
uint8_t flags; // propagated from remap_rule_t
|
|
} active_rewrite_t;
|
|
|
|
static active_rewrite_t active_rw = {0};
|
|
|
|
// Undo an active rewrite: restore saved modifiers and unregister the held key.
|
|
static void teardown_active_rewrite(void) {
|
|
if (!active_rw.trigger_keycode) return;
|
|
set_mods(active_rw.saved_mods);
|
|
unregister_code(active_rw.output_keycode);
|
|
active_rw.trigger_keycode = 0;
|
|
}
|
|
|
|
// Intercept release events for active rewrites.
|
|
// 1. Rewritten key released -> clean up via teardown.
|
|
// 2. Original modifier released while key held -> remove from saved_mods.
|
|
// Returns false to consume the event, true to continue normal processing.
|
|
static bool process_rewrite_release(uint16_t keycode, keyrecord_t *record) {
|
|
if (!active_rw.trigger_keycode) return true;
|
|
if (!record->event.pressed) {
|
|
if (keycode == active_rw.trigger_keycode) {
|
|
teardown_active_rewrite();
|
|
return false;
|
|
}
|
|
if (IS_MODIFIER_KEYCODE(keycode) &&
|
|
(normalize_mods(MOD_BIT(keycode)) & active_rw.from_mods)) {
|
|
active_rw.saved_mods &= ~MOD_BIT(keycode);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Apply a rewrite unconditionally (matching already done by caller).
|
|
static void apply_rewrite(uint16_t trigger_keycode, uint8_t mods_from, uint8_t mods_to, uint16_t key_out, uint8_t flags) {
|
|
uint8_t mods = get_mods();
|
|
if (active_rw.trigger_keycode) teardown_active_rewrite();
|
|
active_rw = (active_rewrite_t){
|
|
.trigger_keycode = trigger_keycode,
|
|
.output_keycode = key_out,
|
|
.from_mods = normalize_mods(mods_from),
|
|
.to_mods = normalize_mods(mods_to),
|
|
.saved_mods = mods,
|
|
.flags = flags,
|
|
};
|
|
set_mods(active_rw.to_mods);
|
|
register_code(key_out);
|
|
}
|
|
|
|
// Walk the rule table; first matching rule wins.
|
|
static bool apply_remap_rules(uint16_t keycode) {
|
|
uint8_t norm = normalize_mods(get_mods());
|
|
for (uint8_t i = 0; i < sizeof(remap_rules) / sizeof(remap_rules[0]); i++) {
|
|
const remap_rule_t *r = &remap_rules[i];
|
|
if (r->key_from != keycode) continue;
|
|
if (!((1 << os_mode) & r->os_mask)) continue;
|
|
if (!((1 << focused_app) & r->app_mask)) continue;
|
|
if (norm != normalize_mods(r->mods_from)) continue;
|
|
apply_rewrite(keycode, r->mods_from, r->mods_to, r->key_to ? r->key_to : keycode, r->flags);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// --- Keymaps -------------------------------------------------------------
|
|
|
|
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 | NOREMAP | | 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, CK_NOREMAP, 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) {
|
|
// Safety: no rewrites in none mode
|
|
if (os_mode == OS_MODE_NONE) return true;
|
|
|
|
// Cycle OS mode (FN+Del)
|
|
if (keycode == CK_OSMODE) {
|
|
if (record->event.pressed) {
|
|
teardown_active_rewrite();
|
|
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)
|
|
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;
|
|
if (no_remap) teardown_active_rewrite();
|
|
return false;
|
|
}
|
|
|
|
// No rewrites when noremap held
|
|
if (no_remap) return true;
|
|
|
|
// Handle release events for active modifier rewrites (key repeat support)
|
|
if (!process_rewrite_release(keycode, record)) return false;
|
|
|
|
// Cancel modifier-only rewrites (e.g. Ctrl->Cmd) when any other key is pressed
|
|
if (record->event.pressed && active_rw.trigger_keycode &&
|
|
(active_rw.flags & RULE_CANCEL_ON_KEYPRESS) &&
|
|
keycode != active_rw.trigger_keycode) {
|
|
teardown_active_rewrite();
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Mac: tap Super -> Cmd+Space (Spotlight)
|
|
if (keycode == KC_LGUI && 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);
|
|
super_tapped = false;
|
|
}
|
|
unregister_mods(MOD_BIT(KC_LGUI));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Apply remap rules on key press
|
|
if (record->event.pressed) {
|
|
if (apply_remap_rules(keycode)) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void matrix_init_user(void) {
|
|
// Force dynamic keymap reset so PROGMEM keymaps always take effect
|
|
dynamic_keymap_reset();
|
|
}
|