From 4ee55fc0ba23c2acf201abb4eb1f8adb65b21107 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 1 Nov 2025 19:06:04 +0800 Subject: [PATCH] feat: add back switch_keybaord_layout --- src/config/parse_config.h | 2 + src/dispatch/bind_declare.h | 1 + src/dispatch/bind_define.h | 86 +++++++++++++++++++++++++++++++++++++ src/mango.c | 1 - 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 04bdfbd..85fe57c 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -908,6 +908,8 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "setkeymode") == 0) { func = setkeymode; (*arg).v = strdup(arg_value); + } else if (strcmp(func_name, "switch_keyboard_layout") == 0) { + func = switch_keyboard_layout; } else if (strcmp(func_name, "setlayout") == 0) { func = setlayout; (*arg).v = strdup(arg_value); diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index a1dfbad..b38e2da 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -25,6 +25,7 @@ int spawn(const Arg *arg); int spawn_shell(const Arg *arg); int spawn_on_empty(const Arg *arg); int setkeymode(const Arg *arg); +int switch_keyboard_layout(const Arg *arg); int setlayout(const Arg *arg); int switch_layout(const Arg *arg); int setmfact(const Arg *arg); diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 7342eee..664048e 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -817,6 +817,92 @@ int spawn_on_empty(const Arg *arg) { return 0; } +int switch_keyboard_layout(const Arg *arg) { + if (!kb_group || !kb_group->wlr_group || !seat) { + wlr_log(WLR_ERROR, "Invalid keyboard group or seat"); + return 0; + } + + struct wlr_keyboard *keyboard = &kb_group->wlr_group->keyboard; + if (!keyboard || !keyboard->keymap) { + wlr_log(WLR_ERROR, "Invalid keyboard or keymap"); + return 0; + } + + // 1. 获取当前布局和计算下一个布局 + xkb_layout_index_t current = xkb_state_serialize_layout( + keyboard->xkb_state, XKB_STATE_LAYOUT_EFFECTIVE); + const int num_layouts = xkb_keymap_num_layouts(keyboard->keymap); + if (num_layouts < 2) { + wlr_log(WLR_INFO, "Only one layout available"); + return 0; + } + xkb_layout_index_t next = (current + 1) % num_layouts; + + // 2. 创建上下文 + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!context) { + wlr_log(WLR_ERROR, "Failed to create XKB context"); + return 0; + } + + // 安全地处理 layout 字符串 + const char *current_layout = xkb_rules.layout; + if (!current_layout || strlen(current_layout) == 0) { + wlr_log(WLR_INFO, "Using default layout 'us'"); + current_layout = "us"; + } + + // 5. 创建新 keymap + struct xkb_keymap *new_keymap = xkb_keymap_new_from_names( + context, &xkb_rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!new_keymap) { + wlr_log(WLR_ERROR, "Failed to create keymap for layouts: %s", + xkb_rules.layout); + goto cleanup_context; + } + + // 6. 应用新 keymap + unsigned int depressed = keyboard->modifiers.depressed; + unsigned int latched = keyboard->modifiers.latched; + unsigned int locked = keyboard->modifiers.locked; + + 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); + + 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. 清理资源 + xkb_keymap_unref(new_keymap); + +cleanup_context: + xkb_context_unref(context); + + printstatus(); + return 0; +} + int switch_layout(const Arg *arg) { int jk, ji; diff --git a/src/mango.c b/src/mango.c index 5600f20..6a8c4bf 100644 --- a/src/mango.c +++ b/src/mango.c @@ -709,7 +709,6 @@ static void resize_tile_client(Client *grabc, bool isdrag, int offsetx, static void refresh_monitors_workspaces_status(Monitor *m); static void init_client_properties(Client *c); static void request_fresh_all_monitors(void); -static bool check_keyboard_rules_validate(struct xkb_rule_names *rules); static float *get_border_color(Client *c); #include "data/static_keymap.h"