diff --git a/src/config/rcxml.c b/src/config/rcxml.c index a3b3ee3a..f14bf203 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -49,7 +49,8 @@ struct parser_state { bool in_touch; bool in_libinput_category; bool in_window_switcher_field; - bool in_window_rules; + bool in_window_rule; + bool in_action; bool in_action_query; bool in_action_then_branch; bool in_action_else_branch; @@ -60,14 +61,13 @@ struct parser_state { struct touch_config_entry *current_touch; struct libinput_category *current_libinput_category; const char *current_mouse_context; - struct action *current_keybind_action; - struct action *current_mousebind_action; struct region *current_region; struct window_switcher_field *current_field; struct window_rule *current_window_rule; - struct action *current_window_rule_action; struct view_query *current_view_query; - struct action *current_child_action; + struct action *current_inline_action; + struct wl_list *current_action_siblings; + struct action *current_action; }; /* for backward compatibility of */ @@ -279,10 +279,14 @@ fill_window_rule(char *nodename, char *content, struct parser_state *state) state->current_window_rule->window_type = -1; // Window types are >= 0 wl_list_append(&rc.window_rules, &state->current_window_rule->link); wl_list_init(&state->current_window_rule->actions); + state->current_action = NULL; + state->current_action_siblings = &state->current_window_rule->actions; + state->current_inline_action = NULL; return; } string_truncate_at_pattern(nodename, ".windowrule.windowrules"); + if (!content) { /* nop */ } else if (!state->current_window_rule) { @@ -328,16 +332,16 @@ fill_window_rule(char *nodename, char *content, struct parser_state *state) /* Actions */ } else if (!strcmp(nodename, "name.action")) { - state->current_window_rule_action = action_create(content); - if (state->current_window_rule_action) { + state->current_inline_action = action_create(content); + if (state->current_inline_action) { wl_list_append(&state->current_window_rule->actions, - &state->current_window_rule_action->link); + &state->current_inline_action->link); } - } else if (!state->current_window_rule_action) { + } else if (!state->current_inline_action) { wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); } else { - action_arg_from_xml_node(state->current_window_rule_action, nodename, content); + action_arg_from_xml_node(state->current_inline_action, nodename, content); } } @@ -399,15 +403,19 @@ fill_region(char *nodename, char *content, struct parser_state *state) } static void -fill_action_query(char *nodename, char *content, struct action *action, struct parser_state *state) +fill_action_query(char *nodename, char *content, struct parser_state *state) { - if (!action) { + if (!state->current_action) { wlr_log(WLR_ERROR, "No parent action for query: %s=%s", nodename, content); return; } + string_truncate_at_pattern(nodename, ".windowrule.windowrules"); string_truncate_at_pattern(nodename, ".keybind.keyboard"); string_truncate_at_pattern(nodename, ".mousebind.context.mouse"); + string_truncate_at_pattern(nodename, ".then.action"); + string_truncate_at_pattern(nodename, ".else.action"); + string_truncate_at_pattern(nodename, ".none.action"); if (!strcasecmp(nodename, "query.action")) { state->current_view_query = NULL; @@ -420,10 +428,10 @@ fill_action_query(char *nodename, char *content, struct action *action, struct p } if (!state->current_view_query) { - struct wl_list *queries = action_get_querylist(action, "query"); + struct wl_list *queries = action_get_querylist(state->current_action, "query"); if (!queries) { - action_arg_add_querylist(action, "query"); - queries = action_get_querylist(action, "query"); + action_arg_add_querylist(state->current_action, "query"); + queries = action_get_querylist(state->current_action, "query"); } state->current_view_query = view_query_create(); wl_list_append(queries, &state->current_view_query->link); @@ -463,14 +471,9 @@ fill_action_query(char *nodename, char *content, struct action *action, struct p } static void -fill_child_action(char *nodename, char *content, struct action *parent, - const char *branch_name, struct parser_state *state) +fill_action(char *nodename, char *content, struct parser_state *state) { - if (!parent) { - wlr_log(WLR_ERROR, "No parent action for branch: %s=%s", nodename, content); - return; - } - + string_truncate_at_pattern(nodename, ".windowrule.windowrules"); string_truncate_at_pattern(nodename, ".keybind.keyboard"); string_truncate_at_pattern(nodename, ".mousebind.context.mouse"); string_truncate_at_pattern(nodename, ".then.action"); @@ -478,33 +481,60 @@ fill_child_action(char *nodename, char *content, struct action *parent, string_truncate_at_pattern(nodename, ".none.action"); if (!strcasecmp(nodename, "action")) { - state->current_child_action = NULL; - } - - if (!content) { return; - } - - struct wl_list *siblings = action_get_actionlist(parent, branch_name); - if (!siblings) { - action_arg_add_actionlist(parent, branch_name); - siblings = action_get_actionlist(parent, branch_name); - } - - if (!strcasecmp(nodename, "name.action")) { - if (!strcasecmp(content, "If") || !strcasecmp(content, "ForEach")) { - wlr_log(WLR_ERROR, "action '%s' cannot be a child action", content); - return; + } else if (!strcmp(nodename, "name.action")) { + state->current_action = action_create(content); + if (state->current_action) { + wl_list_append(state->current_action_siblings, + &state->current_action->link); } - state->current_child_action = action_create(content); - if (state->current_child_action) { - wl_list_append(siblings, &state->current_child_action->link); - } - } else if (!state->current_child_action) { + } else if (!state->current_action) { wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); } else { - action_arg_from_xml_node(state->current_child_action, nodename, content); + action_arg_from_xml_node(state->current_action, nodename, content); + } +} + +static void +fill_child_action(char *nodename, char *content, struct parser_state *state, + const char *branch_name) +{ + string_truncate_at_pattern(nodename, ".windowrule.windowrules"); + string_truncate_at_pattern(nodename, ".keybind.keyboard"); + string_truncate_at_pattern(nodename, ".mousebind.context.mouse"); + string_truncate_at_pattern(nodename, ".then.action"); + string_truncate_at_pattern(nodename, ".else.action"); + string_truncate_at_pattern(nodename, ".none.action"); + + if (!state->current_action) { + wlr_log(WLR_ERROR, "No parent action for branch: %s=%s", nodename, content); + return; + } + + struct wl_list *siblings = action_get_actionlist(state->current_action, branch_name); + if (!siblings) { + action_arg_add_actionlist(state->current_action, branch_name); + siblings = action_get_actionlist(state->current_action, branch_name); + } + state->current_action_siblings = siblings; + + if (!content) { + state->current_inline_action = NULL; + return; + } + + if (!strcasecmp(nodename, "name.action")) { + state->current_inline_action = action_create(content); + if (state->current_inline_action) { + wl_list_append(state->current_action_siblings, + &state->current_inline_action->link); + } + } else if (!state->current_inline_action) { + wlr_log(WLR_ERROR, "expect element first. " + "nodename: '%s' content: '%s'", nodename, content); + } else { + action_arg_from_xml_node(state->current_inline_action, nodename, content); } } @@ -514,10 +544,10 @@ fill_keybind(char *nodename, char *content, struct parser_state *state) if (!content) { return; } + string_truncate_at_pattern(nodename, ".keybind.keyboard"); if (!strcmp(nodename, "key")) { state->current_keybind = keybind_create(content); - state->current_keybind_action = NULL; /* * If an invalid keybind has been provided, * keybind_create() complains. @@ -526,6 +556,9 @@ fill_keybind(char *nodename, char *content, struct parser_state *state) wlr_log(WLR_ERROR, "Invalid keybind: %s", content); return; } + state->current_action = NULL; + state->current_action_siblings = &state->current_keybind->actions; + state->current_inline_action = NULL; } else if (!state->current_keybind) { wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); @@ -536,12 +569,12 @@ fill_keybind(char *nodename, char *content, struct parser_state *state) } else if (!strcasecmp(nodename, "allowWhenLocked")) { set_bool(content, &state->current_keybind->allow_when_locked); } else if (!strcmp(nodename, "name.action")) { - state->current_keybind_action = action_create(content); - if (state->current_keybind_action) { + state->current_inline_action = action_create(content); + if (state->current_inline_action) { wl_list_append(&state->current_keybind->actions, - &state->current_keybind_action->link); + &state->current_inline_action->link); } - } else if (!state->current_keybind_action) { + } else if (!state->current_inline_action) { wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); } else { @@ -550,7 +583,7 @@ fill_keybind(char *nodename, char *content, struct parser_state *state) * , and so on. This is common to key- and * mousebinds. */ - action_arg_from_xml_node(state->current_keybind_action, nodename, content); + action_arg_from_xml_node(state->current_inline_action, nodename, content); } } @@ -574,7 +607,13 @@ fill_mousebind(char *nodename, char *content, struct parser_state *state) wlr_log(WLR_INFO, "create mousebind for %s", state->current_mouse_context); state->current_mousebind = mousebind_create(state->current_mouse_context); - state->current_mousebind_action = NULL; + if (!state->current_mousebind) { + wlr_log(WLR_ERROR, "Invalid mousebind: %s", content); + return; + } + state->current_action = NULL; + state->current_action_siblings = &state->current_mousebind->actions; + state->current_inline_action = NULL; return; } else if (!content) { return; @@ -596,16 +635,16 @@ fill_mousebind(char *nodename, char *content, struct parser_state *state) state->current_mousebind->mouse_event = mousebind_event_from_str(content); } else if (!strcmp(nodename, "name.action")) { - state->current_mousebind_action = action_create(content); - if (state->current_mousebind_action) { + state->current_inline_action = action_create(content); + if (state->current_inline_action) { wl_list_append(&state->current_mousebind->actions, - &state->current_mousebind_action->link); + &state->current_inline_action->link); } - } else if (!state->current_mousebind_action) { + } else if (!state->current_inline_action) { wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); } else { - action_arg_from_xml_node(state->current_mousebind_action, nodename, content); + action_arg_from_xml_node(state->current_inline_action, nodename, content); } } @@ -954,40 +993,29 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) if (state->in_usable_area_override) { fill_usable_area_override(nodename, content, state); } - if (state->in_keybind) { + + if ((state->in_keybind || state->in_mousebind || + state->in_window_rule) && state->in_action) { if (state->in_action_query) { - fill_action_query(nodename, content, - state->current_keybind_action, state); + fill_action_query(nodename, content, state); } else if (state->in_action_then_branch) { - fill_child_action(nodename, content, - state->current_keybind_action, "then", state); + fill_child_action(nodename, content, state, "then"); } else if (state->in_action_else_branch) { - fill_child_action(nodename, content, - state->current_keybind_action, "else", state); + fill_child_action(nodename, content, state, "else"); } else if (state->in_action_none_branch) { - fill_child_action(nodename, content, - state->current_keybind_action, "none", state); + fill_child_action(nodename, content, state, "none"); } else { - fill_keybind(nodename, content, state); - } - } - if (state->in_mousebind) { - if (state->in_action_query) { - fill_action_query(nodename, content, - state->current_mousebind_action, state); - } else if (state->in_action_then_branch) { - fill_child_action(nodename, content, - state->current_mousebind_action, "then", state); - } else if (state->in_action_else_branch) { - fill_child_action(nodename, content, - state->current_mousebind_action, "else", state); - } else if (state->in_action_none_branch) { - fill_child_action(nodename, content, - state->current_mousebind_action, "none", state); - } else { - fill_mousebind(nodename, content, state); + fill_action(nodename, content, state); } + return; + } else if (state->in_keybind) { + fill_keybind(nodename, content, state); + return; + } else if (state->in_mousebind) { + fill_mousebind(nodename, content, state); + return; } + if (state->in_touch) { fill_touch(nodename, content, state); return; @@ -1004,7 +1032,7 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) fill_window_switcher_field(nodename, content, state); return; } - if (state->in_window_rules) { + if (state->in_window_rule) { fill_window_rule(nodename, content, state); return; } @@ -1352,10 +1380,22 @@ xml_tree_walk(xmlNode *node, struct parser_state *state) state->in_window_switcher_field = false; continue; } - if (!strcasecmp((char *)n->name, "windowRules")) { - state->in_window_rules = true; + if (!strcasecmp((char *)n->name, "windowRule")) { + state->in_window_rule = true; traverse(n, state); - state->in_window_rules = false; + state->in_window_rule = false; + continue; + } + if (!strcasecmp((char *)n->name, "action")) { + struct parser_state new_state = *state; + new_state.current_action = NULL; + new_state.current_view_query = NULL; + new_state.in_action = true; + new_state.in_action_query = false; + new_state.in_action_then_branch = false; + new_state.in_action_else_branch = false; + new_state.in_action_none_branch = false; + traverse(n, &new_state); continue; } if (!strcasecmp((char *)n->name, "query")) {