diff --git a/config.def.h b/config.def.h index c6953a7a..ca160b16 100644 --- a/config.def.h +++ b/config.def.h @@ -20,7 +20,7 @@ static const double animation_curve[4] = {0.46,1.0,0.29,0.99}; // Animation curv /* scroller layout setting*/ static const int scroller_structs = 20; static const float scroller_default_proportion = 0.8; -static bool scoller_foucs_center = false; +static bool scoller_focus_center = false; static const float scroller_proportion_preset[] = {0.5,0.8,1.0}; /* master-stack layout setting*/ diff --git a/maomao.c b/maomao.c index ed9a4fbd..2dc752d3 100644 --- a/maomao.c +++ b/maomao.c @@ -97,7 +97,7 @@ /* enums */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { XDGShell, LayerShell, X11 }; /* client types */ -enum { AxisUp, AxisRight, AxisDown, AxisLeft }; // 滚轮滚动的方向 +enum { AxisUp,AxisDown, AxisLeft, AxisRight}; // 滚轮滚动的方向 enum { LyrBg, LyrBottom, @@ -635,7 +635,7 @@ static Atom netatom[NetLast]; #endif /* configuration, allows nested code to access above variables */ -#include "config.h" +#include "preset_config.h" #include "parse_config.h" /* attempt to encapsulate suck into one file */ @@ -1533,7 +1533,7 @@ axisnotify(struct wl_listener *listener, void *data) { struct wlr_pointer_axis_event *event = data; struct wlr_keyboard *keyboard; uint32_t mods; - const AxisBinding *a; + AxisBinding *a; int ji; unsigned int adir; // IDLE_NOTIFY_ACTIVITY; @@ -4340,7 +4340,8 @@ void signalhandler(int signalnumber) void free_config(void) { // 释放内存 - for (int i = 0; i < config.window_rules_count; i++) { + int i; + for (i = 0; i < config.window_rules_count; i++) { ConfigWinRule *rule = &config.window_rules[i]; if (rule->id) free((void *)rule->id); if (rule->title) free((void *)rule->title); @@ -4348,31 +4349,83 @@ void free_config(void) { } free(config.window_rules); - for (int i = 0; i < config.monitor_rules_count; i++) { + for ( i = 0; i < config.monitor_rules_count; i++) { ConfigMonitorRule *rule = &config.monitor_rules[i]; if (rule->name) free((void *)rule->name); if (rule->layout) free((void *)rule->layout); } free(config.monitor_rules); - for (int i = 0; i < config.key_bindings_count; i++) { + for ( i = 0; i < config.key_bindings_count; i++) { if (config.key_bindings[i].arg.v) free((void *)config.key_bindings[i].arg.v); } free(config.key_bindings); - for (int i = 0; i < config.mouse_bindings_count; i++) { + for ( i = 0; i < config.mouse_bindings_count; i++) { if (config.mouse_bindings[i].arg.v) free((void *)config.mouse_bindings[i].arg.v); } free(config.mouse_bindings); - for (int i = 0; i < config.axis_bindings_count; i++) { + for (i = 0; i < config.axis_bindings_count; i++) { if (config.axis_bindings[i].arg.v) free((void *)config.axis_bindings[i].arg.v); } free(config.axis_bindings); } +void override_config(void) { + animations = config.animations; + animation_type = config.animation_type; + animation_fade_in = config.animation_fade_in; + zoom_initial_ratio = config.zoom_initial_ratio; + fadein_begin_opacity = config.fadein_begin_opacity; + animation_duration_move = config.animation_duration_move; + animation_duration_open = config.animation_duration_open; + animation_duration_tag = config.animation_duration_tag; + + // 复制数组类型的变量 + memcpy(animation_curve, config.animation_curve, sizeof(animation_curve)); + memcpy(scroller_proportion_preset, config.scroller_proportion_preset, sizeof(scroller_proportion_preset)); + + scroller_structs = config.scroller_structs; + scroller_default_proportion = config.scroller_default_proportion; + scoller_focus_center = config.scoller_focus_center; + + new_is_master = config.new_is_master; + default_mfact = config.default_mfact; + default_nmaster = config.default_nmaster; + hotarea_size = config.hotarea_size; + enable_hotarea = config.enable_hotarea; + ov_tab_mode = config.ov_tab_mode; + overviewgappi = config.overviewgappi; + overviewgappo = config.overviewgappo; + axis_bind_apply_timeout = config.axis_bind_apply_timeout; + focus_on_activate = config.focus_on_activate; + numlockon = config.numlockon; + bypass_surface_visibility = config.bypass_surface_visibility; + sloppyfocus = config.sloppyfocus; + warpcursor = config.warpcursor; + smartgaps = config.smartgaps; + gappih = config.gappih; + gappiv = config.gappiv; + gappoh = config.gappoh; + gappov = config.gappov; + borderpx = config.borderpx; + + // 复制颜色数组 + memcpy(rootcolor, config.rootcolor, sizeof(rootcolor)); + memcpy(bordercolor, config.bordercolor, sizeof(bordercolor)); + memcpy(focuscolor, config.focuscolor, sizeof(focuscolor)); + memcpy(maxmizescreencolor, config.maxmizescreencolor, sizeof(maxmizescreencolor)); + memcpy(urgentcolor, config.urgentcolor, sizeof(urgentcolor)); + memcpy(scratchpadcolor, config.scratchpadcolor, sizeof(scratchpadcolor)); + memcpy(globalcolor, config.globalcolor, sizeof(globalcolor)); +} + void parse_config(void) { + + char filename[1024]; + memset(&config, 0, sizeof(config)); config.window_rules = NULL; config.window_rules_count = 0; @@ -4385,7 +4438,21 @@ void parse_config(void) { config.axis_bindings = NULL; config.axis_bindings_count = 0; - parse_config_file(&config, "/home/wrq/.config/maomao/config.conf"); + // 获取当前用户家目录 + const char *homedir = getenv("HOME"); + if (!homedir) { + // 如果获取失败,则无法继续 + return; + } + + // 构建日志文件路径 + snprintf(filename, sizeof(filename), "%s/.config/maomao/config.conf", homedir); + + + parse_config_file(&config, filename); + + override_config(); + } void setup(void) { @@ -4656,13 +4723,25 @@ void sigchld(int unused) { } } -void // 17 -spawn(const Arg *arg) { +void spawn(const Arg *arg) { + if (fork() == 0) { - dup2(STDERR_FILENO, STDOUT_FILENO); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwl: execvp %s failed:", ((char **)arg->v)[0]); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + + // 将 arg->v 拆分为字符串数组 + char *argv[64]; // 假设最多有 64 个参数 + int argc = 0; + char *token = strtok((char *)arg->v, " "); + while (token != NULL && argc < 63) { + argv[argc++] = token; + token = strtok(NULL, " "); + } + argv[argc] = NULL; // execvp 需要以 NULL 结尾的数组 + + // 执行命令 + execvp(argv[0], argv); + die("dwl: execvp %s failed:", argv[0]); } } @@ -4902,7 +4981,7 @@ void scroller(Monitor *m, unsigned int gappo, unsigned int gappi) { target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; if (need_scroller) { - if (scoller_foucs_center || + if (scoller_focus_center || selmon->prevsel == NULL || (selmon->prevsel->scroller_proportion * max_client_width) + (root_client->scroller_proportion * max_client_width) > m->w.width - 2 * scroller_structs - gappih) { target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; diff --git a/parse_config.h b/parse_config.h index 1e55b993..5a740c5a 100644 --- a/parse_config.h +++ b/parse_config.h @@ -1,3 +1,8 @@ +#include +#include +#include +#include + typedef struct { const char *id; const char *title; @@ -43,6 +48,7 @@ typedef struct { Arg arg; } AxisBinding; + typedef struct { int animations; char animation_type[10]; @@ -82,13 +88,13 @@ typedef struct { unsigned int gappoh; unsigned int gappov; unsigned int borderpx; - int rootcolor; - int bordercolor; - int focuscolor; - int maxmizescreencolor; - int urgentcolor; - int scratchpadcolor; - int globalcolor; + float rootcolor[4]; + float bordercolor[4]; + float focuscolor[4]; + float maxmizescreencolor[4]; + float urgentcolor[4]; + float scratchpadcolor[4]; + float globalcolor[4]; char autostart[3][256]; @@ -114,6 +120,30 @@ typedef struct { } Config; +int parseDirection(const char* str) { + // 将输入字符串转换为小写 + char lowerStr[10]; + int i = 0; + while (str[i] && i < 9) { + lowerStr[i] = tolower(str[i]); + i++; + } + lowerStr[i] = '\0'; + + // 根据转换后的小写字符串返回对应的枚举值 + if (strcmp(lowerStr, "up") == 0) { + return UP; + } else if (strcmp(lowerStr, "down") == 0) { + return DOWN; + } else if (strcmp(lowerStr, "left") == 0) { + return LEFT; + } else if (strcmp(lowerStr, "right") == 0) { + return RIGHT; + } else { + return UNDIR; + } +} + long int parse_color(const char *hex_str) { char *endptr; long int hex_num = strtol(hex_str, &endptr, 16); @@ -123,12 +153,43 @@ long int parse_color(const char *hex_str) { return hex_num; } +// 辅助函数:检查字符串是否以指定的前缀开头(忽略大小写) +static bool starts_with_ignore_case(const char *str, const char *prefix) { + while (*prefix) { + if (tolower(*str) != tolower(*prefix)) { + return false; + } + str++; + prefix++; + } + return true; +} + uint32_t parse_mod(const char *mod_str) { uint32_t mod = 0; - if (strstr(mod_str, "SUPER")) mod |= WLR_MODIFIER_LOGO; - if (strstr(mod_str, "CTRL")) mod |= WLR_MODIFIER_CTRL; - if (strstr(mod_str, "SHIFT")) mod |= WLR_MODIFIER_SHIFT; - if (strstr(mod_str, "ALT")) mod |= WLR_MODIFIER_ALT; + char lower_str[64]; // 假设输入的字符串长度不超过 64 + int i = 0; + + // 将 mod_str 转换为全小写 + for (i = 0; mod_str[i] && i < sizeof(lower_str) - 1; i++) { + lower_str[i] = tolower(mod_str[i]); + } + lower_str[i] = '\0'; // 确保字符串以 NULL 结尾 + + // 检查修饰键,忽略左右键标识(如 "_l" 和 "_r") + if (strstr(lower_str, "super") || strstr(lower_str, "super_l") || strstr(lower_str, "super_r")) { + mod |= WLR_MODIFIER_LOGO; + } + if (strstr(lower_str, "ctrl") || strstr(lower_str, "ctrl_l") || strstr(lower_str, "ctrl_r")) { + mod |= WLR_MODIFIER_CTRL; + } + if (strstr(lower_str, "shift") || strstr(lower_str, "shift_l") || strstr(lower_str, "shift_r")) { + mod |= WLR_MODIFIER_SHIFT; + } + if (strstr(lower_str, "alt") || strstr(lower_str, "alt_l") || strstr(lower_str, "alt_r")) { + mod |= WLR_MODIFIER_ALT; + } + return mod; } @@ -138,6 +199,71 @@ xkb_keysym_t parse_keysym(const char *keysym_str) { typedef void (*FuncType)(const Arg *); + +int parseButton(const char *str) { + // 将输入字符串转换为小写 + char lowerStr[20]; + int i = 0; + while (str[i] && i < 19) { + lowerStr[i] = tolower(str[i]); + i++; + } + lowerStr[i] = '\0'; // 确保字符串正确终止 + + // 根据转换后的小写字符串返回对应的按钮编号 + if (strcmp(lowerStr, "btn_left") == 0) { + return BTN_LEFT; + } else if (strcmp(lowerStr, "btn_right") == 0) { + return BTN_RIGHT; + } else if (strcmp(lowerStr, "btn_middle") == 0) { + return BTN_MIDDLE; + } else if (strcmp(lowerStr, "btn_side") == 0) { + return BTN_SIDE; + } else if (strcmp(lowerStr, "btn_extra") == 0) { + return BTN_EXTRA; + } else if (strcmp(lowerStr, "btn_forward") == 0) { + return BTN_FORWARD; + } else if (strcmp(lowerStr, "btn_back") == 0) { + return BTN_BACK; + } else if (strcmp(lowerStr, "btn_task") == 0) { + return BTN_TASK; + } else { + return 0; + } +} + + +int parseMouseAction(const char *str) { + // 将输入字符串转换为小写 + char lowerStr[20]; + int i = 0; + while (str[i] && i < 19) { + lowerStr[i] = tolower(str[i]); + i++; + } + lowerStr[i] = '\0'; // 确保字符串正确终止 + + // 根据转换后的小写字符串返回对应的按钮编号 + if (strcmp(lowerStr, "curmove") == 0) { + return CurMove; + } else if (strcmp(lowerStr, "curresize") == 0) { + return CurResize; + } else if (strcmp(lowerStr, "curnormal") == 0) { + return CurNormal; + } else if (strcmp(lowerStr, "curpressed") == 0) { + return CurPressed; + } else { + return 0; + } +} + +void parseColoer(float *color,unsigned long int hex) { + color[0] = ((hex >> 24) & 0xFF) / 255.0f; + color[1] = ((hex >> 16) & 0xFF) / 255.0f; + color[2] = ((hex >> 8) & 0xFF) / 255.0f; + color[3] = (hex & 0xFF) / 255.0f; +} + FuncType parse_func_name(char *func_name,Arg *arg, char *arg_value) { FuncType func = NULL; @@ -148,7 +274,7 @@ FuncType parse_func_name(char *func_name,Arg *arg, char *arg_value) { (*arg).i = atoi(arg_value); } else if (strcmp(func_name, "focusdir") == 0) { func = focusdir; - (*arg).i = atoi(arg_value); + (*arg).i = parseDirection(arg_value); } else if (strcmp(func_name, "incnmaster") == 0) { func = incnmaster; (*arg).i = atoi(arg_value); @@ -214,7 +340,7 @@ FuncType parse_func_name(char *func_name,Arg *arg, char *arg_value) { func = quit; } else if (strcmp(func_name, "moveresize") == 0) { func = moveresize; - (*arg).ui = atoi(arg_value); + (*arg).ui = parseMouseAction(arg_value); } else if (strcmp(func_name, "togglemaxmizescreen") == 0) { func = togglemaxmizescreen; } else if (strcmp(func_name, "viewtoleft_have_client") == 0) { @@ -309,49 +435,49 @@ void parse_config_line(Config *config, const char *line) { if (color == -1) { fprintf(stderr, "Error: Invalid rootcolor format: %s\n", value); } else { - config->rootcolor = color; + parseColoer(config->rootcolor,color); } } else if (strcmp(key, "bordercolor") == 0) { long int color = parse_color(value); if (color == -1) { fprintf(stderr, "Error: Invalid bordercolor format: %s\n", value); } else { - config->bordercolor = color; + parseColoer(config->bordercolor,color); } } else if (strcmp(key, "focuscolor") == 0) { long int color = parse_color(value); if (color == -1) { fprintf(stderr, "Error: Invalid focuscolor format: %s\n", value); } else { - config->focuscolor = color; + parseColoer(config->focuscolor,color); } } else if (strcmp(key, "maxmizescreencolor") == 0) { long int color = parse_color(value); if (color == -1) { fprintf(stderr, "Error: Invalid maxmizescreencolor format: %s\n", value); } else { - config->maxmizescreencolor = color; + parseColoer(config->maxmizescreencolor,color); } } else if (strcmp(key, "urgentcolor") == 0) { long int color = parse_color(value); if (color == -1) { fprintf(stderr, "Error: Invalid urgentcolor format: %s\n", value); } else { - config->urgentcolor = color; + parseColoer(config->urgentcolor,color); } } else if (strcmp(key, "scratchpadcolor") == 0) { long int color = parse_color(value); if (color == -1) { fprintf(stderr, "Error: Invalid scratchpadcolor format: %s\n", value); } else { - config->scratchpadcolor = color; + parseColoer(config->scratchpadcolor,color); } } else if (strcmp(key, "globalcolor") == 0) { long int color = parse_color(value); if (color == -1) { fprintf(stderr, "Error: Invalid globalcolor format: %s\n", value); } else { - config->globalcolor = color; + parseColoer(config->globalcolor,color); } } else if (strcmp(key, "autostart") == 0) { if (sscanf(value, "%[^,],%[^,],%[^,]", config->autostart[0], config->autostart[1], config->autostart[2]) != 3) { @@ -494,7 +620,7 @@ void parse_config_line(Config *config, const char *line) { } binding->mod = parse_mod(mod_str); - binding->button = atoi(button_str); + binding->button = parseButton(button_str); binding->arg.v = NULL; binding->func = parse_func_name(func_name, &binding->arg, arg_value); if (!binding->func){ @@ -519,7 +645,7 @@ void parse_config_line(Config *config, const char *line) { } binding->mod = parse_mod(mod_str); - binding->dir = atoi(dir_str); + binding->dir = parseDirection(dir_str); binding->arg.v = NULL; binding->func = parse_func_name(func_name, &binding->arg, arg_value); diff --git a/preset_config.h b/preset_config.h index c1f37cde..7cac46ce 100644 --- a/preset_config.h +++ b/preset_config.h @@ -39,7 +39,7 @@ unsigned int gappov = 10; /* vert outer gap between windows and screen int scroller_structs = 20; float scroller_default_proportion = 0.9; -int scoller_foucs_center = 0; +int scoller_focus_center = 0; float scroller_proportion_preset[] = {0.5,0.9,1.0}; int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */