mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-04-09 08:21:27 -04:00
feat: add back switch_keybaord_layout
This commit is contained in:
parent
f06dc505e3
commit
c3a34f4ca6
2 changed files with 27 additions and 141 deletions
|
|
@ -846,83 +846,20 @@ int switch_keyboard_layout(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 分配并获取布局缩写
|
|
||||||
const char **layout_ids = calloc(num_layouts, sizeof(char *));
|
|
||||||
if (!layout_ids) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to allocate layout IDs");
|
|
||||||
goto cleanup_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < num_layouts; i++) {
|
|
||||||
layout_ids[i] =
|
|
||||||
get_layout_abbr(xkb_keymap_layout_get_name(keyboard->keymap, i));
|
|
||||||
if (!layout_ids[i]) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to get layout abbreviation");
|
|
||||||
goto cleanup_layouts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 安全地处理 rules.layout
|
|
||||||
struct xkb_rule_names rules = xkb_rules;
|
|
||||||
|
|
||||||
// 验证规则是否有效
|
|
||||||
if (!check_keyboard_rules_validate(&rules)) {
|
|
||||||
wlr_log(WLR_ERROR,
|
|
||||||
"Keyboard rules validation failed, skipping layout reset");
|
|
||||||
rules = xkb_default_rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 安全地处理 layout 字符串
|
// 安全地处理 layout 字符串
|
||||||
const char *current_layout = rules.layout;
|
const char *current_layout = xkb_rules.layout;
|
||||||
if (!current_layout || strlen(current_layout) == 0) {
|
if (!current_layout || strlen(current_layout) == 0) {
|
||||||
wlr_log(WLR_INFO, "Using default layout 'us'");
|
wlr_log(WLR_INFO, "Using default layout 'us'");
|
||||||
current_layout = "us";
|
current_layout = "us";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建足够大的缓冲区来构建新的布局字符串
|
|
||||||
unsigned int layout_buf_size =
|
|
||||||
1024; // 使用固定大小,避免依赖可能为NULL的字符串
|
|
||||||
char *layout_buf = calloc(layout_buf_size, sizeof(char));
|
|
||||||
if (!layout_buf) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to allocate layout buffer");
|
|
||||||
goto cleanup_layouts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建新的布局字符串
|
|
||||||
for (int i = 0; i < num_layouts; i++) {
|
|
||||||
const char *layout = layout_ids[(next + i) % num_layouts];
|
|
||||||
if (!layout)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
strncat(layout_buf, ",", layout_buf_size - strlen(layout_buf) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr(layout, ',')) {
|
|
||||||
// 处理包含逗号的布局名
|
|
||||||
char *quoted = malloc(strlen(layout) + 3);
|
|
||||||
if (quoted) {
|
|
||||||
snprintf(quoted, strlen(layout) + 3, "\"%s\"", layout);
|
|
||||||
strncat(layout_buf, quoted,
|
|
||||||
layout_buf_size - strlen(layout_buf) - 1);
|
|
||||||
free(quoted);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strncat(layout_buf, layout,
|
|
||||||
layout_buf_size - strlen(layout_buf) - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新 rules 结构体
|
|
||||||
rules.layout = layout_buf;
|
|
||||||
|
|
||||||
// 5. 创建新 keymap
|
// 5. 创建新 keymap
|
||||||
struct xkb_keymap *new_keymap =
|
struct xkb_keymap *new_keymap = xkb_keymap_new_from_names(
|
||||||
xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
context, &xkb_rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
if (!new_keymap) {
|
if (!new_keymap) {
|
||||||
wlr_log(WLR_ERROR, "Failed to create keymap for layouts: %s",
|
wlr_log(WLR_ERROR, "Failed to create keymap for layouts: %s",
|
||||||
rules.layout);
|
xkb_rules.layout);
|
||||||
goto cleanup_layout_buf;
|
goto cleanup_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 应用新 keymap
|
// 6. 应用新 keymap
|
||||||
|
|
@ -931,22 +868,34 @@ int switch_keyboard_layout(const Arg *arg) {
|
||||||
unsigned int locked = keyboard->modifiers.locked;
|
unsigned int locked = keyboard->modifiers.locked;
|
||||||
|
|
||||||
wlr_keyboard_set_keymap(keyboard, new_keymap);
|
wlr_keyboard_set_keymap(keyboard, new_keymap);
|
||||||
wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, 0);
|
wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, next);
|
||||||
keyboard->modifiers.group = 0;
|
keyboard->modifiers.group = 0;
|
||||||
|
|
||||||
// 7. 更新 seat
|
// 7. 更新 seat
|
||||||
wlr_seat_set_keyboard(seat, keyboard);
|
wlr_seat_set_keyboard(seat, keyboard);
|
||||||
wlr_seat_keyboard_notify_modifiers(seat, &keyboard->modifiers);
|
wlr_seat_keyboard_notify_modifiers(seat, &keyboard->modifiers);
|
||||||
|
|
||||||
|
InputDevice *id;
|
||||||
|
wl_list_for_each(id, &inputdevices, link) {
|
||||||
|
if (id->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard = (struct wlr_keyboard *)id->device_data;
|
||||||
|
|
||||||
|
wlr_keyboard_set_keymap(keyboard, new_keymap);
|
||||||
|
wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked,
|
||||||
|
next);
|
||||||
|
keyboard->modifiers.group = 0;
|
||||||
|
|
||||||
|
// 7. 更新 seat
|
||||||
|
wlr_seat_set_keyboard(seat, keyboard);
|
||||||
|
wlr_seat_keyboard_notify_modifiers(seat, &keyboard->modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
// 8. 清理资源
|
// 8. 清理资源
|
||||||
xkb_keymap_unref(new_keymap);
|
xkb_keymap_unref(new_keymap);
|
||||||
|
|
||||||
cleanup_layout_buf:
|
|
||||||
free(layout_buf);
|
|
||||||
|
|
||||||
cleanup_layouts:
|
|
||||||
free(layout_ids);
|
|
||||||
|
|
||||||
cleanup_context:
|
cleanup_context:
|
||||||
xkb_context_unref(context);
|
xkb_context_unref(context);
|
||||||
|
|
||||||
|
|
|
||||||
69
src/mango.c
69
src/mango.c
|
|
@ -697,7 +697,6 @@ static void resize_tile_client(Client *grabc, bool isdrag, int offsetx,
|
||||||
int offsety, unsigned int time);
|
int offsety, unsigned int time);
|
||||||
static void refresh_monitors_workspaces_status(Monitor *m);
|
static void refresh_monitors_workspaces_status(Monitor *m);
|
||||||
static void init_client_properties(Client *c);
|
static void init_client_properties(Client *c);
|
||||||
static bool check_keyboard_rules_validate(struct xkb_rule_names *rules);
|
|
||||||
|
|
||||||
#include "data/static_keymap.h"
|
#include "data/static_keymap.h"
|
||||||
#include "dispatch/bind_declare.h"
|
#include "dispatch/bind_declare.h"
|
||||||
|
|
@ -2323,18 +2322,9 @@ KeyboardGroup *createkeyboardgroup(void) {
|
||||||
group->wlr_group = wlr_keyboard_group_create();
|
group->wlr_group = wlr_keyboard_group_create();
|
||||||
group->wlr_group->data = group;
|
group->wlr_group->data = group;
|
||||||
|
|
||||||
// 4. 直接修改 rules.layout(保持原有逻辑)
|
|
||||||
struct xkb_rule_names rules = xkb_rules;
|
|
||||||
// 验证规则是否有效
|
|
||||||
if (!check_keyboard_rules_validate(&rules)) {
|
|
||||||
wlr_log(WLR_ERROR,
|
|
||||||
"Keyboard rules validation failed, skipping layout reset");
|
|
||||||
rules = xkb_default_rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare an XKB keymap and assign it to the keyboard group. */
|
/* Prepare an XKB keymap and assign it to the keyboard group. */
|
||||||
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
if (!(keymap = xkb_keymap_new_from_names(context, &rules,
|
if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
|
||||||
XKB_KEYMAP_COMPILE_NO_FLAGS)))
|
XKB_KEYMAP_COMPILE_NO_FLAGS)))
|
||||||
die("failed to compile keymap");
|
die("failed to compile keymap");
|
||||||
|
|
||||||
|
|
@ -4477,49 +4467,6 @@ void setgaps(int oh, int ov, int ih, int iv) {
|
||||||
arrange(selmon, false);
|
arrange(selmon, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证键盘规则是否有效
|
|
||||||
bool check_keyboard_rules_validate(struct xkb_rule_names *rules) {
|
|
||||||
if (!rules) {
|
|
||||||
wlr_log(WLR_ERROR, "Keyboard rules are NULL");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rules->layout || strlen(rules->layout) == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
||||||
if (!context) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to create XKB context for validation");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool valid = false;
|
|
||||||
struct xkb_keymap *test_keymap =
|
|
||||||
xkb_keymap_new_from_names(context, rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
|
|
||||||
if (test_keymap) {
|
|
||||||
// 检查keymap是否至少有一个布局
|
|
||||||
if (xkb_keymap_num_layouts(test_keymap) > 0) {
|
|
||||||
valid = true;
|
|
||||||
} else {
|
|
||||||
wlr_log(WLR_ERROR, "Keymap has no layouts");
|
|
||||||
}
|
|
||||||
xkb_keymap_unref(test_keymap);
|
|
||||||
} else {
|
|
||||||
wlr_log(WLR_ERROR,
|
|
||||||
"Invalid keyboard rules: rules=%s, model=%s, layout=%s, "
|
|
||||||
"variant=%s, options=%s",
|
|
||||||
rules->rules ? rules->rules : "NULL",
|
|
||||||
rules->model ? rules->model : "NULL",
|
|
||||||
rules->layout ? rules->layout : "NULL",
|
|
||||||
rules->variant ? rules->variant : "NULL",
|
|
||||||
rules->options ? rules->options : "NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
xkb_context_unref(context);
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_keyboard_layout(void) {
|
void reset_keyboard_layout(void) {
|
||||||
if (!kb_group || !kb_group->wlr_group || !seat) {
|
if (!kb_group || !kb_group->wlr_group || !seat) {
|
||||||
wlr_log(WLR_ERROR, "Invalid keyboard group or seat");
|
wlr_log(WLR_ERROR, "Invalid keyboard group or seat");
|
||||||
|
|
@ -4541,16 +4488,6 @@ void reset_keyboard_layout(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the same rules but just reapply them
|
|
||||||
struct xkb_rule_names rules = xkb_rules;
|
|
||||||
|
|
||||||
// 验证规则是否有效
|
|
||||||
if (!check_keyboard_rules_validate(&rules)) {
|
|
||||||
wlr_log(WLR_ERROR,
|
|
||||||
"Keyboard rules validation failed, skipping layout reset");
|
|
||||||
rules = xkb_default_rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create context
|
// Create context
|
||||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
|
|
@ -4559,8 +4496,8 @@ void reset_keyboard_layout(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 现在安全地创建真正的keymap
|
// 现在安全地创建真正的keymap
|
||||||
struct xkb_keymap *new_keymap =
|
struct xkb_keymap *new_keymap = xkb_keymap_new_from_names(
|
||||||
xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
context, &xkb_rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
if (!new_keymap) {
|
if (!new_keymap) {
|
||||||
// 理论上这里不应该失败,因为前面已经验证过了
|
// 理论上这里不应该失败,因为前面已经验证过了
|
||||||
wlr_log(WLR_ERROR,
|
wlr_log(WLR_ERROR,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue