mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
rcxml: rewrite action parser
This commit rewrites the nested action parser into append_actions() which is used by following commits. At this point, it's not used yet and parsing "If" action is temporarily disabled.
This commit is contained in:
parent
8881841098
commit
9462457cc2
1 changed files with 128 additions and 127 deletions
|
|
@ -432,112 +432,141 @@ 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(struct action *action, xmlNode *node, struct view_query *query)
|
||||
{
|
||||
if (!action) {
|
||||
wlr_log(WLR_ERROR, "No parent action for query: %s=%s", nodename, content);
|
||||
return;
|
||||
}
|
||||
|
||||
string_truncate_at_pattern(nodename, ".keybind.keyboard");
|
||||
string_truncate_at_pattern(nodename, ".mousebind.context.mouse");
|
||||
|
||||
if (!strcasecmp(nodename, "query.action")) {
|
||||
state->current_view_query = NULL;
|
||||
}
|
||||
|
||||
string_truncate_at_pattern(nodename, ".query.action");
|
||||
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state->current_view_query) {
|
||||
struct wl_list *queries = action_get_querylist(action, "query");
|
||||
if (!queries) {
|
||||
action_arg_add_querylist(action, "query");
|
||||
queries = action_get_querylist(action, "query");
|
||||
xmlNode *child;
|
||||
char *key, *content;
|
||||
LAB_XML_FOR_EACH(node, child, key, content) {
|
||||
if (!strcasecmp(key, "identifier")) {
|
||||
xstrdup_replace(query->identifier, content);
|
||||
} else if (!strcasecmp(key, "title")) {
|
||||
xstrdup_replace(query->title, content);
|
||||
} else if (!strcmp(key, "type")) {
|
||||
query->window_type = parse_window_type(content);
|
||||
} else if (!strcasecmp(key, "sandboxEngine")) {
|
||||
xstrdup_replace(query->sandbox_engine, content);
|
||||
} else if (!strcasecmp(key, "sandboxAppId")) {
|
||||
xstrdup_replace(query->sandbox_app_id, content);
|
||||
} else if (!strcasecmp(key, "shaded")) {
|
||||
query->shaded = parse_three_state(content);
|
||||
} else if (!strcasecmp(key, "maximized")) {
|
||||
query->maximized = view_axis_parse(content);
|
||||
} else if (!strcasecmp(key, "iconified")) {
|
||||
query->iconified = parse_three_state(content);
|
||||
} else if (!strcasecmp(key, "focused")) {
|
||||
query->focused = parse_three_state(content);
|
||||
} else if (!strcasecmp(key, "omnipresent")) {
|
||||
query->omnipresent = parse_three_state(content);
|
||||
} else if (!strcasecmp(key, "tiled")) {
|
||||
query->tiled = view_edge_parse(content);
|
||||
} else if (!strcasecmp(key, "tiled_region")) {
|
||||
xstrdup_replace(query->tiled_region, content);
|
||||
} else if (!strcasecmp(key, "desktop")) {
|
||||
xstrdup_replace(query->desktop, content);
|
||||
} else if (!strcasecmp(key, "decoration")) {
|
||||
query->decoration = ssd_mode_parse(content);
|
||||
} else if (!strcasecmp(key, "monitor")) {
|
||||
xstrdup_replace(query->monitor, content);
|
||||
}
|
||||
state->current_view_query = view_query_create();
|
||||
wl_list_append(queries, &state->current_view_query->link);
|
||||
}
|
||||
|
||||
if (!strcasecmp(nodename, "identifier")) {
|
||||
xstrdup_replace(state->current_view_query->identifier, content);
|
||||
} else if (!strcasecmp(nodename, "title")) {
|
||||
xstrdup_replace(state->current_view_query->title, content);
|
||||
} else if (!strcmp(nodename, "type")) {
|
||||
state->current_view_query->window_type = parse_window_type(content);
|
||||
} else if (!strcasecmp(nodename, "sandboxEngine")) {
|
||||
xstrdup_replace(state->current_view_query->sandbox_engine, content);
|
||||
} else if (!strcasecmp(nodename, "sandboxAppId")) {
|
||||
xstrdup_replace(state->current_view_query->sandbox_app_id, content);
|
||||
} else if (!strcasecmp(nodename, "shaded")) {
|
||||
state->current_view_query->shaded = parse_three_state(content);
|
||||
} else if (!strcasecmp(nodename, "maximized")) {
|
||||
state->current_view_query->maximized = view_axis_parse(content);
|
||||
} else if (!strcasecmp(nodename, "iconified")) {
|
||||
state->current_view_query->iconified = parse_three_state(content);
|
||||
} else if (!strcasecmp(nodename, "focused")) {
|
||||
state->current_view_query->focused = parse_three_state(content);
|
||||
} else if (!strcasecmp(nodename, "omnipresent")) {
|
||||
state->current_view_query->omnipresent = parse_three_state(content);
|
||||
} else if (!strcasecmp(nodename, "tiled")) {
|
||||
state->current_view_query->tiled = view_edge_parse(content);
|
||||
} else if (!strcasecmp(nodename, "tiled_region")) {
|
||||
xstrdup_replace(state->current_view_query->tiled_region, content);
|
||||
} else if (!strcasecmp(nodename, "desktop")) {
|
||||
xstrdup_replace(state->current_view_query->desktop, content);
|
||||
} else if (!strcasecmp(nodename, "decoration")) {
|
||||
state->current_view_query->decoration = ssd_mode_parse(content);
|
||||
} else if (!strcasecmp(nodename, "monitor")) {
|
||||
xstrdup_replace(state->current_view_query->monitor, content);
|
||||
}
|
||||
}
|
||||
|
||||
static void append_actions(xmlNode *node, struct wl_list *list);
|
||||
|
||||
static void
|
||||
fill_child_action(char *nodename, char *content, struct action *parent,
|
||||
const char *branch_name, struct parser_state *state)
|
||||
parse_action_args(xmlNode *node, struct action *action)
|
||||
{
|
||||
if (!parent) {
|
||||
wlr_log(WLR_ERROR, "No parent action for branch: %s=%s", nodename, content);
|
||||
return;
|
||||
}
|
||||
|
||||
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, "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;
|
||||
xmlNode *child;
|
||||
char *key, *content;
|
||||
LAB_XML_FOR_EACH(node, child, key, content) {
|
||||
if (!strcasecmp(key, "query")) {
|
||||
struct wl_list *querylist =
|
||||
action_get_querylist(action, "query");
|
||||
if (!querylist) {
|
||||
action_arg_add_querylist(action, "query");
|
||||
querylist = action_get_querylist(action, "query");
|
||||
}
|
||||
struct view_query *query = view_query_create();
|
||||
fill_action_query(action, child, query);
|
||||
wl_list_append(querylist, &query->link);
|
||||
} else if (!strcasecmp(key, "then")) {
|
||||
struct wl_list *actions =
|
||||
action_get_actionlist(action, "then");
|
||||
if (!actions) {
|
||||
action_arg_add_actionlist(action, "then");
|
||||
actions = action_get_actionlist(action, "then");
|
||||
}
|
||||
append_actions(child, actions);
|
||||
} else if (!strcasecmp(key, "else")) {
|
||||
struct wl_list *actions =
|
||||
action_get_actionlist(action, "else");
|
||||
if (!actions) {
|
||||
action_arg_add_actionlist(action, "else");
|
||||
actions = action_get_actionlist(action, "else");
|
||||
}
|
||||
append_actions(child, actions);
|
||||
} else if (!strcasecmp(key, "none")) {
|
||||
struct wl_list *actions =
|
||||
action_get_actionlist(action, "none");
|
||||
if (!actions) {
|
||||
action_arg_add_actionlist(action, "none");
|
||||
actions = action_get_actionlist(action, "none");
|
||||
}
|
||||
append_actions(child, actions);
|
||||
} else if (!strcasecmp(key, "name")) {
|
||||
/* Ignore <action name=""> */
|
||||
} else if (lab_xml_node_is_leaf(child)) {
|
||||
/* Handle normal action args */
|
||||
char buffer[256];
|
||||
char *node_name = nodename(child, buffer, sizeof(buffer));
|
||||
action_arg_from_xml_node(action, node_name, content);
|
||||
} else {
|
||||
/* Handle nested args like <position><x> in ShowMenu */
|
||||
parse_action_args(child, action);
|
||||
}
|
||||
state->current_child_action = action_create(content);
|
||||
if (state->current_child_action) {
|
||||
wl_list_append(siblings, &state->current_child_action->link);
|
||||
}
|
||||
}
|
||||
|
||||
static struct action *
|
||||
parse_action(xmlNode *node)
|
||||
{
|
||||
char name[256];
|
||||
struct action *action = NULL;
|
||||
|
||||
if (lab_xml_get_string(node, "name", name, sizeof(name))) {
|
||||
action = action_create(name);
|
||||
}
|
||||
if (!action) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_action_args(node, action);
|
||||
return action;
|
||||
}
|
||||
|
||||
static void
|
||||
append_actions(xmlNode *node, struct wl_list *list)
|
||||
{
|
||||
xmlNode *child;
|
||||
char *key, *content;
|
||||
LAB_XML_FOR_EACH(node, child, key, content) {
|
||||
if (strcasecmp(key, "action")) {
|
||||
continue;
|
||||
}
|
||||
if (lab_xml_node_is_leaf(child)) {
|
||||
/*
|
||||
* A mousebind contains two types of "action" nodes:
|
||||
* <mousebind button="Left" action="Click">
|
||||
* <action name="Close" />
|
||||
* </mousebind>
|
||||
* The first node (action="Click") is skipped.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
struct action *action = parse_action(child);
|
||||
if (action) {
|
||||
wl_list_append(list, &action->link);
|
||||
}
|
||||
} else if (!state->current_child_action) {
|
||||
wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
|
||||
"nodename: '%s' content: '%s'", nodename, content);
|
||||
} else {
|
||||
action_arg_from_xml_node(state->current_child_action, nodename, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1055,38 +1084,10 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state)
|
|||
fill_usable_area_override(nodename, content, state);
|
||||
}
|
||||
if (state->in_keybind) {
|
||||
if (state->in_action_query) {
|
||||
fill_action_query(nodename, content,
|
||||
state->current_keybind_action, state);
|
||||
} else if (state->in_action_then_branch) {
|
||||
fill_child_action(nodename, content,
|
||||
state->current_keybind_action, "then", state);
|
||||
} else if (state->in_action_else_branch) {
|
||||
fill_child_action(nodename, content,
|
||||
state->current_keybind_action, "else", state);
|
||||
} else if (state->in_action_none_branch) {
|
||||
fill_child_action(nodename, content,
|
||||
state->current_keybind_action, "none", state);
|
||||
} else {
|
||||
fill_keybind(nodename, content, state);
|
||||
}
|
||||
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_mousebind(nodename, content, state);
|
||||
}
|
||||
if (state->in_touch) {
|
||||
fill_touch(nodename, content, state);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue