+/*
+
+<keybind key="C-x">
+ <action name="ChangeDesktop">
+ <desktop>3</desktop>
+ </action>
+</keybind>
+
+*/
+
+static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ GList *keylist)
+{
+ gchar *key;
+ xmlNodePtr n;
+ gboolean is_chroot = FALSE;
+
+ if (!parse_attr_string("key", node, &key))
+ return;
+
+ parse_attr_bool("chroot", node, &is_chroot);
+
+ keylist = g_list_append(keylist, key);
+
+ if ((n = parse_find_node("keybind", node->children))) {
+ while (n) {
+ parse_key(i, doc, n, keylist);
+ n = parse_find_node("keybind", n->next);
+ }
+ }
+ else if ((n = parse_find_node("action", node->children))) {
+ while (n) {
+ ObAction *action;
+
+ action = action_parse(i, doc, n, OB_USER_ACTION_KEYBOARD_KEY);
+ if (action)
+ keyboard_bind(keylist, action);
+ n = parse_find_node("action", n->next);
+ }
+ }
+
+ if (is_chroot)
+ keyboard_chroot(keylist);
+
+ g_free(key);
+ keylist = g_list_delete_link(keylist, g_list_last(keylist));
+}
+
+static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n;
+ gchar *key;
+
+ keyboard_unbind_all();
+
+ if ((n = parse_find_node("chainQuitKey", node->children))) {
+ key = parse_string(doc, n);
+ translate_key(key, &config_keyboard_reset_state,
+ &config_keyboard_reset_keycode);
+ g_free(key);
+ }
+
+ if ((n = parse_find_node("keybind", node->children)))
+ while (n) {
+ parse_key(i, doc, n, NULL);
+ n = parse_find_node("keybind", n->next);
+ }
+}
+
+/*
+
+<context name="Titlebar">
+ <mousebind button="Left" action="Press">
+ <action name="Raise"></action>
+ </mousebind>
+</context>
+
+*/
+
+static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n, nbut, nact;
+ gchar *buttonstr;
+ gchar *contextstr;
+ ObUserAction uact;
+ ObMouseAction mact;
+ ObAction *action;
+
+ mouse_unbind_all();
+
+ node = node->children;
+
+ if ((n = parse_find_node("dragThreshold", node)))
+ config_mouse_threshold = parse_int(doc, n);
+ if ((n = parse_find_node("doubleClickTime", node)))
+ config_mouse_dclicktime = parse_int(doc, n);
+
+ n = parse_find_node("context", node);
+ while (n) {
+ if (!parse_attr_string("name", n, &contextstr))
+ goto next_n;
+ nbut = parse_find_node("mousebind", n->children);
+ while (nbut) {
+ if (!parse_attr_string("button", nbut, &buttonstr))
+ goto next_nbut;
+ if (parse_attr_contains("press", nbut, "action")) {
+ uact = OB_USER_ACTION_MOUSE_PRESS;
+ mact = OB_MOUSE_ACTION_PRESS;
+ } else if (parse_attr_contains("release", nbut, "action")) {
+ uact = OB_USER_ACTION_MOUSE_RELEASE;
+ mact = OB_MOUSE_ACTION_RELEASE;
+ } else if (parse_attr_contains("click", nbut, "action")) {
+ uact = OB_USER_ACTION_MOUSE_CLICK;
+ mact = OB_MOUSE_ACTION_CLICK;
+ } else if (parse_attr_contains("doubleclick", nbut,"action")) {
+ uact = OB_USER_ACTION_MOUSE_DOUBLE_CLICK;
+ mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
+ } else if (parse_attr_contains("drag", nbut, "action")) {
+ uact = OB_USER_ACTION_MOUSE_MOTION;
+ mact = OB_MOUSE_ACTION_MOTION;
+ } else
+ goto next_nbut;
+ nact = parse_find_node("action", nbut->children);
+ while (nact) {
+ if ((action = action_parse(i, doc, nact, uact)))
+ mouse_bind(buttonstr, contextstr, mact, action);
+ nact = parse_find_node("action", nact->next);
+ }
+ g_free(buttonstr);
+ next_nbut:
+ nbut = parse_find_node("mousebind", nbut->next);
+ }
+ g_free(contextstr);
+ next_n:
+ n = parse_find_node("context", n->next);
+ }
+}
+
+static void parse_focus(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n;
+
+ node = node->children;
+
+ if ((n = parse_find_node("focusNew", node)))
+ config_focus_new = parse_bool(doc, n);
+ if ((n = parse_find_node("followMouse", node)))
+ config_focus_follow = parse_bool(doc, n);
+ if ((n = parse_find_node("focusDelay", node)))
+ config_focus_delay = parse_int(doc, n) * 1000;
+ if ((n = parse_find_node("raiseOnFocus", node)))
+ config_focus_raise = parse_bool(doc, n);
+ if ((n = parse_find_node("focusLast", node)))
+ config_focus_last = parse_bool(doc, n);
+}
+
+static void parse_placement(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n;
+
+ node = node->children;
+
+ if ((n = parse_find_node("policy", node)))
+ if (parse_contains("UnderMouse", doc, n))
+ config_place_policy = OB_PLACE_POLICY_MOUSE;
+}
+
+static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n;
+
+ node = node->children;
+
+ if ((n = parse_find_node("name", node))) {
+ gchar *c;
+
+ g_free(config_theme);
+ c = parse_string(doc, n);
+ config_theme = parse_expand_tilde(c);
+ g_free(c);
+ }
+ if ((n = parse_find_node("titleLayout", node))) {
+ gchar *c, *d;
+
+ g_free(config_title_layout);
+ config_title_layout = parse_string(doc, n);
+
+ /* replace duplicates with spaces */
+ for (c = config_title_layout; *c != '\0'; ++c)
+ for (d = c+1; *d != '\0'; ++d)
+ if (*c == *d) *d = ' ';
+ }
+ if ((n = parse_find_node("keepBorder", node)))
+ config_theme_keepborder = parse_bool(doc, n);
+ if ((n = parse_find_node("animateIconify", node)))
+ config_animate_iconify = parse_bool(doc, n);
+
+ n = parse_find_node("font", node);
+ while (n) {
+ xmlNodePtr fnode;
+ RrFont **font;
+ gchar *name = g_strdup(RrDefaultFontFamily);
+ gint size = RrDefaultFontSize;
+ RrFontWeight weight = RrDefaultFontWeight;
+ RrFontSlant slant = RrDefaultFontSlant;
+
+ if (parse_attr_contains("ActiveWindow", n, "place"))
+ font = &config_font_activewindow;
+ else if (parse_attr_contains("InactiveWindow", n, "place"))
+ font = &config_font_inactivewindow;
+ else if (parse_attr_contains("MenuHeader", n, "place"))
+ font = &config_font_menutitle;
+ else if (parse_attr_contains("MenuItem", n, "place"))
+ font = &config_font_menuitem;
+ else if (parse_attr_contains("OnScreenDisplay", n, "place"))
+ font = &config_font_osd;
+ else
+ goto next_font;
+
+ if ((fnode = parse_find_node("name", n->children))) {
+ g_free(name);
+ name = parse_string(doc, fnode);
+ }
+ if ((fnode = parse_find_node("size", n->children))) {
+ int s = parse_int(doc, fnode);
+ if (s > 0) size = s;
+ }
+ if ((fnode = parse_find_node("weight", n->children))) {
+ gchar *w = parse_string(doc, fnode);
+ if (!g_ascii_strcasecmp(w, "Bold"))
+ weight = RR_FONTWEIGHT_BOLD;
+ g_free(w);
+ }
+ if ((fnode = parse_find_node("slant", n->children))) {
+ gchar *s = parse_string(doc, fnode);
+ if (!g_ascii_strcasecmp(s, "Italic"))
+ slant = RR_FONTSLANT_ITALIC;
+ if (!g_ascii_strcasecmp(s, "Oblique"))
+ slant = RR_FONTSLANT_OBLIQUE;
+ g_free(s);
+ }
+
+ *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
+ g_free(name);
+ next_font:
+ n = parse_find_node("font", n->next);
+ }
+}
+
+static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n;
+
+ node = node->children;
+
+ if ((n = parse_find_node("number", node))) {
+ gint d = parse_int(doc, n);
+ if (d > 0)
+ config_desktops_num = d;
+ }
+ if ((n = parse_find_node("firstdesk", node))) {
+ gint d = parse_int(doc, n);
+ if (d > 0)
+ config_screen_firstdesk = (unsigned) d;
+ }
+ if ((n = parse_find_node("names", node))) {
+ GSList *it;
+ xmlNodePtr nname;
+
+ for (it = config_desktops_names; it; it = it->next)
+ g_free(it->data);
+ g_slist_free(config_desktops_names);
+ config_desktops_names = NULL;
+
+ nname = parse_find_node("name", n->children);
+ while (nname) {
+ config_desktops_names = g_slist_append(config_desktops_names,
+ parse_string(doc, nname));
+ nname = parse_find_node("name", nname->next);
+ }
+ }
+}
+
+static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)
+{
+ xmlNodePtr n;
+
+ node = node->children;
+
+ if ((n = parse_find_node("drawContents", node)))
+ config_resize_redraw = parse_bool(doc, n);
+ if ((n = parse_find_node("popupShow", node))) {
+ config_resize_popup_show = parse_int(doc, n);
+ if (parse_contains("Always", doc, n))
+ config_resize_popup_show = 2;
+ else if (parse_contains("Never", doc, n))
+ config_resize_popup_show = 0;
+ else if (parse_contains("Nonpixel", doc, n))
+ config_resize_popup_show = 1;
+ }
+ if ((n = parse_find_node("popupPosition", node))) {
+ config_resize_popup_pos = parse_int(doc, n);
+ if (parse_contains("Top", doc, n))
+ config_resize_popup_pos = 1;
+ else if (parse_contains("Center", doc, n))
+ config_resize_popup_pos = 0;
+ }
+}
+
+static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer d)