Add cli_label to criteria and JSON output

Similar to app_id or con_id, labels are present in the IPC JSON output and can
be matched in criteria using [cli_label="regex"].  This can be useful to
support instance-specific rules in applications that do not support changing
app_id/class based on a command line argument.
This commit is contained in:
Daniel De Graaf 2020-12-08 11:30:38 -05:00
parent 05a418c9fe
commit b7f62c9d7a
3 changed files with 33 additions and 0 deletions

View file

@ -35,6 +35,7 @@ struct criteria {
struct pattern *shell; struct pattern *shell;
struct pattern *app_id; struct pattern *app_id;
struct pattern *con_mark; struct pattern *con_mark;
struct pattern *cli_label;
uint32_t con_id; // internal ID uint32_t con_id; // internal ID
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
struct pattern *class; struct pattern *class;

View file

@ -21,6 +21,7 @@ bool criteria_is_empty(struct criteria *criteria) {
&& !criteria->shell && !criteria->shell
&& !criteria->app_id && !criteria->app_id
&& !criteria->con_mark && !criteria->con_mark
&& !criteria->cli_label
&& !criteria->con_id && !criteria->con_id
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
&& !criteria->class && !criteria->class
@ -96,6 +97,7 @@ void criteria_destroy(struct criteria *criteria) {
pattern_destroy(criteria->window_role); pattern_destroy(criteria->window_role);
#endif #endif
pattern_destroy(criteria->con_mark); pattern_destroy(criteria->con_mark);
pattern_destroy(criteria->cli_label);
free(criteria->workspace); free(criteria->workspace);
free(criteria->cmdlist); free(criteria->cmdlist);
free(criteria->raw); free(criteria->raw);
@ -246,6 +248,26 @@ static bool criteria_matches_view(struct criteria *criteria,
} }
} }
if (criteria->cli_label) {
const char *cli_label = view_get_conn_label(view);
if (!cli_label) {
return false;
}
switch (criteria->cli_label->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(cli_label, view_get_conn_label(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(cli_label, criteria->cli_label->regex) != 0) {
return false;
}
break;
}
}
if (!criteria_matches_container(criteria, view->container)) { if (!criteria_matches_container(criteria, view->container)) {
return false; return false;
} }
@ -458,6 +480,7 @@ enum criteria_token {
T_APP_ID, T_APP_ID,
T_CON_ID, T_CON_ID,
T_CON_MARK, T_CON_MARK,
T_CLI_LABEL,
T_FLOATING, T_FLOATING,
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
T_CLASS, T_CLASS,
@ -483,6 +506,8 @@ static enum criteria_token token_from_name(char *name) {
return T_CON_ID; return T_CON_ID;
} else if (strcmp(name, "con_mark") == 0) { } else if (strcmp(name, "con_mark") == 0) {
return T_CON_MARK; return T_CON_MARK;
} else if (strcmp(name, "cli_label") == 0) {
return T_CLI_LABEL;
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
} else if (strcmp(name, "class") == 0) { } else if (strcmp(name, "class") == 0) {
return T_CLASS; return T_CLASS;
@ -559,6 +584,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
case T_CON_MARK: case T_CON_MARK:
pattern_create(&criteria->con_mark, value); pattern_create(&criteria->con_mark, value);
break; break;
case T_CLI_LABEL:
pattern_create(&criteria->cli_label, value);
break;
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
case T_CLASS: case T_CLASS:
pattern_create(&criteria->class, value); pattern_create(&criteria->class, value);

View file

@ -495,6 +495,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
json_object_object_add(object, "app_id", json_object_object_add(object, "app_id",
app_id ? json_object_new_string(app_id) : NULL); app_id ? json_object_new_string(app_id) : NULL);
const char *label = view_get_conn_label(c->view);
json_object_object_add(object, "cli_label",
label ? json_object_new_string(label) : NULL);
bool visible = view_is_visible(c->view); bool visible = view_is_visible(c->view);
json_object_object_add(object, "visible", json_object_new_boolean(visible)); json_object_object_add(object, "visible", json_object_new_boolean(visible));