From 41de529fff2f746807049489e42a1ca5e9cd003e Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Wed, 7 Jun 2023 21:44:38 +0100 Subject: [PATCH] window-rules: support matchOnce attribute ...allowing a rule to be applied to only the first window matching a particular criteria. For example, the following can be used to apply a window rule to lxqt-panel but not its configuration window with the same app_id: yes --- docs/labwc-config.5.scd | 7 ++++-- docs/rc.xml.all | 47 +++++++++++++++++++++++++++++------------ include/window-rules.h | 1 + src/config/rcxml.c | 2 ++ src/window-rules.c | 31 +++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index e3bfe5c2..7a9e5181 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -415,9 +415,9 @@ defined as shown below. ``` -*Actions* +*Criteria* -** +** Define a window rule for any window which matches the criteria defined by the attributes *identifier* or *title*. If both are defined, AND logic is used, so both have to match. @@ -429,6 +429,9 @@ defined as shown below. *title* is the title of the window. + *matchOnce* can be true|false. If true, the rule will only apply to the + first instance of the window with the specified identifier or title. + *Properties* Property values can be *yes*, *no* or *default*. diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 20f92a31..30a3ac62 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -391,20 +391,41 @@ diff --git a/include/window-rules.h b/include/window-rules.h index 4d983df0..69a56195 100644 --- a/include/window-rules.h +++ b/include/window-rules.h @@ -21,6 +21,7 @@ enum property { struct window_rule { char *identifier; char *title; + bool match_once; enum window_rule_event event; struct wl_list actions; diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 633b26bd..cde4fb30 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -130,6 +130,8 @@ fill_window_rule(char *nodename, char *content) } else if (!strcmp(nodename, "title")) { free(current_window_rule->title); current_window_rule->title = xstrdup(content); + } else if (!strcasecmp(nodename, "matchOnce")) { + set_bool(content, ¤t_window_rule->match_once); /* Event */ } else if (!strcmp(nodename, "event")) { diff --git a/src/window-rules.c b/src/window-rules.c index 7b366da0..de9da91d 100644 --- a/src/window-rules.c +++ b/src/window-rules.c @@ -14,6 +14,33 @@ #include "view.h" #include "window-rules.h" +static bool +other_instances_exist(struct view *self, const char *id, const char *title) +{ + struct wl_list *views = &self->server->views; + const char *prop = NULL; + struct view *view; + + wl_list_for_each(view, views, link) { + if (view == self) { + continue; + } + if (id) { + prop = view_get_string_prop(view, "app_id"); + if (prop && !strcmp(prop, id)) { + return true; + } + } + if (title) { + prop = view_get_string_prop(view, "title"); + if (prop && !strcmp(prop, title)) { + return true; + } + } + } + return false; +} + /* Try to match against identifier AND title (if set) */ static bool view_matches_criteria(struct window_rule *rule, struct view *view) @@ -21,6 +48,10 @@ view_matches_criteria(struct window_rule *rule, struct view *view) const char *id = view_get_string_prop(view, "app_id"); const char *title = view_get_string_prop(view, "title"); + if (rule->match_once && other_instances_exist(view, id, title)) { + return false; + } + if (rule->identifier && rule->title) { if (!id || !title) { return false;