From 4e46bdf73dc2e9f98ca14263f42dde664f7d2aba Mon Sep 17 00:00:00 2001 From: Anders Date: Sun, 26 Jan 2020 10:27:52 +0100 Subject: [PATCH] criteria: match containers without view Closes #4929 Replaces criteria_get_views with criteria_get_containers which can return containers without views when the criteria only contains container properties. --- include/sway/criteria.h | 4 +-- sway/commands.c | 16 +++++------ sway/criteria.c | 61 ++++++++++++++++++++++++++--------------- 3 files changed, 49 insertions(+), 32 deletions(-) diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 1ee69a3885..beb76d5f38 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -73,8 +73,8 @@ struct criteria *criteria_parse(char *raw, char **error); list_t *criteria_for_view(struct sway_view *view, enum criteria_type types); /** - * Compile a list of views matching the given criteria. + * Compile a list of containers matching the given criteria. */ -list_t *criteria_get_views(struct criteria *criteria); +list_t *criteria_get_containers(struct criteria *criteria); #endif diff --git a/sway/commands.c b/sway/commands.c index 751dbe9c40..6a56ff5a9d 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -201,7 +201,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, struct sway_container *con) { char *cmd; char matched_delim = ';'; - list_t *views = NULL; + list_t *containers = NULL; if (seat == NULL) { // passing a NULL seat means we just pick the default seat @@ -235,8 +235,8 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, free(error); goto cleanup; } - list_free(views); - views = criteria_get_views(criteria); + list_free(containers); + containers = criteria_get_containers(criteria); head += strlen(criteria->raw); criteria_destroy(criteria); config->handler_context.using_criteria = true; @@ -289,14 +289,14 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, free_argv(argc, argv); goto cleanup; } - } else if (views->length == 0) { + } else if (containers->length == 0) { list_add(res_list, cmd_results_new(CMD_FAILURE, "No matching node.")); } else { struct cmd_results *fail_res = NULL; - for (int i = 0; i < views->length; ++i) { - struct sway_view *view = views->items[i]; - set_config_node(&view->container->node); + for (int i = 0; i < containers->length; ++i) { + struct sway_container *container = containers->items[i]; + set_config_node(&container->node); struct cmd_results *res = handler->handle(argc-1, argv+1); if (res->status == CMD_SUCCESS) { free_cmd_results(res); @@ -320,7 +320,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, } while(head); cleanup: free(exec); - list_free(views); + list_free(containers); return res_list; } diff --git a/sway/criteria.c b/sway/criteria.c index eec625affc..2c8e164464 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -144,6 +144,35 @@ static void find_urgent_iterator(struct sway_container *con, void *data) { list_add(urgent_views, con->view); } +static bool has_container_criteria(struct criteria *criteria) { + return criteria->con_mark || criteria->con_id; +} + +static bool criteria_matches_container(struct criteria *criteria, + struct sway_container *container) { + if (criteria->con_mark) { + bool exists = false; + struct sway_container *con = container; + for (int i = 0; i < con->marks->length; ++i) { + if (regex_cmp(con->marks->items[i], criteria->con_mark->regex) == 0) { + exists = true; + break; + } + } + if (!exists) { + return false; + } + } + + if (criteria->con_id) { // Internal ID + if (container->node.id != criteria->con_id) { + return false; + } + } + + return true; +} + static bool criteria_matches_view(struct criteria *criteria, struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(); @@ -210,24 +239,8 @@ static bool criteria_matches_view(struct criteria *criteria, } } - if (criteria->con_mark) { - bool exists = false; - struct sway_container *con = view->container; - for (int i = 0; i < con->marks->length; ++i) { - if (regex_cmp(con->marks->items[i], criteria->con_mark->regex) == 0) { - exists = true; - break; - } - } - if (!exists) { - return false; - } - } - - if (criteria->con_id) { // Internal ID - if (!view->container || view->container->node.id != criteria->con_id) { - return false; - } + if (!criteria_matches_container(criteria, view->container)) { + return false; } #if HAVE_XWAYLAND @@ -377,23 +390,27 @@ struct match_data { list_t *matches; }; -static void criteria_get_views_iterator(struct sway_container *container, +static void criteria_get_containers_iterator(struct sway_container *container, void *data) { struct match_data *match_data = data; if (container->view) { if (criteria_matches_view(match_data->criteria, container->view)) { - list_add(match_data->matches, container->view); + list_add(match_data->matches, container); + } + } else if (has_container_criteria(match_data->criteria)) { + if (criteria_matches_container(match_data->criteria, container)) { + list_add(match_data->matches, container); } } } -list_t *criteria_get_views(struct criteria *criteria) { +list_t *criteria_get_containers(struct criteria *criteria) { list_t *matches = create_list(); struct match_data data = { .criteria = criteria, .matches = matches, }; - root_for_each_container(criteria_get_views_iterator, &data); + root_for_each_container(criteria_get_containers_iterator, &data); return matches; }