diff --git a/README.md b/README.md index d512f39..087bf13 100644 --- a/README.md +++ b/README.md @@ -285,15 +285,3 @@ Read The Friendly Manual on packaging software in your distribution first. - https://github.com/swaywm/sway - Sample of Wayland protocol - https://github.com/wlrfx/scenefx - Make it simple to add window effect. - - -# Sponsor -At present, I can only accept sponsorship through an encrypted connection. -If you find this project helpful to you, you can offer sponsorship in the following ways. - -image - - -Thanks to the following friends for their sponsorship of this project - -[@tonybanters](https://github.com/tonybanters) diff --git a/config.conf b/config.conf index 6cbb3a2..5483a14 100644 --- a/config.conf +++ b/config.conf @@ -26,7 +26,7 @@ focused_opacity=1.0 unfocused_opacity=1.0 # Animation Configuration(support type:zoom,slide) -# tag_animation_direction: 1-horizontal,0-vertical +# tag_animation_direction: 0-horizontal,1-vertical animations=1 layer_animations=1 animation_type_open=slide diff --git a/mango.desktop b/mango.desktop index 37c4fad..0c109ce 100644 --- a/mango.desktop +++ b/mango.desktop @@ -1,7 +1,6 @@ [Desktop Entry] Encoding=UTF-8 Name=Mango -DesktopNames=mango;wlroots Comment=mango WM Exec=mango Icon=mango diff --git a/meson.build b/meson.build index 0565609..83b9513 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mango', ['c', 'cpp'], - version : '0.12.0', + version : '0.10.10', ) subdir('protocols') diff --git a/src/animation/client.h b/src/animation/client.h index 8de9b06..849bc10 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -363,6 +363,7 @@ void apply_border(Client *c) { current_corner_location = set_client_corner_location(c); } + // Handle no-border cases if (hit_no_border && smartgaps) { c->bw = 0; c->fake_no_border = true; @@ -980,12 +981,6 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) { c->bw = 0; } - bool hit_no_border = check_hit_no_border(c); - if (hit_no_border && smartgaps) { - c->bw = 0; - c->fake_no_border = true; - } - // c->geom 是真实的窗口大小和位置,跟过度的动画无关,用于计算布局 c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); @@ -1054,11 +1049,20 @@ void client_set_focused_opacity_animation(Client *c) { sizeof(c->opacity_animation.target_border_color)); c->opacity_animation.target_opacity = c->focused_opacity; c->opacity_animation.time_started = get_now_in_ms(); - memcpy(c->opacity_animation.initial_border_color, - c->opacity_animation.current_border_color, - sizeof(c->opacity_animation.initial_border_color)); - c->opacity_animation.initial_opacity = c->opacity_animation.current_opacity; - + if (c->opacity_animation.running) { + memcpy(c->opacity_animation.initial_border_color, + c->opacity_animation.current_border_color, + sizeof(c->opacity_animation.initial_border_color)); + c->opacity_animation.initial_opacity = + c->opacity_animation.current_opacity; + } else { + memcpy(c->opacity_animation.initial_border_color, border_color, + sizeof(c->opacity_animation.initial_border_color)); + memcpy(c->opacity_animation.current_border_color, border_color, + sizeof(c->opacity_animation.current_border_color)); + c->opacity_animation.initial_opacity = c->unfocused_opacity; + c->opacity_animation.current_opacity = c->unfocused_opacity; + } c->opacity_animation.running = true; } @@ -1078,10 +1082,20 @@ void client_set_unfocused_opacity_animation(Client *c) { c->opacity_animation.target_opacity = c->unfocused_opacity; c->opacity_animation.time_started = get_now_in_ms(); - memcpy(c->opacity_animation.initial_border_color, - c->opacity_animation.current_border_color, - sizeof(c->opacity_animation.initial_border_color)); - c->opacity_animation.initial_opacity = c->opacity_animation.current_opacity; + if (c->opacity_animation.running) { + memcpy(c->opacity_animation.initial_border_color, + c->opacity_animation.current_border_color, + sizeof(c->opacity_animation.initial_border_color)); + c->opacity_animation.initial_opacity = + c->opacity_animation.current_opacity; + } else { + memcpy(c->opacity_animation.initial_border_color, border_color, + sizeof(c->opacity_animation.initial_border_color)); + memcpy(c->opacity_animation.current_border_color, border_color, + sizeof(c->opacity_animation.current_border_color)); + c->opacity_animation.initial_opacity = c->focused_opacity; + c->opacity_animation.current_opacity = c->focused_opacity; + } c->opacity_animation.running = true; } @@ -1116,12 +1130,7 @@ bool client_apply_focus_opacity(Client *c) { if (target_opacity > opacity) { target_opacity = opacity; } - memcpy(c->opacity_animation.current_border_color, - c->opacity_animation.target_border_color, - sizeof(c->opacity_animation.current_border_color)); - c->opacity_animation.current_opacity = target_opacity; client_set_opacity(c, target_opacity); - client_set_border_color(c, c->opacity_animation.target_border_color); } else if (animations && c->opacity_animation.running) { struct timespec now; @@ -1152,7 +1161,7 @@ bool client_apply_focus_opacity(Client *c) { eased_progress; } client_set_border_color(c, c->opacity_animation.current_border_color); - if (linear_progress >= 1.0f) { + if (linear_progress == 1.0f) { c->opacity_animation.running = false; } else { return true; diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 7e24d43..9c27872 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -101,13 +101,15 @@ typedef struct { } ConfigWinRule; typedef struct { - 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 + const char *name; // 显示器名称 + float mfact; // 主区域比例 + int32_t nmaster; // 主区域窗口数量 + const char *layout; // 布局名称(字符串) + int32_t rr; // 旋转和翻转(假设为整数) + float scale; // 显示器缩放比例 + int32_t x, y; // 显示器位置 + int32_t width, height; // 显示器分辨率 + float refresh; // 刷新率 } ConfigMonitorRule; // 修改后的宏定义 @@ -154,11 +156,9 @@ typedef struct { } GestureBinding; typedef struct { - int32_t id; - char *layout_name; + int32_t id; // 标签ID (1-9) + char *layout_name; // 布局名称 char *monitor_name; - float mfact; - int32_t nmaster; int32_t no_render_border; int32_t no_hide; } ConfigTagRule; @@ -232,7 +232,6 @@ typedef struct { int32_t center_when_single_stack; uint32_t hotarea_size; - uint32_t hotarea_corner; uint32_t enable_hotarea; uint32_t ov_tab_mode; int32_t overviewgappi; @@ -244,8 +243,6 @@ typedef struct { int32_t idleinhibit_ignore_visible; int32_t sloppyfocus; int32_t warpcursor; - int32_t drag_corner; - int32_t drag_warp_cursor; /* keyboard */ int32_t repeat_rate; @@ -347,6 +344,7 @@ typedef struct { int32_t single_scratchpad; int32_t xwayland_persistence; int32_t syncobj_enable; + int32_t adaptive_sync; int32_t allow_tearing; int32_t allow_shortcuts_inhibit; int32_t allow_lock_transparent; @@ -405,10 +403,7 @@ int32_t parse_double_array(const char *input, double *output, char *endptr; double val = strtod(token, &endptr); if (endptr == token || *endptr != '\0') { - fprintf( - stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid number in array: %s\n", - token); + fprintf(stderr, "Error: Invalid number in array: %s\n", token); free(dup); return -1; } @@ -460,9 +455,7 @@ void parse_bind_flags(const char *str, KeyBinding *kb) { kb->ispassapply = true; break; default: - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown bind flag: %c\n", - suffix[i]); + // 忽略其他字符或可根据需要处理错误 break; } } @@ -550,58 +543,15 @@ 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; + return 0; } uint32_t mod = 0; char input_copy[256]; char *token; char *saveptr = NULL; - bool match_success = false; // 复制并转换为小写 strncpy(input_copy, mod_str, sizeof(input_copy) - 1); @@ -639,56 +589,35 @@ uint32_t parse_mod(const char *mod_str) { case 108: mod |= WLR_MODIFIER_ALT; break; - default: - fprintf(stderr, - "unknown modifier keycode: \033[1m\033[31m%s\n", - token); - break; } } } else { // 完整的 modifier 检查(保留原始所有检查项) - if (!strcmp(token, "super") || !strcmp(token, "super_l") || - !strcmp(token, "super_r")) { + if (strstr(token, "super") || strstr(token, "super_l") || + strstr(token, "super_r")) { mod |= WLR_MODIFIER_LOGO; - match_success = true; } - if (!strcmp(token, "ctrl") || !strcmp(token, "ctrl_l") || - !strcmp(token, "ctrl_r")) { + if (strstr(token, "ctrl") || strstr(token, "ctrl_l") || + strstr(token, "ctrl_r")) { mod |= WLR_MODIFIER_CTRL; - match_success = true; } - if (!strcmp(token, "shift") || !strcmp(token, "shift_l") || - !strcmp(token, "shift_r")) { + if (strstr(token, "shift") || strstr(token, "shift_l") || + strstr(token, "shift_r")) { mod |= WLR_MODIFIER_SHIFT; - match_success = true; } - if (!strcmp(token, "alt") || !strcmp(token, "alt_l") || - !strcmp(token, "alt_r")) { + if (strstr(token, "alt") || strstr(token, "alt_l") || + strstr(token, "alt_r")) { mod |= WLR_MODIFIER_ALT; - match_success = true; } - if (!strcmp(token, "hyper") || !strcmp(token, "hyper_l") || - !strcmp(token, "hyper_r")) { + if (strstr(token, "hyper") || strstr(token, "hyper_l") || + strstr(token, "hyper_r")) { mod |= WLR_MODIFIER_MOD3; - match_success = true; - } - if (!strcmp(token, "none")) { - match_success = true; } } token = strtok_r(NULL, "+", &saveptr); } - if (!match_success) { - mod = UINT32_MAX; - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown modifier: " - "\033[1m\033[31m%s\n", - mod_str); - } - return mod; } @@ -779,9 +708,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; @@ -805,17 +733,13 @@ KeySymCode parse_key(const char *key_str, bool isbindsym) { // 无法解析的键名 kc.type = KEY_TYPE_SYM; kc.keysym = XKB_KEY_NoSymbol; - fprintf( - stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown key: \033[1m\033[31m%s\n", - key_str); // keycode 字段保持为0 } return kc; } -uint32_t parse_button(const char *str) { +int32_t parse_button(const char *str) { // 将输入字符串转换为小写 char lowerStr[20]; int32_t i = 0; @@ -843,11 +767,7 @@ uint32_t parse_button(const char *str) { } else if (strcmp(lowerStr, "btn_task") == 0) { return BTN_TASK; } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown button: " - "\033[1m\033[31m%s\n", - str); - return UINT32_MAX; + return 0; } } @@ -898,12 +818,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; @@ -1054,14 +968,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); // 注意:之后需要释放这个内存 @@ -1170,9 +1080,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "toggle_monitor") == 0) { func = toggle_monitor; (*arg).v = strdup(arg_value); - } else if (strcmp(func_name, "scroller_stack") == 0) { - func = scroller_stack; - (*arg).i = parse_direction(arg_value); } else { return NULL; } @@ -1203,7 +1110,7 @@ void run_exec_once() { } } -bool parse_option(Config *config, char *key, char *value) { +void parse_option(Config *config, char *key, char *value) { if (strcmp(key, "keymode") == 0) { snprintf(config->keymode, sizeof(config->keymode), "%.27s", value); } else if (strcmp(key, "animations") == 0) { @@ -1254,70 +1161,53 @@ bool parse_option(Config *config, char *key, char *value) { int32_t num = parse_double_array(value, config->animation_curve_move, 4); if (num != 4) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_move: %s\n", + fprintf(stderr, "Error: Failed to parse animation_curve_move: %s\n", value); - return false; } } else if (strcmp(key, "animation_curve_open") == 0) { int32_t num = parse_double_array(value, config->animation_curve_open, 4); if (num != 4) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_open: %s\n", + fprintf(stderr, "Error: Failed to parse animation_curve_open: %s\n", value); - return false; } } else if (strcmp(key, "animation_curve_tag") == 0) { int32_t num = parse_double_array(value, config->animation_curve_tag, 4); if (num != 4) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_tag: %s\n", + fprintf(stderr, "Error: Failed to parse animation_curve_tag: %s\n", value); - return false; } } else if (strcmp(key, "animation_curve_close") == 0) { int32_t num = parse_double_array(value, config->animation_curve_close, 4); if (num != 4) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_close: %s\n", + "Error: Failed to parse animation_curve_close: %s\n", value); - return false; } } else if (strcmp(key, "animation_curve_focus") == 0) { int32_t num = parse_double_array(value, config->animation_curve_focus, 4); if (num != 4) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_focus: %s\n", + "Error: Failed to parse animation_curve_focus: %s\n", value); - return false; } } else if (strcmp(key, "animation_curve_opafadein") == 0) { int32_t num = parse_double_array(value, config->animation_curve_opafadein, 4); if (num != 4) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_opafadein: %s\n", + "Error: Failed to parse animation_curve_opafadein: %s\n", value); - return false; } } else if (strcmp(key, "animation_curve_opafadeout") == 0) { int32_t num = parse_double_array(value, config->animation_curve_opafadeout, 4); if (num != 4) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to parse " - "animation_curve_opafadeout: %s\n", + "Error: Failed to parse animation_curve_opafadeout: %s\n", value); - return false; } } else if (strcmp(key, "scroller_structs") == 0) { config->scroller_structs = atoi(value); @@ -1383,6 +1273,8 @@ bool parse_option(Config *config, char *key, char *value) { config->xwayland_persistence = atoi(value); } else if (strcmp(key, "syncobj_enable") == 0) { config->syncobj_enable = atoi(value); + } else if (strcmp(key, "adaptive_sync") == 0) { + config->adaptive_sync = atoi(value); } else if (strcmp(key, "allow_tearing") == 0) { config->allow_tearing = atoi(value); } else if (strcmp(key, "allow_shortcuts_inhibit") == 0) { @@ -1438,9 +1330,8 @@ 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"); - return false; + fprintf(stderr, "Error: Memory allocation failed\n"); + return; } // 3. 解析 value 中的浮点数 @@ -1453,18 +1344,16 @@ 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 " + "Error: 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; + return; } - // 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); @@ -1475,14 +1364,13 @@ bool parse_option(Config *config, char *key, char *value) { // 4. 检查解析的浮点数数量是否匹配 if (i != float_count) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid " - "scroller_proportion_preset format: %s\n", + "Error: Invalid scroller_proportion_preset format: %s\n", value); free(value_copy); free(config->scroller_proportion_preset); // 释放已分配的内存 config->scroller_proportion_preset = NULL; // 防止野指针 config->scroller_proportion_preset_count = 0; - return false; + return; } config->scroller_proportion_preset_count = float_count; @@ -1501,9 +1389,8 @@ 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"); - return false; + fprintf(stderr, "Error: Memory allocation failed\n"); + return; } // 3. 解析 value 中的字符串 @@ -1518,9 +1405,7 @@ bool parse_option(Config *config, char *key, char *value) { config->circle_layout[i] = strdup(cleaned_token); if (!config->circle_layout[i]) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Memory allocation " - "failed for " - "string: %s\n", + "Error: Memory allocation failed for string: %s\n", token); // 释放之前分配的内存 for (int32_t j = 0; j < i; j++) { @@ -1530,7 +1415,7 @@ bool parse_option(Config *config, char *key, char *value) { free(value_copy); config->circle_layout = NULL; // 防止野指针 config->circle_layout_count = 0; - return false; + return; } token = strtok(NULL, ","); i++; @@ -1538,10 +1423,7 @@ bool parse_option(Config *config, char *key, char *value) { // 4. 检查解析的字符串数量是否匹配 if (i != string_count) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid circle_layout " - "format: %s\n", - value); + fprintf(stderr, "Error: Invalid circle_layout format: %s\n", value); // 释放之前分配的内存 for (int32_t j = 0; j < i; j++) { free(config->circle_layout[j]); @@ -1550,7 +1432,7 @@ bool parse_option(Config *config, char *key, char *value) { free(value_copy); config->circle_layout = NULL; // 防止野指针 config->circle_layout_count = 0; - return false; + return; } config->circle_layout_count = string_count; @@ -1568,8 +1450,6 @@ bool parse_option(Config *config, char *key, char *value) { config->center_when_single_stack = atoi(value); } else if (strcmp(key, "hotarea_size") == 0) { config->hotarea_size = atoi(value); - } else if (strcmp(key, "hotarea_corner") == 0) { - config->hotarea_corner = atoi(value); } else if (strcmp(key, "enable_hotarea") == 0) { config->enable_hotarea = atoi(value); } else if (strcmp(key, "ov_tab_mode") == 0) { @@ -1592,10 +1472,6 @@ bool parse_option(Config *config, char *key, char *value) { config->sloppyfocus = atoi(value); } else if (strcmp(key, "warpcursor") == 0) { config->warpcursor = atoi(value); - } else if (strcmp(key, "drag_corner") == 0) { - config->drag_corner = atoi(value); - } else if (strcmp(key, "drag_warp_cursor") == 0) { - config->drag_warp_cursor = atoi(value); } else if (strcmp(key, "smartgaps") == 0) { config->smartgaps = atoi(value); } else if (strcmp(key, "repeat_rate") == 0) { @@ -1657,12 +1533,7 @@ bool parse_option(Config *config, char *key, char *value) { } else if (strcmp(key, "rootcolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid rootcolor " - "format: " - "%s\n", - value); - return false; + fprintf(stderr, "Error: Invalid rootcolor format: %s\n", value); } else { convert_hex_to_rgba(config->rootcolor, color); } @@ -1670,172 +1541,68 @@ bool parse_option(Config *config, char *key, char *value) { } else if (strcmp(key, "shadowscolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid shadowscolor " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid shadowscolor format: %s\n", value); } else { convert_hex_to_rgba(config->shadowscolor, color); } } else if (strcmp(key, "bordercolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid bordercolor " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid bordercolor format: %s\n", value); } else { convert_hex_to_rgba(config->bordercolor, color); } } else if (strcmp(key, "focuscolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid focuscolor " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid focuscolor format: %s\n", value); } else { convert_hex_to_rgba(config->focuscolor, color); } } 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", + fprintf(stderr, "Error: Invalid maximizescreencolor format: %s\n", value); - return false; } else { convert_hex_to_rgba(config->maximizescreencolor, color); } } else if (strcmp(key, "urgentcolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid urgentcolor " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid urgentcolor format: %s\n", value); } else { convert_hex_to_rgba(config->urgentcolor, color); } } else if (strcmp(key, "scratchpadcolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid " - "scratchpadcolor " - "format: %s\n", + fprintf(stderr, "Error: Invalid scratchpadcolor format: %s\n", value); - return false; } else { convert_hex_to_rgba(config->scratchpadcolor, color); } } else if (strcmp(key, "globalcolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid globalcolor " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid globalcolor format: %s\n", value); } else { convert_hex_to_rgba(config->globalcolor, color); } } else if (strcmp(key, "overlaycolor") == 0) { int64_t color = parse_color(value); if (color == -1) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid overlaycolor " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid overlaycolor format: %s\n", value); } else { convert_hex_to_rgba(config->overlaycolor, color); } - } else if (strcmp(key, "monitorrule") == 0) { - config->monitor_rules = - realloc(config->monitor_rules, (config->monitor_rules_count + 1) * - sizeof(ConfigMonitorRule)); - if (!config->monitor_rules) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for monitor rules\n"); - return false; - } - - ConfigMonitorRule *rule = - &config->monitor_rules[config->monitor_rules_count]; - memset(rule, 0, sizeof(ConfigMonitorRule)); - - // 设置默认值 - rule->name = NULL; - rule->rr = 0; - rule->scale = 1.0f; - rule->x = INT32_MAX; - rule->y = INT32_MAX; - rule->width = -1; - rule->height = -1; - rule->refresh = 0.0f; - rule->vrr = 0; - - bool parse_error = false; - char *token = strtok(value, ","); - while (token != NULL) { - char *colon = strchr(token, ':'); - if (colon != NULL) { - *colon = '\0'; - char *key = token; - char *val = colon + 1; - - trim_whitespace(key); - trim_whitespace(val); - - if (strcmp(key, "name") == 0) { - rule->name = strdup(val); - } else if (strcmp(key, "rr") == 0) { - rule->rr = CLAMP_INT(atoi(val), 0, 7); - } else if (strcmp(key, "scale") == 0) { - rule->scale = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f); - } else if (strcmp(key, "x") == 0) { - rule->x = atoi(val); - } else if (strcmp(key, "y") == 0) { - rule->y = atoi(val); - } else if (strcmp(key, "width") == 0) { - rule->width = CLAMP_INT(atoi(val), 1, INT32_MAX); - } else if (strcmp(key, "height") == 0) { - rule->height = CLAMP_INT(atoi(val), 1, INT32_MAX); - } else if (strcmp(key, "refresh") == 0) { - rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f); - } 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); - parse_error = true; - } - } - token = strtok(NULL, ","); - } - - config->monitor_rules_count++; - return !parse_error; } else if (strcmp(key, "tagrule") == 0) { config->tag_rules = realloc(config->tag_rules, (config->tag_rules_count + 1) * sizeof(ConfigTagRule)); if (!config->tag_rules) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for tag rules\n"); - return false; + fprintf(stderr, "Error: Failed to allocate memory for tag rules\n"); + return; } ConfigTagRule *rule = &config->tag_rules[config->tag_rules_count]; @@ -1845,12 +1612,7 @@ bool parse_option(Config *config, char *key, char *value) { rule->id = 0; rule->layout_name = NULL; rule->monitor_name = NULL; - rule->nmaster = 0; - rule->mfact = 0.0f; - rule->no_render_border = 0; - rule->no_hide = 0; - bool parse_error = false; char *token = strtok(value, ","); while (token != NULL) { char *colon = strchr(token, ':'); @@ -1872,33 +1634,20 @@ bool parse_option(Config *config, char *key, char *value) { rule->no_render_border = CLAMP_INT(atoi(val), 0, 1); } else if (strcmp(key, "no_hide") == 0) { rule->no_hide = CLAMP_INT(atoi(val), 0, 1); - } else if (strcmp(key, "nmaster") == 0) { - rule->nmaster = CLAMP_INT(atoi(val), 1, 99); - } else if (strcmp(key, "mfact") == 0) { - rule->mfact = CLAMP_FLOAT(atof(val), 0.1f, 0.9f); - } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "tag rule " - "option:\033[1m\033[31m %s\n", - key); - parse_error = true; } } token = strtok(NULL, ","); } config->tag_rules_count++; - return !parse_error; } else if (strcmp(key, "layerrule") == 0) { config->layer_rules = realloc(config->layer_rules, (config->layer_rules_count + 1) * sizeof(ConfigLayerRule)); if (!config->layer_rules) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for layer rules\n"); - return false; + "Error: Failed to allocate memory for layer rules\n"); + return; } ConfigLayerRule *rule = &config->layer_rules[config->layer_rules_count]; @@ -1912,7 +1661,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->noanim = 0; rule->noshadow = 0; - bool parse_error = false; char *token = strtok(value, ","); while (token != NULL) { char *colon = strchr(token, ':'); @@ -1936,13 +1684,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->noanim = CLAMP_INT(atoi(val), 0, 1); } 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); - parse_error = true; } } token = strtok(NULL, ","); @@ -1954,16 +1695,14 @@ bool parse_option(Config *config, char *key, char *value) { } config->layer_rules_count++; - return !parse_error; } else if (strcmp(key, "windowrule") == 0) { config->window_rules = realloc(config->window_rules, (config->window_rules_count + 1) * sizeof(ConfigWinRule)); if (!config->window_rules) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for window rules\n"); - return false; + "Error: Failed to allocate memory for window rules\n"); + return; } ConfigWinRule *rule = &config->window_rules[config->window_rules_count]; @@ -2019,7 +1758,6 @@ bool parse_option(Config *config, char *key, char *value) { rule->globalkeybinding = (KeyBinding){0}; - bool parse_error = false; char *token = strtok(value, ","); while (token != NULL) { char *colon = strchr(token, ':'); @@ -2119,37 +1857,86 @@ bool parse_option(Config *config, char *key, char *value) { rule->globalkeybinding.mod = parse_mod(mod_str); rule->globalkeybinding.keysymcode = parse_key(keysym_str, false); - if (rule->globalkeybinding.mod == UINT32_MAX) { - return false; - } - if (rule->globalkeybinding.keysymcode.type == - KEY_TYPE_SYM && - rule->globalkeybinding.keysymcode.keysym == - XKB_KEY_NoSymbol) { - return false; - } - } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown " - "window rule " - "option:\033[1m\033[31m %s\n", - key); - parse_error = true; } } token = strtok(NULL, ","); } config->window_rules_count++; - return !parse_error; + } else if (strcmp(key, "monitorrule") == 0) { + config->monitor_rules = + realloc(config->monitor_rules, (config->monitor_rules_count + 1) * + sizeof(ConfigMonitorRule)); + if (!config->monitor_rules) { + fprintf(stderr, + "Error: Failed to allocate memory for monitor rules\n"); + return; + } + + ConfigMonitorRule *rule = + &config->monitor_rules[config->monitor_rules_count]; + memset(rule, 0, sizeof(ConfigMonitorRule)); + + // 临时存储每个字段的原始字符串 + char raw_name[256], raw_layout[256]; + char raw_mfact[256], raw_nmaster[256], raw_rr[256]; + char raw_scale[256], raw_x[256], raw_y[256], raw_width[256], + raw_height[256], raw_refresh[256]; + + // 先读取所有字段为字符串 + int32_t parsed = + sscanf(value, + "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[" + "^,],%255[^,],%255[^,],%255[^,],%255[^,],%255s", + raw_name, raw_mfact, raw_nmaster, raw_layout, raw_rr, + raw_scale, raw_x, raw_y, raw_width, raw_height, raw_refresh); + + if (parsed == 11) { + // 修剪每个字段的空格 + trim_whitespace(raw_name); + trim_whitespace(raw_mfact); + trim_whitespace(raw_nmaster); + trim_whitespace(raw_layout); + trim_whitespace(raw_rr); + trim_whitespace(raw_scale); + trim_whitespace(raw_x); + trim_whitespace(raw_y); + trim_whitespace(raw_width); + trim_whitespace(raw_height); + trim_whitespace(raw_refresh); + + // 转换修剪后的字符串为特定类型 + rule->name = strdup(raw_name); + rule->layout = strdup(raw_layout); + rule->mfact = atof(raw_mfact); + rule->nmaster = atoi(raw_nmaster); + rule->rr = atoi(raw_rr); + rule->scale = atof(raw_scale); + rule->x = atoi(raw_x); + rule->y = atoi(raw_y); + rule->width = atoi(raw_width); + rule->height = atoi(raw_height); + rule->refresh = atof(raw_refresh); + + if (!rule->name || !rule->layout) { + if (rule->name) + free((void *)rule->name); + if (rule->layout) + free((void *)rule->layout); + fprintf(stderr, + "Error: Failed to allocate memory for monitor rule\n"); + return; + } + + config->monitor_rules_count++; + } else { + fprintf(stderr, "Error: Invalid monitorrule format: %s\n", value); + } } else if (strncmp(key, "env", 3) == 0) { char env_type[256], env_value[256]; if (sscanf(value, "%255[^,],%255[^\n]", env_type, env_value) < 2) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid bind format: " - "\033[1m\033[31m%s\n", - value); - return false; + fprintf(stderr, "Error: Invalid bind format: %s\n", value); + return; } trim_whitespace(env_type); trim_whitespace(env_value); @@ -2164,9 +1951,8 @@ bool parse_option(Config *config, char *key, char *value) { free(env->type); free(env->value); free(env); - fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Failed to " - "allocate memory for env\n"); - return false; + fprintf(stderr, "Error: Failed to allocate memory for env\n"); + return; } config->env[config->env_count] = env; @@ -2176,18 +1962,15 @@ bool parse_option(Config *config, char *key, char *value) { char **new_exec = realloc(config->exec, (config->exec_count + 1) * sizeof(char *)); if (!new_exec) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for exec\n"); - return false; + fprintf(stderr, "Error: Failed to allocate memory for exec\n"); + return; } config->exec = new_exec; config->exec[config->exec_count] = strdup(value); if (!config->exec[config->exec_count]) { - fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Failed to " - "duplicate exec string\n"); - return false; + fprintf(stderr, "Error: Failed to duplicate exec string\n"); + return; } config->exec_count++; @@ -2197,19 +1980,15 @@ bool parse_option(Config *config, char *key, char *value) { char **new_exec_once = realloc( config->exec_once, (config->exec_once_count + 1) * sizeof(char *)); if (!new_exec_once) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for exec_once\n"); - return false; + fprintf(stderr, "Error: Failed to allocate memory for exec_once\n"); + return; } config->exec_once = new_exec_once; config->exec_once[config->exec_once_count] = strdup(value); if (!config->exec_once[config->exec_once_count]) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to duplicate " - "exec_once string\n"); - return false; + fprintf(stderr, "Error: Failed to duplicate exec_once string\n"); + return; } config->exec_once_count++; @@ -2220,9 +1999,8 @@ bool parse_option(Config *config, char *key, char *value) { (config->key_bindings_count + 1) * sizeof(KeyBinding)); if (!config->key_bindings) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for key bindings\n"); - return false; + "Error: Failed to allocate memory for key bindings\n"); + return; } KeyBinding *binding = &config->key_bindings[config->key_bindings_count]; @@ -2233,16 +2011,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, keysym_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid bind format: " - "\033[1m\033[31m%s\n", - value); - return false; + fprintf(stderr, "Error: Invalid bind format: %s\n", value); + return; } trim_whitespace(mod_str); trim_whitespace(keysym_str); @@ -2269,21 +2043,13 @@ 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; binding->func = parse_func_name(func_name, &binding->arg, arg_value, arg_value2, arg_value3, arg_value4, arg_value5); - if (!binding->func || binding->mod == UINT32_MAX || - (binding->keysymcode.type == KEY_TYPE_SYM && - binding->keysymcode.keysym == XKB_KEY_NoSymbol)) { + if (!binding->func) { if (binding->arg.v) { free(binding->arg.v); binding->arg.v = NULL; @@ -2296,13 +2062,7 @@ 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 bind: " - "\033[1m\033[31m%s\n", - func_name); - return false; + fprintf(stderr, "Error: Unknown function in bind: %s\n", func_name); } else { config->key_bindings_count++; } @@ -2313,9 +2073,8 @@ bool parse_option(Config *config, char *key, char *value) { (config->mouse_bindings_count + 1) * sizeof(MouseBinding)); if (!config->mouse_bindings) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for mouse bindings\n"); - return false; + "Error: Failed to allocate memory for mouse bindings\n"); + return; } MouseBinding *binding = @@ -2327,17 +2086,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: " - "%s\n", - value); - return false; + fprintf(stderr, "Error: Invalid mousebind format: %s\n", value); + return; } trim_whitespace(mod_str); trim_whitespace(button_str); @@ -2350,20 +2104,13 @@ 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; binding->func = parse_func_name(func_name, &binding->arg, arg_value, arg_value2, arg_value3, arg_value4, arg_value5); - if (!binding->func || binding->mod == UINT32_MAX || - binding->button == UINT32_MAX) { + if (!binding->func) { if (binding->arg.v) { free(binding->arg.v); binding->arg.v = NULL; @@ -2376,13 +2123,8 @@ 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 " - "mousebind: \033[1m\033[31m%s\n", - func_name); - return false; + fprintf(stderr, "Error: Unknown function in mousebind: %s\n", + func_name); } else { config->mouse_bindings_count++; } @@ -2392,9 +2134,8 @@ bool parse_option(Config *config, char *key, char *value) { (config->axis_bindings_count + 1) * sizeof(AxisBinding)); if (!config->axis_bindings) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for axis bindings\n"); - return false; + "Error: Failed to allocate memory for axis bindings\n"); + return; } AxisBinding *binding = @@ -2406,16 +2147,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, 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); - return false; + fprintf(stderr, "Error: Invalid axisbind format: %s\n", value); + return; } trim_whitespace(mod_str); @@ -2436,7 +2173,7 @@ bool parse_option(Config *config, char *key, char *value) { parse_func_name(func_name, &binding->arg, arg_value, arg_value2, arg_value3, arg_value4, arg_value5); - if (!binding->func || binding->mod == UINT32_MAX) { + if (!binding->func) { if (binding->arg.v) { free(binding->arg.v); binding->arg.v = NULL; @@ -2449,13 +2186,8 @@ 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 " - "axisbind: \033[1m\033[31m%s\n", - func_name); - return false; + fprintf(stderr, "Error: Unknown function in axisbind: %s\n", + func_name); } else { config->axis_bindings_count++; } @@ -2466,9 +2198,8 @@ bool parse_option(Config *config, char *key, char *value) { sizeof(SwitchBinding)); if (!config->switch_bindings) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for switch bindings\n"); - return false; + "Error: Failed to allocate memory for switch bindings\n"); + return; } SwitchBinding *binding = @@ -2480,16 +2211,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[" "^\n]", fold_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid switchbind " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid switchbind format: %s\n", value); + return; } trim_whitespace(fold_str); trim_whitespace(func_name); @@ -2517,13 +2244,8 @@ bool parse_option(Config *config, char *key, char *value) { free(binding->arg.v3); binding->arg.v3 = NULL; } - - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in " - "switchbind: " - "\033[1m\033[31m%s\n", + fprintf(stderr, "Error: Unknown function in switchbind: %s\n", func_name); - return false; } else { config->switch_bindings_count++; } @@ -2534,9 +2256,8 @@ bool parse_option(Config *config, char *key, char *value) { (config->gesture_bindings_count + 1) * sizeof(GestureBinding)); if (!config->gesture_bindings) { fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Failed to allocate " - "memory for axis gesturebind\n"); - return false; + "Error: Failed to allocate memory for axis gesturebind\n"); + return; } GestureBinding *binding = @@ -2548,16 +2269,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[^,],%255[^\n]", mod_str, motion_str, fingers_count_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 4) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Invalid gesturebind " - "format: %s\n", - value); - return false; + fprintf(stderr, "Error: Invalid gesturebind format: %s\n", value); + return; } trim_whitespace(mod_str); @@ -2573,12 +2290,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; @@ -2586,7 +2297,7 @@ bool parse_option(Config *config, char *key, char *value) { parse_func_name(func_name, &binding->arg, arg_value, arg_value2, arg_value3, arg_value4, arg_value5); - if (!binding->func || binding->mod == UINT32_MAX) { + if (!binding->func) { if (binding->arg.v) { free(binding->arg.v); binding->arg.v = NULL; @@ -2599,13 +2310,8 @@ 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 " - "axisbind: \033[1m\033[31m%s\n", - func_name); - return false; + fprintf(stderr, "Error: Unknown function in axisbind: %s\n", + func_name); } else { config->gesture_bindings_count++; } @@ -2613,30 +2319,22 @@ bool parse_option(Config *config, char *key, char *value) { } else if (strncmp(key, "source", 6) == 0) { parse_config_file(config, value); } else { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m Unknown keyword: " - "\033[1m\033[31m%s\n", - key); - return false; + fprintf(stderr, "Error: Unknown key: %s\n", key); } - - return true; } -bool parse_config_line(Config *config, const char *line) { +void 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); - return false; + // fprintf(stderr, "Error: Invalid line format: %s\n", line); + return; } // Then trim each part separately trim_whitespace(key); trim_whitespace(value); - return parse_option(config, key, value); + parse_option(config, key, value); } void parse_config_file(Config *config, const char *file_path) { @@ -2655,9 +2353,7 @@ void parse_config_file(Config *config, const char *file_path) { } else { const char *home = getenv("HOME"); if (!home) { - fprintf(stderr, - "\033[1m\033[31m[ERROR]:\033[33m HOME environment " - "variable not set.\n"); + fprintf(stderr, "Error: HOME environment variable not set.\n"); return; } snprintf(full_path, sizeof(full_path), "%s/.config/mango/%s", home, @@ -2671,8 +2367,7 @@ void parse_config_file(Config *config, const char *file_path) { const char *home = getenv("HOME"); if (!home) { - fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m HOME environment " - "variable not set.\n"); + fprintf(stderr, "Error: HOME environment variable not set.\n"); return; } snprintf(full_path, sizeof(full_path), "%s%s", home, file_path + 1); @@ -2684,29 +2379,16 @@ void parse_config_file(Config *config, const char *file_path) { } if (!file) { - fprintf(stderr, - "\033[1;31m\033[1;33m[ERROR]:\033[0m Failed to open " - "config file: %s\n", - file_path); + perror("Error opening file"); return; } char line[512]; - bool parse_correct = true; - uint32_t line_count = 0; while (fgets(line, sizeof(line), file)) { - line_count++; if (line[0] == '#' || line[0] == '\n') { continue; } - 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" - " \033[1;36m╰─\033[0;33m%s\033[0m\n\n", - file_path, line_count, line); - } + parse_config_line(config, line); } fclose(file); @@ -2792,6 +2474,18 @@ void free_config(void) { config.window_rules_count = 0; } + // 释放 monitor_rules + if (config.monitor_rules) { + for (int32_t i = 0; i < config.monitor_rules_count; i++) { + ConfigMonitorRule *rule = &config.monitor_rules[i]; + free((void *)rule->name); + free((void *)rule->layout); + } + free(config.monitor_rules); + config.monitor_rules = NULL; + config.monitor_rules_count = 0; + } + // 释放 key_bindings if (config.key_bindings) { for (i = 0; i < config.key_bindings_count; i++) { @@ -2910,17 +2604,6 @@ void free_config(void) { config.tag_rules_count = 0; } - // 释放 monitor_rules - if (config.monitor_rules) { - for (int32_t i = 0; i < config.monitor_rules_count; i++) { - if (config.monitor_rules[i].name) - free((void *)config.monitor_rules[i].name); - } - free(config.monitor_rules); - config.monitor_rules = NULL; - config.monitor_rules_count = 0; - } - // 释放 layer_rules if (config.layer_rules) { for (int32_t i = 0; i < config.layer_rules_count; i++) { @@ -3052,7 +2735,6 @@ void override_config(void) { // 概述模式设置 hotarea_size = CLAMP_INT(config.hotarea_size, 1, 1000); - hotarea_corner = CLAMP_INT(config.hotarea_corner, 0, 3); enable_hotarea = CLAMP_INT(config.enable_hotarea, 0, 1); ov_tab_mode = CLAMP_INT(config.ov_tab_mode, 0, 1); overviewgappi = CLAMP_INT(config.overviewgappi, 0, 1000); @@ -3061,6 +2743,7 @@ void override_config(void) { // 杂项设置 xwayland_persistence = CLAMP_INT(config.xwayland_persistence, 0, 1); syncobj_enable = CLAMP_INT(config.syncobj_enable, 0, 1); + adaptive_sync = CLAMP_INT(config.adaptive_sync, 0, 1); allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2); allow_shortcuts_inhibit = CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1); allow_lock_transparent = CLAMP_INT(config.allow_lock_transparent, 0, 1); @@ -3071,8 +2754,6 @@ void override_config(void) { CLAMP_INT(config.idleinhibit_ignore_visible, 0, 1); sloppyfocus = CLAMP_INT(config.sloppyfocus, 0, 1); warpcursor = CLAMP_INT(config.warpcursor, 0, 1); - drag_corner = CLAMP_INT(config.drag_corner, 0, 4); - drag_warp_cursor = CLAMP_INT(config.drag_warp_cursor, 0, 1); focus_cross_monitor = CLAMP_INT(config.focus_cross_monitor, 0, 1); exchange_cross_monitor = CLAMP_INT(config.exchange_cross_monitor, 0, 1); scratchpad_cross_monitor = CLAMP_INT(config.scratchpad_cross_monitor, 0, 1); @@ -3215,12 +2896,11 @@ void set_value_default() { config.numlockon = numlockon; // 是否打开右边小键盘 - config.ov_tab_mode = ov_tab_mode; // alt tab切换模式 - config.hotarea_size = hotarea_size; // 热区大小,10x10 - config.hotarea_corner = hotarea_corner; + config.ov_tab_mode = ov_tab_mode; // alt tab切换模式 + config.hotarea_size = hotarea_size; // 热区大小,10x10 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 */ @@ -3248,6 +2928,7 @@ void set_value_default() { config.single_scratchpad = single_scratchpad; config.xwayland_persistence = xwayland_persistence; config.syncobj_enable = syncobj_enable; + config.adaptive_sync = adaptive_sync; config.allow_tearing = allow_tearing; config.allow_shortcuts_inhibit = allow_shortcuts_inhibit; config.allow_lock_transparent = allow_lock_transparent; @@ -3270,8 +2951,6 @@ void set_value_default() { config.cursor_hide_timeout = cursor_hide_timeout; config.warpcursor = warpcursor; /* Warp cursor to focused client */ - config.drag_corner = drag_corner; - config.drag_warp_cursor = drag_warp_cursor; config.repeat_rate = repeat_rate; config.repeat_delay = repeat_delay; @@ -3472,8 +3151,7 @@ void reset_blur_params(void) { void reapply_monitor_rules(void) { ConfigMonitorRule *mr; Monitor *m = NULL; - int32_t ji, vrr; - int32_t mx, my; + int32_t ji, jk; struct wlr_output_state state; struct wlr_output_mode *internal_mode = NULL; wlr_output_state_init(&state); @@ -3488,11 +3166,20 @@ void reapply_monitor_rules(void) { break; mr = &config.monitor_rules[ji]; - if (regex_match(mr->name, m->wlr_output->name)) { + if (!mr->name || regex_match(mr->name, m->wlr_output->name)) { - 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; + m->mfact = mr->mfact; + m->nmaster = mr->nmaster; + m->m.x = mr->x; + m->m.y = mr->y; + + if (mr->layout) { + for (jk = 0; jk < LENGTH(layouts); jk++) { + if (strcmp(layouts[jk].name, mr->layout) == 0) { + m->lt = &layouts[jk]; + } + } + } if (mr->width > 0 && mr->height > 0 && mr->refresh > 0) { internal_mode = get_nearest_output_mode( @@ -3506,18 +3193,17 @@ void reapply_monitor_rules(void) { } } - if (vrr) { - enable_adaptive_sync(m, &state); - } else { - wlr_output_state_set_adaptive_sync_enabled(&state, false); - } - wlr_output_state_set_scale(&state, mr->scale); wlr_output_state_set_transform(&state, mr->rr); - wlr_output_layout_add(output_layout, m->wlr_output, mx, my); + wlr_output_layout_add(output_layout, m->wlr_output, mr->x, + mr->y); } } + if (adaptive_sync) { + enable_adaptive_sync(m, &state); + } + wlr_output_commit_state(m->wlr_output, &state); wlr_output_state_finish(&state); updatemons(NULL, NULL); @@ -3558,8 +3244,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; @@ -3622,12 +3306,6 @@ void reapply_master(void) { void parse_tagrule(Monitor *m) { int32_t i, jk; ConfigTagRule tr; - Client *c = NULL; - - for (i = 0; i <= LENGTH(tags); i++) { - m->pertag->nmasters[i] = default_nmaster; - m->pertag->mfacts[i] = default_mfact; - } for (i = 0; i < config.tag_rules_count; i++) { @@ -3644,23 +3322,7 @@ void parse_tagrule(Monitor *m) { } } - if (tr.no_hide >= 0) - m->pertag->no_hide[tr.id] = tr.no_hide; - if (tr.nmaster >= 1) - m->pertag->nmasters[tr.id] = tr.nmaster; - if (tr.mfact > 0.0f) - m->pertag->mfacts[tr.id] = tr.mfact; - if (tr.no_render_border >= 0) - m->pertag->no_render_border[tr.id] = tr.no_render_border; - } - } - - for (i = 1; i <= LENGTH(tags); i++) { - wl_list_for_each(c, &clients, link) { - if ((c->tags & (1 << (i - 1)) & TAGMASK) && ISTILED(c)) { - if (m->pertag->mfacts[i] > 0.0f) - c->master_mfact_per = m->pertag->mfacts[i]; - } + m->pertag->no_hide[tr.id] = tr.no_hide; } } } @@ -3685,7 +3347,6 @@ void reset_option(void) { reapply_cursor_style(); reapply_border(); - reapply_rootbg(); reapply_keyboard(); reapply_pointer(); reapply_master(); diff --git a/src/config/preset.h b/src/config/preset.h index ae4424f..6f3cd89 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -47,9 +47,8 @@ int32_t log_level = WLR_ERROR; uint32_t numlockon = 0; // 是否打开右边小键盘 uint32_t capslock = 0; // 是否启用快捷键 -uint32_t ov_tab_mode = 0; // alt tab切换模式 -uint32_t hotarea_size = 10; // 热区大小,10x10 -uint32_t hotarea_corner = BOTTOM_LEFT; +uint32_t ov_tab_mode = 0; // alt tab切换模式 +uint32_t hotarea_size = 10; // 热区大小,10x10 uint32_t enable_hotarea = 1; // 是否启用鼠标热区 int32_t smartgaps = 0; /* 1 means no outer gap when there is only one window */ int32_t sloppyfocus = 1; /* focus follows mouse */ @@ -63,7 +62,7 @@ float scratchpad_height_ratio = 0.9; int32_t scroller_structs = 20; float scroller_default_proportion = 0.9; float scroller_default_proportion_single = 1.0; -int32_t scroller_ignore_proportion_single = 1; +int32_t scroller_ignore_proportion_single = 0; int32_t scroller_focus_center = 0; int32_t scroller_prefer_center = 0; int32_t focus_cross_monitor = 0; @@ -102,14 +101,12 @@ int32_t overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */ * behavior */ float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; -int32_t warpcursor = 1; -int32_t drag_corner = 3; -int32_t drag_warp_cursor = 1; +int32_t warpcursor = 1; /* Warp cursor to focused client */ int32_t xwayland_persistence = 1; /* xwayland persistence */ int32_t syncobj_enable = 0; +int32_t adaptive_sync = 0; int32_t allow_lock_transparent = 0; -double drag_tile_refresh_interval = 16.0; -double drag_floating_refresh_interval = 8.0; +double drag_refresh_interval = 16.0; int32_t allow_tearing = TEARING_DISABLED; int32_t allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE; @@ -236,3 +233,4 @@ double shadows_blur = 15; int32_t shadows_position_x = 0; int32_t shadows_position_y = 0; float shadowscolor[] = COLOR(0x000000ff); +; diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index 22ef612..b197778 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -68,5 +68,4 @@ int32_t toggle_trackpad_enable(const Arg *arg); int32_t setoption(const Arg *arg); int32_t disable_monitor(const Arg *arg); int32_t enable_monitor(const Arg *arg); -int32_t toggle_monitor(const Arg *arg); -int32_t scroller_stack(const Arg *arg); \ No newline at end of file +int32_t toggle_monitor(const Arg *arg); \ No newline at end of file diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index c0e51dc..28879df 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -129,7 +129,6 @@ int32_t exchange_stack_client(const Arg *arg) { int32_t focusdir(const Arg *arg) { Client *c = NULL; c = direction_select(arg); - c = get_focused_stack_client(c); if (c) { focusclient(c, 1); if (warpcursor) @@ -338,9 +337,6 @@ int32_t killclient(const Arg *arg) { } int32_t moveresize(const Arg *arg) { - const char *cursors[] = {"nw-resize", "ne-resize", "sw-resize", - "se-resize"}; - if (cursor_mode != CurNormal && cursor_mode != CurPressed) return 0; xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); @@ -366,29 +362,10 @@ int32_t moveresize(const Arg *arg) { /* Doesn't work for X11 output - the next absolute motion event * returns the cursor to where it started */ if (grabc->isfloating) { - rzcorner = drag_corner; - grabcx = (int)round(cursor->x); - grabcy = (int)round(cursor->y); - if (rzcorner == 4) - /* identify the closest corner index */ - rzcorner = (grabcx - grabc->geom.x < - grabc->geom.x + grabc->geom.width - grabcx - ? 0 - : 1) + - (grabcy - grabc->geom.y < - grabc->geom.y + grabc->geom.height - grabcy - ? 0 - : 2); - - if (drag_warp_cursor) { - grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width - : grabc->geom.x; - grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height - : grabc->geom.y; - wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy); - } - - wlr_cursor_set_xcursor(cursor, cursor_mgr, cursors[rzcorner]); + wlr_cursor_warp_closest(cursor, NULL, + grabc->geom.x + grabc->geom.width, + grabc->geom.y + grabc->geom.height); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "bottom_right_corner"); } else { wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab"); } @@ -448,10 +425,6 @@ int32_t resizewin(const Arg *arg) { if (!c || c->isfullscreen || c->ismaximizescreen) return 0; - int32_t animations_state_backup = animations; - if (!c->isfloating) - animations = 0; - if (ISTILED(c)) { switch (arg->ui) { case NUM_TYPE_MINUS: @@ -477,7 +450,6 @@ int32_t resizewin(const Arg *arg) { break; } resize_tile_client(c, false, offsetx, offsety, 0); - animations = animations_state_backup; return 0; } @@ -508,7 +480,6 @@ int32_t resizewin(const Arg *arg) { c->iscustomsize = 1; c->float_geom = c->geom; resize(c, c->geom, 0); - animations = animations_state_backup; return 0; } @@ -579,14 +550,12 @@ int32_t set_proportion(const Arg *arg) { !scroller_ignore_proportion_single) return 0; - Client *tc = selmon->sel; - - if (tc) { - tc = get_scroll_stack_head(tc); + if (selmon->sel) { uint32_t max_client_width = selmon->w.width - 2 * scroller_structs - gappih; - tc->scroller_proportion = arg->f; - tc->geom.width = max_client_width * arg->f; + selmon->sel->scroller_proportion = arg->f; + selmon->sel->geom.width = max_client_width * arg->f; + // resize(selmon->sel, selmon->sel->geom, 0); arrange(selmon, false, false); } return 0; @@ -771,7 +740,7 @@ int32_t centerwin(const Arg *arg) { return 0; if (c->isfloating) { - c->float_geom = setclient_coordinate_center(c, c->mon, c->geom, 0, 0); + c->float_geom = setclient_coordinate_center(c, c->geom, 0, 0); c->iscustomsize = 1; resize(c, c->float_geom, 1); return 0; @@ -780,13 +749,10 @@ int32_t centerwin(const Arg *arg) { if (!is_scroller_layout(selmon)) return 0; - Client *stack_head = get_scroll_stack_head(c); if (selmon->pertag->ltidxs[selmon->pertag->curtag]->id == SCROLLER) { - stack_head->geom.x = - selmon->w.x + (selmon->w.width - stack_head->geom.width) / 2; + c->geom.x = selmon->w.x + (selmon->w.width - c->geom.width) / 2; } else { - stack_head->geom.y = - selmon->w.y + (selmon->w.height - stack_head->geom.height) / 2; + c->geom.y = selmon->w.y + (selmon->w.height - c->geom.height) / 2; } arrange(selmon, false, false); @@ -1005,13 +971,11 @@ int32_t switch_proportion_preset(const Arg *arg) { !scroller_ignore_proportion_single) return 0; - Client *tc = selmon->sel; + if (selmon->sel) { - if (tc) { - tc = get_scroll_stack_head(tc); for (int32_t i = 0; i < config.scroller_proportion_preset_count; i++) { if (config.scroller_proportion_preset[i] == - tc->scroller_proportion) { + selmon->sel->scroller_proportion) { if (i == config.scroller_proportion_preset_count - 1) { target_proportion = config.scroller_proportion_preset[0]; break; @@ -1029,8 +993,9 @@ int32_t switch_proportion_preset(const Arg *arg) { uint32_t max_client_width = selmon->w.width - 2 * scroller_structs - gappih; - tc->scroller_proportion = target_proportion; - tc->geom.width = max_client_width * target_proportion; + selmon->sel->scroller_proportion = target_proportion; + selmon->sel->geom.width = max_client_width * target_proportion; + // resize(selmon->sel, selmon->sel->geom, 0); arrange(selmon, false, false); } return 0; @@ -1090,7 +1055,7 @@ int32_t tagmon(const Arg *arg) { c->float_geom.height = (int32_t)(c->float_geom.height * c->mon->w.height / selmon->w.height); selmon = c->mon; - c->float_geom = setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0); + c->float_geom = setclient_coordinate_center(c, c->float_geom, 0, 0); // 重新计算居中的坐标 // 重新计算居中的坐标 @@ -1128,7 +1093,6 @@ int32_t tagsilent(const Arg *arg) { clear_fullscreen_flag(fc); } } - exit_scroller_stack(target_client); focusclient(focustop(selmon), 1); arrange(target_client->mon, false, false); return 0; @@ -1257,11 +1221,9 @@ int32_t toggleglobal(const Arg *arg) { selmon->sel->isnamedscratchpad = 0; } selmon->sel->isglobal ^= 1; - if (selmon->sel->isglobal && - (selmon->sel->prev_in_stack || selmon->sel->next_in_stack)) { - exit_scroller_stack(selmon->sel); - arrange(selmon, false, false); - } + // selmon->sel->tags = + // selmon->sel->isglobal ? TAGMASK : selmon->tagset[selmon->seltags]; + // focustop(selmon); setborder_color(selmon->sel); return 0; } @@ -1444,14 +1406,9 @@ int32_t viewcrossmon(const Arg *arg) { } int32_t tagcrossmon(const Arg *arg) { - if (!selmon || !selmon->sel) + if (!selmon->sel) return 0; - if (regex_match(selmon->wlr_output->name, arg->v)) { - tag_client(arg, selmon->sel); - return 0; - } - tagmon(&(Arg){.ui = arg->ui, .i = UNDIR, .v = arg->v}); return 0; } @@ -1628,106 +1585,3 @@ int32_t toggle_monitor(const Arg *arg) { } return 0; } - -int32_t scroller_stack(const Arg *arg) { - Client *c = selmon->sel; - Client *stack_head = NULL; - Client *source_stack_head = NULL; - if (!c || !c->mon || c->isfloating || !is_scroller_layout(selmon)) - return 0; - - if (c && (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal)) - return 0; - - bool is_horizontal_layout = - c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == SCROLLER ? true - : false; - - Client *target_client = find_client_by_direction(c, arg, false, true); - - if (target_client && (!client_only_in_one_tag(target_client) || - target_client->isglobal || target_client->isunglobal)) - return 0; - - if (target_client) { - stack_head = get_scroll_stack_head(target_client); - } - - if (c) { - source_stack_head = get_scroll_stack_head(c); - } - - if (stack_head == source_stack_head) { - return 0; - } - - if (c->isfullscreen) { - setfullscreen(c, 0); - } - - if (c->ismaximizescreen) { - setmaximizescreen(c, 0); - } - - if (c->prev_in_stack) { - if ((is_horizontal_layout && arg->i == LEFT) || - (!is_horizontal_layout && arg->i == UP)) { - exit_scroller_stack(c); - wl_list_remove(&c->link); - wl_list_insert(source_stack_head->link.prev, &c->link); - arrange(selmon, false, false); - - } else if ((is_horizontal_layout && arg->i == RIGHT) || - (!is_horizontal_layout && arg->i == DOWN)) { - exit_scroller_stack(c); - wl_list_remove(&c->link); - wl_list_insert(&source_stack_head->link, &c->link); - arrange(selmon, false, false); - } - return 0; - } else if (c->next_in_stack) { - Client *next_in_stack = c->next_in_stack; - if ((is_horizontal_layout && arg->i == LEFT) || - (!is_horizontal_layout && arg->i == UP)) { - exit_scroller_stack(c); - wl_list_remove(&c->link); - wl_list_insert(next_in_stack->link.prev, &c->link); - arrange(selmon, false, false); - } else if ((is_horizontal_layout && arg->i == RIGHT) || - (!is_horizontal_layout && arg->i == DOWN)) { - exit_scroller_stack(c); - wl_list_remove(&c->link); - wl_list_insert(&next_in_stack->link, &c->link); - arrange(selmon, false, false); - } - return 0; - } - - if (!target_client || target_client->mon != c->mon) { - return 0; - } - - exit_scroller_stack(c); - - // Find the tail of target_client's stack - Client *stack_tail = target_client; - while (stack_tail->next_in_stack) { - stack_tail = stack_tail->next_in_stack; - } - - // Add c to the stack - stack_tail->next_in_stack = c; - c->prev_in_stack = stack_tail; - c->next_in_stack = NULL; - - if (stack_head->ismaximizescreen) { - setmaximizescreen(stack_head, 0); - } - - if (stack_head->isfullscreen) { - setfullscreen(stack_head, 0); - } - - arrange(selmon, false, false); - return 0; -} \ No newline at end of file diff --git a/src/fetch/client.h b/src/fetch/client.h index bf30e17..22db029 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -12,9 +12,7 @@ bool check_hit_no_border(Client *c) { } } - if (no_border_when_single && c && c->mon && - ((ISSCROLLTILED(c) && c->mon->visible_scroll_tiling_clients == 1) || - c->mon->visible_clients == 1)) { + if (no_border_when_single && c && c->mon && c->mon->visible_clients == 1) { hit_no_border = true; } return hit_no_border; @@ -76,12 +74,12 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) { return target_client; } struct wlr_box // 计算客户端居中坐标 -setclient_coordinate_center(Client *c, Monitor *tm, struct wlr_box geom, - int32_t offsetx, int32_t offsety) { +setclient_coordinate_center(Client *c, struct wlr_box geom, int32_t offsetx, + int32_t offsety) { struct wlr_box tempbox; int32_t offset = 0; int32_t len = 0; - Monitor *m = tm ? tm : selmon; + Monitor *m = c->mon ? c->mon : selmon; uint32_t cbw = check_hit_no_border(c) ? c->bw : 0; @@ -217,27 +215,6 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } } } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y < sel_y && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } if (!tempFocusClients) { for (int32_t _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.y < sel_y) { @@ -275,27 +252,6 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } } } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y > sel_y && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } if (!tempFocusClients) { for (int32_t _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.y > sel_y) { @@ -333,27 +289,6 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } } } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x < sel_x && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } if (!tempFocusClients) { for (int32_t _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.x < sel_x) { @@ -391,27 +326,6 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } } } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x > sel_x && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } if (!tempFocusClients) { for (int32_t _i = 0; _i <= last; _i++) { if (tempClients[_i]->geom.x > sel_x) { @@ -455,9 +369,7 @@ Client *direction_select(const Arg *arg) { } return find_client_by_direction( - tc, arg, true, - (is_scroller_layout(selmon) || is_centertile_layout(selmon)) && - !selmon->isoverview); + tc, arg, true, is_scroller_layout(selmon) && !selmon->isoverview); } /* We probably should change the name of this, it sounds like @@ -535,91 +447,4 @@ bool client_only_in_one_tag(Client *c) { } else { return false; } -} - -Client *get_scroll_stack_head(Client *c) { - Client *scroller_stack_head = c; - - if (!scroller_stack_head) - return NULL; - - while (scroller_stack_head->prev_in_stack) { - scroller_stack_head = scroller_stack_head->prev_in_stack; - } - return scroller_stack_head; -} - -bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) { - if (!sc || !tc) - return false; - - uint32_t id = sc->mon->pertag->ltidxs[sc->mon->pertag->curtag]->id; - - if (id != SCROLLER && id != VERTICAL_SCROLLER && id != TILE && - id != VERTICAL_TILE && id != DECK && id != VERTICAL_DECK && - id != CENTER_TILE && id != RIGHT_TILE && id != TGMIX) - return false; - - if (id == SCROLLER || id == VERTICAL_SCROLLER) { - Client *source_stack_head = get_scroll_stack_head(sc); - Client *target_stack_head = get_scroll_stack_head(tc); - Client *fc_head = fc ? get_scroll_stack_head(fc) : NULL; - if (fc && fc->prev_in_stack && fc_head == source_stack_head) - return false; - if (source_stack_head == target_stack_head) - return true; - else - return false; - } - - if (id == TILE || id == VERTICAL_TILE || id == DECK || - id == VERTICAL_DECK || id == RIGHT_TILE) { - if (fc && !fc->ismaster) - return false; - else if (!sc->ismaster) - return true; - } - - if (id == TGMIX) { - if (fc && !fc->ismaster) - return false; - if (!sc->ismaster && sc->mon->visible_tiling_clients <= 3) - return true; - } - - if (id == CENTER_TILE) { - if (fc && !fc->ismaster) - return false; - if (!sc->ismaster && sc->geom.x == tc->geom.x) - return true; - else - return false; - } - - return false; -} - -Client *get_focused_stack_client(Client *sc) { - if (!sc || sc->isfloating) - return sc; - - Client *tc = NULL; - Client *fc = focustop(sc->mon); - - if (fc->isfloating || sc->isfloating) - return sc; - - wl_list_for_each(tc, &fstack, flink) { - if (tc->iskilling || tc->isunglobal) - continue; - if (!VISIBLEON(tc, sc->mon)) - continue; - if (tc == fc) - continue; - - if (client_is_in_same_stack(sc, tc, fc)) { - return tc; - } - } - return sc; -} +} \ No newline at end of file diff --git a/src/fetch/monitor.h b/src/fetch/monitor.h index 7a1ca4d..47a5b82 100644 --- a/src/fetch/monitor.h +++ b/src/fetch/monitor.h @@ -26,14 +26,6 @@ bool is_scroller_layout(Monitor *m) { return false; } -bool is_centertile_layout(Monitor *m) { - - if (m->pertag->ltidxs[m->pertag->curtag]->id == CENTER_TILE) - return true; - - return false; -} - uint32_t get_tag_status(uint32_t tag, Monitor *m) { Client *c = NULL; uint32_t status = 0; diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 3721364..d668f30 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -210,7 +210,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, } if (last_apply_drap_time == 0 || - time - last_apply_drap_time > drag_tile_refresh_interval) { + time - last_apply_drap_time > drag_refresh_interval) { arrange(grabc->mon, false, false); last_apply_drap_time = time; } @@ -367,7 +367,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, } if (last_apply_drap_time == 0 || - time - last_apply_drap_time > drag_tile_refresh_interval) { + time - last_apply_drap_time > drag_refresh_interval) { arrange(grabc->mon, false, false); last_apply_drap_time = time; } @@ -378,8 +378,6 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, int32_t offsety, uint32_t time, bool isvertical) { float delta_x, delta_y; float new_scroller_proportion; - float new_stack_proportion; - Client *stack_head = get_scroll_stack_head(grabc); if (grabc && grabc->mon->visible_tiling_clients == 1 && !scroller_ignore_proportion_single) @@ -391,8 +389,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, start_drag_window = true; // 记录初始状态 - stack_head->old_scroller_pproportion = stack_head->scroller_proportion; - grabc->old_stack_proportion = grabc->stack_proportion; + grabc->old_scroller_pproportion = grabc->scroller_proportion; grabc->cursor_in_left_half = cursor->x < grabc->geom.x + grabc->geom.width / 2; @@ -412,26 +409,15 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, grabc->old_master_inner_per = grabc->master_inner_per; grabc->old_stack_inner_per = grabc->stack_inner_per; grabc->drag_begin_geom = grabc->geom; - stack_head->old_scroller_pproportion = - stack_head->scroller_proportion; - grabc->old_stack_proportion = grabc->stack_proportion; + grabc->old_scroller_pproportion = grabc->scroller_proportion; grabc->cursor_in_upper_half = false; grabc->cursor_in_left_half = false; } - if (isvertical) { - delta_y = (float)(offsety) * - (stack_head->old_scroller_pproportion) / - grabc->drag_begin_geom.height; - delta_x = (float)(offsetx) * (grabc->old_stack_proportion) / - grabc->drag_begin_geom.width; - } else { - delta_x = (float)(offsetx) * - (stack_head->old_scroller_pproportion) / - grabc->drag_begin_geom.width; - delta_y = (float)(offsety) * (grabc->old_stack_proportion) / - grabc->drag_begin_geom.height; - } + delta_x = (float)(offsetx) * (grabc->old_scroller_pproportion) / + grabc->drag_begin_geom.width; + delta_y = (float)(offsety) * (grabc->old_scroller_pproportion) / + grabc->drag_begin_geom.height; bool moving_up; bool moving_down; @@ -466,81 +452,18 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, delta_x = -fabsf(delta_x); } - if (isvertical) { - if (!grabc->next_in_stack && grabc->prev_in_stack && !isdrag) { - delta_x = delta_x * -1.0f; - } - if (!grabc->next_in_stack && grabc->prev_in_stack && isdrag) { - if (moving_right) { - delta_x = -fabsf(delta_x); - } else { - delta_x = fabsf(delta_x); - } - } - if (!grabc->prev_in_stack && grabc->next_in_stack && isdrag) { - if (moving_left) { - delta_x = -fabsf(delta_x); - } else { - delta_x = fabsf(delta_x); - } - } - - if (isdrag) { - if (moving_up) { - delta_y = -fabsf(delta_y); - } else { - delta_y = fabsf(delta_y); - } - } - - } else { - if (!grabc->next_in_stack && grabc->prev_in_stack && !isdrag) { - delta_y = delta_y * -1.0f; - } - if (!grabc->next_in_stack && grabc->prev_in_stack && isdrag) { - if (moving_down) { - delta_y = -fabsf(delta_y); - } else { - delta_y = fabsf(delta_y); - } - } - if (!grabc->prev_in_stack && grabc->next_in_stack && isdrag) { - if (moving_up) { - delta_y = -fabsf(delta_y); - } else { - delta_y = fabsf(delta_y); - } - } - - if (isdrag) { - if (moving_left) { - delta_x = -fabsf(delta_x); - } else { - delta_x = fabsf(delta_x); - } - } - } - // 直接设置新的比例,基于初始值 + 变化量 if (isvertical) { - new_scroller_proportion = - stack_head->old_scroller_pproportion + delta_y; - new_stack_proportion = grabc->old_stack_proportion + delta_x; - + new_scroller_proportion = grabc->old_scroller_pproportion + delta_y; } else { - new_scroller_proportion = - stack_head->old_scroller_pproportion + delta_x; - new_stack_proportion = grabc->old_stack_proportion + delta_y; + new_scroller_proportion = grabc->old_scroller_pproportion + delta_x; } // 应用限制,确保比例在合理范围内 new_scroller_proportion = fmaxf(0.1f, fminf(1.0f, new_scroller_proportion)); - new_stack_proportion = fmaxf(0.1f, fminf(1.0f, new_stack_proportion)); - grabc->stack_proportion = new_stack_proportion; - - stack_head->scroller_proportion = new_scroller_proportion; + grabc->scroller_proportion = new_scroller_proportion; if (!isdrag) { arrange(grabc->mon, false, false); @@ -548,7 +471,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, } if (last_apply_drap_time == 0 || - time - last_apply_drap_time > drag_tile_refresh_interval) { + time - last_apply_drap_time > drag_refresh_interval) { arrange(grabc->mon, false, false); last_apply_drap_time = time; } @@ -682,20 +605,14 @@ arrange(Monitor *m, bool want_animation, bool from_view) { wl_list_for_each(c, &clients, link) { - if (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal) { - exit_scroller_stack(c); - } - if (from_view && (c->isglobal || c->isunglobal)) { set_size_per(m, c); } if (c->mon == m && (c->isglobal || c->isunglobal)) { c->tags = m->tagset[m->seltags]; - } - - if (from_view && m->sel == NULL && c->isglobal && VISIBLEON(c, m)) { - focusclient(c, 1); + if (c->mon->sel == NULL) + focusclient(c, 0); } if (VISIBLEON(c, m)) { @@ -710,7 +627,7 @@ arrange(Monitor *m, bool want_animation, bool from_view) { m->visible_tiling_clients++; } - if (ISSCROLLTILED(c) && !c->prev_in_stack) { + if (ISSCROLLTILED(c)) { m->visible_scroll_tiling_clients++; } } diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index e1a335d..a2f5e5c 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -117,7 +117,6 @@ void deck(Monitor *m) { Client *c = NULL; Client *fc = NULL; float mfact; - uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag]; int32_t cur_gappih = enablegaps ? m->gappih : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0; @@ -143,8 +142,8 @@ void deck(Monitor *m) { : m->pertag->mfacts[m->pertag->curtag]; // Calculate master width including outer gaps - if (n > nmasters) - mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; + if (n > m->nmaster) + mw = m->nmaster ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; else mw = m->w.width - 2 * cur_gappoh; @@ -152,7 +151,7 @@ void deck(Monitor *m) { wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; - if (i < nmasters) { + if (i < m->nmaster) { c->master_mfact_per = mfact; // Master area clients resize( @@ -161,7 +160,7 @@ void deck(Monitor *m) { .y = m->w.y + cur_gappov + my, .width = mw, .height = (m->w.height - 2 * cur_gappov - my) / - (MIN(n, nmasters) - i)}, + (MIN(n, m->nmaster) - i)}, 0); my += c->geom.height; } else { @@ -213,66 +212,6 @@ void horizontal_scroll_adjust_fullandmax(Client *c, target_geom->y = m->w.y + (m->w.height - target_geom->height) / 2; } -void arrange_stack(Client *scroller_stack_head, struct wlr_box geometry, - int32_t gappiv) { - int32_t stack_size = 0; - Client *iter = scroller_stack_head; - - while (iter) { - stack_size++; - iter = iter->next_in_stack; - } - - if (stack_size == 0) - return; - - float total_proportion = 0.0f; - iter = scroller_stack_head; - while (iter) { - if (iter->stack_proportion <= 0.0f || iter->stack_proportion >= 1.0f) { - iter->stack_proportion = - stack_size == 1 ? 1.0f : 1.0f / (stack_size - 1); - } - total_proportion += iter->stack_proportion; - iter = iter->next_in_stack; - } - - iter = scroller_stack_head; - while (iter) { - iter->stack_proportion = iter->stack_proportion / total_proportion; - iter = iter->next_in_stack; - } - - int32_t client_height; - int32_t current_y = geometry.y; - int32_t remain_client_height = geometry.height - (stack_size - 1) * gappiv; - float remain_proportion = 1.0f; - - iter = scroller_stack_head; - while (iter) { - - client_height = - remain_client_height * (iter->stack_proportion / remain_proportion); - - struct wlr_box client_geom = {.x = geometry.x, - .y = current_y, - .width = geometry.width, - .height = client_height}; - resize(iter, client_geom, 0); - remain_proportion -= iter->stack_proportion; - remain_client_height -= client_height; - current_y += client_height + gappiv; - iter = iter->next_in_stack; - } -} - -void horizontal_check_scroller_root_inside_mon(Client *c, - struct wlr_box *geometry) { - if (!GEOMINSIDEMON(geometry, c->mon)) { - geometry->x = c->mon->w.x + (c->mon->w.width - geometry->width) / 2; - } -} - // 滚动布局 void scroller(Monitor *m) { int32_t i, n, j; @@ -286,7 +225,6 @@ void scroller(Monitor *m) { int32_t cur_gappih = enablegaps ? m->gappih : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0; - int32_t cur_gappiv = enablegaps ? m->gappiv : 0; cur_gappih = smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih; @@ -313,7 +251,7 @@ void scroller(Monitor *m) { // 第二次遍历,填充 tempClients j = 0; wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) { + if (VISIBLEON(c, m) && ISSCROLLTILED(c)) { tempClients[j] = c; j++; } @@ -331,8 +269,7 @@ void scroller(Monitor *m) { target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; - horizontal_check_scroller_root_inside_mon(c, &target_geom); - arrange_stack(c, target_geom, cur_gappiv); + resize(c, target_geom, 0); free(tempClients); // 释放内存 return; } @@ -346,11 +283,6 @@ void scroller(Monitor *m) { root_client = center_tiled_select(m); } - // root_client might be in a stack, find the stack head - if (root_client) { - root_client = get_scroll_stack_head(root_client); - } - if (!root_client) { free(tempClients); // 释放内存 return; @@ -385,14 +317,10 @@ void scroller(Monitor *m) { &target_geom); if (tempClients[focus_client_index]->isfullscreen) { target_geom.x = m->m.x; - horizontal_check_scroller_root_inside_mon( - tempClients[focus_client_index], &target_geom); - arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); + resize(tempClients[focus_client_index], target_geom, 0); } else if (tempClients[focus_client_index]->ismaximizescreen) { target_geom.x = m->w.x + cur_gappoh; - horizontal_check_scroller_root_inside_mon( - tempClients[focus_client_index], &target_geom); - arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); + resize(tempClients[focus_client_index], target_geom, 0); } else if (need_scroller) { if (scroller_focus_center || ((!m->prevsel || @@ -410,14 +338,10 @@ void scroller(Monitor *m) { scroller_structs) : m->w.x + scroller_structs; } - horizontal_check_scroller_root_inside_mon( - tempClients[focus_client_index], &target_geom); - arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); + resize(tempClients[focus_client_index], target_geom, 0); } else { target_geom.x = c->geom.x; - horizontal_check_scroller_root_inside_mon( - tempClients[focus_client_index], &target_geom); - arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv); + resize(tempClients[focus_client_index], target_geom, 0); } for (i = 1; i <= focus_client_index; i++) { @@ -427,7 +351,7 @@ void scroller(Monitor *m) { target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - cur_gappih - target_geom.width; - arrange_stack(c, target_geom, cur_gappiv); + resize(c, target_geom, 0); } for (i = 1; i < n - focus_client_index; i++) { @@ -437,7 +361,7 @@ void scroller(Monitor *m) { target_geom.x = tempClients[focus_client_index + i - 1]->geom.x + cur_gappih + tempClients[focus_client_index + i - 1]->geom.width; - arrange_stack(c, target_geom, cur_gappiv); + resize(c, target_geom, 0); } free(tempClients); // 最后释放内存 @@ -929,4 +853,4 @@ void tgmix(Monitor *m) { grid(m); return; } -} +} \ No newline at end of file diff --git a/src/layout/layout.h b/src/layout/layout.h index f896ac2..169ab11 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -17,8 +17,8 @@ static void tgmix(Monitor *m); Layout overviewlayout = {"󰃇", overview, "overview"}; enum { - TILE, SCROLLER, + TILE, GRID, MONOCLE, DECK, @@ -34,8 +34,8 @@ enum { Layout layouts[] = { // 最少两个,不能删除少于两个 /* symbol arrange function name */ - {"T", tile, "tile", TILE}, // 平铺布局 {"S", scroller, "scroller", SCROLLER}, // 滚动布局 + {"T", tile, "tile", TILE}, // 平铺布局 {"G", grid, "grid", GRID}, // 格子布局 {"M", monocle, "monocle", MONOCLE}, // 单屏布局 {"K", deck, "deck", DECK}, // 卡片布局 diff --git a/src/layout/vertical.h b/src/layout/vertical.h index f7bd442..9513824 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -110,7 +110,6 @@ void vertical_deck(Monitor *m) { Client *c = NULL; Client *fc = NULL; float mfact; - uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag]; int32_t cur_gappiv = enablegaps ? m->gappiv : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0; @@ -135,8 +134,8 @@ void vertical_deck(Monitor *m) { mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per : m->pertag->mfacts[m->pertag->curtag]; - if (n > nmasters) - mh = nmasters ? round((m->w.height - 2 * cur_gappov) * mfact) : 0; + if (n > m->nmaster) + mh = m->nmaster ? round((m->w.height - 2 * cur_gappov) * mfact) : 0; else mh = m->w.height - 2 * cur_gappov; @@ -144,13 +143,13 @@ void vertical_deck(Monitor *m) { wl_list_for_each(c, &clients, link) { if (!VISIBLEON(c, m) || !ISTILED(c)) continue; - if (i < nmasters) { + if (i < m->nmaster) { resize( c, (struct wlr_box){.x = m->w.x + cur_gappoh + mx, .y = m->w.y + cur_gappov, .width = (m->w.width - 2 * cur_gappoh - mx) / - (MIN(n, nmasters) - i), + (MIN(n, m->nmaster) - i), .height = mh}, 0); mx += c->geom.width; @@ -200,66 +199,6 @@ void vertical_scroll_adjust_fullandmax(Client *c, struct wlr_box *target_geom) { target_geom->x = m->w.x + (m->w.width - target_geom->width) / 2; } -void arrange_stack_vertical(Client *scroller_stack_head, - struct wlr_box geometry, int32_t gappih) { - int32_t stack_size = 0; - Client *iter = scroller_stack_head; - - while (iter) { - stack_size++; - iter = iter->next_in_stack; - } - - if (stack_size == 0) - return; - - float total_proportion = 0.0f; - iter = scroller_stack_head; - while (iter) { - if (iter->stack_proportion <= 0.0f || iter->stack_proportion >= 1.0f) { - iter->stack_proportion = - stack_size == 1 ? 1.0f : 1.0f / (stack_size - 1); - } - total_proportion += iter->stack_proportion; - iter = iter->next_in_stack; - } - - iter = scroller_stack_head; - while (iter) { - iter->stack_proportion = iter->stack_proportion / total_proportion; - iter = iter->next_in_stack; - } - - int32_t client_width; - int32_t current_x = geometry.x; - int32_t remain_client_width = geometry.width - (stack_size - 1) * gappih; - float remain_proportion = 1.0f; - - iter = scroller_stack_head; - while (iter) { - - client_width = - remain_client_width * (iter->stack_proportion / remain_proportion); - - struct wlr_box client_geom = {.y = geometry.y, - .x = current_x, - .height = geometry.height, - .width = client_width}; - resize(iter, client_geom, 0); - remain_proportion -= iter->stack_proportion; - remain_client_width -= client_width; - current_x += client_width + gappih; - iter = iter->next_in_stack; - } -} - -void vertical_check_scroller_root_inside_mon(Client *c, - struct wlr_box *geometry) { - if (!GEOMINSIDEMON(geometry, c->mon)) { - geometry->y = c->mon->w.y + (c->mon->w.height - geometry->height) / 2; - } -} - // 竖屏滚动布局 void vertical_scroller(Monitor *m) { int32_t i, n, j; @@ -273,7 +212,6 @@ void vertical_scroller(Monitor *m) { int32_t cur_gappiv = enablegaps ? m->gappiv : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0; - int32_t cur_gappih = enablegaps ? m->gappih : 0; cur_gappiv = smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappiv; @@ -297,7 +235,7 @@ void vertical_scroller(Monitor *m) { j = 0; wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) { + if (VISIBLEON(c, m) && ISSCROLLTILED(c)) { tempClients[j] = c; j++; } @@ -315,8 +253,7 @@ void vertical_scroller(Monitor *m) { target_geom.height = (m->w.height - 2 * cur_gappov) * single_proportion; target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; - vertical_check_scroller_root_inside_mon(c, &target_geom); - arrange_stack_vertical(c, target_geom, cur_gappih); + resize(c, target_geom, 0); free(tempClients); return; } @@ -330,11 +267,6 @@ void vertical_scroller(Monitor *m) { root_client = center_tiled_select(m); } - // root_client might be in a stack, find the stack head - if (root_client) { - root_client = get_scroll_stack_head(root_client); - } - if (!root_client) { free(tempClients); return; @@ -370,16 +302,10 @@ void vertical_scroller(Monitor *m) { if (tempClients[focus_client_index]->isfullscreen) { target_geom.y = m->m.y; - vertical_check_scroller_root_inside_mon(tempClients[focus_client_index], - &target_geom); - arrange_stack_vertical(tempClients[focus_client_index], target_geom, - cur_gappih); + resize(tempClients[focus_client_index], target_geom, 0); } else if (tempClients[focus_client_index]->ismaximizescreen) { target_geom.y = m->w.y + cur_gappov; - vertical_check_scroller_root_inside_mon(tempClients[focus_client_index], - &target_geom); - arrange_stack_vertical(tempClients[focus_client_index], target_geom, - cur_gappih); + resize(tempClients[focus_client_index], target_geom, 0); } else if (need_scroller) { if (scroller_focus_center || ((!m->prevsel || @@ -397,16 +323,10 @@ void vertical_scroller(Monitor *m) { scroller_structs) : m->w.y + scroller_structs; } - vertical_check_scroller_root_inside_mon(tempClients[focus_client_index], - &target_geom); - arrange_stack_vertical(tempClients[focus_client_index], target_geom, - cur_gappih); + resize(tempClients[focus_client_index], target_geom, 0); } else { target_geom.y = c->geom.y; - vertical_check_scroller_root_inside_mon(tempClients[focus_client_index], - &target_geom); - arrange_stack_vertical(tempClients[focus_client_index], target_geom, - cur_gappih); + resize(tempClients[focus_client_index], target_geom, 0); } for (i = 1; i <= focus_client_index; i++) { @@ -416,7 +336,7 @@ void vertical_scroller(Monitor *m) { target_geom.y = tempClients[focus_client_index - i + 1]->geom.y - cur_gappiv - target_geom.height; - arrange_stack_vertical(c, target_geom, cur_gappih); + resize(c, target_geom, 0); } for (i = 1; i < n - focus_client_index; i++) { @@ -426,7 +346,7 @@ void vertical_scroller(Monitor *m) { target_geom.y = tempClients[focus_client_index + i - 1]->geom.y + cur_gappiv + tempClients[focus_client_index + i - 1]->geom.height; - arrange_stack_vertical(c, target_geom, cur_gappih); + resize(c, target_geom, 0); } free(tempClients); diff --git a/src/mango.c b/src/mango.c index 591d4f6..e3e658a 100644 --- a/src/mango.c +++ b/src/mango.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -102,10 +101,6 @@ (A->geom.x >= A->mon->m.x && A->geom.y >= A->mon->m.y && \ A->geom.x + A->geom.width <= A->mon->m.x + A->mon->m.width && \ A->geom.y + A->geom.height <= A->mon->m.y + A->mon->m.height) -#define GEOMINSIDEMON(A, M) \ - (A->x >= M->m.x && A->y >= M->m.y && \ - A->x + A->width <= M->m.x + M->m.width && \ - A->y + A->height <= M->m.y + M->m.height) #define ISTILED(A) \ (A && !(A)->isfloating && !(A)->isminimized && !(A)->iskilling && \ !(A)->ismaximizescreen && !(A)->isfullscreen && !(A)->isunglobal) @@ -143,8 +138,6 @@ #define BAKED_POINTS_COUNT 256 /* enums */ -enum { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }; - enum { VERTICAL, HORIZONTAL }; enum { SWIPE_UP, SWIPE_DOWN, SWIPE_LEFT, SWIPE_RIGHT }; enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ @@ -382,8 +375,6 @@ struct Client { bool is_pending_open_animation; bool is_restoring_from_ov; float scroller_proportion; - float stack_proportion; - float old_stack_proportion; bool need_output_flush; struct dwl_animation animation; struct dwl_opacity_animation opacity_animation; @@ -416,8 +407,6 @@ struct Client { int32_t allow_shortcuts_inhibit; float scroller_proportion_single; bool isfocusing; - struct Client *next_in_stack; - struct Client *prev_in_stack; }; typedef struct { @@ -480,7 +469,6 @@ typedef struct { char *animation_type_open; char *animation_type_close; bool need_output_flush; - bool being_unmapped; } LayerSurface; typedef struct { @@ -503,8 +491,11 @@ struct Monitor { struct wlr_box m; /* monitor area, layout-relative */ struct wlr_box w; /* window area, layout-relative */ struct wl_list layers[4]; /* LayerSurface::link */ + const Layout *lt; uint32_t seltags; uint32_t tagset[2]; + double mfact; + int32_t nmaster; struct wl_list dwl_ipc_outputs; int32_t gappih; /* horizontal gap between windows */ @@ -593,7 +584,7 @@ static void cursorwarptohint(void); static void destroydecoration(struct wl_listener *listener, void *data); static void destroydragicon(struct wl_listener *listener, void *data); static void destroyidleinhibitor(struct wl_listener *listener, void *data); -static void destroylayernodenotify(struct wl_listener *listener, void *data); +static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroylock(SessionLock *lock, int32_t unlocked); static void destroylocksurface(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); @@ -698,7 +689,7 @@ static void show_scratchpad(Client *c); static void show_hide_client(Client *c); static void tag_client(const Arg *arg, Client *target_client); -static struct wlr_box setclient_coordinate_center(Client *c, Monitor *m, +static struct wlr_box setclient_coordinate_center(Client *c, struct wlr_box geom, int32_t offsetx, int32_t offsety); @@ -752,7 +743,6 @@ static struct wlr_scene_tree * wlr_scene_tree_snapshot(struct wlr_scene_node *node, struct wlr_scene_tree *parent); static bool is_scroller_layout(Monitor *m); -static bool is_centertile_layout(Monitor *m); static void create_output(struct wlr_backend *backend, void *data); static void get_layout_abbr(char *abbr, const char *full_name); static void apply_named_scratchpad(Client *target_client); @@ -772,13 +762,6 @@ static void init_client_properties(Client *c); static float *get_border_color(Client *c); static void clear_fullscreen_and_maximized_state(Monitor *m); static void request_fresh_all_monitors(void); -static Client *find_client_by_direction(Client *tc, const Arg *arg, - bool findfloating, bool ignore_align); -static void exit_scroller_stack(Client *c); -static Client *get_scroll_stack_head(Client *c); -static bool client_only_in_one_tag(Client *c); -static Client *get_focused_stack_client(Client *sc); -static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc); #include "data/static_keymap.h" #include "dispatch/bind_declare.h" @@ -841,7 +824,6 @@ static struct wl_list inputdevices; static struct wl_list keyboard_shortcut_inhibitors; static uint32_t cursor_mode; static Client *grabc; -static int32_t rzcorner; static int32_t grabcx, grabcy; /* client-relative */ static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */ static bool start_drag_window = false; @@ -898,7 +880,6 @@ struct Pertag { int32_t nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */ - bool no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */ const Layout *ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */ }; @@ -969,9 +950,9 @@ static struct wlr_xwayland *xwayland; 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); + c->float_geom = c->geom = setclient_coordinate_center(c, c->geom, 0, 0); } } @@ -1038,7 +1019,7 @@ void show_scratchpad(Client *c) { : c->mon->w.height * scratchpad_height_ratio; // 重新计算居中的坐标 c->float_geom = c->geom = c->animainit_geom = c->animation.current = - setclient_coordinate_center(c, c->mon, c->geom, 0, 0); + setclient_coordinate_center(c, c->geom, 0, 0); c->iscustomsize = 1; resize(c, c->geom, 0); } @@ -1070,17 +1051,7 @@ 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; - if (w->next_in_stack) - w->next_in_stack->prev_in_stack = c; - if (w->prev_in_stack) - w->prev_in_stack->next_in_stack = c; - c->stack_proportion = w->stack_proportion; wl_list_insert(&w->link, &c->link); wl_list_insert(&w->flink, &c->flink); @@ -1118,8 +1089,7 @@ bool switch_scratchpad_client_state(Client *c) { c->float_geom.height = (int32_t)(c->float_geom.height * c->mon->w.height / oldmon->w.height); - c->float_geom = - setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0); + c->float_geom = setclient_coordinate_center(c, c->float_geom, 0, 0); // 只有显示状态的scratchpad才需要聚焦和返回true if (c->is_scratchpad_show) { @@ -1220,59 +1190,17 @@ void toggle_hotarea(int32_t x_root, int32_t y_root) { if (grabc) return; - // 根据热角位置计算不同的热区坐标 - unsigned hx, hy; + unsigned hx = selmon->m.x + hotarea_size; + unsigned hy = selmon->m.y + selmon->m.height - hotarea_size; - switch (hotarea_corner) { - case BOTTOM_RIGHT: // 右下角 - hx = selmon->m.x + selmon->m.width - hotarea_size; - hy = selmon->m.y + selmon->m.height - hotarea_size; - break; - case TOP_LEFT: // 左上角 - hx = selmon->m.x + hotarea_size; - hy = selmon->m.y + hotarea_size; - break; - case TOP_RIGHT: // 右上角 - hx = selmon->m.x + selmon->m.width - hotarea_size; - hy = selmon->m.y + hotarea_size; - break; - case BOTTOM_LEFT: // 左下角(默认) - default: - hx = selmon->m.x + hotarea_size; - hy = selmon->m.y + selmon->m.height - hotarea_size; - break; - } - - // 判断鼠标是否在热区内 - int in_hotarea = 0; - - switch (hotarea_corner) { - case BOTTOM_RIGHT: // 右下角 - in_hotarea = (y_root > hy && x_root > hx && - x_root <= (selmon->m.x + selmon->m.width) && - y_root <= (selmon->m.y + selmon->m.height)); - break; - case TOP_LEFT: // 左上角 - in_hotarea = (y_root < hy && x_root < hx && x_root >= selmon->m.x && - y_root >= selmon->m.y); - break; - case TOP_RIGHT: // 右上角 - in_hotarea = (y_root < hy && x_root > hx && - x_root <= (selmon->m.x + selmon->m.width) && - y_root >= selmon->m.y); - break; - case BOTTOM_LEFT: // 左下角(默认) - default: - in_hotarea = (y_root > hy && x_root < hx && x_root >= selmon->m.x && - y_root <= (selmon->m.y + selmon->m.height)); - break; - } - - if (enable_hotarea == 1 && selmon->is_in_hotarea == 0 && in_hotarea) { + if (enable_hotarea == 1 && selmon->is_in_hotarea == 0 && y_root > hy && + x_root < hx && x_root >= selmon->m.x && + y_root <= (selmon->m.y + selmon->m.height)) { toggleoverview(&arg); selmon->is_in_hotarea = 1; } else if (enable_hotarea == 1 && selmon->is_in_hotarea == 1 && - !in_hotarea) { + (y_root <= hy || x_root >= hx || x_root < selmon->m.x || + y_root > (selmon->m.y + selmon->m.height))) { selmon->is_in_hotarea = 0; } } @@ -1417,7 +1345,7 @@ void applyrules(Client *c) { if (r->offsetx || r->offsety) { c->iscustompos = 1; c->float_geom = c->geom = setclient_coordinate_center( - c, mon, c->float_geom, r->offsetx, r->offsety); + c, c->float_geom, r->offsetx, r->offsety); } if (c->isfloating) { c->geom = c->float_geom.width > 0 && c->float_geom.height > 0 @@ -1435,8 +1363,7 @@ void applyrules(Client *c) { // the hit size if (!c->iscustompos && (!client_is_x11(c) || (c->geom.x == 0 && c->geom.y == 0))) { - c->float_geom = c->geom = - setclient_coordinate_center(c, mon, c->geom, 0, 0); + c->float_geom = c->geom = setclient_coordinate_center(c, c->geom, 0, 0); } else { c->float_geom = c->geom; } @@ -1524,9 +1451,6 @@ void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, !layer_surface->initialized) continue; - if (l->being_unmapped) - continue; - wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area); wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, @@ -2025,6 +1949,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; @@ -2342,15 +2267,6 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) { return; } - // 检查surface是否有buffer - // 空buffer,只是隐藏,不改变mapped状态 - if (l->mapped && !layer_surface->surface->buffer) { - wlr_scene_node_set_enabled(&l->scene->node, false); - return; - } else { - wlr_scene_node_set_enabled(&l->scene->node, true); - } - get_layer_target_geometry(l, &box); if (animations && layer_animations && !l->noanim && l->mapped && @@ -2499,12 +2415,12 @@ void commitpopup(struct wl_listener *listener, void *data) { struct wlr_box box; int32_t type = -1; - if (!popup || !popup->base->initial_commit) - goto commitpopup_listen_free; + if (!popup->base->initial_commit) + return; type = toplevel_from_wlr_surface(popup->base->surface, &c, &l); - if (!popup->parent || !popup->parent->data || type < 0) - goto commitpopup_listen_free; + if (!popup->parent || type < 0) + return; wlr_scene_node_raise_to_top(popup->parent->data); @@ -2512,14 +2428,13 @@ void commitpopup(struct wl_listener *listener, void *data) { wlr_scene_xdg_surface_create(popup->parent->data, popup->base); if ((l && !l->mon) || (c && !c->mon)) { wlr_xdg_popup_destroy(popup); - goto commitpopup_listen_free; + return; } box = type == LayerShell ? l->mon->m : c->mon->w; box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x); box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y); wlr_xdg_popup_unconstrain_from_box(popup, &box); -commitpopup_listen_free: wl_list_remove(&listener->link); free(listener); } @@ -2647,6 +2562,8 @@ void createlayersurface(struct wl_listener *listener, void *data) { LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); + LISTEN(&layer_surface->events.destroy, &l->destroy, + destroylayersurfacenotify); l->layer_surface = layer_surface; l->mon = layer_surface->output->data; @@ -2659,8 +2576,6 @@ void createlayersurface(struct wl_listener *listener, void *data) { : scene_layer); l->scene->node.data = l->popups->node.data = l; - LISTEN(&l->scene->node.events.destroy, &l->destroy, destroylayernodenotify); - wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link); wlr_surface_send_enter(surface, layer_surface->output); } @@ -2723,7 +2638,7 @@ void createmon(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; const ConfigMonitorRule *r; uint32_t i; - int32_t ji, vrr; + int32_t ji, jk; struct wlr_output_state state; Monitor *m = NULL; struct wlr_output_mode *internal_mode = NULL; @@ -2759,19 +2674,30 @@ void createmon(struct wl_listener *listener, void *data) { m->sel = NULL; m->is_in_hotarea = 0; float scale = 1; + m->mfact = default_mfact; + m->nmaster = default_nmaster; enum wl_output_transform rr = WL_OUTPUT_TRANSFORM_NORMAL; wlr_output_state_set_scale(&state, scale); wlr_output_state_set_transform(&state, rr); + m->lt = &layouts[0]; for (ji = 0; ji < config.monitor_rules_count; ji++) { if (config.monitor_rules_count < 1) break; r = &config.monitor_rules[ji]; - 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; + if (!r->name || regex_match(r->name, wlr_output->name)) { + m->mfact = r->mfact; + m->nmaster = r->nmaster; + m->m.x = r->x; + m->m.y = r->y; + if (r->layout) { + for (jk = 0; jk < LENGTH(layouts); jk++) { + if (strcmp(layouts[jk].name, r->layout) == 0) { + m->lt = &layouts[jk]; + } + } + } scale = r->scale; rr = r->rr; @@ -2788,13 +2714,6 @@ void createmon(struct wl_listener *listener, void *data) { (int32_t)roundf(r->refresh * 1000)); } } - - if (vrr) { - enable_adaptive_sync(m, &state); - } else { - wlr_output_state_set_adaptive_sync_enabled(&state, false); - } - wlr_output_state_set_scale(&state, r->scale); wlr_output_state_set_transform(&state, r->rr); break; @@ -2809,6 +2728,10 @@ void createmon(struct wl_listener *listener, void *data) { wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); + if (adaptive_sync) { + enable_adaptive_sync(m, &state); + } + /* Set up event listeners */ LISTEN(&wlr_output->events.frame, &m->frame, rendermon); LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); @@ -2833,9 +2756,9 @@ void createmon(struct wl_listener *listener, void *data) { } for (i = 0; i <= LENGTH(tags); i++) { - m->pertag->nmasters[i] = default_nmaster; - m->pertag->mfacts[i] = default_mfact; - m->pertag->ltidxs[i] = &layouts[0]; + m->pertag->nmasters[i] = m->nmaster; + m->pertag->mfacts[i] = m->mfact; + m->pertag->ltidxs[i] = m->lt; } // apply tag rule @@ -2857,7 +2780,7 @@ void createmon(struct wl_listener *listener, void *data) { * output (such as DPI, scale factor, manufacturer, etc). */ m->scene_output = wlr_scene_output_create(scene, wlr_output); - if (m->m.x == INT32_MAX || m->m.y == INT32_MAX) + if (m->m.x == -1 && m->m.y == -1) wlr_output_layout_add_auto(output_layout, wlr_output); else wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); @@ -2974,14 +2897,9 @@ void configure_pointer(struct libinput_device *device) { if (libinput_device_config_send_events_get_modes(device)) libinput_device_config_send_events_set_mode(device, send_events_mode); - if (accel_profile && libinput_device_config_accel_is_available(device)) { + if (libinput_device_config_accel_is_available(device)) { libinput_device_config_accel_set_profile(device, accel_profile); libinput_device_config_accel_set_speed(device, accel_speed); - } else { - // profile cannot be directly applied to 0, need to set to 1 first - libinput_device_config_accel_set_profile(device, 1); - libinput_device_config_accel_set_profile(device, 0); - libinput_device_config_accel_set_speed(device, 0); } } @@ -3126,7 +3044,7 @@ void destroyidleinhibitor(struct wl_listener *listener, void *data) { free(listener); } -void destroylayernodenotify(struct wl_listener *listener, void *data) { +void destroylayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *l = wl_container_of(listener, l, destroy); wl_list_remove(&l->link); @@ -3134,6 +3052,7 @@ void destroylayernodenotify(struct wl_listener *listener, void *data) { wl_list_remove(&l->map.link); wl_list_remove(&l->unmap.link); wl_list_remove(&l->surface_commit.link); + wlr_scene_node_destroy(&l->scene->node); wlr_scene_node_destroy(&l->popups->node); free(l); } @@ -3714,8 +3633,7 @@ void keypressmod(struct wl_listener *listener, void *data) { } void pending_kill_client(Client *c) { - if (!c || c->iskilling) - return; + // c->iskilling = 1; //不可以提前标记已经杀掉,因为有些客户端可能拒绝 client_send_close(c); } @@ -3823,15 +3741,6 @@ void init_client_properties(Client *c) { c->float_geom.height = 0; c->float_geom.x = 0; c->float_geom.y = 0; - 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 @@ -3911,7 +3820,7 @@ mapnotify(struct wl_listener *listener, void *data) { if (selmon->sel && ISSCROLLTILED(selmon->sel) && VISIBLEON(selmon->sel, selmon)) { - at_client = get_scroll_stack_head(selmon->sel); + at_client = selmon->sel; } else { at_client = center_tiled_select(selmon); } @@ -4048,30 +3957,6 @@ void motionabsolute(struct wl_listener *listener, void *data) { motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); } -void resize_floating_window(Client *grabc) { - int cdx = (int)round(cursor->x) - grabcx; - int cdy = (int)round(cursor->y) - grabcy; - - cdx = !(rzcorner & 1) && grabc->geom.width - 2 * (int)grabc->bw - cdx < 1 - ? 0 - : cdx; - cdy = !(rzcorner & 2) && grabc->geom.height - 2 * (int)grabc->bw - cdy < 1 - ? 0 - : cdy; - - const struct wlr_box box = { - .x = grabc->geom.x + (rzcorner & 1 ? 0 : cdx), - .y = grabc->geom.y + (rzcorner & 2 ? 0 : cdy), - .width = grabc->geom.width + (rzcorner & 1 ? cdx : -cdx), - .height = grabc->geom.height + (rzcorner & 2 ? cdy : -cdy)}; - - grabc->float_geom = box; - - resize(grabc, box, 1); - grabcx += cdx; - grabcy += cdy; -} - void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, double dx_unaccel, double dy_unaccel) { double sx = 0, sy = 0, sx_confined, sy_confined; @@ -4149,9 +4034,14 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, } else if (cursor_mode == CurResize) { if (grabc->isfloating) { grabc->iscustomsize = 1; + grabc->float_geom = (struct wlr_box){ + .x = grabc->geom.x, + .y = grabc->geom.y, + .width = (int32_t)round(cursor->x) - grabc->geom.x, + .height = (int32_t)round(cursor->y) - grabc->geom.y}; if (last_apply_drap_time == 0 || - time - last_apply_drap_time > drag_floating_refresh_interval) { - resize_floating_window(grabc); + time - last_apply_drap_time > drag_refresh_interval) { + resize(grabc, grabc->float_geom, 1); last_apply_drap_time = time; } return; @@ -4282,10 +4172,8 @@ 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->node.enabled && !c->animation.tagining && - (surface != seat->pointer_state.focused_surface) && - !client_is_unmanaged(c) && VISIBLEON(c, c->mon)) + if (surface != seat->pointer_state.focused_surface && sloppyfocus && time && + c && c->scene->node.enabled && !client_is_unmanaged(c)) focusclient(c, 0); /* If surface is NULL, clear pointer focus */ @@ -4460,32 +4348,12 @@ void exchange_two_client(Client *c1, Client *c2) { double master_inner_per = 0.0f; double master_mfact_per = 0.0f; double stack_inner_per = 0.0f; - float scroller_proportion = 0.0f; - float stack_proportion = 0.0f; if (c1 == NULL || c2 == NULL || (!exchange_cross_monitor && c1->mon != c2->mon)) { return; } - if (c1->mon != c2->mon && (c1->prev_in_stack || c2->prev_in_stack || - c1->next_in_stack || c2->next_in_stack)) - return; - - Client *c1head = get_scroll_stack_head(c1); - Client *c2head = get_scroll_stack_head(c2); - - // 交换布局参数 - if (c1head == c2head) { - scroller_proportion = c1->scroller_proportion; - stack_proportion = c1->stack_proportion; - - c1->scroller_proportion = c2->scroller_proportion; - c1->stack_proportion = c2->stack_proportion; - c2->scroller_proportion = scroller_proportion; - c2->stack_proportion = stack_proportion; - } - master_inner_per = c1->master_inner_per; master_mfact_per = c1->master_mfact_per; stack_inner_per = c1->stack_inner_per; @@ -4498,47 +4366,17 @@ void exchange_two_client(Client *c1, Client *c2) { c2->master_mfact_per = master_mfact_per; c2->stack_inner_per = stack_inner_per; - // 交换栈链表连接 - Client *tmp1_next_in_stack = c1->next_in_stack; - Client *tmp1_prev_in_stack = c1->prev_in_stack; - Client *tmp2_next_in_stack = c2->next_in_stack; - Client *tmp2_prev_in_stack = c2->prev_in_stack; - - // 处理相邻节点的情况 - if (c1->next_in_stack == c2) { - c1->next_in_stack = tmp2_next_in_stack; - c2->next_in_stack = c1; - c1->prev_in_stack = c2; - c2->prev_in_stack = tmp1_prev_in_stack; - if (tmp1_prev_in_stack) - tmp1_prev_in_stack->next_in_stack = c2; - if (tmp2_next_in_stack) - tmp2_next_in_stack->prev_in_stack = c1; - } else if (c2->next_in_stack == c1) { - c2->next_in_stack = tmp1_next_in_stack; - c1->next_in_stack = c2; - c2->prev_in_stack = c1; - c1->prev_in_stack = tmp2_prev_in_stack; - if (tmp2_prev_in_stack) - tmp2_prev_in_stack->next_in_stack = c1; - if (tmp1_next_in_stack) - tmp1_next_in_stack->prev_in_stack = c2; - } else if (is_scroller_layout(c1->mon) && - (c1->prev_in_stack || c2->prev_in_stack)) { - Client *c1head = get_scroll_stack_head(c1); - Client *c2head = get_scroll_stack_head(c2); - exchange_two_client(c1head, c2head); - focusclient(c1, 0); - return; - } - - // 交换全局链表连接 struct wl_list *tmp1_prev = c1->link.prev; struct wl_list *tmp2_prev = c2->link.prev; struct wl_list *tmp1_next = c1->link.next; struct wl_list *tmp2_next = c2->link.next; - // 处理相邻节点的情况 + // wl_list + // 是双向链表,其中clients是头部节点,它的下一个节点是第一个客户端的链表节点 + // 最后一个客户端的链表节点的下一个节点也指向clients,但clients本身不是客户端的链表节点 + // 客户端遍历从clients的下一个节点开始,到检测到客户端节点的下一个是clients结束 + + // 当c1和c2为相邻节点时 if (c1->link.next == &c2->link) { c1->link.next = c2->link.next; c1->link.prev = &c2->link; @@ -4565,7 +4403,6 @@ void exchange_two_client(Client *c1, Client *c2) { tmp2_next->prev = &c1->link; } - // 处理跨监视器交换 if (exchange_cross_monitor) { tmp_mon = c2->mon; tmp_tags = c2->tags; @@ -4576,6 +4413,7 @@ void exchange_two_client(Client *c1, Client *c2) { focusclient(c1, 0); } else { arrange(c1->mon, false, false); + focusclient(c1, 0); } } @@ -4679,7 +4517,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; @@ -4696,12 +4533,9 @@ setfloating(Client *c, int32_t floating) { c->bw = c->isnoborder ? 0 : borderpx; } - exit_scroller_stack(c); - // 重新计算居中的坐标 if (!client_is_x11(c) && !c->iscustompos) - target_box = - setclient_coordinate_center(c, c->mon, target_box, 0, 0); + target_box = setclient_coordinate_center(c, target_box, 0, 0); else target_box = c->geom; @@ -4717,7 +4551,7 @@ setfloating(Client *c, int32_t floating) { } if (window_size_outofrange) { c->float_geom = - setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0); + setclient_coordinate_center(c, c->float_geom, 0, 0); } resize(c, c->float_geom, 0); } else { @@ -4749,7 +4583,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); } @@ -4769,27 +4603,6 @@ void reset_maximizescreen_size(Client *c) { resize(c, c->geom, 0); } -void exit_scroller_stack(Client *c) { - // If c is already in a stack, remove it. - if (c->prev_in_stack) { - c->prev_in_stack->next_in_stack = c->next_in_stack; - } - - if (!c->prev_in_stack && c->next_in_stack) { - c->next_in_stack->scroller_proportion = c->scroller_proportion; - wl_list_remove(&c->next_in_stack->link); - wl_list_insert(&c->link, &c->next_in_stack->link); - } - - if (c->next_in_stack) { - c->next_in_stack->prev_in_stack = c->prev_in_stack; - } - - c->prev_in_stack = NULL; - c->next_in_stack = NULL; - c->stack_proportion = 0.0f; -} - void setmaximizescreen(Client *c, int32_t maximizescreen) { struct wlr_box maximizescreen_box; if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling) @@ -4798,7 +4611,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) { @@ -4806,8 +4618,6 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { if (c->isfullscreen) setfullscreen(c, 0); - exit_scroller_stack(c); - if (c->isfloating) c->float_geom = c->geom; @@ -4828,7 +4638,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); } @@ -4845,11 +4655,10 @@ void setfakefullscreen(Client *c, int32_t fakefullscreen) { c->isfakefullscreen = fakefullscreen; if (!c->mon) return; - if (c->isfullscreen) setfullscreen(c, 0); - - client_set_fullscreen(c, fakefullscreen); + else + client_set_fullscreen(c, fakefullscreen); } void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自带全屏 @@ -4861,7 +4670,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); @@ -4870,13 +4678,9 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自 if (c->ismaximizescreen) setmaximizescreen(c, 0); - exit_scroller_stack(c); - if (c->isfloating) c->float_geom = c->geom; - c->isfakefullscreen = 0; - c->bw = 0; wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 if (!is_scroller_layout(c->mon) || c->isfloating) @@ -4885,6 +4689,7 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自 } else { c->bw = c->isnoborder ? 0 : borderpx; c->isfullscreen = 0; + c->isfakefullscreen = 0; if (c->isfloating) setfloating(c, 1); } @@ -4899,7 +4704,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); } @@ -5028,7 +4833,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 @@ -5040,6 +4844,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) { @@ -5432,7 +5251,6 @@ void tag_client(const Arg *arg, Client *target_client) { Client *fc = NULL; if (target_client && arg->ui & TAGMASK) { - exit_scroller_stack(target_client); target_client->tags = arg->ui & TAGMASK; target_client->istagswitching = 1; @@ -5562,7 +5380,6 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *l = wl_container_of(listener, l, unmap); l->mapped = 0; - l->being_unmapped = true; init_fadeout_layers(l); @@ -5574,9 +5391,6 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) { if (l->layer_surface->surface == seat->keyboard_state.focused_surface) focusclient(focustop(selmon), 1); motionnotify(0, NULL, 0, 0, 0, 0); - l->being_unmapped = false; - wlr_scene_node_destroy(&l->shadow->node); - l->shadow = NULL; } void unmapnotify(struct wl_listener *listener, void *data) { @@ -5584,22 +5398,15 @@ void unmapnotify(struct wl_listener *listener, void *data) { */ Client *c = wl_container_of(listener, c, unmap); Monitor *m = NULL; - Client *nextfocus = NULL; - Client *next_in_stack = c->next_in_stack; - Client *prev_in_stack = c->prev_in_stack; c->iskilling = 1; if (animations && !c->is_clip_to_hide && !c->isminimized && (!c->mon || VISIBLEON(c, c->mon))) init_fadeout_client(c); - // If the client is in a stack, remove it from the stack - if (c->swallowedby) { c->swallowedby->mon = c->mon; swallow(c->swallowedby, c); - } else { - exit_scroller_stack(c); } if (c == grabc) { @@ -5620,13 +5427,7 @@ void unmapnotify(struct wl_listener *listener, void *data) { } if (c->mon && c->mon == selmon) { - if (next_in_stack && !c->swallowedby) { - nextfocus = next_in_stack; - } else if (prev_in_stack && !c->swallowedby) { - nextfocus = prev_in_stack; - } else { - nextfocus = focustop(selmon); - } + Client *nextfocus = focustop(selmon); if (nextfocus) { focusclient(nextfocus, 0); @@ -5673,10 +5474,6 @@ void unmapnotify(struct wl_listener *listener, void *data) { c->swallowing = NULL; } - c->stack_proportion = 0.0f; - c->next_in_stack = NULL; - c->prev_in_stack = NULL; - wlr_scene_node_destroy(&c->scene->node); printstatus(); motionnotify(0, NULL, 0, 0, 0, 0); @@ -5794,8 +5591,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); @@ -6157,22 +5953,17 @@ int32_t main(int32_t argc, char *argv[]) { char *startup_cmd = NULL; int32_t c; - while ((c = getopt(argc, argv, "s:c:hdvp")) != -1) { - if (c == 's') { + while ((c = getopt(argc, argv, "s:c:hdv")) != -1) { + if (c == 's') startup_cmd = optarg; - } else if (c == 'd') { + else if (c == 'd') log_level = WLR_DEBUG; - } else if (c == 'v') { - printf("mango " VERSION "\n"); - return EXIT_SUCCESS; - } else if (c == 'c') { + else if (c == 'v') + die("mango " VERSION); + else if (c == 'c') cli_config_path = optarg; - } else if (c == 'p') { - parse_config(); - return EXIT_SUCCESS; - } else { + else goto usage; - } } if (optind < argc) goto usage; @@ -6186,14 +5977,7 @@ int32_t main(int32_t argc, char *argv[]) { run(startup_cmd); cleanup(); return EXIT_SUCCESS; + usage: - printf("Usage: mango [OPTIONS]\n" - "\n" - "Options:\n" - " -v Show mango version\n" - " -d Enable debug log\n" - " -c Use custom configuration file\n" - " -s Execute startup command\n" - " -p Check configuration file error\n"); - return EXIT_SUCCESS; + die("Usage: %s [-v] [-d] [-c config file] [-s startup command]", argv[0]); }