From 505e0ec4ffb482a9bf916a4e9a9f659044899120 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Fri, 16 May 2025 12:10:23 +0800 Subject: [PATCH] feat: optimize named scratchpad --- protocols/dwl-ipc-unstable-v2.xml | 1 + src/config/parse_config.h | 102 ++++++++++++++++++++--------- src/dispatch/dispatch.h | 2 +- src/maomao.c | 105 +++++++++++++++++------------- 4 files changed, 136 insertions(+), 74 deletions(-) diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml index 81ab022..efbb64a 100644 --- a/protocols/dwl-ipc-unstable-v2.xml +++ b/protocols/dwl-ipc-unstable-v2.xml @@ -174,6 +174,7 @@ I would probably just submit raphi's patchset but I don't think that would be po + diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 4b2f691..e068043 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -27,6 +27,7 @@ typedef struct { const char *animation_type_close; int isnoborder; int isopensilent; + int isopenscratchpad; int isunglobal; int isglobal; int monitor; @@ -36,8 +37,8 @@ typedef struct { int height; int isterm; int noswallow; - int scratch_width; - int scratch_height; + int scratchpad_width; + int scratchpad_height; uint32_t passmod; xkb_keysym_t keysym; KeyBinding globalkeybinding; @@ -504,11 +505,12 @@ unsigned int parse_num_type(char *str) { } FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, - char *arg_value2, char *arg_value3, char *arg_value4) { + char *arg_value2, char *arg_value3, char *arg_value4, char *arg_value5) { FuncType func = NULL; (*arg).v = NULL; (*arg).v2 = NULL; + (*arg).v3 = NULL; if (strcmp(func_name, "focusstack") == 0) { func = focusstack; @@ -648,10 +650,11 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, (*arg).ui == NUM_TYPE_DEFAULT ? atoi(arg_value) : atoi(arg_value + 1); (*arg).i2 = (*arg).ui2 == NUM_TYPE_DEFAULT ? atoi(arg_value2) : atoi(arg_value2 + 1); - } else if (strcmp(func_name, "toggle_named_scratch") == 0) { - func = toggle_named_scratch; + } else if (strcmp(func_name, "toggle_named_scratchpad") == 0) { + func = toggle_named_scratchpad; (*arg).v = strdup(arg_value); (*arg).v2 = strdup(arg_value2); + (*arg).v3 = strdup(arg_value5); (*arg).ui = arg_value3 ? atoi(arg_value3) : 0; (*arg).ui2 = arg_value4 ? atoi(arg_value4) : 0; } else { @@ -1061,6 +1064,7 @@ void parse_config_line(Config *config, const char *line) { rule->isfullscreen = -1; rule->isnoborder = -1; rule->isopensilent = -1; + rule->isopenscratchpad = -1; rule->isunglobal = -1; rule->isglobal = -1; rule->isterm = -1; @@ -1068,8 +1072,8 @@ void parse_config_line(Config *config, const char *line) { rule->monitor = -1; rule->offsetx = 0; rule->offsety = 0; - rule->scratch_width = 0; - rule->scratch_height = 0; + rule->scratchpad_width = 0; + rule->scratchpad_height = 0; rule->width = -1; rule->height = -1; rule->animation_type_open = NULL; @@ -1109,10 +1113,10 @@ void parse_config_line(Config *config, const char *line) { rule->offsetx = atoi(val); } else if (strcmp(key, "offsety") == 0) { rule->offsety = atoi(val); - } else if (strcmp(key, "scratch_width") == 0) { - rule->scratch_width = atoi(val); - } else if (strcmp(key, "scratch_height") == 0) { - rule->scratch_height = atoi(val); + } else if (strcmp(key, "scratchpad_width") == 0) { + rule->scratchpad_width = atoi(val); + } else if (strcmp(key, "scratchpad_height") == 0) { + rule->scratchpad_height = atoi(val); } else if (strcmp(key, "width") == 0) { rule->width = atoi(val); } else if (strcmp(key, "height") == 0) { @@ -1121,6 +1125,8 @@ void parse_config_line(Config *config, const char *line) { rule->isnoborder = atoi(val); } else if (strcmp(key, "isopensilent") == 0) { rule->isopensilent = atoi(val); + } else if (strcmp(key, "isopenscratchpad") == 0) { + rule->isopenscratchpad = atoi(val); } else if (strcmp(key, "isunglobal") == 0) { rule->isunglobal = atoi(val); } else if (strcmp(key, "isglobal") == 0) { @@ -1264,10 +1270,10 @@ void parse_config_line(Config *config, const char *line) { char mod_str[256], keysym_str[256], func_name[256], arg_value[256] = "none", arg_value2[256] = "none", - arg_value3[256] = "none", arg_value4[256] = "none"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, + arg_value3[256] = "none", arg_value4[256] = "none", arg_value5[256] = "none"; + if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, keysym_str, func_name, arg_value, arg_value2, arg_value3, - arg_value4) < 3) { + arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid bind format: %s\n", value); return; } @@ -1278,13 +1284,15 @@ void parse_config_line(Config *config, const char *line) { trim_whitespace(arg_value2); trim_whitespace(arg_value3); trim_whitespace(arg_value4); + trim_whitespace(arg_value5); binding->mod = parse_mod(mod_str); binding->keysym = parse_keysym(keysym_str); 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_value2, arg_value3, arg_value4, arg_value5); if (!binding->func) { if (binding->arg.v) { free(binding->arg.v); @@ -1294,6 +1302,10 @@ void parse_config_line(Config *config, const char *line) { free(binding->arg.v2); binding->arg.v2 = NULL; } + if (binding->arg.v3) { + free(binding->arg.v3); + binding->arg.v3 = NULL; + } fprintf(stderr, "Error: Unknown function in bind: %s\n", func_name); } else { config->key_bindings_count++; @@ -1314,10 +1326,9 @@ void parse_config_line(Config *config, const char *line) { char mod_str[256], button_str[256], func_name[256], arg_value[256] = "none", arg_value2[256] = "none", - arg_value3[256] = "none", arg_value4[256] = "none"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, - button_str, func_name, arg_value, arg_value2, arg_value3, - arg_value4) < 3) { + arg_value3[256] = "none", arg_value4[256] = "none", arg_value5[256] = "none"; + if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, + button_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid mousebind format: %s\n", value); return; } @@ -1328,13 +1339,15 @@ void parse_config_line(Config *config, const char *line) { trim_whitespace(arg_value2); trim_whitespace(arg_value3); trim_whitespace(arg_value4); + trim_whitespace(arg_value5); binding->mod = parse_mod(mod_str); binding->button = parse_button(button_str); 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_value2, arg_value3, arg_value4, arg_value5); if (!binding->func) { if (binding->arg.v) { free(binding->arg.v); @@ -1344,6 +1357,10 @@ void parse_config_line(Config *config, const char *line) { free(binding->arg.v2); binding->arg.v2 = NULL; } + if (binding->arg.v3) { + free(binding->arg.v3); + binding->arg.v3 = NULL; + } fprintf(stderr, "Error: Unknown function in mousebind: %s\n", func_name); } else { config->mouse_bindings_count++; @@ -1362,10 +1379,9 @@ void parse_config_line(Config *config, const char *line) { char mod_str[256], dir_str[256], func_name[256], arg_value[256] = "none", arg_value2[256] = "none", - arg_value3[256] = "none", arg_value4[256] = "none"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, - dir_str, func_name, arg_value, arg_value2, arg_value3, - arg_value4) < 3) { + arg_value3[256] = "none", arg_value4[256] = "none", arg_value5[256] = "none"; + if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, + dir_str, func_name, arg_value, arg_value2, arg_value3, arg_value4, arg_value5) < 3) { fprintf(stderr, "Error: Invalid axisbind format: %s\n", value); return; } @@ -1377,13 +1393,15 @@ void parse_config_line(Config *config, const char *line) { trim_whitespace(arg_value2); trim_whitespace(arg_value3); trim_whitespace(arg_value4); + trim_whitespace(arg_value5); binding->mod = parse_mod(mod_str); binding->dir = parse_direction(dir_str); 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_value2, arg_value3, arg_value4, arg_value5); if (!binding->func) { if (binding->arg.v) { @@ -1394,6 +1412,10 @@ void parse_config_line(Config *config, const char *line) { free(binding->arg.v2); binding->arg.v2 = NULL; } + if (binding->arg.v3) { + free(binding->arg.v3); + binding->arg.v3 = NULL; + } fprintf(stderr, "Error: Unknown function in axisbind: %s\n", func_name); } else { config->axis_bindings_count++; @@ -1415,10 +1437,10 @@ void parse_config_line(Config *config, const char *line) { char mod_str[256], motion_str[256], fingers_count_str[256], func_name[256], arg_value[256] = "none", arg_value2[256] = "none", - arg_value3[256] = "none", arg_value4[256] = "none"; - if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", + arg_value3[256] = "none", arg_value4[256] = "none", arg_value5[256] = "none"; + if (sscanf(value, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", mod_str, motion_str, fingers_count_str, func_name, arg_value, - arg_value2, arg_value3, arg_value4) < 4) { + arg_value2, arg_value3, arg_value4, arg_value5) < 4) { fprintf(stderr, "Error: Invalid gesturebind format: %s\n", value); return; } @@ -1431,14 +1453,16 @@ void parse_config_line(Config *config, const char *line) { trim_whitespace(arg_value2); trim_whitespace(arg_value3); trim_whitespace(arg_value4); + trim_whitespace(arg_value5); binding->mod = parse_mod(mod_str); binding->motion = parse_direction(motion_str); binding->fingers_count = atoi(fingers_count_str); 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_value2, arg_value3, arg_value4, arg_value5); if (!binding->func) { if (binding->arg.v) { @@ -1449,6 +1473,10 @@ void parse_config_line(Config *config, const char *line) { free(binding->arg.v2); binding->arg.v2 = NULL; } + if (binding->arg.v3) { + free(binding->arg.v3); + binding->arg.v3 = NULL; + } fprintf(stderr, "Error: Unknown function in axisbind: %s\n", func_name); } else { config->gesture_bindings_count++; @@ -1578,6 +1606,10 @@ void free_config(void) { free((void *)config.key_bindings[i].arg.v2); config.key_bindings[i].arg.v2 = NULL; } + if (config.key_bindings[i].arg.v3) { + free((void *)config.key_bindings[i].arg.v3); + config.key_bindings[i].arg.v3 = NULL; + } } free(config.key_bindings); config.key_bindings = NULL; @@ -1595,6 +1627,10 @@ void free_config(void) { free((void *)config.mouse_bindings[i].arg.v2); config.mouse_bindings[i].arg.v2 = NULL; } + if (config.mouse_bindings[i].arg.v3) { + free((void *)config.mouse_bindings[i].arg.v3); + config.mouse_bindings[i].arg.v3 = NULL; + } } free(config.mouse_bindings); config.mouse_bindings = NULL; @@ -1612,6 +1648,10 @@ void free_config(void) { free((void *)config.axis_bindings[i].arg.v2); config.axis_bindings[i].arg.v2 = NULL; } + if (config.axis_bindings[i].arg.v3) { + free((void *)config.axis_bindings[i].arg.v3); + config.axis_bindings[i].arg.v3 = NULL; + } } free(config.axis_bindings); config.axis_bindings = NULL; @@ -1629,6 +1669,10 @@ void free_config(void) { free((void *)config.gesture_bindings[i].arg.v2); config.gesture_bindings[i].arg.v2 = NULL; } + if (config.gesture_bindings[i].arg.v3) { + free((void *)config.gesture_bindings[i].arg.v3); + config.gesture_bindings[i].arg.v3 = NULL; + } } free(config.gesture_bindings); config.gesture_bindings = NULL; diff --git a/src/dispatch/dispatch.h b/src/dispatch/dispatch.h index 841c2ea..b6cb3d3 100644 --- a/src/dispatch/dispatch.h +++ b/src/dispatch/dispatch.h @@ -53,7 +53,7 @@ void togglefakefullscreen(const Arg *arg); void toggleoverlay(const Arg *arg); void movewin(const Arg *arg); void resizewin(const Arg *arg); -void toggle_named_scratch(const Arg *arg); +void toggle_named_scratchpad(const Arg *arg); void toggle_render_border(const Arg *arg); void create_virtual_output(const Arg *arg); void destroy_all_virtual_output(const Arg *arg); \ No newline at end of file diff --git a/src/maomao.c b/src/maomao.c index cab75b9..c598de4 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -155,6 +155,7 @@ typedef struct { float f2; char *v; char *v2; + char *v3; unsigned int ui; unsigned int ui2; } Arg; @@ -204,7 +205,7 @@ typedef struct Client Client; struct Client { /* Must keep these three elements in this order */ unsigned int type; /* XDGShell or X11* */ - struct wlr_box geom, pending, oldgeom, scratch_geom, animainit_geom, + struct wlr_box geom, pending, oldgeom, scratchpad_geom, animainit_geom, overview_backup_geom, current; /* layout-relative, includes border */ Monitor *mon; struct wlr_scene_tree *scene; @@ -261,6 +262,7 @@ struct Client { int isglobal; int isnoborder; int isopensilent; + int isopenscratchpad; int iskilling; struct wlr_box bounds; bool is_open_animation; @@ -503,7 +505,7 @@ static void dwl_ipc_output_dispatch(struct wl_client *client, struct wl_resource *resource, const char *dispatch, const char *arg1, const char *arg2, const char *arg3, - const char *arg4); + const char *arg4, const char *arg5); static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource); static void focusclient(Client *c, int lift); @@ -1387,26 +1389,26 @@ void show_scratchpad(Client *c) { } if (c->oldgeom.width) - c->scratch_geom.width = c->oldgeom.width; + c->scratchpad_geom.width = c->oldgeom.width; if (c->oldgeom.height) - c->scratch_geom.height = c->oldgeom.height; + c->scratchpad_geom.height = c->oldgeom.height; /* return if fullscreen */ if (!c->isfloating) { setfloating(c, 1); c->geom.width = - c->scratch_geom.width ? c->scratch_geom.width : c->mon->w.width * 0.7; - c->geom.height = c->scratch_geom.height ? c->scratch_geom.height + c->scratchpad_geom.width ? c->scratchpad_geom.width : c->mon->w.width * 0.7; + c->geom.height = c->scratchpad_geom.height ? c->scratchpad_geom.height : c->mon->w.height * 0.8; // 重新计算居中的坐标 c->geom = c->animainit_geom = c->animation.current = setclient_coordinate_center(c->geom, 0, 0); resize(c, c->geom, 0); - } else if (c->geom.width != c->scratch_geom.width || - c->geom.height != c->scratch_geom.height) { + } else if (c->geom.width != c->scratchpad_geom.width || + c->geom.height != c->scratchpad_geom.height) { c->geom.width = - c->scratch_geom.width ? c->scratch_geom.width : c->mon->w.width * 0.7; - c->geom.height = c->scratch_geom.height ? c->scratch_geom.height + c->scratchpad_geom.width ? c->scratchpad_geom.width : c->mon->w.width * 0.7; + c->geom.height = c->scratchpad_geom.height ? c->scratchpad_geom.height : c->mon->w.height * 0.8; c->geom = c->animainit_geom = c->animation.current = setclient_coordinate_center(c->geom, 0, 0); @@ -1531,7 +1533,7 @@ void swallow(Client *c, Client *w) { } } -bool switch_scratch_client_state(Client *c) { +bool switch_scratchpad_client_state(Client *c) { if (c->is_in_scratchpad && c->is_scratchpad_show && (selmon->tagset[selmon->seltags] & c->tags) == 0) { unsigned int target = get_tags_first_tag(selmon->tagset[selmon->seltags]); @@ -1585,17 +1587,8 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) { return target_client; } -void toggle_named_scratch(const Arg *arg) { - Client *target_client = NULL; +void apply_named_scratchpad(Client *target_client) { Client *c = NULL; - char *arg_id = arg->v; - char *arg_title = arg->v2; - - target_client = get_client_by_id_or_title(arg_id, arg_title); - - if (!target_client) - return; - wl_list_for_each(c, &clients, link) { if (c->mon != selmon) { continue; @@ -1605,14 +1598,30 @@ void toggle_named_scratch(const Arg *arg) { } } - target_client->scratch_geom.width = arg->ui; - target_client->scratch_geom.height = arg->ui2; - if (!target_client->is_in_scratchpad) { set_minized(target_client); - switch_scratch_client_state(target_client); + switch_scratchpad_client_state(target_client); } else - switch_scratch_client_state(target_client); + switch_scratchpad_client_state(target_client); +} + +void toggle_named_scratchpad(const Arg *arg) { + Client *target_client = NULL; + char *arg_id = arg->v; + char *arg_title = arg->v2; + + target_client = get_client_by_id_or_title(arg_id, arg_title); + + if (!target_client) { + Arg arg_spawn = {.v = arg->v3}; + spawn(&arg_spawn); + return; + } + + target_client->scratchpad_geom.width = arg->ui; + target_client->scratchpad_geom.height = arg->ui2; + + apply_named_scratchpad(target_client); } void toggle_scratchpad(const Arg *arg) { @@ -1622,7 +1631,7 @@ void toggle_scratchpad(const Arg *arg) { if (c->mon != selmon) { continue; } - hit = switch_scratch_client_state(c); + hit = switch_scratchpad_client_state(c); if (hit) break; } @@ -1814,10 +1823,10 @@ applyrules(Client *c) { strstr(title, r->title))) { c->isterm = r->isterm > 0 ? r->isterm : c->isterm; c->noswallow = r->noswallow > 0 ? r->noswallow : c->noswallow; - c->scratch_geom.width = - r->scratch_width > 0 ? r->scratch_width : c->scratch_geom.width; - c->scratch_geom.height = - r->scratch_height > 0 ? r->scratch_height : c->scratch_geom.height; + c->scratchpad_geom.width = + r->scratchpad_width > 0 ? r->scratchpad_width : c->scratchpad_geom.width; + c->scratchpad_geom.height = + r->scratchpad_height > 0 ? r->scratchpad_height : c->scratchpad_geom.height; c->isfloating = r->isfloating > 0 ? r->isfloating : c->isfloating; c->isfullscreen = r->isfullscreen > 0 ? r->isfullscreen : c->isfullscreen; c->animation_type_open = r->animation_type_open == NULL @@ -1831,19 +1840,23 @@ applyrules(Client *c) { : c->scroller_proportion; c->isnoborder = r->isnoborder > 0 ? r->isnoborder : c->isnoborder; c->isopensilent = r->isopensilent > 0 ? r->isopensilent : c->isopensilent; + c->isopenscratchpad = r->isopenscratchpad > 0 ? r->isopenscratchpad : c->isopenscratchpad; c->isglobal = r->isglobal > 0 ? r->isglobal : c->isglobal; c->isglobal = r->isunglobal > 0 && (client_is_unmanaged(c) || client_should_ignore_focus(c)) ? r->isunglobal : c->isglobal; newtags = r->tags > 0 ? r->tags | newtags : newtags; i = 0; wl_list_for_each(m, &mons, link) if (r->monitor == i++) mon = m; + if(c->isopenscratchpad) + c->isfloating = 1; + if (c->isfloating) { c->geom.width = r->width > 0 ? r->width : c->geom.width; c->geom.height = r->height > 0 ? r->height : c->geom.height; // 重新计算居中的坐标 if (r->offsetx || r->offsety || (!client_is_x11(c) || !client_should_ignore_focus(c))) - c->geom = + c->oldgeom = c->geom = setclient_coordinate_center(c->geom, r->offsetx, r->offsety); } } @@ -1886,7 +1899,11 @@ applyrules(Client *c) { } setfullscreen(c, fullscreen_state_backup); - setborder_color(c); + + if(c->isopenscratchpad) { + apply_named_scratchpad(c); + setborder_color(c); + } } void // 17 @@ -3770,12 +3787,12 @@ void dwl_ipc_output_quit(struct wl_client *client, void dwl_ipc_output_dispatch(struct wl_client *client, struct wl_resource *resource, const char *dispatch, const char *arg1, const char *arg2, - const char *arg3, const char *arg4) { + const char *arg3, const char *arg4, const char *arg5) { void (*func)(const Arg *); Arg arg; func = parse_func_name((char *)dispatch, &arg, (char *)arg1, (char *)arg2, - (char *)arg3, (char *)arg4); + (char *)arg3, (char *)arg4, (char *)arg5); if (func) { func(&arg); } @@ -4457,15 +4474,6 @@ mapnotify(struct wl_listener *listener, void *data) { applyrules(c); } - if (!c->foreign_toplevel && c->mon) - add_foreign_toplevel(c); - - if (selmon->sel && selmon->sel->foreign_toplevel) - wlr_foreign_toplevel_handle_v1_set_activated(selmon->sel->foreign_toplevel, - false); - if (c->foreign_toplevel) - wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true); - // make sure the animation is open type c->is_open_animation = true; resize(c, c->geom, 0); @@ -5675,6 +5683,15 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) { } if (focus) focusclient(focustop(selmon), 1); + + if (!c->foreign_toplevel && c->mon) { + add_foreign_toplevel(c); + if (selmon->sel && selmon->sel->foreign_toplevel) + wlr_foreign_toplevel_handle_v1_set_activated(selmon->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) {