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.
This commit is contained in:
Anders 2020-01-26 10:27:52 +01:00 committed by Brian Ashworth
parent 3f0225eea3
commit 4e46bdf73d
3 changed files with 49 additions and 32 deletions

View file

@ -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); 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 #endif

View file

@ -201,7 +201,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat,
struct sway_container *con) { struct sway_container *con) {
char *cmd; char *cmd;
char matched_delim = ';'; char matched_delim = ';';
list_t *views = NULL; list_t *containers = NULL;
if (seat == NULL) { if (seat == NULL) {
// passing a NULL seat means we just pick the default seat // 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); free(error);
goto cleanup; goto cleanup;
} }
list_free(views); list_free(containers);
views = criteria_get_views(criteria); containers = criteria_get_containers(criteria);
head += strlen(criteria->raw); head += strlen(criteria->raw);
criteria_destroy(criteria); criteria_destroy(criteria);
config->handler_context.using_criteria = true; config->handler_context.using_criteria = true;
@ -289,14 +289,14 @@ list_t *execute_command(char *_exec, struct sway_seat *seat,
free_argv(argc, argv); free_argv(argc, argv);
goto cleanup; goto cleanup;
} }
} else if (views->length == 0) { } else if (containers->length == 0) {
list_add(res_list, list_add(res_list,
cmd_results_new(CMD_FAILURE, "No matching node.")); cmd_results_new(CMD_FAILURE, "No matching node."));
} else { } else {
struct cmd_results *fail_res = NULL; struct cmd_results *fail_res = NULL;
for (int i = 0; i < views->length; ++i) { for (int i = 0; i < containers->length; ++i) {
struct sway_view *view = views->items[i]; struct sway_container *container = containers->items[i];
set_config_node(&view->container->node); set_config_node(&container->node);
struct cmd_results *res = handler->handle(argc-1, argv+1); struct cmd_results *res = handler->handle(argc-1, argv+1);
if (res->status == CMD_SUCCESS) { if (res->status == CMD_SUCCESS) {
free_cmd_results(res); free_cmd_results(res);
@ -320,7 +320,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat,
} while(head); } while(head);
cleanup: cleanup:
free(exec); free(exec);
list_free(views); list_free(containers);
return res_list; return res_list;
} }

View file

@ -144,6 +144,35 @@ static void find_urgent_iterator(struct sway_container *con, void *data) {
list_add(urgent_views, con->view); 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, static bool criteria_matches_view(struct criteria *criteria,
struct sway_view *view) { struct sway_view *view) {
struct sway_seat *seat = input_manager_current_seat(); struct sway_seat *seat = input_manager_current_seat();
@ -210,25 +239,9 @@ static bool criteria_matches_view(struct criteria *criteria,
} }
} }
if (criteria->con_mark) { if (!criteria_matches_container(criteria, view->container)) {
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; return false;
} }
}
if (criteria->con_id) { // Internal ID
if (!view->container || view->container->node.id != criteria->con_id) {
return false;
}
}
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
if (criteria->id) { // X11 window ID if (criteria->id) { // X11 window ID
@ -377,23 +390,27 @@ struct match_data {
list_t *matches; 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) { void *data) {
struct match_data *match_data = data; struct match_data *match_data = data;
if (container->view) { if (container->view) {
if (criteria_matches_view(match_data->criteria, 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(); list_t *matches = create_list();
struct match_data data = { struct match_data data = {
.criteria = criteria, .criteria = criteria,
.matches = matches, .matches = matches,
}; };
root_for_each_container(criteria_get_views_iterator, &data); root_for_each_container(criteria_get_containers_iterator, &data);
return matches; return matches;
} }