This commit is contained in:
DreamMaoMao 2026-02-11 11:59:08 +08:00
parent 8a1f3597e1
commit a2b6ab3e54
4 changed files with 196 additions and 10 deletions

View file

@ -111,6 +111,13 @@ typedef struct {
int32_t vrr; // variable refresh rate
} ConfigMonitorRule;
typedef struct {
const char *name;
int32_t vendor, product;
struct xkb_keymap *keymap;
struct xkb_context *ctx;
} ConfigKeyboardRule;
// 修改后的宏定义
#define CHVT(n) \
{ \
@ -321,6 +328,9 @@ typedef struct {
ConfigMonitorRule *monitor_rules; // 动态数组
int32_t monitor_rules_count; // 条数
ConfigKeyboardRule *keyboard_rules; // 动态数组
int32_t keyboard_rules_count; // 条数
KeyBinding *key_bindings;
int32_t key_bindings_count;
@ -1840,6 +1850,113 @@ bool parse_option(Config *config, char *key, char *value) {
config->monitor_rules_count++;
return !parse_error;
} else if (strcmp(key, "keyboardrule") == 0) {
config->keyboard_rules =
realloc(config->keyboard_rules, (config->keyboard_rules_count + 1) *
sizeof(ConfigKeyboardRule));
if (!config->keyboard_rules) {
fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Failed to allocate "
"memory for keyboard rules\n");
return false;
}
ConfigKeyboardRule *rule =
&config->keyboard_rules[config->keyboard_rules_count];
memset(rule, 0, sizeof(ConfigKeyboardRule));
// 设置默认值
rule->vendor = -1;
rule->product = -1;
rule->keymap = NULL;
char rule_xkb_rules_rules[256];
char rule_xkb_rules_model[256];
char rule_xkb_rules_layout[256];
char rule_xkb_rules_variant[256];
char rule_xkb_rules_options[256];
strcpy(rule_xkb_rules_rules, xkb_rules_rules);
strcpy(rule_xkb_rules_model, xkb_rules_model);
strcpy(rule_xkb_rules_layout, xkb_rules_layout);
strcpy(rule_xkb_rules_variant, xkb_rules_variant);
strcpy(rule_xkb_rules_options, xkb_rules_options);
bool parse_error = false;
char *token = strtok(value, ",");
while (token != NULL) {
char *colon = strchr(token, ':');
if (colon != NULL) {
*colon = '\0';
char *key = token;
char *val = colon + 1;
trim_whitespace(key);
trim_whitespace(val);
if (strcmp(key, "vendor") == 0) {
rule->vendor = atoi(val);
} else if (strcmp(key, "product") == 0) {
rule->product = atoi(val);
} else if (strcmp(key, "name") == 0) {
rule->name = strdup(val);
} else if (strcmp(key, "xkb_rules_rules") == 0) {
strcpy(rule_xkb_rules_rules, val);
rule_xkb_rules_rules[sizeof(rule_xkb_rules_rules) - 1] =
'\0'; // 确保字符串以 null 结尾
} else if (strcmp(key, "xkb_rules_model") == 0) {
strcpy(rule_xkb_rules_model, val);
rule_xkb_rules_model[sizeof(rule_xkb_rules_model) - 1] =
'\0'; // 确保字符串以 null 结尾
} else if (strcmp(key, "xkb_rules_layout") == 0) {
strcpy(rule_xkb_rules_layout, val);
rule_xkb_rules_layout[sizeof(rule_xkb_rules_layout) - 1] =
'\0'; // 确保字符串以 null 结尾
} else if (strcmp(key, "xkb_rules_variant") == 0) {
strcpy(rule_xkb_rules_variant, val);
rule_xkb_rules_variant[sizeof(rule_xkb_rules_variant) - 1] =
'\0'; // 确保字符串以 null 结尾
} else if (strcmp(key, "xkb_rules_options") == 0) {
strcpy(rule_xkb_rules_options, val);
rule_xkb_rules_options[sizeof(rule_xkb_rules_options) - 1] =
'\0'; // 确保字符串以 null 结尾
} else {
fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Unknown "
"keyboard rule "
"option:\033[1m\033[31m %s\n",
key);
parse_error = true;
}
}
token = strtok(NULL, ",");
}
struct xkb_rule_names rule_xkb_rules = {
.rules = (rule_xkb_rules_rules[0] == '\0') ? NULL : rule_xkb_rules_rules,
.model = (rule_xkb_rules_model[0] == '\0') ? NULL : rule_xkb_rules_model,
.layout = (rule_xkb_rules_layout[0] == '\0') ? NULL : rule_xkb_rules_layout,
.variant = (rule_xkb_rules_variant[0] == '\0') ? NULL : rule_xkb_rules_variant,
.options = (rule_xkb_rules_options[0] == '\0') ? NULL : rule_xkb_rules_options,
};
rule->ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
rule->keymap = xkb_keymap_new_from_names(rule->ctx, &rule_xkb_rules,
XKB_KEYMAP_COMPILE_NO_FLAGS);
// 添加调试信息
fprintf(stderr, "\033[1m\033[32m[DEBUG]:\033[0m Created keymap: %p\n", (void*)rule->keymap);
if (rule->keymap) {
fprintf(stderr, " Keymap created successfully.\n");
} else {
fprintf(stderr, " Failed to create keymap.\n");
// 可以尝试获取更多错误信息
// xkb_context_get_log_string(rule->ctx) 可能会提供错误信息
}
config->keyboard_rules_count++;
return !parse_error;
} else if (strcmp(key, "tagrule") == 0) {
config->tag_rules =
realloc(config->tag_rules,
@ -2976,6 +3093,21 @@ void free_config(void) {
config.monitor_rules_count = 0;
}
// 释放 keyboard_rules
if (config.keyboard_rules) {
for (int32_t i = 0; i < config.keyboard_rules_count; i++) {
if (config.keyboard_rules[i].name)
free((void *)config.keyboard_rules[i].name);
if (config.keyboard_rules[i].ctx)
xkb_context_unref(config.keyboard_rules[i].ctx);
if (config.keyboard_rules[i].keymap)
xkb_keymap_unref(config.keyboard_rules[i].keymap);
}
free(config.keyboard_rules);
config.keyboard_rules = NULL;
config.keyboard_rules_count = 0;
}
// 释放 layer_rules
if (config.layer_rules) {
for (int32_t i = 0; i < config.layer_rules_count; i++) {
@ -3443,6 +3575,8 @@ bool parse_config(void) {
config.window_rules_count = 0;
config.monitor_rules = NULL;
config.monitor_rules_count = 0;
config.keyboard_rules = NULL;
config.keyboard_rules_count = 0;
config.key_bindings = NULL;
config.key_bindings_count = 0;
config.mouse_bindings = NULL;

View file

@ -150,20 +150,20 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
}
active_kb = get_active_keyboard_device();
if(active_kb) {
sprintf(active_kb_name, "vendor:%d,product:%d,name:%s", active_kb->vendor, active_kb->product, active_kb->name);
if (active_kb) {
sprintf(active_kb_name, "vendor:%d,product:%d,name:%s",
active_kb->vendor, active_kb->product, active_kb->name);
} else {
sprintf(active_kb_name, "-1 -1 unknown");
}
keyboard = active_kb ? (struct wlr_keyboard*)active_kb->device_data: &kb_group->wlr_group->keyboard;
keyboard = active_kb ? (struct wlr_keyboard *)active_kb->device_data
: &kb_group->wlr_group->keyboard;
current = xkb_state_serialize_layout(keyboard->xkb_state,
XKB_STATE_LAYOUT_EFFECTIVE);
get_layout_abbr(kb_layout,
xkb_keymap_layout_get_name(keyboard->keymap, current));
zdwl_ipc_output_v2_send_layout(
ipc_output->resource,
monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts);

View file

@ -129,13 +129,13 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
*pl = l;
}
InputDevice * get_active_keyboard_device(void) {
InputDevice *get_active_keyboard_device(void) {
InputDevice *id;
wl_list_for_each(id, &inputdevices, link) {
if (id->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
continue;
}
if (id->isactivate) {
return id;
}

View file

@ -786,7 +786,9 @@ static Client *get_scroll_stack_head(Client *c);
static bool client_only_in_one_tag(Client *c);
static Client *get_focused_stack_client(Client *sc);
static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc);
static InputDevice * get_active_keyboard_device(void);
static InputDevice *get_active_keyboard_device(void);
static bool apply_keyboard_rules(InputDevice *id,
struct wlr_keyboard *keyboard);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"
@ -2560,9 +2562,52 @@ void createidleinhibitor(struct wl_listener *listener, void *data) {
checkidleinhibitor(NULL);
}
bool apply_keyboard_rules(InputDevice *id, struct wlr_keyboard *keyboard) {
int ji = 0;
ConfigKeyboardRule *r;
bool match_rule = true;
if (id->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
return false;
}
for (ji = 0; ji < config.keyboard_rules_count; ji++) {
if (config.keyboard_rules_count < 1)
break;
r = &config.keyboard_rules[ji];
if (r->vendor != -1) {
if (r->vendor != id->vendor) {
match_rule = false;
}
}
if (r->product != -1) {
if (r->product != id->product) {
match_rule = false;
}
}
if (r->name != NULL) {
if (strcmp(r->name, id->name) != 0) {
match_rule = false;
}
}
if (match_rule) {
wlr_keyboard_set_keymap(keyboard, r->keymap);
return true;
}
}
return false;
}
void createkeyboard(struct wlr_keyboard *keyboard) {
struct libinput_device *device = NULL;
bool hit_rule = false;
if (wlr_input_device_is_libinput(&keyboard->base) &&
(device = wlr_libinput_get_device_handle(&keyboard->base))) {
@ -2592,10 +2637,13 @@ void createkeyboard(struct wlr_keyboard *keyboard) {
wl_signal_add(&keyboard->events.key, &input_dev->source_keyboard_key);
wl_list_insert(&inputdevices, &input_dev->link);
hit_rule = apply_keyboard_rules(input_dev, keyboard);
}
/* Set the keymap to match the group keymap */
wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap);
if (!hit_rule)
wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap);
wlr_keyboard_notify_modifiers(keyboard, 0, 0, locked_mods, 0);
@ -5084,7 +5132,11 @@ void reset_keyboard_layout(void) {
struct wlr_keyboard *tkb = (struct wlr_keyboard *)id->device_data;
wlr_keyboard_set_keymap(tkb, keyboard->keymap);
bool hit_rules = apply_keyboard_rules(id, tkb);
if (!hit_rules)
wlr_keyboard_set_keymap(tkb, keyboard->keymap);
wlr_keyboard_notify_modifiers(tkb, depressed, latched, locked, 0);
tkb->modifiers.group = 0;