diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 82fc2ec..5860fe9 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -880,18 +880,26 @@ void parse_config_line(Config *config, const char *line) { config->drag_tile_to_tile = atoi(value); } else if (strcmp(key, "swipe_min_threshold") == 0) { config->swipe_min_threshold = atoi(value); - } else if (!xkb_rules.rules && strcmp(key, "xkb_rules_rules") == 0) { - xkb_rules.rules = strdup(value); - } else if (!xkb_rules.model && strcmp(key, "xkb_rules_model") == 0) { - xkb_rules.model = strdup(value); - } else if (!xkb_rules.layout && strcmp(key, "xkb_rules_layout") == 0) { - char *new_layouts_str = malloc(256); // 不要释放,只赋值一次 - strcpy(new_layouts_str, value); - xkb_rules.layout = new_layouts_str; - } else if (!xkb_rules.variant && strcmp(key, "xkb_rules_variant") == 0) { - xkb_rules.variant = strdup(value); - } else if (!xkb_rules.options && strcmp(key, "xkb_rules_options") == 0) { - xkb_rules.options = strdup(value); + } else if (strcmp(key, "xkb_rules_rules") == 0) { + strncpy(xkb_rules_rules, value, sizeof(xkb_rules_rules) - 1); + xkb_rules_rules[sizeof(xkb_rules_rules) - 1] = + '\0'; // 确保字符串以 null 结尾 + } else if (strcmp(key, "xkb_rules_model") == 0) { + strncpy(xkb_rules_model, value, sizeof(xkb_rules_model) - 1); + xkb_rules_model[sizeof(xkb_rules_model) - 1] = + '\0'; // 确保字符串以 null 结尾 + } else if (strcmp(key, "xkb_rules_layout") == 0) { + strncpy(xkb_rules_layout, value, sizeof(xkb_rules_layout) - 1); + xkb_rules_layout[sizeof(xkb_rules_layout) - 1] = + '\0'; // 确保字符串以 null 结尾 + } else if (strcmp(key, "xkb_rules_variant") == 0) { + strncpy(xkb_rules_variant, value, sizeof(xkb_rules_variant) - 1); + xkb_rules_variant[sizeof(xkb_rules_variant) - 1] = + '\0'; // 确保字符串以 null 结尾 + } else if (strcmp(key, "xkb_rules_options") == 0) { + strncpy(xkb_rules_options, value, sizeof(xkb_rules_options) - 1); + xkb_rules_options[sizeof(xkb_rules_options) - 1] = + '\0'; // 确保字符串以 null 结尾 } else if (strcmp(key, "scroller_proportion_preset") == 0) { // 1. 统计 value 中有多少个逗号,确定需要解析的浮点数个数 int count = 0; // 初始化为 0 @@ -2230,6 +2238,7 @@ void reload_config(const Arg *arg) { parse_config(); init_baked_points(); handlecursoractivity(); + reset_keyboard_layout(); run_exec(); // reset border width when config change diff --git a/src/config/preset_config.h b/src/config/preset_config.h index 10c8993..dab4400 100644 --- a/src/config/preset_config.h +++ b/src/config/preset_config.h @@ -102,13 +102,25 @@ Layout layouts[] = { }; /* keyboard */ + +/* + only layout can modify after fisrt init + other fields change will be ignored. +*/ +char xkb_rules_rules[256]; +char xkb_rules_model[256]; +char xkb_rules_layout[256]; +char xkb_rules_variant[256]; +char xkb_rules_options[256]; + struct xkb_rule_names xkb_rules = { /* can specify fields: rules, model, layout, variant, options */ /* example: .options = "ctrl:nocaps", */ - .rules = NULL, .model = NULL, .layout = NULL, - .variant = NULL, .options = NULL, + .rules = xkb_rules_rules, .model = xkb_rules_model, + .layout = xkb_rules_layout, .variant = xkb_rules_variant, + .options = xkb_rules_options, }; int repeat_rate = 25; diff --git a/src/maomao.c b/src/maomao.c index 036f4ad..b092040 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -650,6 +650,7 @@ static Client *center_select(Monitor *m); static void handlecursoractivity(void); static int hidecursor(void *data); static bool check_hit_no_border(Client *c); +static void reset_keyboard_layout(void); #include "data/static_keymap.h" #include "dispatch/dispatch.h" @@ -5797,6 +5798,89 @@ char *get_layout_abbr(const char *full_name) { return strdup("xx"); } +void reset_keyboard_layout(void) { + if (!kb_group || !kb_group->wlr_group || !seat) { + wlr_log(WLR_ERROR, "Invalid keyboard group or seat"); + return; + } + + struct wlr_keyboard *keyboard = &kb_group->wlr_group->keyboard; + if (!keyboard || !keyboard->keymap) { + wlr_log(WLR_ERROR, "Invalid keyboard or keymap"); + return; + } + + // Get current layout + 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 < 1) { + wlr_log(WLR_INFO, "No layouts available"); + return; + } + + // Create context + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!context) { + wlr_log(WLR_ERROR, "Failed to create XKB context"); + return; + } + + // Get layout abbreviations + 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; + } + } + + // Keep the same rules but just reapply them + struct xkb_rule_names rules = xkb_rules; + + // Create new keymap with current rules + struct xkb_keymap *new_keymap = + xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!new_keymap) { + wlr_log(WLR_ERROR, "Failed to create keymap for layouts: %s", + rules.layout); + goto cleanup_layouts; + } + + // Apply the same keymap (this will reset the layout state) + uint32_t depressed = keyboard->modifiers.depressed; + uint32_t latched = keyboard->modifiers.latched; + uint32_t locked = keyboard->modifiers.locked; + + wlr_keyboard_set_keymap(keyboard, new_keymap); + + wlr_keyboard_notify_modifiers(keyboard, depressed, latched, locked, 0); + keyboard->modifiers.group = current; // Keep the same layout index + + // Update seat + wlr_seat_set_keyboard(seat, keyboard); + wlr_seat_keyboard_notify_modifiers(seat, &keyboard->modifiers); + + // Cleanup + xkb_keymap_unref(new_keymap); + +cleanup_layouts: + for (int i = 0; i < num_layouts; i++) { + free(layout_ids[i]); + } + free(layout_ids); + +cleanup_context: + xkb_context_unref(context); +} + void switch_keyboard_layout(const Arg *arg) { if (!kb_group || !kb_group->wlr_group || !seat) { wlr_log(WLR_ERROR, "Invalid keyboard group or seat");