mirror of
https://github.com/swaywm/sway.git
synced 2025-02-17 23:04:31 +00:00
Add trigger information to criteria
This allows writing commands like "for_window [trigger="map",workspace="1"]" that only execute if the criteria matches during the initial mapping of the window. Currently implemented trigger names: - command: explicit invocation by a command, not very useful - map: initial window creation - mark, title, app_id, class, window_role, window_type: the given property changed
This commit is contained in:
parent
2c76923282
commit
9c30140b0a
|
@ -34,6 +34,7 @@ struct criteria {
|
|||
struct pattern *shell;
|
||||
struct pattern *app_id;
|
||||
struct pattern *con_mark;
|
||||
char *trigger; // event that triggered this criteria match
|
||||
uint32_t con_id; // internal ID
|
||||
#if HAVE_XWAYLAND
|
||||
struct pattern *class;
|
||||
|
@ -71,11 +72,11 @@ struct criteria *criteria_parse(char *raw, char **error);
|
|||
*
|
||||
* Criteria types can be bitwise ORed.
|
||||
*/
|
||||
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, const char* trigger);
|
||||
|
||||
/**
|
||||
* Compile a list of containers matching the given criteria.
|
||||
*/
|
||||
list_t *criteria_get_containers(struct criteria *criteria);
|
||||
list_t *criteria_get_containers(struct criteria *criteria, const char* trigger);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -341,7 +341,7 @@ void view_update_title(struct sway_view *view, bool force);
|
|||
* Run any criteria that match the view and haven't been run on this view
|
||||
* before.
|
||||
*/
|
||||
void view_execute_criteria(struct sway_view *view);
|
||||
void view_execute_criteria(struct sway_view *view, const char* trigger);
|
||||
|
||||
/**
|
||||
* Returns true if there's a possibility the view may be rendered on screen.
|
||||
|
|
|
@ -236,7 +236,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat,
|
|||
goto cleanup;
|
||||
}
|
||||
list_free(containers);
|
||||
containers = criteria_get_containers(criteria);
|
||||
containers = criteria_get_containers(criteria, "command");
|
||||
head += strlen(criteria->raw);
|
||||
criteria_destroy(criteria);
|
||||
config->handler_context.using_criteria = true;
|
||||
|
|
|
@ -61,7 +61,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
|
|||
free(mark);
|
||||
container_update_marks_textures(container);
|
||||
if (container->view) {
|
||||
view_execute_criteria(container->view);
|
||||
view_execute_criteria(container->view, "mark");
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
|
|
|
@ -20,6 +20,7 @@ bool criteria_is_empty(struct criteria *criteria) {
|
|||
&& !criteria->shell
|
||||
&& !criteria->app_id
|
||||
&& !criteria->con_mark
|
||||
&& !criteria->trigger
|
||||
&& !criteria->con_id
|
||||
#if HAVE_XWAYLAND
|
||||
&& !criteria->class
|
||||
|
@ -93,6 +94,7 @@ void criteria_destroy(struct criteria *criteria) {
|
|||
pattern_destroy(criteria->window_role);
|
||||
#endif
|
||||
pattern_destroy(criteria->con_mark);
|
||||
free(criteria->trigger);
|
||||
free(criteria->workspace);
|
||||
free(criteria->cmdlist);
|
||||
free(criteria->raw);
|
||||
|
@ -175,11 +177,15 @@ static bool criteria_matches_container(struct criteria *criteria,
|
|||
}
|
||||
|
||||
static bool criteria_matches_view(struct criteria *criteria,
|
||||
struct sway_view *view) {
|
||||
struct sway_view *view, const char* trigger) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_container *focus = seat_get_focused_container(seat);
|
||||
struct sway_view *focused = focus ? focus->view : NULL;
|
||||
|
||||
if (criteria->trigger && trigger && strcmp(criteria->trigger, trigger)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (criteria->title) {
|
||||
const char *title = view_get_title(view);
|
||||
if (!title) {
|
||||
|
@ -380,12 +386,12 @@ static bool criteria_matches_view(struct criteria *criteria,
|
|||
return true;
|
||||
}
|
||||
|
||||
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, const char* trigger) {
|
||||
list_t *criterias = config->criteria;
|
||||
list_t *matches = create_list();
|
||||
for (int i = 0; i < criterias->length; ++i) {
|
||||
struct criteria *criteria = criterias->items[i];
|
||||
if ((criteria->type & types) && criteria_matches_view(criteria, view)) {
|
||||
if ((criteria->type & types) && criteria_matches_view(criteria, view, trigger)) {
|
||||
list_add(matches, criteria);
|
||||
}
|
||||
}
|
||||
|
@ -395,13 +401,14 @@ list_t *criteria_for_view(struct sway_view *view, enum criteria_type types) {
|
|||
struct match_data {
|
||||
struct criteria *criteria;
|
||||
list_t *matches;
|
||||
const char* trigger;
|
||||
};
|
||||
|
||||
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)) {
|
||||
if (criteria_matches_view(match_data->criteria, container->view, match_data->trigger)) {
|
||||
list_add(match_data->matches, container);
|
||||
}
|
||||
} else if (has_container_criteria(match_data->criteria)) {
|
||||
|
@ -411,11 +418,12 @@ static void criteria_get_containers_iterator(struct sway_container *container,
|
|||
}
|
||||
}
|
||||
|
||||
list_t *criteria_get_containers(struct criteria *criteria) {
|
||||
list_t *criteria_get_containers(struct criteria *criteria, const char* trigger) {
|
||||
list_t *matches = create_list();
|
||||
struct match_data data = {
|
||||
.criteria = criteria,
|
||||
.matches = matches,
|
||||
.trigger = trigger,
|
||||
};
|
||||
root_for_each_container(criteria_get_containers_iterator, &data);
|
||||
return matches;
|
||||
|
@ -466,6 +474,7 @@ enum criteria_token {
|
|||
T_URGENT,
|
||||
T_WORKSPACE,
|
||||
T_PID,
|
||||
T_TRIGGER,
|
||||
|
||||
T_INVALID,
|
||||
};
|
||||
|
@ -475,6 +484,8 @@ static enum criteria_token token_from_name(char *name) {
|
|||
return T_APP_ID;
|
||||
} else if (strcmp(name, "con_id") == 0) {
|
||||
return T_CON_ID;
|
||||
} else if (strcmp(name, "trigger") == 0) {
|
||||
return T_TRIGGER;
|
||||
} else if (strcmp(name, "con_mark") == 0) {
|
||||
return T_CON_MARK;
|
||||
#if HAVE_XWAYLAND
|
||||
|
@ -550,6 +561,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case T_TRIGGER:
|
||||
criteria->trigger = strdup(value);
|
||||
break;
|
||||
case T_CON_MARK:
|
||||
pattern_create(&criteria->con_mark, value);
|
||||
break;
|
||||
|
|
|
@ -317,14 +317,14 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xdg_shell_view, set_title);
|
||||
struct sway_view *view = &xdg_shell_view->view;
|
||||
view_update_title(view, false);
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "title");
|
||||
}
|
||||
|
||||
static void handle_set_app_id(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_shell_view *xdg_shell_view =
|
||||
wl_container_of(listener, xdg_shell_view, set_app_id);
|
||||
struct sway_view *view = &xdg_shell_view->view;
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "app_id");
|
||||
}
|
||||
|
||||
static void handle_new_popup(struct wl_listener *listener, void *data) {
|
||||
|
|
|
@ -582,7 +582,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
view_update_title(view, false);
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "title");
|
||||
}
|
||||
|
||||
static void handle_set_class(struct wl_listener *listener, void *data) {
|
||||
|
@ -593,7 +593,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) {
|
|||
if (!xsurface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "class");
|
||||
}
|
||||
|
||||
static void handle_set_role(struct wl_listener *listener, void *data) {
|
||||
|
@ -604,7 +604,7 @@ static void handle_set_role(struct wl_listener *listener, void *data) {
|
|||
if (!xsurface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "window_role");
|
||||
}
|
||||
|
||||
static void handle_set_window_type(struct wl_listener *listener, void *data) {
|
||||
|
@ -615,7 +615,7 @@ static void handle_set_window_type(struct wl_listener *listener, void *data) {
|
|||
if (!xsurface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "window_type");
|
||||
}
|
||||
|
||||
static void handle_set_hints(struct wl_listener *listener, void *data) {
|
||||
|
|
|
@ -483,8 +483,8 @@ static bool view_has_executed_criteria(struct sway_view *view,
|
|||
return false;
|
||||
}
|
||||
|
||||
void view_execute_criteria(struct sway_view *view) {
|
||||
list_t *criterias = criteria_for_view(view, CT_COMMAND);
|
||||
void view_execute_criteria(struct sway_view *view, const char* trigger) {
|
||||
list_t *criterias = criteria_for_view(view, CT_COMMAND, trigger);
|
||||
for (int i = 0; i < criterias->length; i++) {
|
||||
struct criteria *criteria = criterias->items[i];
|
||||
sway_log(SWAY_DEBUG, "Checking criteria %s", criteria->raw);
|
||||
|
@ -531,7 +531,7 @@ static struct sway_workspace *select_workspace(struct sway_view *view) {
|
|||
|
||||
// Check if there's any `assign` criteria for the view
|
||||
list_t *criterias = criteria_for_view(view,
|
||||
CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT);
|
||||
CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT, NULL);
|
||||
struct sway_workspace *ws = NULL;
|
||||
for (int i = 0; i < criterias->length; ++i) {
|
||||
struct criteria *criteria = criterias->items[i];
|
||||
|
@ -611,7 +611,7 @@ static bool should_focus(struct sway_view *view) {
|
|||
}
|
||||
|
||||
// Check no_focus criteria
|
||||
list_t *criterias = criteria_for_view(view, CT_NO_FOCUS);
|
||||
list_t *criterias = criteria_for_view(view, CT_NO_FOCUS, NULL);
|
||||
size_t len = criterias->length;
|
||||
list_free(criterias);
|
||||
return len == 0;
|
||||
|
@ -781,7 +781,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
|||
}
|
||||
}
|
||||
|
||||
view_execute_criteria(view);
|
||||
view_execute_criteria(view, "map");
|
||||
|
||||
if (should_focus(view)) {
|
||||
input_manager_set_focus(&view->container->node);
|
||||
|
|
Loading…
Reference in a new issue