feat: add config check option in mango cli

This commit is contained in:
DreamMaoMao 2026-02-01 19:21:01 +08:00 committed by Tomate0613
parent 8484093e32
commit 376ee463c2
2 changed files with 131 additions and 389 deletions

View file

@ -102,7 +102,6 @@ typedef struct {
typedef struct { typedef struct {
const char *name; // Monitor name const char *name; // Monitor name
char *make, *model, *serial; // may be NULL
int32_t rr; // Rotate and flip (assume integer) int32_t rr; // Rotate and flip (assume integer)
float scale; // Monitor scale factor float scale; // Monitor scale factor
int32_t x, y; // Monitor position int32_t x, y; // Monitor position
@ -158,9 +157,6 @@ typedef struct {
int32_t id; int32_t id;
char *layout_name; char *layout_name;
char *monitor_name; char *monitor_name;
char *monitor_make;
char *monitor_model;
char *monitor_serial;
float mfact; float mfact;
int32_t nmaster; int32_t nmaster;
int32_t no_render_border; int32_t no_render_border;
@ -366,7 +362,7 @@ typedef struct {
typedef int32_t (*FuncType)(const Arg *); typedef int32_t (*FuncType)(const Arg *);
Config config; Config config;
bool parse_config_file(Config *config, const char *file_path, bool must_exist); void parse_config_file(Config *config, const char *file_path);
// Helper function to trim whitespace from start and end of a string // Helper function to trim whitespace from start and end of a string
void trim_whitespace(char *str) { void trim_whitespace(char *str) {
@ -554,48 +550,6 @@ static bool starts_with_ignore_case(const char *str, const char *prefix) {
return true; 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) { uint32_t parse_mod(const char *mod_str) {
if (!mod_str || !*mod_str) { if (!mod_str || !*mod_str) {
return UINT32_MAX; return UINT32_MAX;
@ -783,9 +737,8 @@ KeySymCode parse_key(const char *key_str, bool isbindsym) {
return kc; return kc;
} }
// change key string to keysym, case insensitive // 普通键名直接转换
xkb_keysym_t sym = xkb_keysym_t sym = xkb_keysym_from_name(key_str, XKB_KEYSYM_NO_FLAGS);
xkb_keysym_from_name(key_str, XKB_KEYSYM_CASE_INSENSITIVE);
if (isbindsym) { if (isbindsym) {
kc.type = KEY_TYPE_SYM; kc.type = KEY_TYPE_SYM;
@ -902,12 +855,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
char *arg_value5) { char *arg_value5) {
FuncType func = NULL; 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).v = NULL;
(*arg).v2 = NULL; (*arg).v2 = NULL;
(*arg).v3 = NULL; (*arg).v3 = NULL;
@ -1058,14 +1005,10 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
(*arg).ui = atoi(arg_value); (*arg).ui = atoi(arg_value);
} else if (strcmp(func_name, "spawn") == 0) { } else if (strcmp(func_name, "spawn") == 0) {
func = spawn; func = spawn;
char *values[] = {arg_value, arg_value2, arg_value3, arg_value4, (*arg).v = strdup(arg_value);
arg_value5};
(*arg).v = combine_args_until_empty(values, 5);
} else if (strcmp(func_name, "spawn_shell") == 0) { } else if (strcmp(func_name, "spawn_shell") == 0) {
func = spawn_shell; func = spawn_shell;
char *values[] = {arg_value, arg_value2, arg_value3, arg_value4, (*arg).v = strdup(arg_value);
arg_value5};
(*arg).v = combine_args_until_empty(values, 5);
} else if (strcmp(func_name, "spawn_on_empty") == 0) { } else if (strcmp(func_name, "spawn_on_empty") == 0) {
func = spawn_on_empty; func = spawn_on_empty;
(*arg).v = strdup(arg_value); // 注意:之后需要释放这个内存 (*arg).v = strdup(arg_value); // 注意:之后需要释放这个内存
@ -1442,8 +1385,9 @@ bool parse_option(Config *config, char *key, char *value) {
config->scroller_proportion_preset = config->scroller_proportion_preset =
(float *)malloc(float_count * sizeof(float)); (float *)malloc(float_count * sizeof(float));
if (!config->scroller_proportion_preset) { if (!config->scroller_proportion_preset) {
fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Memory " fprintf(
"allocation failed\n"); stderr,
"\033[1m\033[31m[ERROR]:\033[33m Memory allocation failed\n");
return false; return false;
} }
@ -1456,9 +1400,9 @@ bool parse_option(Config *config, char *key, char *value) {
while (token != NULL && i < float_count) { while (token != NULL && i < float_count) {
if (sscanf(token, "%f", &value_set) != 1) { if (sscanf(token, "%f", &value_set) != 1) {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Invalid float " stderr,
"value in " "\033[1m\033[31m[ERROR]:\033[33m Invalid float value in "
"scroller_proportion_preset: %s\n", "scroller_proportion_preset: %s\n",
token); token);
free(value_copy); free(value_copy);
@ -1467,8 +1411,7 @@ bool parse_option(Config *config, char *key, char *value) {
return false; return false;
} }
// Clamp the value between 0.0 and 1.0 (or your desired // Clamp the value between 0.0 and 1.0 (or your desired range)
// range)
config->scroller_proportion_preset[i] = config->scroller_proportion_preset[i] =
CLAMP_FLOAT(value_set, 0.1f, 1.0f); CLAMP_FLOAT(value_set, 0.1f, 1.0f);
@ -1505,8 +1448,9 @@ bool parse_option(Config *config, char *key, char *value) {
config->circle_layout = (char **)malloc(string_count * sizeof(char *)); config->circle_layout = (char **)malloc(string_count * sizeof(char *));
memset(config->circle_layout, 0, string_count * sizeof(char *)); memset(config->circle_layout, 0, string_count * sizeof(char *));
if (!config->circle_layout) { if (!config->circle_layout) {
fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Memory " fprintf(
"allocation failed\n"); stderr,
"\033[1m\033[31m[ERROR]:\033[33m Memory allocation failed\n");
return false; return false;
} }
@ -1662,8 +1606,7 @@ bool parse_option(Config *config, char *key, char *value) {
int64_t color = parse_color(value); int64_t color = parse_color(value);
if (color == -1) { if (color == -1) {
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Invalid rootcolor " "\033[1m\033[31m[ERROR]:\033[33m Invalid rootcolor format: "
"format: "
"%s\n", "%s\n",
value); value);
return false; return false;
@ -1707,9 +1650,9 @@ bool parse_option(Config *config, char *key, char *value) {
} else if (strcmp(key, "maximizescreencolor") == 0) { } else if (strcmp(key, "maximizescreencolor") == 0) {
int64_t color = parse_color(value); int64_t color = parse_color(value);
if (color == -1) { if (color == -1) {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Invalid " stderr,
"maximizescreencolor " "\033[1m\033[31m[ERROR]:\033[33m Invalid maximizescreencolor "
"format: %s\n", "format: %s\n",
value); value);
return false; return false;
@ -1731,8 +1674,7 @@ bool parse_option(Config *config, char *key, char *value) {
int64_t color = parse_color(value); int64_t color = parse_color(value);
if (color == -1) { if (color == -1) {
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Invalid " "\033[1m\033[31m[ERROR]:\033[33m Invalid scratchpadcolor "
"scratchpadcolor "
"format: %s\n", "format: %s\n",
value); value);
return false; return false;
@ -1778,9 +1720,6 @@ bool parse_option(Config *config, char *key, char *value) {
// 设置默认值 // 设置默认值
rule->name = NULL; rule->name = NULL;
rule->make = NULL;
rule->model = NULL;
rule->serial = NULL;
rule->rr = 0; rule->rr = 0;
rule->scale = 1.0f; rule->scale = 1.0f;
rule->x = INT32_MAX; rule->x = INT32_MAX;
@ -1804,12 +1743,6 @@ bool parse_option(Config *config, char *key, char *value) {
if (strcmp(key, "name") == 0) { if (strcmp(key, "name") == 0) {
rule->name = strdup(val); rule->name = strdup(val);
} else if (strcmp(key, "make") == 0) {
rule->make = strdup(val);
} else if (strcmp(key, "model") == 0) {
rule->model = strdup(val);
} else if (strcmp(key, "serial") == 0) {
rule->serial = strdup(val);
} else if (strcmp(key, "rr") == 0) { } else if (strcmp(key, "rr") == 0) {
rule->rr = CLAMP_INT(atoi(val), 0, 7); rule->rr = CLAMP_INT(atoi(val), 0, 7);
} else if (strcmp(key, "scale") == 0) { } else if (strcmp(key, "scale") == 0) {
@ -1827,9 +1760,9 @@ bool parse_option(Config *config, char *key, char *value) {
} else if (strcmp(key, "vrr") == 0) { } else if (strcmp(key, "vrr") == 0) {
rule->vrr = CLAMP_INT(atoi(val), 0, 1); rule->vrr = CLAMP_INT(atoi(val), 0, 1);
} else { } else {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Unknown " stderr,
"monitor rule " "\033[1m\033[31m[ERROR]:\033[33m Unknown monitor rule "
"option:\033[1m\033[31m %s\n", "option:\033[1m\033[31m %s\n",
key); key);
parse_error = true; parse_error = true;
@ -1858,9 +1791,6 @@ bool parse_option(Config *config, char *key, char *value) {
rule->id = 0; rule->id = 0;
rule->layout_name = NULL; rule->layout_name = NULL;
rule->monitor_name = NULL; rule->monitor_name = NULL;
rule->monitor_make = NULL;
rule->monitor_model = NULL;
rule->monitor_serial = NULL;
rule->nmaster = 0; rule->nmaster = 0;
rule->mfact = 0.0f; rule->mfact = 0.0f;
rule->no_render_border = 0; rule->no_render_border = 0;
@ -1884,12 +1814,6 @@ bool parse_option(Config *config, char *key, char *value) {
rule->layout_name = strdup(val); rule->layout_name = strdup(val);
} else if (strcmp(key, "monitor_name") == 0) { } else if (strcmp(key, "monitor_name") == 0) {
rule->monitor_name = strdup(val); rule->monitor_name = strdup(val);
} else if (strcmp(key, "monitor_make") == 0) {
rule->monitor_make = strdup(val);
} else if (strcmp(key, "monitor_model") == 0) {
rule->monitor_model = strdup(val);
} else if (strcmp(key, "monitor_serial") == 0) {
rule->monitor_serial = strdup(val);
} else if (strcmp(key, "no_render_border") == 0) { } else if (strcmp(key, "no_render_border") == 0) {
rule->no_render_border = CLAMP_INT(atoi(val), 0, 1); rule->no_render_border = CLAMP_INT(atoi(val), 0, 1);
} else if (strcmp(key, "no_hide") == 0) { } else if (strcmp(key, "no_hide") == 0) {
@ -1900,8 +1824,7 @@ bool parse_option(Config *config, char *key, char *value) {
rule->mfact = CLAMP_FLOAT(atof(val), 0.1f, 0.9f); rule->mfact = CLAMP_FLOAT(atof(val), 0.1f, 0.9f);
} else { } else {
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Unknown " "\033[1m\033[31m[ERROR]:\033[33m Unknown tag rule "
"tag rule "
"option:\033[1m\033[31m %s\n", "option:\033[1m\033[31m %s\n",
key); key);
parse_error = true; parse_error = true;
@ -1959,9 +1882,9 @@ bool parse_option(Config *config, char *key, char *value) {
} else if (strcmp(key, "noshadow") == 0) { } else if (strcmp(key, "noshadow") == 0) {
rule->noshadow = CLAMP_INT(atoi(val), 0, 1); rule->noshadow = CLAMP_INT(atoi(val), 0, 1);
} else { } else {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Unknown " stderr,
"layer rule " "\033[1m\033[31m[ERROR]:\033[33m Unknown layer rule "
"option:\033[1m\033[31m %s\n", "option:\033[1m\033[31m %s\n",
key); key);
parse_error = true; parse_error = true;
@ -2151,9 +2074,9 @@ bool parse_option(Config *config, char *key, char *value) {
return false; return false;
} }
} else { } else {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Unknown " stderr,
"window rule " "\033[1m\033[31m[ERROR]:\033[33m Unknown window rule "
"option:\033[1m\033[31m %s\n", "option:\033[1m\033[31m %s\n",
key); key);
parse_error = true; parse_error = true;
@ -2255,8 +2178,7 @@ bool parse_option(Config *config, char *key, char *value) {
arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0",
arg_value5[256] = "0\0"; arg_value5[256] = "0\0";
if (sscanf(value, if (sscanf(value,
"%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255["
",],%255["
"^,],%255[^\n]", "^,],%255[^\n]",
mod_str, keysym_str, func_name, arg_value, arg_value2, mod_str, keysym_str, func_name, arg_value, arg_value2,
arg_value3, arg_value4, arg_value5) < 3) { arg_value3, arg_value4, arg_value5) < 3) {
@ -2291,12 +2213,6 @@ bool parse_option(Config *config, char *key, char *value) {
binding->keysymcode = binding->keysymcode =
parse_key(keysym_str, binding->keysymcode.type == KEY_TYPE_SYM); parse_key(keysym_str, binding->keysymcode.type == KEY_TYPE_SYM);
binding->mod = parse_mod(mod_str); 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.v = NULL;
binding->arg.v2 = NULL; binding->arg.v2 = NULL;
binding->arg.v3 = NULL; binding->arg.v3 = NULL;
@ -2319,9 +2235,9 @@ bool parse_option(Config *config, char *key, char *value) {
binding->arg.v3 = NULL; binding->arg.v3 = NULL;
} }
if (!binding->func) if (!binding->func)
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Unknown " stderr,
"dispatch in bind: " "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in bind: "
"\033[1m\033[31m%s\n", "\033[1m\033[31m%s\n",
func_name); func_name);
return false; return false;
@ -2349,14 +2265,12 @@ bool parse_option(Config *config, char *key, char *value) {
arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0",
arg_value5[256] = "0\0"; arg_value5[256] = "0\0";
if (sscanf(value, if (sscanf(value,
"%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255["
",],%255["
"^,],%255[^\n]", "^,],%255[^\n]",
mod_str, button_str, func_name, arg_value, arg_value2, mod_str, button_str, func_name, arg_value, arg_value2,
arg_value3, arg_value4, arg_value5) < 3) { arg_value3, arg_value4, arg_value5) < 3) {
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Invalid mousebind " "\033[1m\033[31m[ERROR]:\033[33m Invalid mousebind format: "
"format: "
"%s\n", "%s\n",
value); value);
return false; return false;
@ -2372,26 +2286,9 @@ bool parse_option(Config *config, char *key, char *value) {
binding->mod = parse_mod(mod_str); binding->mod = parse_mod(mod_str);
binding->button = parse_button(button_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.v = NULL;
binding->arg.v2 = NULL; binding->arg.v2 = NULL;
binding->arg.v3 = NULL; binding->arg.v3 = NULL;
// TODO: remove this in next version
if (binding->mod == 0 &&
(binding->button == BTN_LEFT || binding->button == BTN_RIGHT)) {
fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m \033[31m%s\033[33m can't "
"bind to \033[31m%s\033[33m mod key\n",
button_str, mod_str);
return false;
}
binding->func = binding->func =
parse_func_name(func_name, &binding->arg, arg_value, arg_value2, parse_func_name(func_name, &binding->arg, arg_value, arg_value2,
arg_value3, arg_value4, arg_value5); arg_value3, arg_value4, arg_value5);
@ -2409,11 +2306,9 @@ bool parse_option(Config *config, char *key, char *value) {
free(binding->arg.v3); free(binding->arg.v3);
binding->arg.v3 = NULL; binding->arg.v3 = NULL;
} }
if (!binding->func) if (!binding->func)
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Unknown " "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in "
"dispatch in "
"mousebind: \033[1m\033[31m%s\n", "mousebind: \033[1m\033[31m%s\n",
func_name); func_name);
return false; return false;
@ -2440,14 +2335,13 @@ bool parse_option(Config *config, char *key, char *value) {
arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0",
arg_value5[256] = "0\0"; arg_value5[256] = "0\0";
if (sscanf(value, if (sscanf(value,
"%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255["
",],%255["
"^,],%255[^\n]", "^,],%255[^\n]",
mod_str, dir_str, func_name, arg_value, arg_value2, mod_str, dir_str, func_name, arg_value, arg_value2,
arg_value3, arg_value4, arg_value5) < 3) { arg_value3, arg_value4, arg_value5) < 3) {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Invalid axisbind " stderr,
"format: %s\n", "\033[1m\033[31m[ERROR]:\033[33m Invalid axisbind format: %s\n",
value); value);
return false; return false;
} }
@ -2485,8 +2379,7 @@ bool parse_option(Config *config, char *key, char *value) {
} }
if (!binding->func) if (!binding->func)
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Unknown " "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in "
"dispatch in "
"axisbind: \033[1m\033[31m%s\n", "axisbind: \033[1m\033[31m%s\n",
func_name); func_name);
return false; return false;
@ -2514,8 +2407,7 @@ bool parse_option(Config *config, char *key, char *value) {
arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0",
arg_value5[256] = "0\0"; arg_value5[256] = "0\0";
if (sscanf(value, if (sscanf(value,
"%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255["
",],%255["
"^\n]", "^\n]",
fold_str, func_name, arg_value, arg_value2, arg_value3, fold_str, func_name, arg_value, arg_value2, arg_value3,
arg_value4, arg_value5) < 3) { arg_value4, arg_value5) < 3) {
@ -2582,8 +2474,7 @@ bool parse_option(Config *config, char *key, char *value) {
arg_value3[256] = "0\0", arg_value4[256] = "0\0", arg_value3[256] = "0\0", arg_value4[256] = "0\0",
arg_value5[256] = "0\0"; arg_value5[256] = "0\0";
if (sscanf(value, if (sscanf(value,
"%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^" "%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255[^,],%255["
",],%255["
"^,],%255[^,],%255[^\n]", "^,],%255[^,],%255[^\n]",
mod_str, motion_str, fingers_count_str, func_name, arg_value, mod_str, motion_str, fingers_count_str, func_name, arg_value,
arg_value2, arg_value3, arg_value4, arg_value5) < 4) { arg_value2, arg_value3, arg_value4, arg_value5) < 4) {
@ -2607,12 +2498,6 @@ bool parse_option(Config *config, char *key, char *value) {
binding->mod = parse_mod(mod_str); binding->mod = parse_mod(mod_str);
binding->motion = parse_direction(motion_str); binding->motion = parse_direction(motion_str);
binding->fingers_count = atoi(fingers_count_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.v = NULL;
binding->arg.v2 = NULL; binding->arg.v2 = NULL;
binding->arg.v3 = NULL; binding->arg.v3 = NULL;
@ -2635,8 +2520,7 @@ bool parse_option(Config *config, char *key, char *value) {
} }
if (!binding->func) if (!binding->func)
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m Unknown " "\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in "
"dispatch in "
"axisbind: \033[1m\033[31m%s\n", "axisbind: \033[1m\033[31m%s\n",
func_name); func_name);
return false; return false;
@ -2644,14 +2528,12 @@ bool parse_option(Config *config, char *key, char *value) {
config->gesture_bindings_count++; config->gesture_bindings_count++;
} }
} else if (strncmp(key, "source-optional", 15) == 0) {
parse_config_file(config, value, false);
} else if (strncmp(key, "source", 6) == 0) { } else if (strncmp(key, "source", 6) == 0) {
parse_config_file(config, value, true); parse_config_file(config, value);
} else { } else {
fprintf(stderr, fprintf(
"\033[1m\033[31m[ERROR]:\033[33m Unknown keyword: " stderr,
"\033[1m\033[31m%s\n", "\033[1m\033[31m[ERROR]:\033[33m Unknown key: \033[1m\033[31m%s\n",
key); key);
return false; return false;
} }
@ -2662,9 +2544,8 @@ bool parse_option(Config *config, char *key, char *value) {
bool parse_config_line(Config *config, const char *line) { bool parse_config_line(Config *config, const char *line) {
char key[256], value[256]; char key[256], value[256];
if (sscanf(line, "%255[^=]=%255[^\n]", key, value) != 2) { if (sscanf(line, "%255[^=]=%255[^\n]", key, value) != 2) {
fprintf(stderr, // fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Invalid line format:
"\033[1m\033[31m[ERROR]:\033[33m Invalid line format: %s", // %s\n", line);
line);
return false; return false;
} }
@ -2675,7 +2556,7 @@ bool parse_config_line(Config *config, const char *line) {
return parse_option(config, key, value); return parse_option(config, key, value);
} }
bool parse_config_file(Config *config, const char *file_path, bool must_exist) { void parse_config_file(Config *config, const char *file_path) {
FILE *file; FILE *file;
char full_path[1024]; char full_path[1024];
@ -2694,7 +2575,7 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) {
fprintf(stderr, fprintf(stderr,
"\033[1m\033[31m[ERROR]:\033[33m HOME environment " "\033[1m\033[31m[ERROR]:\033[33m HOME environment "
"variable not set.\n"); "variable not set.\n");
return false; return;
} }
snprintf(full_path, sizeof(full_path), "%s/.config/mango/%s", home, snprintf(full_path, sizeof(full_path), "%s/.config/mango/%s", home,
file_path + 1); file_path + 1);
@ -2709,7 +2590,7 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) {
if (!home) { if (!home) {
fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m HOME environment " fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m HOME environment "
"variable not set.\n"); "variable not set.\n");
return false; return;
} }
snprintf(full_path, sizeof(full_path), "%s%s", home, file_path + 1); snprintf(full_path, sizeof(full_path), "%s%s", home, file_path + 1);
file = fopen(full_path, "r"); file = fopen(full_path, "r");
@ -2720,29 +2601,20 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) {
} }
if (!file) { if (!file) {
if (must_exist) { perror("Error opening file");
fprintf(stderr, return;
"\033[1;31m\033[1;33m[ERROR]:\033[0m Failed to open "
"config file: %s\n",
file_path);
return false;
} else {
return true;
}
} }
char line[512]; char line[512];
bool parse_correct = true; bool parse_correct = true;
bool parse_line_correct = true;
uint32_t line_count = 0; uint32_t line_count = 0;
while (fgets(line, sizeof(line), file)) { while (fgets(line, sizeof(line), file)) {
line_count++; line_count++;
if (line[0] == '#' || line[0] == '\n') { if (line[0] == '#' || line[0] == '\n') {
continue; continue;
} }
parse_line_correct = parse_config_line(config, line); parse_correct = parse_config_line(config, line);
if (!parse_line_correct) { if (!parse_correct) {
parse_correct = false;
fprintf(stderr, fprintf(stderr,
"\033[1;31m╰─\033[1;33m[Index]\033[0m " "\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%s\033[0m:\033[1;35m%d\033[0m\n"
@ -2752,7 +2624,6 @@ bool parse_config_file(Config *config, const char *file_path, bool must_exist) {
} }
fclose(file); fclose(file);
return parse_correct;
} }
void free_circle_layout(Config *config) { void free_circle_layout(Config *config) {
@ -2947,12 +2818,6 @@ void free_config(void) {
free((void *)config.tag_rules[i].layout_name); free((void *)config.tag_rules[i].layout_name);
if (config.tag_rules[i].monitor_name) if (config.tag_rules[i].monitor_name)
free((void *)config.tag_rules[i].monitor_name); free((void *)config.tag_rules[i].monitor_name);
if (config.tag_rules[i].monitor_make)
free((void *)config.tag_rules[i].monitor_make);
if (config.tag_rules[i].monitor_model)
free((void *)config.tag_rules[i].monitor_model);
if (config.tag_rules[i].monitor_serial)
free((void *)config.tag_rules[i].monitor_serial);
} }
free(config.tag_rules); free(config.tag_rules);
config.tag_rules = NULL; config.tag_rules = NULL;
@ -2964,12 +2829,6 @@ void free_config(void) {
for (int32_t i = 0; i < config.monitor_rules_count; i++) { for (int32_t i = 0; i < config.monitor_rules_count; i++) {
if (config.monitor_rules[i].name) if (config.monitor_rules[i].name)
free((void *)config.monitor_rules[i].name); free((void *)config.monitor_rules[i].name);
if (config.monitor_rules[i].make)
free((void *)config.monitor_rules[i].make);
if (config.monitor_rules[i].model)
free((void *)config.monitor_rules[i].model);
if (config.monitor_rules[i].serial)
free((void *)config.monitor_rules[i].serial);
} }
free(config.monitor_rules); free(config.monitor_rules);
config.monitor_rules = NULL; config.monitor_rules = NULL;
@ -3274,8 +3133,8 @@ void set_value_default() {
config.hotarea_size = hotarea_size; // 热区大小,10x10 config.hotarea_size = hotarea_size; // 热区大小,10x10
config.hotarea_corner = hotarea_corner; config.hotarea_corner = hotarea_corner;
config.enable_hotarea = enable_hotarea; // 是否启用鼠标热区 config.enable_hotarea = enable_hotarea; // 是否启用鼠标热区
config.smartgaps = smartgaps; /* 1 means no outer gap when there is config.smartgaps =
only one window */ smartgaps; /* 1 means no outer gap when there is only one window */
config.sloppyfocus = sloppyfocus; /* focus follows mouse */ config.sloppyfocus = sloppyfocus; /* focus follows mouse */
config.gappih = gappih; /* horiz inner gap between windows */ config.gappih = gappih; /* horiz inner gap between windows */
config.gappiv = gappiv; /* vert inner gap between windows */ config.gappiv = gappiv; /* vert inner gap between windows */
@ -3424,7 +3283,7 @@ void set_default_key_bindings(Config *config) {
config->key_bindings_count += default_key_bindings_count; config->key_bindings_count += default_key_bindings_count;
} }
bool parse_config(void) { void parse_config(void) {
char filename[1024]; char filename[1024];
@ -3477,7 +3336,7 @@ bool parse_config(void) {
const char *homedir = getenv("HOME"); const char *homedir = getenv("HOME");
if (!homedir) { if (!homedir) {
// 如果获取失败,则无法继续 // 如果获取失败,则无法继续
return false; return;
} }
// 构建日志文件路径 // 构建日志文件路径
snprintf(filename, sizeof(filename), "%s/.config/mango/config.conf", snprintf(filename, sizeof(filename), "%s/.config/mango/config.conf",
@ -3491,12 +3350,10 @@ bool parse_config(void) {
} }
} }
bool parse_correct = true;
set_value_default(); set_value_default();
parse_correct = parse_config_file(&config, filename, true); parse_config_file(&config, filename);
set_default_key_bindings(&config); set_default_key_bindings(&config);
override_config(); override_config();
return parse_correct;
} }
void reset_blur_params(void) { void reset_blur_params(void) {
@ -3534,7 +3391,6 @@ void reapply_monitor_rules(void) {
struct wlr_output_state state; struct wlr_output_state state;
struct wlr_output_mode *internal_mode = NULL; struct wlr_output_mode *internal_mode = NULL;
wlr_output_state_init(&state); wlr_output_state_init(&state);
bool match_rule = false;
wl_list_for_each(m, &mons, link) { wl_list_for_each(m, &mons, link) {
if (!m->wlr_output->enabled) { if (!m->wlr_output->enabled) {
@ -3546,40 +3402,8 @@ void reapply_monitor_rules(void) {
break; break;
mr = &config.monitor_rules[ji]; mr = &config.monitor_rules[ji];
if (regex_match(mr->name, m->wlr_output->name)) {
// 检查是否匹配的变量
match_rule = true;
// 检查四个标识字段的匹配
if (mr->name != NULL) {
if (!regex_match(mr->name, m->wlr_output->name)) {
match_rule = false;
}
}
if (mr->make != NULL) {
if (m->wlr_output->make == NULL ||
strcmp(mr->make, m->wlr_output->make) != 0) {
match_rule = false;
}
}
if (mr->model != NULL) {
if (m->wlr_output->model == NULL ||
strcmp(mr->model, m->wlr_output->model) != 0) {
match_rule = false;
}
}
if (mr->serial != NULL) {
if (m->wlr_output->serial == NULL ||
strcmp(mr->serial, m->wlr_output->serial) != 0) {
match_rule = false;
}
}
// 只有当所有指定的标识都匹配时才应用规则
if (match_rule) {
mx = mr->x == INT32_MAX ? m->m.x : mr->x; mx = mr->x == INT32_MAX ? m->m.x : mr->x;
my = mr->y == INT32_MAX ? m->m.y : mr->y; my = mr->y == INT32_MAX ? m->m.y : mr->y;
vrr = mr->vrr >= 0 ? mr->vrr : 0; vrr = mr->vrr >= 0 ? mr->vrr : 0;
@ -3648,8 +3472,6 @@ void reapply_cursor_style(void) {
} }
} }
void reapply_rootbg(void) { wlr_scene_rect_set_color(root_bg, rootcolor); }
void reapply_border(void) { void reapply_border(void) {
Client *c = NULL; Client *c = NULL;
@ -3713,7 +3535,6 @@ void parse_tagrule(Monitor *m) {
int32_t i, jk; int32_t i, jk;
ConfigTagRule tr; ConfigTagRule tr;
Client *c = NULL; Client *c = NULL;
bool match_rule = false;
for (i = 0; i <= LENGTH(tags); i++) { for (i = 0; i <= LENGTH(tags); i++) {
m->pertag->nmasters[i] = default_nmaster; m->pertag->nmasters[i] = default_nmaster;
@ -3724,36 +3545,9 @@ void parse_tagrule(Monitor *m) {
tr = config.tag_rules[i]; tr = config.tag_rules[i];
match_rule = true; if (config.tag_rules_count > 0 &&
(!tr.monitor_name ||
if (tr.monitor_name != NULL) { regex_match(tr.monitor_name, m->wlr_output->name))) {
if (!regex_match(tr.monitor_name, m->wlr_output->name)) {
match_rule = false;
}
}
if (tr.monitor_make != NULL) {
if (m->wlr_output->make == NULL ||
strcmp(tr.monitor_make, m->wlr_output->make) != 0) {
match_rule = false;
}
}
if (tr.monitor_model != NULL) {
if (m->wlr_output->model == NULL ||
strcmp(tr.monitor_model, m->wlr_output->model) != 0) {
match_rule = false;
}
}
if (tr.monitor_serial != NULL) {
if (m->wlr_output->serial == NULL ||
strcmp(tr.monitor_serial, m->wlr_output->serial) != 0) {
match_rule = false;
}
}
if (config.tag_rules_count > 0 && match_rule) {
for (jk = 0; jk < LENGTH(layouts); jk++) { for (jk = 0; jk < LENGTH(layouts); jk++) {
if (tr.layout_name && if (tr.layout_name &&
@ -3803,7 +3597,6 @@ void reset_option(void) {
reapply_cursor_style(); reapply_cursor_style();
reapply_border(); reapply_border();
reapply_rootbg();
reapply_keyboard(); reapply_keyboard();
reapply_pointer(); reapply_pointer();
reapply_master(); reapply_master();

View file

@ -942,7 +942,6 @@ static struct wl_listener keyboard_shortcuts_inhibit_new_inhibitor = {
.notify = handle_keyboard_shortcuts_inhibit_new_inhibitor}; .notify = handle_keyboard_shortcuts_inhibit_new_inhibitor};
#ifdef XWAYLAND #ifdef XWAYLAND
static int32_t synckeymap(void *data);
static void activatex11(struct wl_listener *listener, void *data); static void activatex11(struct wl_listener *listener, void *data);
static void configurex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data);
static void createnotifyx11(struct wl_listener *listener, void *data); static void createnotifyx11(struct wl_listener *listener, void *data);
@ -954,7 +953,6 @@ static void setgeometrynotify(struct wl_listener *listener, void *data);
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready}; static struct wl_listener xwayland_ready = {.notify = xwaylandready};
static struct wlr_xwayland *xwayland; static struct wlr_xwayland *xwayland;
static struct wl_event_source *sync_keymap;
#endif #endif
#include "animation/client.h" #include "animation/client.h"
@ -971,6 +969,7 @@ static struct wl_event_source *sync_keymap;
void client_change_mon(Client *c, Monitor *m) { void client_change_mon(Client *c, Monitor *m) {
setmon(c, m, c->tags, true); setmon(c, m, c->tags, true);
reset_foreign_tolevel(c);
if (c->isfloating) { if (c->isfloating) {
c->float_geom = c->geom = c->float_geom = c->geom =
setclient_coordinate_center(c, c->mon, c->geom, 0, 0); setclient_coordinate_center(c, c->mon, c->geom, 0, 0);
@ -1072,9 +1071,6 @@ void swallow(Client *c, Client *w) {
c->tags = w->tags; c->tags = w->tags;
c->geom = w->geom; c->geom = w->geom;
c->float_geom = w->float_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->scroller_proportion = w->scroller_proportion;
c->next_in_stack = w->next_in_stack; c->next_in_stack = w->next_in_stack;
c->prev_in_stack = w->prev_in_stack; c->prev_in_stack = w->prev_in_stack;
@ -1998,21 +1994,14 @@ buttonpress(struct wl_listener *listener, void *data) {
if (config.mouse_bindings_count < 1) if (config.mouse_bindings_count < 1)
break; break;
m = &config.mouse_bindings[ji]; m = &config.mouse_bindings[ji];
if (selmon->isoverview && event->button == BTN_LEFT && c) {
toggleoverview(&(Arg){.i = 1});
return;
}
if (selmon->isoverview && event->button == BTN_RIGHT && c) {
pending_kill_client(c);
return;
}
if (CLEANMASK(mods) == CLEANMASK(m->mod) && if (CLEANMASK(mods) == CLEANMASK(m->mod) &&
event->button == m->button && m->func && event->button == m->button && m->func &&
(CLEANMASK(m->mod) != 0 || (selmon->isoverview == 1 || m->button == BTN_MIDDLE) && c) {
(event->button != BTN_LEFT && event->button != BTN_RIGHT))) { m->func(&m->arg);
return;
} else if (CLEANMASK(mods) == CLEANMASK(m->mod) &&
event->button == m->button && m->func &&
CLEANMASK(m->mod) != 0) {
m->func(&m->arg); m->func(&m->arg);
return; return;
} }
@ -2034,6 +2023,7 @@ buttonpress(struct wl_listener *listener, void *data) {
selmon = xytomon(cursor->x, cursor->y); selmon = xytomon(cursor->x, cursor->y);
client_update_oldmonname_record(grabc, selmon); client_update_oldmonname_record(grabc, selmon);
setmon(grabc, selmon, 0, true); setmon(grabc, selmon, 0, true);
reset_foreign_tolevel(grabc);
selmon->prevsel = ISTILED(selmon->sel) ? selmon->sel : NULL; selmon->prevsel = ISTILED(selmon->sel) ? selmon->sel : NULL;
selmon->sel = grabc; selmon->sel = grabc;
tmpc = grabc; tmpc = grabc;
@ -2737,7 +2727,6 @@ void createmon(struct wl_listener *listener, void *data) {
Monitor *m = NULL; Monitor *m = NULL;
struct wlr_output_mode *internal_mode = NULL; struct wlr_output_mode *internal_mode = NULL;
bool custom_monitor_mode = false; bool custom_monitor_mode = false;
bool match_rule = false;
if (!wlr_output_init_render(wlr_output, alloc, drw)) if (!wlr_output_init_render(wlr_output, alloc, drw))
return; return;
@ -2778,39 +2767,7 @@ void createmon(struct wl_listener *listener, void *data) {
break; break;
r = &config.monitor_rules[ji]; r = &config.monitor_rules[ji];
if (regex_match(r->name, wlr_output->name)) {
// 检查是否匹配的变量
match_rule = true;
// 检查四个标识字段的匹配
if (r->name != NULL) {
if (!regex_match(r->name, m->wlr_output->name)) {
match_rule = false;
}
}
if (r->make != NULL) {
if (m->wlr_output->make == NULL ||
strcmp(r->make, m->wlr_output->make) != 0) {
match_rule = false;
}
}
if (r->model != NULL) {
if (m->wlr_output->model == NULL ||
strcmp(r->model, m->wlr_output->model) != 0) {
match_rule = false;
}
}
if (r->serial != NULL) {
if (m->wlr_output->serial == NULL ||
strcmp(r->serial, m->wlr_output->serial) != 0) {
match_rule = false;
}
}
if (match_rule) {
m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x; m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x;
m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y; m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y;
vrr = r->vrr >= 0 ? r->vrr : 0; vrr = r->vrr >= 0 ? r->vrr : 0;
@ -3461,10 +3418,7 @@ void requestmonstate(struct wl_listener *listener, void *data) {
void inputdevice(struct wl_listener *listener, void *data) { void inputdevice(struct wl_listener *listener, void *data) {
/* This event is raised by the backend when a new input device becomes /* This event is raised by the backend when a new input device becomes
* available. * available. */
* when the backend is a headless backend, this event will never be
* triggered.
*/
struct wlr_input_device *device = data; struct wlr_input_device *device = data;
uint32_t caps; uint32_t caps;
@ -3535,6 +3489,11 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym,
int32_t ji; int32_t ji;
int32_t isbreak = 0; int32_t isbreak = 0;
// not allow modifier keys to be used as a keybinding
if (keycode == 50 || keycode == 37 || keycode == 133 || keycode == 64 ||
keycode == 62 || keycode == 108 || keycode == 105 || keycode == 134)
return false;
if (is_keyboard_shortcut_inhibitor(seat->keyboard_state.focused_surface)) { if (is_keyboard_shortcut_inhibitor(seat->keyboard_state.focused_surface)) {
return false; return false;
} }
@ -3866,12 +3825,6 @@ void init_client_properties(Client *c) {
c->stack_proportion = 0.0f; c->stack_proportion = 0.0f;
c->next_in_stack = NULL; c->next_in_stack = NULL;
c->prev_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 void // old fix to 0.5
@ -4190,7 +4143,7 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
if (grabc->isfloating) { if (grabc->isfloating) {
grabc->iscustomsize = 1; grabc->iscustomsize = 1;
if (last_apply_drap_time == 0 || if (last_apply_drap_time == 0 ||
time - last_apply_drap_time > drag_floating_refresh_interval) { time - last_apply_drap_time > drag_refresh_interval) {
resize_floating_window(grabc); resize_floating_window(grabc);
last_apply_drap_time = time; last_apply_drap_time = time;
} }
@ -4322,7 +4275,7 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
uint32_t time) { uint32_t time) {
struct timespec now; struct timespec now;
if (sloppyfocus && !start_drag_window && c && time && c->scene && if (sloppyfocus && !start_drag_window && c && time &&
c->scene->node.enabled && !c->animation.tagining && c->scene->node.enabled && !c->animation.tagining &&
(surface != seat->pointer_state.focused_surface) && (surface != seat->pointer_state.focused_surface) &&
!client_is_unmanaged(c) && VISIBLEON(c, c->mon)) !client_is_unmanaged(c) && VISIBLEON(c, c->mon))
@ -4719,7 +4672,6 @@ setfloating(Client *c, int32_t floating) {
Client *fc = NULL; Client *fc = NULL;
struct wlr_box target_box; struct wlr_box target_box;
int32_t old_floating_state = c->isfloating;
c->isfloating = floating; c->isfloating = floating;
bool window_size_outofrange = false; bool window_size_outofrange = false;
@ -4789,7 +4741,7 @@ setfloating(Client *c, int32_t floating) {
layers[c->isfloating ? LyrTop : LyrTile]); layers[c->isfloating ? LyrTop : LyrTile]);
} }
if (!c->isfloating && old_floating_state) { if (!c->isfloating) {
set_size_per(c->mon, c); set_size_per(c->mon, c);
} }
@ -4838,7 +4790,6 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
if (c->mon->isoverview) if (c->mon->isoverview)
return; return;
int32_t old_maximizescreen_state = c->ismaximizescreen;
c->ismaximizescreen = maximizescreen; c->ismaximizescreen = maximizescreen;
if (maximizescreen) { if (maximizescreen) {
@ -4868,7 +4819,7 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
wlr_scene_node_reparent(&c->scene->node, wlr_scene_node_reparent(&c->scene->node,
layers[c->isfloating ? LyrTop : LyrTile]); layers[c->isfloating ? LyrTop : LyrTile]);
if (!c->ismaximizescreen && old_maximizescreen_state) { if (!c->ismaximizescreen) {
set_size_per(c->mon, c); set_size_per(c->mon, c);
} }
@ -4901,7 +4852,6 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
if (c->mon->isoverview) if (c->mon->isoverview)
return; return;
int32_t old_fullscreen_state = c->isfullscreen;
c->isfullscreen = fullscreen; c->isfullscreen = fullscreen;
client_set_fullscreen(c, fullscreen); client_set_fullscreen(c, fullscreen);
@ -4939,7 +4889,7 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
layers[fullscreen || c->isfloating ? LyrTop : LyrTile]); layers[fullscreen || c->isfloating ? LyrTop : LyrTile]);
} }
if (!c->isfullscreen && old_fullscreen_state) { if (!c->isfullscreen) {
set_size_per(c->mon, c); set_size_per(c->mon, c);
} }
@ -5068,7 +5018,6 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) {
arrange(oldmon, false, false); arrange(oldmon, false, false);
if (m) { if (m) {
/* Make sure window actually overlaps with the monitor */ /* Make sure window actually overlaps with the monitor */
reset_foreign_tolevel(c);
resize(c, c->geom, 0); resize(c, c->geom, 0);
c->tags = c->tags =
newtags ? newtags newtags ? newtags
@ -5080,6 +5029,21 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) {
if (focus && !client_is_x11_popup(c)) { if (focus && !client_is_x11_popup(c)) {
focusclient(focustop(selmon), 1); 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) { void setpsel(struct wl_listener *listener, void *data) {
@ -5217,7 +5181,7 @@ void setup(void) {
if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) { if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) {
wlr_drm_create(dpy, drw); wlr_drm_create(dpy, drw);
wlr_scene_set_linux_dmabuf_v1( wlr_scene_set_linux_dmabuf_v1(
scene, wlr_linux_dmabuf_v1_create_with_renderer(dpy, 4, drw)); scene, wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw));
} }
if (syncobj_enable && (drm_fd = wlr_renderer_get_drm_fd(drw)) >= 0 && if (syncobj_enable && (drm_fd = wlr_renderer_get_drm_fd(drw)) >= 0 &&
@ -5364,6 +5328,7 @@ void setup(void) {
&request_set_cursor_shape); &request_set_cursor_shape);
hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy), hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
hidecursor, cursor); hidecursor, cursor);
/* /*
* Configures a seat, which is a single "seat" at which a user sits and * Configures a seat, which is a single "seat" at which a user sits and
* operates the computer. This conceptually includes up to one keyboard, * operates the computer. This conceptually includes up to one keyboard,
@ -5455,8 +5420,6 @@ void setup(void) {
fprintf(stderr, fprintf(stderr,
"failed to setup XWayland X server, continuing without it\n"); "failed to setup XWayland X server, continuing without it\n");
} }
sync_keymap = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
synckeymap, NULL);
#endif #endif
} }
@ -5835,8 +5798,7 @@ void updatemons(struct wl_listener *listener, void *data) {
if (selmon && selmon->wlr_output->enabled) { if (selmon && selmon->wlr_output->enabled) {
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (!c->mon && client_surface(c)->mapped) { if (!c->mon && client_surface(c)->mapped) {
c->mon = selmon; client_change_mon(c, selmon);
reset_foreign_tolevel(c);
} }
} }
focusclient(focustop(selmon), 1); focusclient(focustop(selmon), 1);
@ -6014,8 +5976,6 @@ void handle_keyboard_shortcuts_inhibit_new_inhibitor(
void virtualkeyboard(struct wl_listener *listener, void *data) { void virtualkeyboard(struct wl_listener *listener, void *data) {
struct wlr_virtual_keyboard_v1 *kb = data; struct wlr_virtual_keyboard_v1 *kb = data;
/* virtual keyboards shouldn't share keyboard group */ /* virtual keyboards shouldn't share keyboard group */
wlr_seat_set_capabilities(seat,
seat->capabilities | WL_SEAT_CAPABILITY_KEYBOARD);
KeyboardGroup *group = createkeyboardgroup(); KeyboardGroup *group = createkeyboardgroup();
/* Set the keymap to match the group keymap */ /* Set the keymap to match the group keymap */
wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap);
@ -6027,7 +5987,8 @@ void virtualkeyboard(struct wl_listener *listener, void *data) {
} }
void warp_cursor(const Client *c) { void warp_cursor(const Client *c) {
if (INSIDEMON(c)) { if (cursor->x < c->geom.x || cursor->x > c->geom.x + c->geom.width ||
cursor->y < c->geom.y || cursor->y > c->geom.y + c->geom.height) {
wlr_cursor_warp_closest(cursor, NULL, c->geom.x + c->geom.width / 2.0, wlr_cursor_warp_closest(cursor, NULL, c->geom.x + c->geom.width / 2.0,
c->geom.y + c->geom.height / 2.0); c->geom.y + c->geom.height / 2.0);
motionnotify(0, NULL, 0, 0, 0, 0); motionnotify(0, NULL, 0, 0, 0, 0);
@ -6045,8 +6006,7 @@ void warp_cursor_to_selmon(Monitor *m) {
void virtualpointer(struct wl_listener *listener, void *data) { void virtualpointer(struct wl_listener *listener, void *data) {
struct wlr_virtual_pointer_v1_new_pointer_event *event = data; struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
struct wlr_input_device *device = &event->new_pointer->pointer.base; struct wlr_input_device *device = &event->new_pointer->pointer.base;
wlr_seat_set_capabilities(seat,
seat->capabilities | WL_SEAT_CAPABILITY_POINTER);
wlr_cursor_attach_input_device(cursor, device); wlr_cursor_attach_input_device(cursor, device);
if (event->suggested_output) if (event->suggested_output)
wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
@ -6055,14 +6015,6 @@ void virtualpointer(struct wl_listener *listener, void *data) {
} }
#ifdef XWAYLAND #ifdef XWAYLAND
int32_t synckeymap(void *data) {
reset_keyboard_layout();
// we only need to sync keymap once
wlr_log(WLR_INFO, "timer to synckeymap done");
wl_event_source_timer_update(sync_keymap, 0);
return 0;
}
void activatex11(struct wl_listener *listener, void *data) { void activatex11(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, activate); Client *c = wl_container_of(listener, c, activate);
bool need_arrange = false; bool need_arrange = false;
@ -6193,10 +6145,6 @@ void xwaylandready(struct wl_listener *listener, void *data) {
xwayland, xcursor->images[0]->buffer, xcursor->images[0]->width * 4, xwayland, xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
xcursor->images[0]->width, xcursor->images[0]->height, xcursor->images[0]->width, xcursor->images[0]->height,
xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
/* xwayland can't auto sync the keymap, so we do it manually
and we need to wait the xwayland completely inited
*/
wl_event_source_timer_update(sync_keymap, 500);
} }
static void setgeometrynotify(struct wl_listener *listener, void *data) { static void setgeometrynotify(struct wl_listener *listener, void *data) {
@ -6223,7 +6171,8 @@ int32_t main(int32_t argc, char *argv[]) {
} else if (c == 'c') { } else if (c == 'c') {
cli_config_path = optarg; cli_config_path = optarg;
} else if (c == 'p') { } else if (c == 'p') {
return parse_config() ? EXIT_SUCCESS : EXIT_FAILURE; parse_config();
return EXIT_SUCCESS;
} else { } else {
goto usage; goto usage;
} }