From 376ee463c238b60aa3f583746dd6aa077a5d7d76 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 1 Feb 2026 19:21:01 +0800 Subject: [PATCH] feat: add config check option in mango cli --- src/config/parse_config.h | 383 +++++++++----------------------------- src/mango.c | 137 +++++--------- 2 files changed, 131 insertions(+), 389 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 556fc352..9ae5aa0c 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -101,14 +101,13 @@ typedef struct { } ConfigWinRule; typedef struct { - const char *name; // Monitor name - char *make, *model, *serial; // may be NULL - int32_t rr; // Rotate and flip (assume integer) - float scale; // Monitor scale factor - int32_t x, y; // Monitor position - int32_t width, height; // Monitor resolution - float refresh; // Refresh rate - int32_t vrr; // variable refresh rate + const char *name; // Monitor name + int32_t rr; // Rotate and flip (assume integer) + float scale; // Monitor scale factor + int32_t x, y; // Monitor position + int32_t width, height; // Monitor resolution + float refresh; // Refresh rate + int32_t vrr; // variable refresh rate } ConfigMonitorRule; // 修改后的宏定义 @@ -158,9 +157,6 @@ typedef struct { int32_t id; char *layout_name; char *monitor_name; - char *monitor_make; - char *monitor_model; - char *monitor_serial; float mfact; int32_t nmaster; int32_t no_render_border; @@ -366,7 +362,7 @@ typedef struct { typedef int32_t (*FuncType)(const Arg *); Config config; -bool parse_config_file(Config *config, const char *file_path, bool must_exist); +void parse_config_file(Config *config, const char *file_path); // Helper function to trim whitespace from start and end of a string void trim_whitespace(char *str) { @@ -554,48 +550,6 @@ static bool starts_with_ignore_case(const char *str, const char *prefix) { return true; } -static char *combine_args_until_empty(char *values[], int count) { - // find the first empty string - int first_empty = count; - for (int i = 0; i < count; i++) { - // check if it's empty: empty string or only contains "0" (initialized) - if (values[i][0] == '\0' || - (strlen(values[i]) == 1 && values[i][0] == '0')) { - first_empty = i; - break; - } - } - - // if there are no valid parameters, return an empty string - if (first_empty == 0) { - return strdup(""); - } - - // calculate the total length - size_t total_len = 0; - for (int i = 0; i < first_empty; i++) { - total_len += strlen(values[i]); - } - // plus the number of commas (first_empty-1 commas) - total_len += (first_empty - 1); - - // allocate memory and concatenate - char *combined = malloc(total_len + 1); - if (combined == NULL) { - return strdup(""); - } - - combined[0] = '\0'; - for (int i = 0; i < first_empty; i++) { - if (i > 0) { - strcat(combined, ","); - } - strcat(combined, values[i]); - } - - return combined; -} - uint32_t parse_mod(const char *mod_str) { if (!mod_str || !*mod_str) { return UINT32_MAX; @@ -783,9 +737,8 @@ KeySymCode parse_key(const char *key_str, bool isbindsym) { return kc; } - // change key string to keysym, case insensitive - xkb_keysym_t sym = - xkb_keysym_from_name(key_str, XKB_KEYSYM_CASE_INSENSITIVE); + // 普通键名直接转换 + xkb_keysym_t sym = xkb_keysym_from_name(key_str, XKB_KEYSYM_NO_FLAGS); if (isbindsym) { kc.type = KEY_TYPE_SYM; @@ -902,12 +855,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, char *arg_value5) { FuncType func = NULL; - (*arg).i = 0; - (*arg).i2 = 0; - (*arg).f = 0.0f; - (*arg).f2 = 0.0f; - (*arg).ui = 0; - (*arg).ui2 = 0; (*arg).v = NULL; (*arg).v2 = NULL; (*arg).v3 = NULL; @@ -1058,14 +1005,10 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, (*arg).ui = atoi(arg_value); } else if (strcmp(func_name, "spawn") == 0) { func = spawn; - char *values[] = {arg_value, arg_value2, arg_value3, arg_value4, - arg_value5}; - (*arg).v = combine_args_until_empty(values, 5); + (*arg).v = strdup(arg_value); } else if (strcmp(func_name, "spawn_shell") == 0) { func = spawn_shell; - char *values[] = {arg_value, arg_value2, arg_value3, arg_value4, - arg_value5}; - (*arg).v = combine_args_until_empty(values, 5); + (*arg).v = strdup(arg_value); } else if (strcmp(func_name, "spawn_on_empty") == 0) { func = spawn_on_empty; (*arg).v = strdup(arg_value); // 注意:之后需要释放这个内存 @@ -1442,8 +1385,9 @@ bool parse_option(Config *config, char *key, char *value) { config->scroller_proportion_preset = (float *)malloc(float_count * sizeof(float)); if (!config->scroller_proportion_preset) { - fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Memory " - "allocation failed\n"); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Memory allocation failed\n"); return false; } @@ -1456,19 +1400,18 @@ bool parse_option(Config *config, char *key, char *value) { while (token != NULL && i < float_count) { if (sscanf(token, "%f", &value_set) != 1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid float " - "value in " - "scroller_proportion_preset: %s\n", - token); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Invalid float value in " + "scroller_proportion_preset: %s\n", + token); free(value_copy); free(config->scroller_proportion_preset); config->scroller_proportion_preset = NULL; return false; } - // Clamp the value between 0.0 and 1.0 (or your desired - // range) + // Clamp the value between 0.0 and 1.0 (or your desired range) config->scroller_proportion_preset[i] = CLAMP_FLOAT(value_set, 0.1f, 1.0f); @@ -1505,8 +1448,9 @@ bool parse_option(Config *config, char *key, char *value) { config->circle_layout = (char **)malloc(string_count * sizeof(char *)); memset(config->circle_layout, 0, string_count * sizeof(char *)); if (!config->circle_layout) { - fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Memory " - "allocation failed\n"); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Memory allocation failed\n"); return false; } @@ -1662,8 +1606,7 @@ bool parse_option(Config *config, char *key, char *value) { int64_t color = parse_color(value); if (color == -1) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid rootcolor " - "format: " + "\033[1m\033[31m[ERROR]:\033[33m Invalid rootcolor format: " "%s\n", value); return false; @@ -1707,11 +1650,11 @@ bool parse_option(Config *config, char *key, char *value) { } else if (strcmp(key, "maximizescreencolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid " - "maximizescreencolor " - "format: %s\n", - value); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Invalid maximizescreencolor " + "format: %s\n", + value); return false; } else { convert_hex_to_rgba(config->maximizescreencolor, color); @@ -1731,8 +1674,7 @@ bool parse_option(Config *config, char *key, char *value) { int64_t color = parse_color(value); if (color == -1) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid " - "scratchpadcolor " + "\033[1m\033[31m[ERROR]:\033[33m Invalid scratchpadcolor " "format: %s\n", value); return false; @@ -1778,9 +1720,6 @@ bool parse_option(Config *config, char *key, char *value) { // 设置默认值 rule->name = NULL; - rule->make = NULL; - rule->model = NULL; - rule->serial = NULL; rule->rr = 0; rule->scale = 1.0f; rule->x = INT32_MAX; @@ -1804,12 +1743,6 @@ bool parse_option(Config *config, char *key, char *value) { if (strcmp(key, "name") == 0) { rule->name = strdup(val); - } else if (strcmp(key, "make") == 0) { - rule->make = strdup(val); - } else if (strcmp(key, "model") == 0) { - rule->model = strdup(val); - } else if (strcmp(key, "serial") == 0) { - rule->serial = strdup(val); } else if (strcmp(key, "rr") == 0) { rule->rr = CLAMP_INT(atoi(val), 0, 7); } else if (strcmp(key, "scale") == 0) { @@ -1827,11 +1760,11 @@ bool parse_option(Config *config, char *key, char *value) { } else if (strcmp(key, "vrr") == 0) { rule->vrr = CLAMP_INT(atoi(val), 0, 1); } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "monitor rule " - "option:\033[1m\033[31m %s\n", - key); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Unknown monitor rule " + "option:\033[1m\033[31m %s\n", + key); parse_error = true; } } @@ -1858,9 +1791,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->id = 0; rule->layout_name = NULL; rule->monitor_name = NULL; - rule->monitor_make = NULL; - rule->monitor_model = NULL; - rule->monitor_serial = NULL; rule->nmaster = 0; rule->mfact = 0.0f; rule->no_render_border = 0; @@ -1884,12 +1814,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->layout_name = strdup(val); } else if (strcmp(key, "monitor_name") == 0) { rule->monitor_name = strdup(val); - } else if (strcmp(key, "monitor_make") == 0) { - rule->monitor_make = strdup(val); - } else if (strcmp(key, "monitor_model") == 0) { - rule->monitor_model = strdup(val); - } else if (strcmp(key, "monitor_serial") == 0) { - rule->monitor_serial = strdup(val); } else if (strcmp(key, "no_render_border") == 0) { rule->no_render_border = CLAMP_INT(atoi(val), 0, 1); } else if (strcmp(key, "no_hide") == 0) { @@ -1900,8 +1824,7 @@ bool parse_option(Config *config, char *key, char *value) { rule->mfact = CLAMP_FLOAT(atof(val), 0.1f, 0.9f); } else { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "tag rule " + "\033[1m\033[31m[ERROR]:\033[33m Unknown tag rule " "option:\033[1m\033[31m %s\n", key); parse_error = true; @@ -1959,11 +1882,11 @@ bool parse_option(Config *config, char *key, char *value) { } else if (strcmp(key, "noshadow") == 0) { rule->noshadow = CLAMP_INT(atoi(val), 0, 1); } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "layer rule " - "option:\033[1m\033[31m %s\n", - key); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Unknown layer rule " + "option:\033[1m\033[31m %s\n", + key); parse_error = true; } } @@ -2151,11 +2074,11 @@ bool parse_option(Config *config, char *key, char *value) { return false; } } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "window rule " - "option:\033[1m\033[31m %s\n", - key); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Unknown window rule " + "option:\033[1m\033[31m %s\n", + key); parse_error = true; } } @@ -2255,8 +2178,7 @@ bool parse_option(Config *config, char *key, char *value) { arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; if (sscanf(value, - "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" - ",],%255[" + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" "^,],%255[^\n]", mod_str, keysym_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { @@ -2291,12 +2213,6 @@ bool parse_option(Config *config, char *key, char *value) { binding->keysymcode = parse_key(keysym_str, binding->keysymcode.type == KEY_TYPE_SYM); binding->mod = parse_mod(mod_str); - binding->arg.i = 0; - binding->arg.i2 = 0; - binding->arg.f = 0.0f; - binding->arg.f2 = 0.0f; - binding->arg.ui = 0; - binding->arg.ui2 = 0; binding->arg.v = NULL; binding->arg.v2 = NULL; binding->arg.v3 = NULL; @@ -2319,11 +2235,11 @@ bool parse_option(Config *config, char *key, char *value) { binding->arg.v3 = NULL; } if (!binding->func) - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "dispatch in bind: " - "\033[1m\033[31m%s\n", - func_name); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in bind: " + "\033[1m\033[31m%s\n", + func_name); return false; } else { config->key_bindings_count++; @@ -2349,14 +2265,12 @@ bool parse_option(Config *config, char *key, char *value) { arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; if (sscanf(value, - "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" - ",],%255[" + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" "^,],%255[^\n]", mod_str, button_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid mousebind " - "format: " + "\033[1m\033[31m[ERROR]:\033[33m Invalid mousebind format: " "%s\n", value); return false; @@ -2372,26 +2286,9 @@ bool parse_option(Config *config, char *key, char *value) { binding->mod = parse_mod(mod_str); binding->button = parse_button(button_str); - binding->arg.i = 0; - binding->arg.i2 = 0; - binding->arg.f = 0.0f; - binding->arg.f2 = 0.0f; - binding->arg.ui = 0; - binding->arg.ui2 = 0; binding->arg.v = NULL; binding->arg.v2 = NULL; binding->arg.v3 = NULL; - - // TODO: remove this in next version - if (binding->mod == 0 && - (binding->button == BTN_LEFT || binding->button == BTN_RIGHT)) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m \033[31m%s\033[33m can't " - "bind to \033[31m%s\033[33m mod key\n", - button_str, mod_str); - return false; - } - binding->func = parse_func_name(func_name, &binding->arg, arg_value, arg_value2, arg_value3, arg_value4, arg_value5); @@ -2409,11 +2306,9 @@ bool parse_option(Config *config, char *key, char *value) { free(binding->arg.v3); binding->arg.v3 = NULL; } - if (!binding->func) fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "dispatch in " + "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in " "mousebind: \033[1m\033[31m%s\n", func_name); return false; @@ -2440,15 +2335,14 @@ bool parse_option(Config *config, char *key, char *value) { arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; if (sscanf(value, - "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" - ",],%255[" + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" "^,],%255[^\n]", mod_str, dir_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid axisbind " - "format: %s\n", - value); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Invalid axisbind format: %s\n", + value); return false; } @@ -2485,8 +2379,7 @@ bool parse_option(Config *config, char *key, char *value) { } if (!binding->func) fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "dispatch in " + "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in " "axisbind: \033[1m\033[31m%s\n", func_name); return false; @@ -2514,8 +2407,7 @@ bool parse_option(Config *config, char *key, char *value) { arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; if (sscanf(value, - "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" - ",],%255[" + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" "^\n]", fold_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { @@ -2582,8 +2474,7 @@ bool parse_option(Config *config, char *key, char *value) { arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value5[256] = "0\0"; if (sscanf(value, - "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" - ",],%255[" + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" "^,],%255[^,],%255[^\n]", mod_str, motion_str, fingers_count_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 4) { @@ -2607,12 +2498,6 @@ bool parse_option(Config *config, char *key, char *value) { binding->mod = parse_mod(mod_str); binding->motion = parse_direction(motion_str); binding->fingers_count = atoi(fingers_count_str); - binding->arg.i = 0; - binding->arg.i2 = 0; - binding->arg.f = 0.0f; - binding->arg.f2 = 0.0f; - binding->arg.ui = 0; - binding->arg.ui2 = 0; binding->arg.v = NULL; binding->arg.v2 = NULL; binding->arg.v3 = NULL; @@ -2635,8 +2520,7 @@ bool parse_option(Config *config, char *key, char *value) { } if (!binding->func) fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "dispatch in " + "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in " "axisbind: \033[1m\033[31m%s\n", func_name); return false; @@ -2644,15 +2528,13 @@ bool parse_option(Config *config, char *key, char *value) { config->gesture_bindings_count++; } - } else if (strncmp(key, "source-optional", 15) == 0) { - parse_config_file(config, value, false); } else if (strncmp(key, "source", 6) == 0) { - parse_config_file(config, value, true); + parse_config_file(config, value); } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown keyword: " - "\033[1m\033[31m%s\n", - key); + fprintf( + stderr, + "\033[1m\033[31m[ERROR]:\033[33m Unknown key: \033[1m\033[31m%s\n", + key); return false; } @@ -2662,9 +2544,8 @@ bool parse_option(Config *config, char *key, char *value) { bool parse_config_line(Config *config, const char *line) { char key[256], value[256]; if (sscanf(line, "%255[^=]=%255[^\n]", key, value) != 2) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid line format: %s", - line); + // fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Invalid line format: + // %s\n", line); return false; } @@ -2675,7 +2556,7 @@ bool parse_config_line(Config *config, const char *line) { return parse_option(config, key, value); } -bool parse_config_file(Config *config, const char *file_path, bool must_exist) { +void parse_config_file(Config *config, const char *file_path) { FILE *file; char full_path[1024]; @@ -2694,7 +2575,7 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) { fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m HOME environment " "variable not set.\n"); - return false; + return; } snprintf(full_path, sizeof(full_path), "%s/.config/mango/%s", home, file_path + 1); @@ -2709,7 +2590,7 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) { if (!home) { fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m HOME environment " "variable not set.\n"); - return false; + return; } snprintf(full_path, sizeof(full_path), "%s%s", home, file_path + 1); file = fopen(full_path, "r"); @@ -2720,29 +2601,20 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) { } if (!file) { - if (must_exist) { - fprintf(stderr, - "\033[1;31m\033[1;33m[ERROR]:\033[0m Failed to open " - "config file: %s\n", - file_path); - return false; - } else { - return true; - } + perror("Error opening file"); + return; } char line[512]; bool parse_correct = true; - bool parse_line_correct = true; uint32_t line_count = 0; while (fgets(line, sizeof(line), file)) { line_count++; if (line[0] == '#' || line[0] == '\n') { continue; } - parse_line_correct = parse_config_line(config, line); - if (!parse_line_correct) { - parse_correct = false; + parse_correct = parse_config_line(config, line); + if (!parse_correct) { fprintf(stderr, "\033[1;31m╰─\033[1;33m[Index]\033[0m " "\033[1;36m%s\033[0m:\033[1;35m%d\033[0m\n" @@ -2752,7 +2624,6 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) { } fclose(file); - return parse_correct; } void free_circle_layout(Config *config) { @@ -2947,12 +2818,6 @@ void free_config(void) { free((void *)config.tag_rules[i].layout_name); if (config.tag_rules[i].monitor_name) free((void *)config.tag_rules[i].monitor_name); - if (config.tag_rules[i].monitor_make) - free((void *)config.tag_rules[i].monitor_make); - if (config.tag_rules[i].monitor_model) - free((void *)config.tag_rules[i].monitor_model); - if (config.tag_rules[i].monitor_serial) - free((void *)config.tag_rules[i].monitor_serial); } free(config.tag_rules); config.tag_rules = NULL; @@ -2964,12 +2829,6 @@ void free_config(void) { for (int32_t i = 0; i < config.monitor_rules_count; i++) { if (config.monitor_rules[i].name) free((void *)config.monitor_rules[i].name); - if (config.monitor_rules[i].make) - free((void *)config.monitor_rules[i].make); - if (config.monitor_rules[i].model) - free((void *)config.monitor_rules[i].model); - if (config.monitor_rules[i].serial) - free((void *)config.monitor_rules[i].serial); } free(config.monitor_rules); config.monitor_rules = NULL; @@ -3274,8 +3133,8 @@ void set_value_default() { config.hotarea_size = hotarea_size; // 热区大小,10x10 config.hotarea_corner = hotarea_corner; config.enable_hotarea = enable_hotarea; // 是否启用鼠标热区 - config.smartgaps = smartgaps; /* 1 means no outer gap when there is - only one window */ + config.smartgaps = + smartgaps; /* 1 means no outer gap when there is only one window */ config.sloppyfocus = sloppyfocus; /* focus follows mouse */ config.gappih = gappih; /* horiz inner gap between windows */ config.gappiv = gappiv; /* vert inner gap between windows */ @@ -3424,7 +3283,7 @@ void set_default_key_bindings(Config *config) { config->key_bindings_count += default_key_bindings_count; } -bool parse_config(void) { +void parse_config(void) { char filename[1024]; @@ -3477,7 +3336,7 @@ bool parse_config(void) { const char *homedir = getenv("HOME"); if (!homedir) { // 如果获取失败,则无法继续 - return false; + return; } // 构建日志文件路径 snprintf(filename, sizeof(filename), "%s/.config/mango/config.conf", @@ -3491,12 +3350,10 @@ bool parse_config(void) { } } - bool parse_correct = true; set_value_default(); - parse_correct = parse_config_file(&config, filename, true); + parse_config_file(&config, filename); set_default_key_bindings(&config); override_config(); - return parse_correct; } void reset_blur_params(void) { @@ -3534,7 +3391,6 @@ void reapply_monitor_rules(void) { struct wlr_output_state state; struct wlr_output_mode *internal_mode = NULL; wlr_output_state_init(&state); - bool match_rule = false; wl_list_for_each(m, &mons, link) { if (!m->wlr_output->enabled) { @@ -3546,40 +3402,8 @@ void reapply_monitor_rules(void) { break; mr = &config.monitor_rules[ji]; + if (regex_match(mr->name, m->wlr_output->name)) { - // 检查是否匹配的变量 - match_rule = true; - - // 检查四个标识字段的匹配 - if (mr->name != NULL) { - if (!regex_match(mr->name, m->wlr_output->name)) { - match_rule = false; - } - } - - if (mr->make != NULL) { - if (m->wlr_output->make == NULL || - strcmp(mr->make, m->wlr_output->make) != 0) { - match_rule = false; - } - } - - if (mr->model != NULL) { - if (m->wlr_output->model == NULL || - strcmp(mr->model, m->wlr_output->model) != 0) { - match_rule = false; - } - } - - if (mr->serial != NULL) { - if (m->wlr_output->serial == NULL || - strcmp(mr->serial, m->wlr_output->serial) != 0) { - match_rule = false; - } - } - - // 只有当所有指定的标识都匹配时才应用规则 - if (match_rule) { mx = mr->x == INT32_MAX ? m->m.x : mr->x; my = mr->y == INT32_MAX ? m->m.y : mr->y; vrr = mr->vrr >= 0 ? mr->vrr : 0; @@ -3648,8 +3472,6 @@ void reapply_cursor_style(void) { } } -void reapply_rootbg(void) { wlr_scene_rect_set_color(root_bg, rootcolor); } - void reapply_border(void) { Client *c = NULL; @@ -3713,7 +3535,6 @@ void parse_tagrule(Monitor *m) { int32_t i, jk; ConfigTagRule tr; Client *c = NULL; - bool match_rule = false; for (i = 0; i <= LENGTH(tags); i++) { m->pertag->nmasters[i] = default_nmaster; @@ -3724,36 +3545,9 @@ void parse_tagrule(Monitor *m) { tr = config.tag_rules[i]; - match_rule = true; - - if (tr.monitor_name != NULL) { - if (!regex_match(tr.monitor_name, m->wlr_output->name)) { - match_rule = false; - } - } - - if (tr.monitor_make != NULL) { - if (m->wlr_output->make == NULL || - strcmp(tr.monitor_make, m->wlr_output->make) != 0) { - match_rule = false; - } - } - - if (tr.monitor_model != NULL) { - if (m->wlr_output->model == NULL || - strcmp(tr.monitor_model, m->wlr_output->model) != 0) { - match_rule = false; - } - } - - if (tr.monitor_serial != NULL) { - if (m->wlr_output->serial == NULL || - strcmp(tr.monitor_serial, m->wlr_output->serial) != 0) { - match_rule = false; - } - } - - if (config.tag_rules_count > 0 && match_rule) { + if (config.tag_rules_count > 0 && + (!tr.monitor_name || + regex_match(tr.monitor_name, m->wlr_output->name))) { for (jk = 0; jk < LENGTH(layouts); jk++) { if (tr.layout_name && @@ -3803,7 +3597,6 @@ void reset_option(void) { reapply_cursor_style(); reapply_border(); - reapply_rootbg(); reapply_keyboard(); reapply_pointer(); reapply_master(); diff --git a/src/mango.c b/src/mango.c index 3ce74222..5a8b6fc1 100644 --- a/src/mango.c +++ b/src/mango.c @@ -942,7 +942,6 @@ static struct wl_listener keyboard_shortcuts_inhibit_new_inhibitor = { .notify = handle_keyboard_shortcuts_inhibit_new_inhibitor}; #ifdef XWAYLAND -static int32_t synckeymap(void *data); static void activatex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data); static void createnotifyx11(struct wl_listener *listener, void *data); @@ -954,7 +953,6 @@ static void setgeometrynotify(struct wl_listener *listener, void *data); static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; static struct wl_listener xwayland_ready = {.notify = xwaylandready}; static struct wlr_xwayland *xwayland; -static struct wl_event_source *sync_keymap; #endif #include "animation/client.h" @@ -971,6 +969,7 @@ static struct wl_event_source *sync_keymap; void client_change_mon(Client *c, Monitor *m) { setmon(c, m, c->tags, true); + reset_foreign_tolevel(c); if (c->isfloating) { c->float_geom = c->geom = setclient_coordinate_center(c, c->mon, c->geom, 0, 0); @@ -1072,9 +1071,6 @@ void swallow(Client *c, Client *w) { c->tags = w->tags; c->geom = w->geom; c->float_geom = w->float_geom; - c->stack_inner_per = w->stack_inner_per; - c->master_inner_per = w->master_inner_per; - c->master_mfact_per = w->master_mfact_per; c->scroller_proportion = w->scroller_proportion; c->next_in_stack = w->next_in_stack; c->prev_in_stack = w->prev_in_stack; @@ -1998,21 +1994,14 @@ buttonpress(struct wl_listener *listener, void *data) { if (config.mouse_bindings_count < 1) break; m = &config.mouse_bindings[ji]; - - if (selmon->isoverview && event->button == BTN_LEFT && c) { - toggleoverview(&(Arg){.i = 1}); - return; - } - - if (selmon->isoverview && event->button == BTN_RIGHT && c) { - pending_kill_client(c); - return; - } - if (CLEANMASK(mods) == CLEANMASK(m->mod) && event->button == m->button && m->func && - (CLEANMASK(m->mod) != 0 || - (event->button != BTN_LEFT && event->button != BTN_RIGHT))) { + (selmon->isoverview == 1 || m->button == BTN_MIDDLE) && c) { + m->func(&m->arg); + return; + } else if (CLEANMASK(mods) == CLEANMASK(m->mod) && + event->button == m->button && m->func && + CLEANMASK(m->mod) != 0) { m->func(&m->arg); return; } @@ -2034,6 +2023,7 @@ buttonpress(struct wl_listener *listener, void *data) { selmon = xytomon(cursor->x, cursor->y); client_update_oldmonname_record(grabc, selmon); setmon(grabc, selmon, 0, true); + reset_foreign_tolevel(grabc); selmon->prevsel = ISTILED(selmon->sel) ? selmon->sel : NULL; selmon->sel = grabc; tmpc = grabc; @@ -2737,7 +2727,6 @@ void createmon(struct wl_listener *listener, void *data) { Monitor *m = NULL; struct wlr_output_mode *internal_mode = NULL; bool custom_monitor_mode = false; - bool match_rule = false; if (!wlr_output_init_render(wlr_output, alloc, drw)) return; @@ -2778,39 +2767,7 @@ void createmon(struct wl_listener *listener, void *data) { break; r = &config.monitor_rules[ji]; - - // 检查是否匹配的变量 - match_rule = true; - - // 检查四个标识字段的匹配 - if (r->name != NULL) { - if (!regex_match(r->name, m->wlr_output->name)) { - match_rule = false; - } - } - - if (r->make != NULL) { - if (m->wlr_output->make == NULL || - strcmp(r->make, m->wlr_output->make) != 0) { - match_rule = false; - } - } - - if (r->model != NULL) { - if (m->wlr_output->model == NULL || - strcmp(r->model, m->wlr_output->model) != 0) { - match_rule = false; - } - } - - if (r->serial != NULL) { - if (m->wlr_output->serial == NULL || - strcmp(r->serial, m->wlr_output->serial) != 0) { - match_rule = false; - } - } - - if (match_rule) { + if (regex_match(r->name, wlr_output->name)) { m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x; m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y; vrr = r->vrr >= 0 ? r->vrr : 0; @@ -3461,10 +3418,7 @@ void requestmonstate(struct wl_listener *listener, void *data) { void inputdevice(struct wl_listener *listener, void *data) { /* This event is raised by the backend when a new input device becomes - * available. - * when the backend is a headless backend, this event will never be - * triggered. - */ + * available. */ struct wlr_input_device *device = data; uint32_t caps; @@ -3535,6 +3489,11 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym, int32_t ji; int32_t isbreak = 0; + // not allow modifier keys to be used as a keybinding + if (keycode == 50 || keycode == 37 || keycode == 133 || keycode == 64 || + keycode == 62 || keycode == 108 || keycode == 105 || keycode == 134) + return false; + if (is_keyboard_shortcut_inhibitor(seat->keyboard_state.focused_surface)) { return false; } @@ -3866,12 +3825,6 @@ void init_client_properties(Client *c) { c->stack_proportion = 0.0f; c->next_in_stack = NULL; c->prev_in_stack = NULL; - memcpy(c->opacity_animation.initial_border_color, bordercolor, - sizeof(c->opacity_animation.initial_border_color)); - memcpy(c->opacity_animation.current_border_color, bordercolor, - sizeof(c->opacity_animation.current_border_color)); - c->opacity_animation.initial_opacity = c->unfocused_opacity; - c->opacity_animation.current_opacity = c->unfocused_opacity; } void // old fix to 0.5 @@ -4190,7 +4143,7 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, if (grabc->isfloating) { grabc->iscustomsize = 1; if (last_apply_drap_time == 0 || - time - last_apply_drap_time > drag_floating_refresh_interval) { + time - last_apply_drap_time > drag_refresh_interval) { resize_floating_window(grabc); last_apply_drap_time = time; } @@ -4322,7 +4275,7 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, uint32_t time) { struct timespec now; - if (sloppyfocus && !start_drag_window && c && time && c->scene && + if (sloppyfocus && !start_drag_window && c && time && c->scene->node.enabled && !c->animation.tagining && (surface != seat->pointer_state.focused_surface) && !client_is_unmanaged(c) && VISIBLEON(c, c->mon)) @@ -4719,7 +4672,6 @@ setfloating(Client *c, int32_t floating) { Client *fc = NULL; struct wlr_box target_box; - int32_t old_floating_state = c->isfloating; c->isfloating = floating; bool window_size_outofrange = false; @@ -4789,7 +4741,7 @@ setfloating(Client *c, int32_t floating) { layers[c->isfloating ? LyrTop : LyrTile]); } - if (!c->isfloating && old_floating_state) { + if (!c->isfloating) { set_size_per(c->mon, c); } @@ -4838,7 +4790,6 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { if (c->mon->isoverview) return; - int32_t old_maximizescreen_state = c->ismaximizescreen; c->ismaximizescreen = maximizescreen; if (maximizescreen) { @@ -4868,7 +4819,7 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrTop : LyrTile]); - if (!c->ismaximizescreen && old_maximizescreen_state) { + if (!c->ismaximizescreen) { set_size_per(c->mon, c); } @@ -4901,7 +4852,6 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自 if (c->mon->isoverview) return; - int32_t old_fullscreen_state = c->isfullscreen; c->isfullscreen = fullscreen; client_set_fullscreen(c, fullscreen); @@ -4939,7 +4889,7 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自 layers[fullscreen || c->isfloating ? LyrTop : LyrTile]); } - if (!c->isfullscreen && old_fullscreen_state) { + if (!c->isfullscreen) { set_size_per(c->mon, c); } @@ -5068,7 +5018,6 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) { arrange(oldmon, false, false); if (m) { /* Make sure window actually overlaps with the monitor */ - reset_foreign_tolevel(c); resize(c, c->geom, 0); c->tags = newtags ? newtags @@ -5080,6 +5029,21 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) { if (focus && !client_is_x11_popup(c)) { focusclient(focustop(selmon), 1); } + + if (m) { + + if (c->foreign_toplevel) { + remove_foreign_topleve(c); + } + + add_foreign_toplevel(c); + if (m->sel && m->sel->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_set_activated( + m->sel->foreign_toplevel, false); + if (c->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, + true); + } } void setpsel(struct wl_listener *listener, void *data) { @@ -5217,7 +5181,7 @@ void setup(void) { if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) { wlr_drm_create(dpy, drw); wlr_scene_set_linux_dmabuf_v1( - scene, wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw)); + scene, wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw)); } if (syncobj_enable && (drm_fd = wlr_renderer_get_drm_fd(drw)) >= 0 && @@ -5364,6 +5328,7 @@ void setup(void) { &request_set_cursor_shape); hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy), hidecursor, cursor); + /* * Configures a seat, which is a single "seat" at which a user sits and * operates the computer. This conceptually includes up to one keyboard, @@ -5455,8 +5420,6 @@ void setup(void) { fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); } - sync_keymap = wl_event_loop_add_timer(wl_display_get_event_loop(dpy), - synckeymap, NULL); #endif } @@ -5835,8 +5798,7 @@ void updatemons(struct wl_listener *listener, void *data) { if (selmon && selmon->wlr_output->enabled) { wl_list_for_each(c, &clients, link) { if (!c->mon && client_surface(c)->mapped) { - c->mon = selmon; - reset_foreign_tolevel(c); + client_change_mon(c, selmon); } } focusclient(focustop(selmon), 1); @@ -6014,8 +5976,6 @@ void handle_keyboard_shortcuts_inhibit_new_inhibitor( void virtualkeyboard(struct wl_listener *listener, void *data) { struct wlr_virtual_keyboard_v1 *kb = data; /* virtual keyboards shouldn't share keyboard group */ - wlr_seat_set_capabilities(seat, - seat->capabilities | WL_SEAT_CAPABILITY_KEYBOARD); KeyboardGroup *group = createkeyboardgroup(); /* Set the keymap to match the group keymap */ wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); @@ -6027,7 +5987,8 @@ void virtualkeyboard(struct wl_listener *listener, void *data) { } void warp_cursor(const Client *c) { - if (INSIDEMON(c)) { + if (cursor->x < c->geom.x || cursor->x > c->geom.x + c->geom.width || + cursor->y < c->geom.y || cursor->y > c->geom.y + c->geom.height) { wlr_cursor_warp_closest(cursor, NULL, c->geom.x + c->geom.width / 2.0, c->geom.y + c->geom.height / 2.0); motionnotify(0, NULL, 0, 0, 0, 0); @@ -6045,8 +6006,7 @@ void warp_cursor_to_selmon(Monitor *m) { void virtualpointer(struct wl_listener *listener, void *data) { struct wlr_virtual_pointer_v1_new_pointer_event *event = data; struct wlr_input_device *device = &event->new_pointer->pointer.base; - wlr_seat_set_capabilities(seat, - seat->capabilities | WL_SEAT_CAPABILITY_POINTER); + wlr_cursor_attach_input_device(cursor, device); if (event->suggested_output) wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); @@ -6055,14 +6015,6 @@ void virtualpointer(struct wl_listener *listener, void *data) { } #ifdef XWAYLAND -int32_t synckeymap(void *data) { - reset_keyboard_layout(); - // we only need to sync keymap once - wlr_log(WLR_INFO, "timer to synckeymap done"); - wl_event_source_timer_update(sync_keymap, 0); - return 0; -} - void activatex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, activate); bool need_arrange = false; @@ -6193,10 +6145,6 @@ void xwaylandready(struct wl_listener *listener, void *data) { xwayland, xcursor->images[0]->buffer, xcursor->images[0]->width * 4, xcursor->images[0]->width, xcursor->images[0]->height, xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); - /* xwayland can't auto sync the keymap, so we do it manually - and we need to wait the xwayland completely inited - */ - wl_event_source_timer_update(sync_keymap, 500); } static void setgeometrynotify(struct wl_listener *listener, void *data) { @@ -6223,7 +6171,8 @@ int32_t main(int32_t argc, char *argv[]) { } else if (c == 'c') { cli_config_path = optarg; } else if (c == 'p') { - return parse_config() ? EXIT_SUCCESS : EXIT_FAILURE; + parse_config(); + return EXIT_SUCCESS; } else { goto usage; }