From 6667708d9aa069f72687ab3c015738ea2ddf6684 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Wed, 25 Feb 2026 19:16:06 +0800 Subject: [PATCH] feat: monitor arg support multi spec match in disptach --- src/dispatch/bind_define.h | 12 +++---- src/fetch/monitor.h | 69 ++++++++++++++++++++++++++++++++++++++ src/mango.c | 1 + 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 94d3d4f..03d34cb 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -210,7 +210,7 @@ int32_t focusmon(const Arg *arg) { if (!m->wlr_output->enabled) { continue; } - if (regex_match(arg->v, m->wlr_output->name)) { + if (match_monitor_spec(arg->v, m)) { tm = m; break; } @@ -1102,7 +1102,7 @@ int32_t tagmon(const Arg *arg) { if (!cm->wlr_output->enabled) { continue; } - if (regex_match(arg->v, cm->wlr_output->name)) { + if (match_monitor_spec(arg->v, cm)) { m = cm; break; } @@ -1543,7 +1543,7 @@ int32_t tagcrossmon(const Arg *arg) { if (!selmon || !selmon->sel) return 0; - if (regex_match(selmon->wlr_output->name, arg->v)) { + if (match_monitor_spec(arg->v, selmon)) { tag_client(arg, selmon->sel); return 0; } @@ -1701,7 +1701,7 @@ int32_t disable_monitor(const Arg *arg) { Monitor *m = NULL; struct wlr_output_state state = {0}; wl_list_for_each(m, &mons, link) { - if (regex_match(arg->v, m->wlr_output->name)) { + if (match_monitor_spec(arg->v, m)) { wlr_output_state_set_enabled(&state, false); wlr_output_commit_state(m->wlr_output, &state); m->asleep = 1; @@ -1716,7 +1716,7 @@ int32_t enable_monitor(const Arg *arg) { Monitor *m = NULL; struct wlr_output_state state = {0}; wl_list_for_each(m, &mons, link) { - if (regex_match(arg->v, m->wlr_output->name)) { + if (match_monitor_spec(arg->v, m)) { wlr_output_state_set_enabled(&state, true); wlr_output_commit_state(m->wlr_output, &state); m->asleep = 0; @@ -1731,7 +1731,7 @@ int32_t toggle_monitor(const Arg *arg) { Monitor *m = NULL; struct wlr_output_state state = {0}; wl_list_for_each(m, &mons, link) { - if (regex_match(arg->v, m->wlr_output->name)) { + if (match_monitor_spec(arg->v, m)) { wlr_output_state_set_enabled(&state, !m->wlr_output->enabled); wlr_output_commit_state(m->wlr_output, &state); m->asleep = !m->wlr_output->enabled; diff --git a/src/fetch/monitor.h b/src/fetch/monitor.h index fd18498..d2b4fe6 100644 --- a/src/fetch/monitor.h +++ b/src/fetch/monitor.h @@ -104,4 +104,73 @@ Monitor *get_monitor_nearest_to(int32_t lx, int32_t ly) { return output_from_wlr_output( wlr_output_layout_output_at(output_layout, closest_x, closest_y)); +} + +bool match_monitor_spec(char *spec, Monitor *m) { + if (!spec || !m) + return false; + + // if the spec does not contain a colon, treat it as a match on the monitor + // name + if (strchr(spec, ':') == NULL) { + return regex_match(spec, m->wlr_output->name); + } + + char *spec_copy = strdup(spec); + if (!spec_copy) + return false; + + char *name_rule = NULL; + char *make_rule = NULL; + char *model_rule = NULL; + char *serial_rule = NULL; + + char *token = strtok(spec_copy, "&&"); + while (token) { + char *colon = strchr(token, ':'); + if (colon) { + *colon = '\0'; + char *key = token; + char *value = colon + 1; + + if (strcmp(key, "name") == 0) + name_rule = strdup(value); + else if (strcmp(key, "make") == 0) + make_rule = strdup(value); + else if (strcmp(key, "model") == 0) + model_rule = strdup(value); + else if (strcmp(key, "serial") == 0) + serial_rule = strdup(value); + } + token = strtok(NULL, "&&"); + } + + bool match = true; + + if (name_rule) { + if (!regex_match(name_rule, m->wlr_output->name)) + match = false; + } + if (make_rule) { + if (!m->wlr_output->make || strcmp(make_rule, m->wlr_output->make) != 0) + match = false; + } + if (model_rule) { + if (!m->wlr_output->model || + strcmp(model_rule, m->wlr_output->model) != 0) + match = false; + } + if (serial_rule) { + if (!m->wlr_output->serial || + strcmp(serial_rule, m->wlr_output->serial) != 0) + match = false; + } + + free(spec_copy); + free(name_rule); + free(make_rule); + free(model_rule); + free(serial_rule); + + return match; } \ No newline at end of file diff --git a/src/mango.c b/src/mango.c index 3344ca7..d4cc1fb 100644 --- a/src/mango.c +++ b/src/mango.c @@ -799,6 +799,7 @@ static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc); static void monitor_stop_skip_frame_timer(Monitor *m); static int monitor_skip_frame_timeout_callback(void *data); static Monitor *get_monitor_nearest_to(int32_t lx, int32_t ly); +static bool match_monitor_spec(char *spec, Monitor *m); #include "data/static_keymap.h" #include "dispatch/bind_declare.h"