diff --git a/include/action.h b/include/action.h index 76c6fc98..f11e4c11 100644 --- a/include/action.h +++ b/include/action.h @@ -30,6 +30,8 @@ bool actions_contain_toggle_keybinds(struct wl_list *action_list); void actions_run(struct view *activator, struct server *server, struct wl_list *actions, uint32_t resize_edges); + +void action_free(struct action *action); void action_list_free(struct wl_list *action_list); #endif /* LABWC_ACTION_H */ diff --git a/src/action.c b/src/action.c index ad5a657b..65f33de1 100644 --- a/src/action.c +++ b/src/action.c @@ -401,23 +401,30 @@ action_is_valid(struct action *action) return false; } -void action_list_free(struct wl_list *action_list) +void +action_free(struct action *action) { + /* Free args */ struct action_arg *arg, *arg_tmp; + wl_list_for_each_safe(arg, arg_tmp, &action->args, link) { + wl_list_remove(&arg->link); + zfree(arg->key); + if (arg->type == LAB_ACTION_ARG_STR) { + struct action_arg_str *str_arg = (struct action_arg_str *)arg; + zfree(str_arg->value); + } + zfree(arg); + } + zfree(action); +} + +void +action_list_free(struct wl_list *action_list) +{ struct action *action, *action_tmp; - /* Free actions */ wl_list_for_each_safe(action, action_tmp, action_list, link) { wl_list_remove(&action->link); - /* Free args */ - wl_list_for_each_safe(arg, arg_tmp, &action->args, link) { - wl_list_remove(&arg->link); - zfree(arg->key); - if (arg->type == LAB_ACTION_ARG_STR) { - free((void *)action_str_from_arg(arg)); - } - zfree(arg); - } - zfree(action); + action_free(action); } } diff --git a/src/config/rcxml.c b/src/config/rcxml.c index f78559d3..f0af0b51 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1121,6 +1121,45 @@ rule_destroy(struct window_rule *rule) zfree(rule); } +static void +validate_actions(void) +{ + struct action *action, *action_tmp; + + struct keybind *keybind; + wl_list_for_each(keybind, &rc.keybinds, link) { + wl_list_for_each_safe(action, action_tmp, &keybind->actions, link) { + if (!action_is_valid(action)) { + wl_list_remove(&action->link); + action_free(action); + wlr_log(WLR_ERROR, "Removed invalid keybind action"); + } + } + } + + struct mousebind *mousebind; + wl_list_for_each(mousebind, &rc.mousebinds, link) { + wl_list_for_each_safe(action, action_tmp, &mousebind->actions, link) { + if (!action_is_valid(action)) { + wl_list_remove(&action->link); + action_free(action); + wlr_log(WLR_ERROR, "Removed invalid mousebind action"); + } + } + } + + struct window_rule *rule; + wl_list_for_each(rule, &rc.window_rules, link) { + wl_list_for_each_safe(action, action_tmp, &rule->actions, link) { + if (!action_is_valid(action)) { + wl_list_remove(&action->link); + action_free(action); + wlr_log(WLR_ERROR, "Removed invalid window rule action"); + } + } + } +} + static void validate(void) { @@ -1144,13 +1183,15 @@ validate(void) } /* Window-rule criteria */ - struct window_rule *rule, *next; - wl_list_for_each_safe(rule, next, &rc.window_rules, link) { + struct window_rule *rule, *rule_tmp; + wl_list_for_each_safe(rule, rule_tmp, &rc.window_rules, link) { if (!rule->identifier && !rule->title) { wlr_log(WLR_ERROR, "Deleting rule %p as it has no criteria", rule); rule_destroy(rule); } } + + validate_actions(); } static void diff --git a/src/menu/menu.c b/src/menu/menu.c index ff7bfda8..71419be4 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -128,6 +128,30 @@ post_processing(struct server *server) } } +static void +validate_menu(struct menu *menu) +{ + struct menuitem *item; + struct action *action, *action_tmp; + wl_list_for_each(item, &menu->menuitems, link) { + wl_list_for_each_safe(action, action_tmp, &item->actions, link) { + if (!action_is_valid(action)) { + wl_list_remove(&action->link); + action_free(action); + wlr_log(WLR_ERROR, "Removed invalid menu action"); + } + } + } +} + +static void +validate(struct server *server) +{ + for (int i = 0; i < nr_menus; ++i) { + validate_menu(menus + i); + } +} + static struct menuitem * item_create(struct menu *menu, const char *text, bool show_arrow) { @@ -730,6 +754,7 @@ menu_init(struct server *server) init_rootmenu(server); init_windowmenu(server); post_processing(server); + validate(server); } void