mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
rcxml: simplify the logic to traverse xml tree
This commit is contained in:
parent
ad970544e1
commit
2f414a438b
1 changed files with 38 additions and 199 deletions
|
|
@ -38,35 +38,6 @@
|
||||||
#include "window-rules.h"
|
#include "window-rules.h"
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
|
|
||||||
struct parser_state {
|
|
||||||
bool in_regions;
|
|
||||||
bool in_usable_area_override;
|
|
||||||
bool in_keybind;
|
|
||||||
bool in_mousebind;
|
|
||||||
bool in_touch;
|
|
||||||
bool in_libinput_category;
|
|
||||||
bool in_window_switcher_field;
|
|
||||||
bool in_window_rules;
|
|
||||||
bool in_action_query;
|
|
||||||
bool in_action_then_branch;
|
|
||||||
bool in_action_else_branch;
|
|
||||||
bool in_action_none_branch;
|
|
||||||
struct usable_area_override *current_usable_area_override;
|
|
||||||
struct keybind *current_keybind;
|
|
||||||
struct mousebind *current_mousebind;
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* for backward compatibility of <mouse><scrollFactor> */
|
/* for backward compatibility of <mouse><scrollFactor> */
|
||||||
static double mouse_scroll_factor = -1;
|
static double mouse_scroll_factor = -1;
|
||||||
|
|
||||||
|
|
@ -1065,12 +1036,10 @@ set_tearing_mode(const char *str, enum tearing_mode *variable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* Returns true if the node's children should also be traversed */
|
||||||
entry(xmlNode *node, char *nodename, char *content, struct parser_state *state)
|
static bool
|
||||||
|
entry(xmlNode *node, char *nodename, char *content)
|
||||||
{
|
{
|
||||||
if (!nodename) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string_truncate_at_pattern(nodename, ".openbox_config");
|
string_truncate_at_pattern(nodename, ".openbox_config");
|
||||||
string_truncate_at_pattern(nodename, ".labwc_config");
|
string_truncate_at_pattern(nodename, ".labwc_config");
|
||||||
|
|
||||||
|
|
@ -1078,81 +1047,45 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state)
|
||||||
printf("%s: %s\n", nodename, content);
|
printf("%s: %s\n", nodename, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handle nested nodes */
|
||||||
if (!strcasecmp(nodename, "margin")) {
|
if (!strcasecmp(nodename, "margin")) {
|
||||||
fill_usable_area_override(node);
|
fill_usable_area_override(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "keybind.keyboard")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "keybind.keyboard")) {
|
|
||||||
fill_keybind(node);
|
fill_keybind(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "context.mouse")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "context.mouse")) {
|
|
||||||
fill_mouse_context(node);
|
fill_mouse_context(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "touch")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "touch")) {
|
|
||||||
fill_touch(node);
|
fill_touch(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "device.libinput")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "device.libinput")) {
|
|
||||||
fill_libinput_category(node);
|
fill_libinput_category(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "regions")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "regions")) {
|
|
||||||
fill_regions(node);
|
fill_regions(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "fields.windowSwitcher")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "fields.windowSwitcher")) {
|
|
||||||
fill_window_switcher_fields(node);
|
fill_window_switcher_fields(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "windowRules")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "windowRules")) {
|
|
||||||
fill_window_rules(node);
|
fill_window_rules(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "font.theme")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "font.theme")) {
|
|
||||||
fill_font(node);
|
fill_font(node);
|
||||||
return;
|
} else if (!strcasecmp(nodename, "map.tablet")) {
|
||||||
}
|
|
||||||
if (!strcasecmp(nodename, "map.tablet")) {
|
|
||||||
fill_tablet_button_map(node);
|
fill_tablet_button_map(node);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* handle nodes without content, e.g. <keyboard><default /> */
|
/* handle nodes without content, e.g. <keyboard><default /> */
|
||||||
if (!strcmp(nodename, "default.keyboard")) {
|
} else if (!strcmp(nodename, "default.keyboard")) {
|
||||||
load_default_key_bindings();
|
load_default_key_bindings();
|
||||||
return;
|
} else if (!strcmp(nodename, "default.mouse")) {
|
||||||
}
|
|
||||||
if (!strcmp(nodename, "devault.mouse")
|
|
||||||
|| !strcmp(nodename, "default.mouse")) {
|
|
||||||
load_default_mouse_bindings();
|
load_default_mouse_bindings();
|
||||||
return;
|
} else if (!strcasecmp(nodename, "prefix.desktops")) {
|
||||||
}
|
xstrdup_replace(rc.workspace_config.prefix, content);
|
||||||
|
|
||||||
if (!strcasecmp(nodename, "prefix.desktops")) {
|
} else if (!lab_xml_node_is_leaf(node)) {
|
||||||
xstrdup_replace(rc.workspace_config.prefix, content ? content : "");
|
/* parse children of nested nodes other than above */
|
||||||
return;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
} else if (str_space_only(content)) {
|
||||||
* Nodenames where we want to honour !content have to be parsed above
|
/* ignore empty leaf nodes other than above */
|
||||||
* this point. An example of this is:
|
|
||||||
*
|
|
||||||
* <desktops>
|
|
||||||
* <prefix></prefix>
|
|
||||||
* </desktops>
|
|
||||||
*
|
|
||||||
* In the case of the <prefix> element having content, the node will be
|
|
||||||
* processed twice; first for the element itself (with no content) and
|
|
||||||
* then the content itself. In this situation xstrdup_replace() is
|
|
||||||
* called twice, but the end result is the right one.
|
|
||||||
*/
|
|
||||||
if (!content) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(nodename, "decoration.core")) {
|
/* handle non-empty leaf nodes */
|
||||||
|
} else if (!strcmp(nodename, "decoration.core")) {
|
||||||
if (!strcmp(content, "client")) {
|
if (!strcmp(content, "client")) {
|
||||||
rc.xdg_shell_server_side_deco = false;
|
rc.xdg_shell_server_side_deco = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1361,117 +1294,22 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state)
|
||||||
} else if (!strcasecmp(nodename, "useFilter.magnifier")) {
|
} else if (!strcasecmp(nodename, "useFilter.magnifier")) {
|
||||||
set_bool(content, &rc.mag_filter);
|
set_bool(content, &rc.mag_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_node(xmlNode *node, struct parser_state *state)
|
traverse(xmlNode *node)
|
||||||
{
|
{
|
||||||
char *content;
|
xmlNode *child;
|
||||||
static char buffer[256];
|
char *key, *content;
|
||||||
char *name;
|
LAB_XML_FOR_EACH(node, child, key, content) {
|
||||||
|
(void)key;
|
||||||
content = (char *)node->content;
|
char buffer[256];
|
||||||
if (xmlIsBlankNode(node)) {
|
char *name = nodename(child, buffer, sizeof(buffer));
|
||||||
return;
|
if (entry(child, name, content)) {
|
||||||
}
|
traverse(child);
|
||||||
name = nodename(node, buffer, sizeof(buffer));
|
|
||||||
entry(node, name, content, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xml_tree_walk(xmlNode *node, struct parser_state *state);
|
|
||||||
|
|
||||||
static void
|
|
||||||
traverse(xmlNode *n, struct parser_state *state)
|
|
||||||
{
|
|
||||||
xmlAttr *attr;
|
|
||||||
|
|
||||||
process_node(n, state);
|
|
||||||
for (attr = n->properties; attr; attr = attr->next) {
|
|
||||||
xml_tree_walk(attr->children, state);
|
|
||||||
}
|
|
||||||
xml_tree_walk(n->children, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xml_tree_walk(xmlNode *node, struct parser_state *state)
|
|
||||||
{
|
|
||||||
for (xmlNode *n = node; n && n->name; n = n->next) {
|
|
||||||
if (!strcasecmp((char *)n->name, "comment")) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (!strcasecmp((char *)n->name, "margin")) {
|
|
||||||
state->in_usable_area_override = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_usable_area_override = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "keybind")) {
|
|
||||||
state->in_keybind = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_keybind = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "mousebind")) {
|
|
||||||
state->in_mousebind = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_mousebind = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "touch")) {
|
|
||||||
state->in_touch = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_touch = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "device")) {
|
|
||||||
state->in_libinput_category = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_libinput_category = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "regions")) {
|
|
||||||
state->in_regions = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_regions = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "fields")) {
|
|
||||||
state->in_window_switcher_field = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_window_switcher_field = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "windowRules")) {
|
|
||||||
state->in_window_rules = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_window_rules = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "query")) {
|
|
||||||
state->in_action_query = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_action_query = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "then")) {
|
|
||||||
state->in_action_then_branch = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_action_then_branch = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "else")) {
|
|
||||||
state->in_action_else_branch = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_action_else_branch = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strcasecmp((char *)n->name, "none")) {
|
|
||||||
state->in_action_none_branch = true;
|
|
||||||
traverse(n, state);
|
|
||||||
state->in_action_none_branch = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
traverse(n, state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1485,10 +1323,11 @@ rcxml_parse_xml(struct buf *b)
|
||||||
wlr_log(WLR_ERROR, "error parsing config file");
|
wlr_log(WLR_ERROR, "error parsing config file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct parser_state init_state = {0};
|
|
||||||
xmlNode *root = xmlDocGetRootElement(d);
|
xmlNode *root = xmlDocGetRootElement(d);
|
||||||
|
|
||||||
lab_xml_expand_dotted_attributes(root);
|
lab_xml_expand_dotted_attributes(root);
|
||||||
xml_tree_walk(root, &init_state);
|
traverse(root);
|
||||||
|
|
||||||
xmlFreeDoc(d);
|
xmlFreeDoc(d);
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue