diff --git a/keymaps/custom/keymap.c b/keymaps/custom/keymap.c index 1e83406..90b7a15 100644 --- a/keymaps/custom/keymap.c +++ b/keymaps/custom/keymap.c @@ -1,10 +1,10 @@ #include QMK_KEYBOARD_H #include "keymap_introspection.h" #include "dynamic_keymap.h" -#include "mac_mode.h" +#include "os_mode.h" enum custom_keycodes { - CK_MCMD = SAFE_RANGE, // toggle mac-command mode + CK_OSMODE = SAFE_RANGE, // cycle OS mode }; typedef struct { @@ -121,7 +121,7 @@ ________________________________________________________________________________ */ [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, + 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_OSMODE, 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, @@ -130,7 +130,7 @@ ________________________________________________________________________________ ), [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, @@ -139,7 +139,7 @@ ________________________________________________________________________________ ), [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, @@ -148,62 +148,65 @@ ________________________________________________________________________________ ), }; -// Override layer resolution: in mac mode, any modifier forces layer 0 (ignores FN) +// Override layer resolution: 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))) { + if (os_mode != OS_MODE_NONE && get_mods()) { layer = 0; } - if (key.row < MATRIX_ROWS && key.col < MATRIX_COLS) { - return keycode_at_keymap_location(layer, key.row, key.col); - } - return KC_NO; + return keycode_at_keymap_location(layer, key.row, key.col); } -static bool gui_tapped = false; +static bool super_tapped = 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; + } + + // No rewrites in none mode + if (os_mode == OS_MODE_NONE) return true; + // 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; + super_tapped = false; } switch (keycode) { // Mac mode: tap Super -> Cmd+Space (Spotlight) - // Linux: tap Super passes through normally (KDE app menu) + // Linux/Windows: tap Super passes through normally (KDE app menu) case KC_LGUI: - if (mac_mode) { + if (os_mode == OS_MODE_MAC) { if (record->event.pressed) { - gui_tapped = true; + super_tapped = true; register_mods(MOD_BIT(KC_LGUI)); } else { - if (gui_tapped) { + if (super_tapped) { tap_code(KC_SPC); // GUI still held, sends Super+Space - gui_tapped = false; + super_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 (os_mode == OS_MODE_MAC && record->event.pressed) { if (rewrite_mods(keycode, CTRL_TO_SUPER)) return false; if (rewrite_mods(keycode, CTRL_SHIFT_TO_SUPER)) return false; } @@ -218,7 +221,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { case KC_W: case KC_L: case KC_R: - if (mac_mode && record->event.pressed) { + if (os_mode == OS_MODE_MAC && record->event.pressed) { if (rewrite_mods(keycode, CTRL_TO_SUPER)) return false; } break; @@ -228,7 +231,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { case KC_Z: case KC_T: case KC_N: - if (mac_mode && record->event.pressed) { + 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; } @@ -238,7 +241,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Ctrl+Left/Right -> Alt+Left/Right (word navigation) case KC_LEFT: case KC_RGHT: - if (mac_mode && record->event.pressed) { + 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; } @@ -246,7 +249,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Mac mode rewrites: // Ctrl+Backspace -> Alt+Backspace (delete word backward) case KC_BSPC: - if (mac_mode && record->event.pressed) { + if (os_mode == OS_MODE_MAC && record->event.pressed) { if (rewrite_mods(keycode, CTRL_TO_ALT)) return false; } break; @@ -254,38 +257,41 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Home -> Super+Left (line start) // End -> Super+Right (line end) case KC_HOME: - if (mac_mode && record->event.pressed) { + if (os_mode == OS_MODE_MAC && 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 (os_mode == OS_MODE_MAC && 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 (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 (mac_mode && record->event.pressed) { + if (os_mode == OS_MODE_MAC && 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) + // 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 (mac_mode) { + if (os_mode == OS_MODE_MAC) { if (rewrite_mods(keycode, SUPER_TO_CTRL)) return false; - } else { + } 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; diff --git a/keymaps/custom/mac_mode.h b/keymaps/custom/mac_mode.h deleted file mode 100644 index 148d337..0000000 --- a/keymaps/custom/mac_mode.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -extern bool mac_mode; -extern bool mac_mode_manual; diff --git a/keymaps/custom/os_detect.c b/keymaps/custom/os_detect.c index d736d93..b828701 100644 --- a/keymaps/custom/os_detect.c +++ b/keymaps/custom/os_detect.c @@ -2,28 +2,48 @@ #include "timer.h" #include "rgb_matrix.h" -#include "mac_mode.h" +#include "os_mode.h" -bool mac_mode = false; -bool mac_mode_manual = false; +os_mode_t os_mode = OS_MODE_NONE; +bool os_mode_manual = false; static bool os_detected = false; static uint32_t flash_start = 0; +static void flash_mode_color(void) { + 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; + } + flash_start = timer_read32(); +} + // Poll OS detection after USB enumeration settles (~2s) // Flash indicator color for 500ms then restore default animation void matrix_scan_user(void) { - if (!os_detected && !mac_mode_manual && timer_elapsed32(0) > 2000) { + if (!os_detected && !os_mode_manual && timer_elapsed32(0) > 2000) { os_detected = true; os_variant_t os = detected_host_os(); - mac_mode = (os == OS_MACOS || os == OS_IOS); - rgb_matrix_mode_noeeprom(RGB_MATRIX_SOLID_COLOR); - if (mac_mode) { - rgb_matrix_sethsv_noeeprom(HSV_GREEN); - } else { - rgb_matrix_sethsv_noeeprom(HSV_BLUE); + switch (os) { + case OS_MACOS: + case OS_IOS: + os_mode = OS_MODE_MAC; + break; + case OS_LINUX: + os_mode = OS_MODE_LINUX; + break; + case OS_WINDOWS: + os_mode = OS_MODE_WINDOWS; + break; + default: + os_mode = OS_MODE_NONE; + break; } - flash_start = timer_read32(); + flash_mode_color(); } + // Restore default RGB animation after 500ms indicator flash if (flash_start && timer_elapsed32(flash_start) > 500) { flash_start = 0; rgb_matrix_reload_from_eeprom(); diff --git a/keymaps/custom/os_mode.h b/keymaps/custom/os_mode.h new file mode 100644 index 0000000..3de621e --- /dev/null +++ b/keymaps/custom/os_mode.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +// Active OS mode, determines which shortcut rewrites are applied. +// Set automatically by OS detection or manually via FN+Del cycle. +typedef enum { + OS_MODE_NONE, // no shortcut rewrites + OS_MODE_LINUX, // linux-specific rewrites (e.g. Super+Up -> Super+W) + OS_MODE_MAC, // Ctrl->Super rewrites, Spotlight tap, etc. + OS_MODE_WINDOWS, // reserved, currently same as none +} os_mode_t; + +// Current mode, defined in os_detect.c +extern os_mode_t os_mode; + +// True once user manually cycles mode via FN+Del, prevents OS detection override +extern bool os_mode_manual;