opt: change keymode length not limit

This commit is contained in:
DreamMaoMao 2026-02-04 18:39:29 +08:00
parent 65fcd58949
commit 0b35b00f91
4 changed files with 104 additions and 36 deletions

View file

@ -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();
}

View file

@ -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;

View file

@ -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) >=

View file

@ -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();