Add mac app agent and Terminal.app specific keybinds
This commit is contained in:
51
keymaps/custom/app_focus.c
Normal file
51
keymaps/custom/app_focus.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "raw_hid.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "app_focus.h"
|
||||
|
||||
#define CMD_SET_FOCUSED_APP 0x80
|
||||
#define APP_NAME_BUF_SIZE 64
|
||||
|
||||
focused_app_t focused_app = APP_UNKNOWN;
|
||||
|
||||
static char app_name_buf[APP_NAME_BUF_SIZE];
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
focused_app_t app;
|
||||
} app_mapping_t;
|
||||
|
||||
static const app_mapping_t app_map[] = {
|
||||
{ "Terminal", APP_TERMINAL },
|
||||
{ "iTerm2", APP_TERMINAL },
|
||||
{ "Xcode", APP_XCODE },
|
||||
{ "Code", APP_VSCODE }, // "Code" is VSCode's localizedName
|
||||
{ "Visual Studio Code", APP_VSCODE },
|
||||
};
|
||||
|
||||
static focused_app_t resolve_app(const char *name) {
|
||||
for (uint8_t i = 0; i < sizeof(app_map) / sizeof(app_map[0]); i++) {
|
||||
if (strcmp(name, app_map[i].name) == 0) {
|
||||
return app_map[i].app;
|
||||
}
|
||||
}
|
||||
return APP_UNKNOWN;
|
||||
}
|
||||
|
||||
// Called from system76_ec.c's raw_hid_receive (injected via sed at build time).
|
||||
// Returns true if the command was handled.
|
||||
bool app_focus_raw_hid_intercept(uint8_t *data, uint8_t length) {
|
||||
if (data[0] == CMD_SET_FOCUSED_APP) {
|
||||
uint8_t copy_len = length - 1;
|
||||
if (copy_len >= APP_NAME_BUF_SIZE) {
|
||||
copy_len = APP_NAME_BUF_SIZE - 1;
|
||||
}
|
||||
memcpy(app_name_buf, &data[1], copy_len);
|
||||
app_name_buf[copy_len] = '\0';
|
||||
focused_app = resolve_app(app_name_buf);
|
||||
data[1] = 0; // success
|
||||
raw_hid_send(data, length);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
15
keymaps/custom/app_focus.h
Normal file
15
keymaps/custom/app_focus.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
APP_UNKNOWN,
|
||||
APP_TERMINAL, // Terminal.app, iTerm2
|
||||
APP_XCODE,
|
||||
APP_VSCODE, // Visual Studio Code
|
||||
} focused_app_t;
|
||||
|
||||
extern focused_app_t focused_app;
|
||||
|
||||
bool app_focus_raw_hid_intercept(uint8_t *data, uint8_t length);
|
||||
@@ -2,6 +2,7 @@
|
||||
#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[];
|
||||
@@ -26,6 +27,7 @@ static const mod_rewrite_t ALT_TO_SUPER = { MOD_MASK_ALT,
|
||||
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.
|
||||
@@ -34,9 +36,9 @@ static uint8_t normalize_mods(uint8_t mods) {
|
||||
}
|
||||
|
||||
// Check if current mods exactly match a rule's `from` mods.
|
||||
// Returns false if FN layer is active (skip rewrites when FN is held).
|
||||
// Returns false if FN layer is active (skip rewrites when FN + any modifier is held).
|
||||
static bool mods_match(uint8_t mods, mod_rewrite_t rule) {
|
||||
if (layer_state_is(1)) return false;
|
||||
if (layer_state_is(1) && get_mods() != 0) return false;
|
||||
return normalize_mods(mods) == normalize_mods(rule.from);
|
||||
}
|
||||
|
||||
@@ -223,8 +225,11 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_C:
|
||||
case KC_V:
|
||||
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;
|
||||
// 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:
|
||||
@@ -274,11 +279,19 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
// 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;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
OS_DETECTION_ENABLE = yes
|
||||
SRC += os_detect.c
|
||||
SRC += app_focus.c
|
||||
|
||||
Reference in New Issue
Block a user