diff --git a/src/config/parse_config.h b/src/config/parse_config.h index a559432..b2fd8eb 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -27,7 +27,6 @@ typedef struct { uint32_t keycode2; uint32_t keycode3; } MultiKeycode; - typedef struct { xkb_keysym_t keysym; MultiKeycode keycode; @@ -39,9 +38,7 @@ typedef struct { KeySymCode keysymcode; int32_t (*func)(const Arg *); Arg arg; - char mode[28]; - bool iscommonmode; - bool isdefaultmode; + int32_t keymode_idx; // 改为索引,指向config.keymodes数组 bool islockapply; bool isreleaseapply; bool ispassapply; @@ -353,7 +350,9 @@ typedef struct { struct xkb_rule_names xkb_rules; - char keymode[28]; + KeyMode *keymodes; // 动态数组,存储所有keymode + int32_t keymodes_count; // keymode数量 + int32_t current_keymode_idx; // 当前使用的keymode索引 struct xkb_context *ctx; struct xkb_keymap *keymap; @@ -364,6 +363,39 @@ Config config; void parse_config_file(Config *config, const char *file_path); +// 查找或添加keymode,返回索引 +int32_t find_or_add_keymode(Config *config, const char *name) { + // 检查是否已存在 + for (int32_t i = 0; i < config->keymodes_count; i++) { + if (strcmp(config->keymodes[i].name, name) == 0) { + return i; + } + } + + // 添加新的keymode + config->keymodes = realloc(config->keymodes, + (config->keymodes_count + 1) * sizeof(KeyMode)); + if (!config->keymodes) { + fprintf(stderr, "Failed to allocate memory for keymodes\n"); + return -1; + } + + KeyMode *new_mode = &config->keymodes[config->keymodes_count]; + new_mode->name = strdup(name); + new_mode->is_default = (strcmp(name, "default") == 0); + new_mode->is_common = (strcmp(name, "common") == 0); + + return config->keymodes_count++; // 返回索引,然后增加计数 +} + +// 设置当前keymode +void set_current_keymode(Config *config, const char *name) { + int32_t idx = find_or_add_keymode(config, name); + if (idx >= 0) { + config->current_keymode_idx = idx; + } +} + // Helper function to trim whitespace from start and end of a string void trim_whitespace(char *str) { if (str == NULL || *str == '\0') @@ -1204,7 +1236,7 @@ void run_exec_once() { bool parse_option(Config *config, char *key, char *value) { if (strcmp(key, "keymode") == 0) { - snprintf(config->keymode, sizeof(config->keymode), "%.27s", value); + set_current_keymode(config, value); } else if (strcmp(key, "animations") == 0) { config->animations = atoi(value); } else if (strcmp(key, "layer_animations") == 0) { @@ -2252,17 +2284,7 @@ bool parse_option(Config *config, char *key, char *value) { trim_whitespace(arg_value4); trim_whitespace(arg_value5); - strcpy(binding->mode, config->keymode); - if (strcmp(binding->mode, "common") == 0) { - binding->iscommonmode = true; - binding->isdefaultmode = false; - } else if (strcmp(binding->mode, "default") == 0) { - binding->isdefaultmode = true; - binding->iscommonmode = false; - } else { - binding->isdefaultmode = false; - binding->iscommonmode = false; - } + binding->keymode_idx = config->current_keymode_idx; parse_bind_flags(key, binding); binding->keysymcode = @@ -2983,6 +3005,16 @@ void free_config(void) { config.cursor_theme = NULL; } + if (config.keymodes) { + for (int32_t i = 0; i < config.keymodes_count; i++) { + free(config.keymodes[i].name); + } + free(config.keymodes); + config.keymodes = NULL; + config.keymodes_count = 0; + config.current_keymode_idx = -1; + } + // 释放 circle_layout free_circle_layout(&config); @@ -3342,6 +3374,9 @@ void set_value_default() { } void set_default_key_bindings(Config *config) { + // 确保common模式存在 + int32_t common_idx = find_or_add_keymode(config, "common"); + // 计算默认按键绑定的数量 size_t default_key_bindings_count = sizeof(default_key_bindings) / sizeof(KeyBinding); @@ -3359,8 +3394,10 @@ void set_default_key_bindings(Config *config) { for (size_t i = 0; i < default_key_bindings_count; i++) { config->key_bindings[config->key_bindings_count + i] = default_key_bindings[i]; - config->key_bindings[config->key_bindings_count + i].iscommonmode = - true; + // 设置keymode为common模式 + config->key_bindings[config->key_bindings_count + i].keymode_idx = + common_idx; + // 设置其他标志 config->key_bindings[config->key_bindings_count + i].islockapply = true; } @@ -3383,6 +3420,9 @@ void parse_config(void) { memset(&xkb_rules_options, 0, sizeof(xkb_rules_options)); // 初始化动态数组的指针为NULL,避免野指针 + config.keymodes = NULL; + config.keymodes_count = 0; + config.current_keymode_idx = -1; config.window_rules = NULL; config.window_rules_count = 0; config.monitor_rules = NULL; @@ -3410,7 +3450,6 @@ void parse_config(void) { config.tag_rules = NULL; config.tag_rules_count = 0; config.cursor_theme = NULL; - strcpy(config.keymode, "default"); create_config_keymap(); @@ -3437,6 +3476,7 @@ void parse_config(void) { set_value_default(); parse_config_file(&config, filename); + set_current_keymode(&config, "default"); set_default_key_bindings(&config); override_config(); } diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index c0e51dc..fbf1cd3 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -560,11 +560,17 @@ int32_t setlayout(const Arg *arg) { } int32_t setkeymode(const Arg *arg) { - snprintf(keymode.mode, sizeof(keymode.mode), "%.27s", arg->v); - if (strcmp(keymode.mode, "default") == 0) { - keymode.isdefault = true; + free(server.keymode.name); + server.keymode.name = strdup(arg->v); + if (strcmp(server.keymode.name, "default") == 0) { + server.keymode.is_default = true; } else { - keymode.isdefault = false; + server.keymode.is_default = false; + } + if (strcmp(server.keymode.name, "common") == 0) { + server.keymode.is_common = true; + } else { + server.keymode.is_common = false; } printstatus(); return 1; diff --git a/src/ext-protocol/dwl-ipc.h b/src/ext-protocol/dwl-ipc.h index ab0bdb8..ed93c95 100644 --- a/src/ext-protocol/dwl-ipc.h +++ b/src/ext-protocol/dwl-ipc.h @@ -202,7 +202,7 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) { if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_KEYMODE_SINCE_VERSION) { - zdwl_ipc_output_v2_send_keymode(ipc_output->resource, keymode.mode); + zdwl_ipc_output_v2_send_keymode(ipc_output->resource, server.keymode.name); } if (wl_resource_get_version(ipc_output->resource) >= diff --git a/src/mango.c b/src/mango.c index 591d4f6..12ee9ee 100644 --- a/src/mango.c +++ b/src/mango.c @@ -234,6 +234,12 @@ typedef struct { uint32_t ui2; } Arg; +typedef struct { + char *name; // keymode名称 + bool is_default; // 是否为默认模式 + bool is_common; // 是否为公共模式 +} KeyMode; + typedef struct { uint32_t mod; uint32_t button; @@ -241,11 +247,6 @@ typedef struct { const Arg arg; } Button; // 鼠标按键 -typedef struct { - char mode[28]; - bool isdefault; -} KeyMode; - typedef struct { uint32_t mod; uint32_t dir; @@ -538,7 +539,13 @@ typedef struct { struct wl_listener destroy; } SessionLock; +typedef struct { + KeyMode keymode; +} Server; + /* function declarations */ +static void init_server(void); +static void free_server(void); static void applybounds( Client *c, struct wlr_box *bbox); // 设置边界规则,能让一些窗口拥有比较适合的大小 @@ -785,6 +792,7 @@ static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc); #include "layout/layout.h" /* variables */ +Server server; static const char broken[] = "broken"; static pid_t child_pid = -1; static int32_t locked; @@ -879,10 +887,7 @@ static struct wl_event_source *hide_source; static bool cursor_hidden = false; static bool tag_combo = false; static const char *cli_config_path = NULL; -static KeyMode keymode = { - .mode = {'d', 'e', 'f', 'a', 'u', 'l', 't', '\0'}, - .isdefault = true, -}; + static struct { enum wp_cursor_shape_device_v1_shape shape; struct wlr_surface *surface; @@ -967,6 +972,16 @@ static struct wlr_xwayland *xwayland; #include "layout/horizontal.h" #include "layout/vertical.h" +void init_server() { + server.keymode = (KeyMode){ + .is_default = true, + .is_common = false, + .name = strdup("default"), + }; +} + +void free_server() { free(server.keymode.name); } + void client_change_mon(Client *c, Monitor *m) { setmon(c, m, c->tags, true); if (c->isfloating) { @@ -2162,6 +2177,8 @@ void cleanup(void) { /* Destroy after the wayland display (when the monitors are already destroyed) to avoid destroying them with an invalid scene output. */ wlr_scene_node_destroy(&scene->tree.node); + + free_server(); } void cleanupmon(struct wl_listener *listener, void *data) { @@ -3489,6 +3506,7 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym, const KeyBinding *k; int32_t ji; int32_t isbreak = 0; + KeyMode bind_keymode; // not allow modifier keys to be used as a keybinding if (keycode == 50 || keycode == 37 || keycode == 133 || keycode == 64 || @@ -3519,8 +3537,11 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym, continue; k = &config.key_bindings[ji]; - if ((k->iscommonmode || (k->isdefaultmode && keymode.isdefault) || - (strcmp(keymode.mode, k->mode) == 0)) && + bind_keymode = config.keymodes[k->keymode_idx]; + + if ((bind_keymode.is_common || + (bind_keymode.is_default && server.keymode.is_default) || + (strcmp(server.keymode.name, bind_keymode.name) == 0)) && CLEANMASK(mods) == CLEANMASK(k->mod) && ((k->keysymcode.type == KEY_TYPE_SYM && xkb_keysym_to_lower(sym) == @@ -5119,6 +5140,7 @@ void setup(void) { setenv("XCURSOR_SIZE", "24", 1); setenv("XDG_CURRENT_DESKTOP", "mango", 1); + init_server(); parse_config(); init_baked_points();