1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config_parser.c for the Openbox window manager
4 Copyright (c) 2011 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 #include "config_parser.h"
22 #include "obt/paths.h"
29 ObConfigValueDataType type;
30 ObConfigValueDataPtr data;
31 const ObConfigValueEnum *enum_choices;
32 gchar* (*string_modify_func)(const gchar *s);
33 } ObConfigParserEntity;
35 static GHashTable *entities;
37 static void entity_free(ObConfigParserEntity *e)
40 config_value_unref(e->def);
41 config_value_unref(e->value);
42 e->data.pointer = NULL; /* if it was holding a pointer, then NULL it */
43 g_slice_free(ObConfigParserEntity, e);
46 void config_parser_startup(gboolean reconfig)
50 entities = g_hash_table_new_full(
51 g_str_hash, g_str_equal, NULL, (GDestroyNotify)entity_free);
54 void config_parser_shutdown(gboolean reconfig)
58 g_hash_table_unref(entities);
62 static void copy_value(ObConfigParserEntity *e)
66 if (e->string_modify_func && config_value_is_string(e->value)) {
67 gchar *s = e->string_modify_func(config_value_string(e->value));
69 config_value_unref(e->value);
70 e->value = config_value_new_string_steal(s);
75 case OB_CONFIG_VALUE_ENUM:
76 b = config_value_copy_ptr(e->value, e->type, e->data, e->enum_choices);
79 b = config_value_copy_ptr(e->value, e->type, e->data, NULL);
83 /* replace the bad value with the default (if it's not the default) */
84 if (!b && e->value != e->def) {
85 config_value_unref(e->value);
87 config_value_ref(e->value);
92 static ObConfigParserEntity* add(const gchar *name, ObConfigValue *def,
93 ObConfigValueDataType type,
94 ObConfigValueDataPtr v)
96 ObConfigParserEntity *e;
98 g_return_val_if_fail(def != NULL, NULL);
99 g_return_val_if_fail(g_hash_table_lookup(entities, name) != NULL, NULL);
101 e = g_slice_new(ObConfigParserEntity);
102 e->name = g_strdup(name);
105 config_value_ref(def);
106 config_value_ref(def);
109 g_hash_table_replace(entities, e->name, e);
115 void config_parser_bool(const gchar *name, const gchar *def, gboolean *v)
117 ObConfigValue *cv = config_value_new_string(def);
118 add(name, cv, OB_CONFIG_VALUE_BOOLEAN, (ObConfigValueDataPtr)v);
119 config_value_unref(cv);
122 void config_parser_int(const gchar *name, const gchar *def, gint *v)
124 ObConfigValue *cv = config_value_new_string(def);
125 add(name, cv, OB_CONFIG_VALUE_INTEGER, (ObConfigValueDataPtr)v);
126 config_value_unref(cv);
129 void config_parser_string(const gchar *name, const gchar *def, const gchar **v)
131 ObConfigValue *cv = config_value_new_string(def);
132 add(name, cv, OB_CONFIG_VALUE_STRING, (ObConfigValueDataPtr)v);
133 config_value_unref(cv);
136 void config_parser_enum(const gchar *name, const gchar *def, guint *v,
137 const ObConfigValueEnum choices[])
140 ObConfigParserEntity *e;
142 cv = config_value_new_string(def);
143 e = add(name, cv, OB_CONFIG_VALUE_ENUM, (ObConfigValueDataPtr)v);
144 config_value_unref(cv);
145 e->enum_choices = choices;
148 void config_parser_list(const gchar *name, GList *def, const GList **v)
150 ObConfigValue *cv = config_value_new_list(def);
151 add(name, cv, OB_CONFIG_VALUE_LIST, (ObConfigValueDataPtr)v);
152 config_value_unref(cv);
155 gchar *modify_uniq(const gchar *s)
158 gchar *str = g_strdup(s);
159 /* look at each char c.
160 scan ahead and look at each char d past c.
161 if d == c, then move everything past d up one position, destroying d
163 for (c = str; *c != '\0'; ++c)
164 for (d = c+1; *d != '\0'; ++d)
166 for (e = d; *e != '\0'; ++e)
171 void config_parser_string_uniq(const gchar *name, const gchar *def,
175 ObConfigParserEntity *e;
177 cv = config_value_new_string(def);
178 e = add(name, cv, OB_CONFIG_VALUE_STRING, (ObConfigValueDataPtr)v);
179 config_value_unref(cv);
180 e->string_modify_func = modify_uniq;
183 gchar *modify_path(const gchar *s)
185 return obt_paths_expand_tilde(s);
188 void config_parser_string_path(const gchar *name, const gchar *def,
192 ObConfigParserEntity *e;
194 cv = config_value_new_string(def);
195 e = add(name, cv, OB_CONFIG_VALUE_STRING, (ObConfigValueDataPtr)v);
196 config_value_unref(cv);
197 e->string_modify_func = modify_path;
199 void config_parser_key(const gchar *name, const gchar *def,
203 ObConfigParserEntity *e;
205 cv = config_value_new_string(def);
206 e = add(name, cv, OB_CONFIG_VALUE_KEY, (ObConfigValueDataPtr)v);
207 config_value_unref(cv);
213 void config_parser_options(void)
215 ObtXmlInst *i = obt_xml_instance_new();
217 gchar *fpath, *dpath;
220 paths = obt_paths_new();
221 dpath = g_build_filename(obt_paths_cache_home(paths), "openbox", NULL);
222 fpath = g_build_filename(dpath, "config", NULL);
224 obt_paths_mkdir_path(dpath, 0777);
225 if (!obt_xml_load_file(i, fpath, "openbox_config"))
226 obt_xml_new_file(i, "openbox_config");
227 root = obt_xml_root(i);
229 n = obt_xml_tree_get_node("focus");
230 config_focus_new = read_bool(n, "focusnew", TRUE);
231 config_focus_follow = read_bool(n, "followmouse", FALSE);
232 config_focus_delay = read_int(n, "focusdelay", 0);
233 config_focus_raise = read_bool(n, "raiseonfocus", FALSE);
234 config_focus_last = read_bool(n, "focuslast", TRUE);
235 config_focus_under_mouse = read_bool(n, "undermouse", FALSE);
236 config_unfocus_leave = read_bool(n, "unfocusonleave", FALSE);
238 n = obt_xml_tree_get_node("placement");
239 config_place_policy = read_enum(
242 {"smart", OB_PLACE_POLICY_SMART},
243 {"undermouse", OB_PLACE_POLICY_MOUSE},
247 config_place_center = read_bool(n "center", TRUE);
248 config_place_monitor = read_enum(
251 {"any", OB_PLACE_MONITOR_ANY},
252 {"active", OB_PLACE_MONITOR_ACTIVE},
253 {"mouse", OB_PLACE_MONITOR_MOUSE},
254 {"primary", OB_PLACE_MONITOR_PRIMARY},
258 config_primary_monitor_index = read_int(n, "primarymonitor" 1);
259 if (!config_primary_monitor_index)
260 config_primary_monitor = read_enum(
263 {"active", OB_PLACE_MONITOR_ACTIVE},
264 {"mouse", OB_PLACE_MONITOR_MOUSE},
269 n = obt_xml_tree_get_node("margins");
270 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
271 config_margins.top = MAX(0, read_int(n, "top", 0));
272 config_margins.left = MAX(0, read_int(n, "left", 0));
273 config_margins.bottom = MAX(0, read_int(n, "bottom", 0));
274 config_margins.right = MAX(0, read_int(n, "right", 0));
276 n = obt_xml_tree_get_node("theme");
277 config_theme = read_path(n, "name", NULL);
278 config_animate_iconify = read_bool(n, "animateiconify", TRUE);
279 config_title_layout = read_string_uniq(n, "titlelayout", "NLIMC");
280 config_theme_keepborder = read_bool(n, "keepborder", TRUE);
281 config_theme_window_list_icon_size = read_int(n, "windowlisticonsize", 36);
282 config_font_activewindow = read_font(n, "font:place=activewindow");
283 config_font_inactivewindow = read_font(n, "font:place=inactivewindow");
284 config_font_menuitem = read_font(n, "font:place=menuitem");
285 config_font_menutitle = read_font(n, "font:place=menuheader");
286 config_font_activeosd = read_font(n, "font:place=activeonscreendisplay");
287 config_font_inactiveosd =
288 read_font(n, "font:place=inactiveonscreendisplay");
290 n = obt_xml_tree_get_node("desktops");
291 config_desktops_num = MAX(1, read_int(n, "number", 4));
292 config_screen_firstdesk = 1; /* XXX remove me */
293 config_desktop_popup_time = MAX(0, read_int(n, "popuptime", 875));
294 config_desktops_names = NULL; /* XXX remove me */
296 n = obt_xml_tree_get_node("resize");
297 config_resize_redraw = read_bool(n, "drawcontents", TRUE);
298 config_resize_popup_show = read_enum(
307 config_resize_popup_pos = read_enum(
310 {"top", OB_RESIZE_POS_TOP},
311 {"center", OB_RESIZE_POS_CENTER},
312 {"fixed", OB_RESIZE_POS_FIXED},
315 if (config_resize_popup_pos == OB_RESIZE_POS_FIXED)
316 config_resize_popup_fixed =
317 read_gravity_point(n, "popupfixedposition",
318 0, 0, FALSE, FALSE, 0, 0, FALSE, FALSE);
320 n = obt_xml_tree_get_node("dock");
321 config_dock_pos = read_enum(
324 {"topleft", OB_DIRECTION_NORTHWEST},
325 {"top", OB_DIRECTION_NORTH},
326 {"topright", OB_DIRECTION_NORTHEAST},
327 {"right", OB_DIRECTION_EAST},
328 {"bottomright", OB_DIRECTION_SOUTHEAST},
329 {"bottom", OB_DIRECTION_SOUTH},
330 {"bottomleft", OB_DIRECTION_SOUTHWEST},
331 {"left", OB_DIRECTION_WEST},
332 {"floating", (guint)-1},
336 config_dock_floating = (config_dock_pos == (guint)-1);
337 config_dock_layer = read_enum(
340 {"normal", OB_STACKING_LAYER_NORMAL},
341 {"above", OB_STACKING_LAYER_ABOVE},
342 {"below", OB_STACKING_LAYER_BELOW},
346 config_dock_nostrut = read_bool(n, "nostrut", FALSE);
347 config_dock_x = read_int(n, "floatingx", 0);
348 config_dock_y = read_int(n, "floatingx", y);
349 config_dock_orient = read_enum(
352 {"horizontal", OB_ORIENTATION_HORZ},
353 {"vertical", OB_ORIENTATION_VERT},
357 config_dock_hide = read_bool(n, "autohide", FALSE);
358 config_dock_hide_delay = read_int(n, "hidedelay", 300);
359 config_dock_show_delay = read_int(n, "showdelay", 300);
360 read_button(n, "movebutton", "2",
361 &config_dock_app_move_button,
362 &config_dock_app_move_modifiers);
364 n = obt_xml_tree_get_node("keyboard");
365 read_key(n, "chainquitkey", "C-g",
366 &config_keyboard_reset_keycode,
367 &config_keyboard_reset_state);
369 n = obt_xml_tree_get_node("mouse");
370 config_mouse_threshold = read_int(n, "dragthreshold", 8);
371 config_mouse_dclicktime = read_int(n, "doubleclicktime", 200);
372 config_mouse_screenedgetime = read_int(n, "screenedgewarptime", 400);
373 /* minimum value of 25 for this property, when it is 1 and you hit the
374 edge it basically never stops */
375 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
376 config_mouse_screenedgetime = 25;
377 config_mouse_screenedgewarp = read_bool(n, "screenedgewarpmouse", FALSE);
379 n = obt_xml_tree_get_node("resistance");
380 config_resist_win = read_int(n, "strength", 10);
381 config_resist_edge = read_int(n, "screen_edge_strength", 20);
383 n = obt_xml_tree_get_node("menu");
384 config_menu_hide_delay = read_int(n, "hidedelay", 250);
385 config_menu_middle = read_bool(n, "middle", FALSE);
386 config_submenu_show_delay = read_int(n, "submenushowdelay", 100);
387 config_submenu_hide_delay = read_int(n, "submenuhidedelay", 400);
388 config_menu_manage_desktops = read_bool(n, "managedesktops", TRUE);
389 config_menu_show_icons = read_bool(n, "showicons", TRUE);
391 if (config_menu_show_icons)
392 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
395 config_menu_files = NULL; /* XXX remove me */
400 RrFont *read_font(xmlNodePtr n, const gchar *path)
408 n = obt_xml_tree_get_node(n, path);
410 name = read_string(n, "name", RrDefaultFontFamily);
411 size = read_int(n, "size", RrDefaultFontSize);
412 weight = read_enum(n, "weight",
414 {"normal", RR_FONTWEIGHT_NORMAL},
415 {"bold", RR_FONTWEIGHT_BOLD},
419 slant = read_enum(n, "slant",
421 {"normal", RR_FONTSLANT_NORMAL},
422 {"italic", RR_FONTSLANT_ITALIC},
423 {"oblique", RR_FONTSLANT_OBLIQUE},
427 font = RrFontOpen(ob_rr_inst, name, size, weight, slant);