1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new;
32 gboolean config_focus_follow;
33 guint config_focus_delay;
34 gboolean config_focus_raise;
35 gboolean config_focus_last;
36 gboolean config_focus_under_mouse;
37 gboolean config_unfocus_leave;
39 ObPlacePolicy config_place_policy;
40 ObPlaceMonitor config_place_monitor;
42 guint config_primary_monitor_index;
43 ObPlaceMonitor config_primary_monitor;
45 StrutPartial config_margins;
48 gboolean config_theme_keepborder;
49 guint config_theme_window_list_icon_size;
51 gchar *config_title_layout;
53 gboolean config_animate_iconify;
55 RrFont *config_font_activewindow;
56 RrFont *config_font_inactivewindow;
57 RrFont *config_font_menuitem;
58 RrFont *config_font_menutitle;
59 RrFont *config_font_activeosd;
60 RrFont *config_font_inactiveosd;
62 guint config_desktops_num;
63 GSList *config_desktops_names;
64 guint config_screen_firstdesk;
65 guint config_desktop_popup_time;
66 gint config_emulate_xinerama;
68 gboolean config_resize_redraw;
69 gint config_resize_popup_show;
70 ObResizePopupPos config_resize_popup_pos;
71 GravityPoint config_resize_popup_fixed;
73 ObStackingLayer config_dock_layer;
74 gboolean config_dock_floating;
75 gboolean config_dock_nostrut;
76 ObDirection config_dock_pos;
79 ObOrientation config_dock_orient;
80 gboolean config_dock_hide;
81 guint config_dock_hide_delay;
82 guint config_dock_show_delay;
83 guint config_dock_app_move_button;
84 guint config_dock_app_move_modifiers;
86 guint config_keyboard_reset_keycode;
87 guint config_keyboard_reset_state;
88 gboolean config_keyboard_rebind_on_mapping_notify;
90 gint config_mouse_threshold;
91 gint config_mouse_dclicktime;
92 gint config_mouse_screenedgetime;
93 gboolean config_mouse_screenedgewarp;
95 guint config_menu_hide_delay;
96 gboolean config_menu_middle;
97 guint config_submenu_show_delay;
98 guint config_submenu_hide_delay;
99 gboolean config_menu_manage_desktops;
100 gboolean config_menu_show_icons;
102 GSList *config_menu_files;
104 gint config_resist_win;
105 gint config_resist_edge;
107 GSList *config_per_app_settings;
109 ObAppSettings* config_create_app_settings(void)
111 ObAppSettings *settings = g_slice_new0(ObAppSettings);
113 settings->decor = -1;
114 settings->shade = -1;
115 settings->monitor_type = OB_PLACE_MONITOR_ANY;
116 settings->monitor = -1;
117 settings->focus = -1;
118 settings->desktop = 0;
119 settings->layer = -2;
120 settings->iconic = -1;
121 settings->skip_pager = -1;
122 settings->skip_taskbar = -1;
123 settings->fullscreen = -1;
124 settings->max_horz = -1;
125 settings->max_vert = -1;
129 #define copy_if(setting, default) \
130 if (src->setting != default) dst->setting = src->setting
131 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
134 g_assert(src != NULL);
135 g_assert(dst != NULL);
137 copy_if(type, (ObClientType)-1);
140 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
141 copy_if(monitor, -1);
146 copy_if(skip_pager, -1);
147 copy_if(skip_taskbar, -1);
148 copy_if(fullscreen, -1);
149 copy_if(max_horz, -1);
150 copy_if(max_vert, -1);
152 if (src->pos_given) {
153 dst->pos_given = TRUE;
154 dst->pos_force = src->pos_force;
155 dst->position = src->position;
156 /* monitor is copied above */
159 if (src->size_given) {
160 dst->size_given = TRUE;
161 dst->width_num = src->width_num;
162 dst->width_denom = src->width_denom;
163 dst->height_num = src->height_num;
164 dst->height_denom = src->height_denom;
168 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
170 *num = strtol(s, &s, 10);
174 } else if (*s == '/') {
179 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
181 gchar *s = obt_xml_node_string(node);
182 if (!g_ascii_strcasecmp(s, "center"))
188 if (s[0] == '-' || s[0] == '+')
190 config_parse_relative_number(ps, &c->pos, &c->denom);
197 <application name="aterm">
200 <application name="Rhythmbox">
207 .. there is a lot more settings available
212 static void parse_single_per_app_settings(xmlNodePtr app,
213 ObAppSettings *settings)
216 gboolean x_pos_given = FALSE;
218 if ((n = obt_xml_find_node(app->children, "decor")))
219 if (!obt_xml_node_contains(n, "default"))
220 settings->decor = obt_xml_node_bool(n);
222 if ((n = obt_xml_find_node(app->children, "shade")))
223 if (!obt_xml_node_contains(n, "default"))
224 settings->shade = obt_xml_node_bool(n);
226 if ((n = obt_xml_find_node(app->children, "position"))) {
227 if ((c = obt_xml_find_node(n->children, "x"))) {
228 if (!obt_xml_node_contains(c, "default")) {
229 config_parse_gravity_coord(c, &settings->position.x);
234 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
235 if (!obt_xml_node_contains(c, "default")) {
236 config_parse_gravity_coord(c, &settings->position.y);
237 settings->pos_given = TRUE;
241 /* monitor can be set without setting x or y */
242 if ((c = obt_xml_find_node(n->children, "monitor"))) {
243 if (!obt_xml_node_contains(c, "default")) {
244 gchar *s = obt_xml_node_string(c);
245 if (!g_ascii_strcasecmp(s, "mouse"))
246 settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
247 else if (!g_ascii_strcasecmp(s, "active"))
248 settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
249 else if (!g_ascii_strcasecmp(s, "primary"))
250 settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
252 settings->monitor = obt_xml_node_int(c);
257 obt_xml_attr_bool(n, "force", &settings->pos_force);
260 if ((n = obt_xml_find_node(app->children, "size"))) {
261 if ((c = obt_xml_find_node(n->children, "width"))) {
262 if (!obt_xml_node_contains(c, "default")) {
263 gchar *s = obt_xml_node_string(c);
264 config_parse_relative_number(s,
265 &settings->width_num,
266 &settings->width_denom);
267 if (settings->width_num > 0 && settings->width_denom >= 0)
268 settings->size_given = TRUE;
271 settings->size_given = TRUE;
274 if ((c = obt_xml_find_node(n->children, "height"))) {
275 if (!obt_xml_node_contains(c, "default")) {
276 gchar *s = obt_xml_node_string(c);
277 config_parse_relative_number(s,
278 &settings->height_num,
279 &settings->height_denom);
280 if (settings->height_num > 0 && settings->height_denom >= 0)
281 settings->size_given = TRUE;
284 settings->size_given = TRUE;
288 if ((n = obt_xml_find_node(app->children, "focus"))) {
289 if (!obt_xml_node_contains(n, "default"))
290 settings->focus = obt_xml_node_bool(n);
293 if ((n = obt_xml_find_node(app->children, "desktop"))) {
294 if (!obt_xml_node_contains(n, "default")) {
295 gchar *s = obt_xml_node_string(n);
296 if (!g_ascii_strcasecmp(s, "all"))
297 settings->desktop = DESKTOP_ALL;
299 gint i = obt_xml_node_int(n);
301 settings->desktop = i;
307 if ((n = obt_xml_find_node(app->children, "layer"))) {
308 if (!obt_xml_node_contains(n, "default")) {
309 gchar *s = obt_xml_node_string(n);
310 if (!g_ascii_strcasecmp(s, "above"))
312 else if (!g_ascii_strcasecmp(s, "below"))
313 settings->layer = -1;
320 if ((n = obt_xml_find_node(app->children, "iconic")))
321 if (!obt_xml_node_contains(n, "default"))
322 settings->iconic = obt_xml_node_bool(n);
324 if ((n = obt_xml_find_node(app->children, "skip_pager")))
325 if (!obt_xml_node_contains(n, "default"))
326 settings->skip_pager = obt_xml_node_bool(n);
328 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
329 if (!obt_xml_node_contains(n, "default"))
330 settings->skip_taskbar = obt_xml_node_bool(n);
332 if ((n = obt_xml_find_node(app->children, "fullscreen")))
333 if (!obt_xml_node_contains(n, "default"))
334 settings->fullscreen = obt_xml_node_bool(n);
336 if ((n = obt_xml_find_node(app->children, "maximized"))) {
337 if (!obt_xml_node_contains(n, "default")) {
338 gchar *s = obt_xml_node_string(n);
339 if (!g_ascii_strcasecmp(s, "horizontal")) {
340 settings->max_horz = TRUE;
341 settings->max_vert = FALSE;
342 } else if (!g_ascii_strcasecmp(s, "vertical")) {
343 settings->max_horz = FALSE;
344 settings->max_vert = TRUE;
346 settings->max_horz = settings->max_vert =
347 obt_xml_node_bool(n);
353 /* Manages settings for individual applications.
354 Some notes: monitor is the screen number in a multi monitor
355 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
356 is on, active: the active monitor, primary: the primary monitor.
357 Layer can be three values, above (Always on top), below
358 (Always on bottom) and everything else (normal behaviour).
359 Positions can be an integer value or center, which will
360 center the window in the specified axis. Position is within
361 the monitor, so <position><x>center</x></position><monitor>2</monitor>
362 will center the window on the second monitor.
364 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
366 xmlNodePtr app = obt_xml_find_node(node->children, "application");
367 for (; app; app = obt_xml_find_node(app->next, "application")) {
368 ObAppSettings *settings;
370 gboolean name_set, class_set, role_set, title_set,
371 type_set, group_name_set, group_class_set;
372 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
373 *type_str = NULL, *group_name = NULL, *group_class = NULL;
376 class_set = obt_xml_attr_string(app, "class", &class);
377 name_set = obt_xml_attr_string(app, "name", &name);
378 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
379 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
380 type_set = obt_xml_attr_string(app, "type", &type_str);
381 role_set = obt_xml_attr_string(app, "role", &role);
382 title_set = obt_xml_attr_string(app, "title", &title);
384 /* validate the type tho */
386 if (!g_ascii_strcasecmp(type_str, "normal"))
387 type = OB_CLIENT_TYPE_NORMAL;
388 else if (!g_ascii_strcasecmp(type_str, "dialog"))
389 type = OB_CLIENT_TYPE_DIALOG;
390 else if (!g_ascii_strcasecmp(type_str, "splash"))
391 type = OB_CLIENT_TYPE_SPLASH;
392 else if (!g_ascii_strcasecmp(type_str, "utility"))
393 type = OB_CLIENT_TYPE_UTILITY;
394 else if (!g_ascii_strcasecmp(type_str, "menu"))
395 type = OB_CLIENT_TYPE_MENU;
396 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
397 type = OB_CLIENT_TYPE_TOOLBAR;
398 else if (!g_ascii_strcasecmp(type_str, "dock"))
399 type = OB_CLIENT_TYPE_DOCK;
400 else if (!g_ascii_strcasecmp(type_str, "desktop"))
401 type = OB_CLIENT_TYPE_DESKTOP;
403 type_set = FALSE; /* not valid! */
406 if (!(class_set || name_set || role_set || title_set ||
407 type_set || group_class_set || group_name_set))
410 settings = config_create_app_settings();
413 settings->name = g_pattern_spec_new(name);
415 settings->class = g_pattern_spec_new(class);
417 settings->group_name = g_pattern_spec_new(group_name);
419 settings->group_class = g_pattern_spec_new(group_class);
421 settings->role = g_pattern_spec_new(role);
423 settings->title = g_pattern_spec_new(title);
425 settings->type = type;
435 parse_single_per_app_settings(app, settings);
436 config_per_app_settings = g_slist_append(config_per_app_settings,
444 <action name="ChangeDesktop">
451 static void parse_key(xmlNodePtr node, GList *keylist)
453 gchar *keystring, **keys, **key;
455 gboolean is_chroot = FALSE;
456 gboolean grab = TRUE;
458 if (!obt_xml_attr_string(node, "key", &keystring))
461 obt_xml_attr_bool(node, "chroot", &is_chroot);
462 obt_xml_attr_bool(node, "grab", &grab);
464 keys = g_strsplit(keystring, " ", 0);
465 for (key = keys; *key; ++key) {
466 keylist = g_list_append(keylist, *key);
468 if ((n = obt_xml_find_node(node->children, "keybind"))) {
470 parse_key(n, keylist);
471 n = obt_xml_find_node(n->next, "keybind");
474 else if ((n = obt_xml_find_node(node->children, "action"))) {
476 ObActionsAct *action;
478 action = actions_parse(n);
480 keyboard_bind(keylist, action, grab);
481 n = obt_xml_find_node(n->next, "action");
487 keyboard_chroot(keylist);
488 keylist = g_list_delete_link(keylist, g_list_last(keylist));
495 static void parse_keyboard(xmlNodePtr node, gpointer d)
500 keyboard_unbind_all();
502 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
503 key = obt_xml_node_string(n);
504 translate_key(key, &config_keyboard_reset_state,
505 &config_keyboard_reset_keycode);
509 if ((n = obt_xml_find_node(node->children, "keybind")))
512 n = obt_xml_find_node(n->next, "keybind");
515 if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
516 config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
521 <context name="Titlebar">
522 <mousebind button="Left" action="Press">
523 <action name="Raise"></action>
529 static void parse_mouse(xmlNodePtr node, gpointer d)
531 xmlNodePtr n, nbut, nact;
538 node = node->children;
540 if ((n = obt_xml_find_node(node, "dragThreshold")))
541 config_mouse_threshold = obt_xml_node_int(n);
542 if ((n = obt_xml_find_node(node, "doubleClickTime")))
543 config_mouse_dclicktime = obt_xml_node_int(n);
544 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
545 config_mouse_screenedgetime = obt_xml_node_int(n);
546 /* minimum value of 25 for this property, when it is 1 and you hit the
547 edge it basically never stops */
548 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
549 config_mouse_screenedgetime = 25;
551 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
552 config_mouse_screenedgewarp = obt_xml_node_bool(n);
554 n = obt_xml_find_node(node, "context");
559 if (!obt_xml_attr_string(n, "name", &cxstr))
562 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
563 while (frame_next_context_from_string(modcxstr, &cx)) {
565 gchar *s = strchr(modcxstr, ' ');
568 g_message(_("Invalid context \"%s\" in mouse binding"),
575 nbut = obt_xml_find_node(n->children, "mousebind");
577 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
579 if (obt_xml_attr_contains(nbut, "action", "press"))
580 mact = OB_MOUSE_ACTION_PRESS;
581 else if (obt_xml_attr_contains(nbut, "action", "release"))
582 mact = OB_MOUSE_ACTION_RELEASE;
583 else if (obt_xml_attr_contains(nbut, "action", "click"))
584 mact = OB_MOUSE_ACTION_CLICK;
585 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
586 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
587 else if (obt_xml_attr_contains(nbut, "action", "drag"))
588 mact = OB_MOUSE_ACTION_MOTION;
592 nact = obt_xml_find_node(nbut->children, "action");
594 ObActionsAct *action;
596 if ((action = actions_parse(nact))) {
597 gchar *p = buttonstr;
599 gchar *s = strchr(p, ' ');
607 mouse_bind(p, cx, mact, action);
608 actions_act_ref(action); /* ref the action for each binding */
611 actions_act_unref(action); /* remove the extra ref */
613 nact = obt_xml_find_node(nact->next, "action");
617 nbut = obt_xml_find_node(nbut->next, "mousebind");
623 n = obt_xml_find_node(n->next, "context");
627 static void parse_focus(xmlNodePtr node, gpointer d)
631 node = node->children;
633 if ((n = obt_xml_find_node(node, "focusNew")))
634 config_focus_new = obt_xml_node_bool(n);
635 if ((n = obt_xml_find_node(node, "followMouse")))
636 config_focus_follow = obt_xml_node_bool(n);
637 if ((n = obt_xml_find_node(node, "focusDelay")))
638 config_focus_delay = obt_xml_node_int(n);
639 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
640 config_focus_raise = obt_xml_node_bool(n);
641 if ((n = obt_xml_find_node(node, "focusLast")))
642 config_focus_last = obt_xml_node_bool(n);
643 if ((n = obt_xml_find_node(node, "underMouse")))
644 config_focus_under_mouse = obt_xml_node_bool(n);
645 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
646 config_unfocus_leave = obt_xml_node_bool(n);
649 static void parse_placement(xmlNodePtr node, gpointer d)
653 node = node->children;
655 if ((n = obt_xml_find_node(node, "policy")))
656 if (obt_xml_node_contains(n, "UnderMouse"))
657 config_place_policy = OB_PLACE_POLICY_MOUSE;
658 if (obt_xml_node_contains(n, "Random"))
659 config_place_policy = OB_PLACE_POLICY_RANDOM;
660 if ((n = obt_xml_find_node(node, "monitor"))) {
661 if (obt_xml_node_contains(n, "active"))
662 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
663 else if (obt_xml_node_contains(n, "mouse"))
664 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
665 else if (obt_xml_node_contains(n, "any"))
666 config_place_monitor = OB_PLACE_MONITOR_ANY;
668 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
669 config_primary_monitor_index = obt_xml_node_int(n);
670 if (!config_primary_monitor_index) {
671 if (obt_xml_node_contains(n, "mouse"))
672 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
677 static void parse_margins(xmlNodePtr node, gpointer d)
681 node = node->children;
683 if ((n = obt_xml_find_node(node, "top")))
684 config_margins.top = MAX(0, obt_xml_node_int(n));
685 if ((n = obt_xml_find_node(node, "left")))
686 config_margins.left = MAX(0, obt_xml_node_int(n));
687 if ((n = obt_xml_find_node(node, "right")))
688 config_margins.right = MAX(0, obt_xml_node_int(n));
689 if ((n = obt_xml_find_node(node, "bottom")))
690 config_margins.bottom = MAX(0, obt_xml_node_int(n));
693 static void parse_theme(xmlNodePtr node, gpointer d)
697 node = node->children;
699 if ((n = obt_xml_find_node(node, "name"))) {
702 g_free(config_theme);
703 c = obt_xml_node_string(n);
704 config_theme = obt_paths_expand_tilde(c);
707 if ((n = obt_xml_find_node(node, "titleLayout"))) {
710 g_free(config_title_layout);
711 config_title_layout = obt_xml_node_string(n);
713 /* replace duplicates with spaces */
714 for (c = config_title_layout; *c != '\0'; ++c)
715 for (d = c+1; *d != '\0'; ++d)
716 if (*c == *d) *d = ' ';
718 if ((n = obt_xml_find_node(node, "keepBorder")))
719 config_theme_keepborder = obt_xml_node_bool(n);
720 if ((n = obt_xml_find_node(node, "animateIconify")))
721 config_animate_iconify = obt_xml_node_bool(n);
722 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
723 config_theme_window_list_icon_size = obt_xml_node_int(n);
724 if (config_theme_window_list_icon_size < 16)
725 config_theme_window_list_icon_size = 16;
726 else if (config_theme_window_list_icon_size > 96)
727 config_theme_window_list_icon_size = 96;
730 n = obt_xml_find_node(node, "font");
734 gchar *name = g_strdup(RrDefaultFontFamily);
735 gint size = RrDefaultFontSize;
736 RrFontWeight weight = RrDefaultFontWeight;
737 RrFontSlant slant = RrDefaultFontSlant;
739 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
740 font = &config_font_activewindow;
741 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
742 font = &config_font_inactivewindow;
743 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
744 font = &config_font_menutitle;
745 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
746 font = &config_font_menuitem;
747 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
748 font = &config_font_activeosd;
749 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
750 font = &config_font_activeosd;
751 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
752 font = &config_font_inactiveosd;
756 if ((fnode = obt_xml_find_node(n->children, "name"))) {
758 name = obt_xml_node_string(fnode);
760 if ((fnode = obt_xml_find_node(n->children, "size"))) {
761 int s = obt_xml_node_int(fnode);
764 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
765 gchar *w = obt_xml_node_string(fnode);
766 if (!g_ascii_strcasecmp(w, "Bold"))
767 weight = RR_FONTWEIGHT_BOLD;
770 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
771 gchar *s = obt_xml_node_string(fnode);
772 if (!g_ascii_strcasecmp(s, "Italic"))
773 slant = RR_FONTSLANT_ITALIC;
774 if (!g_ascii_strcasecmp(s, "Oblique"))
775 slant = RR_FONTSLANT_OBLIQUE;
779 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
782 if ((fnode = obt_xml_find_node(n->children, "description"))) {
783 gchar *s = obt_xml_node_string(fnode);
784 RrFontDescriptionFromString(*font, s);
789 n = obt_xml_find_node(n->next, "font");
793 static void parse_desktops(xmlNodePtr node, gpointer d)
797 node = node->children;
799 if ((n = obt_xml_find_node(node, "number"))) {
800 gint d = obt_xml_node_int(n);
802 config_desktops_num = (unsigned) d;
804 if ((n = obt_xml_find_node(node, "firstdesk"))) {
805 gint d = obt_xml_node_int(n);
807 config_screen_firstdesk = (unsigned) d;
809 if ((n = obt_xml_find_node(node, "emulatexinerama")))
810 config_emulate_xinerama = obt_xml_node_bool(n);
811 if ((n = obt_xml_find_node(node, "names"))) {
815 for (it = config_desktops_names; it; it = it->next)
817 g_slist_free(config_desktops_names);
818 config_desktops_names = NULL;
820 nname = obt_xml_find_node(n->children, "name");
822 config_desktops_names =
823 g_slist_append(config_desktops_names,
824 obt_xml_node_string(nname));
825 nname = obt_xml_find_node(nname->next, "name");
828 if ((n = obt_xml_find_node(node, "popupTime")))
829 config_desktop_popup_time = obt_xml_node_int(n);
832 static void parse_resize(xmlNodePtr node, gpointer d)
836 node = node->children;
838 if ((n = obt_xml_find_node(node, "drawContents")))
839 config_resize_redraw = obt_xml_node_bool(n);
840 if ((n = obt_xml_find_node(node, "popupShow"))) {
841 config_resize_popup_show = obt_xml_node_int(n);
842 if (obt_xml_node_contains(n, "Always"))
843 config_resize_popup_show = 2;
844 else if (obt_xml_node_contains(n, "Never"))
845 config_resize_popup_show = 0;
846 else if (obt_xml_node_contains(n, "Nonpixel"))
847 config_resize_popup_show = 1;
849 if ((n = obt_xml_find_node(node, "popupPosition"))) {
850 if (obt_xml_node_contains(n, "Top"))
851 config_resize_popup_pos = OB_RESIZE_POS_TOP;
852 else if (obt_xml_node_contains(n, "Center"))
853 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
854 else if (obt_xml_node_contains(n, "Fixed")) {
855 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
857 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
860 if ((n2 = obt_xml_find_node(n->children, "x")))
861 config_parse_gravity_coord(n2,
862 &config_resize_popup_fixed.x);
863 if ((n2 = obt_xml_find_node(n->children, "y")))
864 config_parse_gravity_coord(n2,
865 &config_resize_popup_fixed.y);
867 config_resize_popup_fixed.x.pos =
868 MAX(config_resize_popup_fixed.x.pos, 0);
869 config_resize_popup_fixed.y.pos =
870 MAX(config_resize_popup_fixed.y.pos, 0);
876 static void parse_dock(xmlNodePtr node, gpointer d)
880 node = node->children;
882 if ((n = obt_xml_find_node(node, "position"))) {
883 if (obt_xml_node_contains(n, "TopLeft"))
884 config_dock_floating = FALSE,
885 config_dock_pos = OB_DIRECTION_NORTHWEST;
886 else if (obt_xml_node_contains(n, "Top"))
887 config_dock_floating = FALSE,
888 config_dock_pos = OB_DIRECTION_NORTH;
889 else if (obt_xml_node_contains(n, "TopRight"))
890 config_dock_floating = FALSE,
891 config_dock_pos = OB_DIRECTION_NORTHEAST;
892 else if (obt_xml_node_contains(n, "Right"))
893 config_dock_floating = FALSE,
894 config_dock_pos = OB_DIRECTION_EAST;
895 else if (obt_xml_node_contains(n, "BottomRight"))
896 config_dock_floating = FALSE,
897 config_dock_pos = OB_DIRECTION_SOUTHEAST;
898 else if (obt_xml_node_contains(n, "Bottom"))
899 config_dock_floating = FALSE,
900 config_dock_pos = OB_DIRECTION_SOUTH;
901 else if (obt_xml_node_contains(n, "BottomLeft"))
902 config_dock_floating = FALSE,
903 config_dock_pos = OB_DIRECTION_SOUTHWEST;
904 else if (obt_xml_node_contains(n, "Left"))
905 config_dock_floating = FALSE,
906 config_dock_pos = OB_DIRECTION_WEST;
907 else if (obt_xml_node_contains(n, "Floating"))
908 config_dock_floating = TRUE;
910 if (config_dock_floating) {
911 if ((n = obt_xml_find_node(node, "floatingX")))
912 config_dock_x = obt_xml_node_int(n);
913 if ((n = obt_xml_find_node(node, "floatingY")))
914 config_dock_y = obt_xml_node_int(n);
916 if ((n = obt_xml_find_node(node, "noStrut")))
917 config_dock_nostrut = obt_xml_node_bool(n);
919 if ((n = obt_xml_find_node(node, "stacking"))) {
920 if (obt_xml_node_contains(n, "normal"))
921 config_dock_layer = OB_STACKING_LAYER_NORMAL;
922 else if (obt_xml_node_contains(n, "below"))
923 config_dock_layer = OB_STACKING_LAYER_BELOW;
924 else if (obt_xml_node_contains(n, "above"))
925 config_dock_layer = OB_STACKING_LAYER_ABOVE;
927 if ((n = obt_xml_find_node(node, "direction"))) {
928 if (obt_xml_node_contains(n, "horizontal"))
929 config_dock_orient = OB_ORIENTATION_HORZ;
930 else if (obt_xml_node_contains(n, "vertical"))
931 config_dock_orient = OB_ORIENTATION_VERT;
933 if ((n = obt_xml_find_node(node, "autoHide")))
934 config_dock_hide = obt_xml_node_bool(n);
935 if ((n = obt_xml_find_node(node, "hideDelay")))
936 config_dock_hide_delay = obt_xml_node_int(n);
937 if ((n = obt_xml_find_node(node, "showDelay")))
938 config_dock_show_delay = obt_xml_node_int(n);
939 if ((n = obt_xml_find_node(node, "moveButton"))) {
940 gchar *str = obt_xml_node_string(n);
942 if (translate_button(str, &s, &b)) {
943 config_dock_app_move_button = b;
944 config_dock_app_move_modifiers = s;
946 g_message(_("Invalid button \"%s\" specified in config file"), str);
952 static void parse_menu(xmlNodePtr node, gpointer d)
955 node = node->children;
957 if ((n = obt_xml_find_node(node, "hideDelay")))
958 config_menu_hide_delay = obt_xml_node_int(n);
959 if ((n = obt_xml_find_node(node, "middle")))
960 config_menu_middle = obt_xml_node_bool(n);
961 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
962 config_submenu_show_delay = obt_xml_node_int(n);
963 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
964 config_submenu_hide_delay = obt_xml_node_int(n);
965 if ((n = obt_xml_find_node(node, "manageDesktops")))
966 config_menu_manage_desktops = obt_xml_node_bool(n);
967 if ((n = obt_xml_find_node(node, "showIcons"))) {
968 config_menu_show_icons = obt_xml_node_bool(n);
969 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
970 if (config_menu_show_icons)
971 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
975 while ((node = obt_xml_find_node(node, "file"))) {
976 gchar *c = obt_xml_node_string(node);
977 config_menu_files = g_slist_append(config_menu_files,
978 obt_paths_expand_tilde(c));
984 static void parse_resistance(xmlNodePtr node, gpointer d)
988 node = node->children;
989 if ((n = obt_xml_find_node(node, "strength")))
990 config_resist_win = obt_xml_node_int(n);
991 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
992 config_resist_edge = obt_xml_node_int(n);
998 const gchar *actname;
1001 static void bind_default_keyboard(void)
1004 ObDefKeyBind binds[] = {
1005 { "A-Tab", "NextWindow" },
1006 { "S-A-Tab", "PreviousWindow" },
1007 { "A-F4", "Close" },
1010 for (it = binds; it->key; ++it) {
1011 GList *l = g_list_append(NULL, g_strdup(it->key));
1012 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
1018 const gchar *button;
1019 const gchar *context;
1020 const ObMouseAction mact;
1021 const gchar *actname;
1024 static void bind_default_mouse(void)
1027 ObDefMouseBind binds[] = {
1028 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1029 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1030 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1031 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1032 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1033 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1034 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1035 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1036 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1037 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1038 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1039 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1040 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1041 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1042 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1043 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1044 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1045 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1046 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1047 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1048 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1049 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1050 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1051 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1052 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1053 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1054 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1055 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1056 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1057 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1058 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1059 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1060 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1061 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1062 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1063 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1064 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1065 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1066 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1067 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1068 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1069 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1070 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1071 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1072 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1073 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1074 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1075 { NULL, NULL, 0, NULL }
1078 for (it = binds; it->button; ++it)
1079 mouse_bind(it->button, frame_context_from_string(it->context),
1080 it->mact, actions_parse_string(it->actname));
1083 void config_startup(ObtXmlInst *i)
1085 config_focus_new = TRUE;
1086 config_focus_follow = FALSE;
1087 config_focus_delay = 0;
1088 config_focus_raise = FALSE;
1089 config_focus_last = TRUE;
1090 config_focus_under_mouse = FALSE;
1091 config_unfocus_leave = FALSE;
1093 obt_xml_register(i, "focus", parse_focus, NULL);
1095 config_place_policy = OB_PLACE_POLICY_SMART;
1096 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1098 config_primary_monitor_index = 1;
1099 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1101 obt_xml_register(i, "placement", parse_placement, NULL);
1103 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1105 obt_xml_register(i, "margins", parse_margins, NULL);
1107 config_theme = NULL;
1109 config_animate_iconify = TRUE;
1110 config_title_layout = g_strdup("NLIMC");
1111 config_theme_keepborder = TRUE;
1112 config_theme_window_list_icon_size = 36;
1114 config_font_activewindow = NULL;
1115 config_font_inactivewindow = NULL;
1116 config_font_menuitem = NULL;
1117 config_font_menutitle = NULL;
1118 config_font_activeosd = NULL;
1119 config_font_inactiveosd = NULL;
1121 obt_xml_register(i, "theme", parse_theme, NULL);
1123 config_desktops_num = 4;
1124 config_screen_firstdesk = 1;
1125 config_emulate_xinerama = FALSE;
1126 config_desktops_names = NULL;
1127 config_desktop_popup_time = 875;
1129 obt_xml_register(i, "desktops", parse_desktops, NULL);
1131 config_resize_redraw = TRUE;
1132 config_resize_popup_show = 1; /* nonpixel increments */
1133 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1134 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1135 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1137 obt_xml_register(i, "resize", parse_resize, NULL);
1139 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1140 config_dock_pos = OB_DIRECTION_NORTHEAST;
1141 config_dock_floating = FALSE;
1142 config_dock_nostrut = FALSE;
1145 config_dock_orient = OB_ORIENTATION_VERT;
1146 config_dock_hide = FALSE;
1147 config_dock_hide_delay = 300;
1148 config_dock_show_delay = 300;
1149 config_dock_app_move_button = 2; /* middle */
1150 config_dock_app_move_modifiers = 0;
1152 obt_xml_register(i, "dock", parse_dock, NULL);
1154 translate_key("C-g", &config_keyboard_reset_state,
1155 &config_keyboard_reset_keycode);
1156 config_keyboard_rebind_on_mapping_notify = TRUE;
1158 bind_default_keyboard();
1160 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1162 config_mouse_threshold = 8;
1163 config_mouse_dclicktime = 500;
1164 config_mouse_screenedgetime = 400;
1165 config_mouse_screenedgewarp = FALSE;
1167 bind_default_mouse();
1169 obt_xml_register(i, "mouse", parse_mouse, NULL);
1171 config_resist_win = 10;
1172 config_resist_edge = 20;
1174 obt_xml_register(i, "resistance", parse_resistance, NULL);
1176 config_menu_hide_delay = 250;
1177 config_menu_middle = FALSE;
1178 config_submenu_show_delay = 100;
1179 config_submenu_hide_delay = 400;
1180 config_menu_manage_desktops = TRUE;
1181 config_menu_files = NULL;
1182 config_menu_show_icons = TRUE;
1184 obt_xml_register(i, "menu", parse_menu, NULL);
1186 config_per_app_settings = NULL;
1188 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1191 void config_shutdown(void)
1195 g_free(config_theme);
1197 g_free(config_title_layout);
1199 RrFontClose(config_font_activewindow);
1200 RrFontClose(config_font_inactivewindow);
1201 RrFontClose(config_font_menuitem);
1202 RrFontClose(config_font_menutitle);
1203 RrFontClose(config_font_activeosd);
1204 RrFontClose(config_font_inactiveosd);
1206 for (it = config_desktops_names; it; it = g_slist_next(it))
1208 g_slist_free(config_desktops_names);
1210 for (it = config_menu_files; it; it = g_slist_next(it))
1212 g_slist_free(config_menu_files);
1214 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1215 ObAppSettings *itd = (ObAppSettings *)it->data;
1216 if (itd->name) g_pattern_spec_free(itd->name);
1217 if (itd->role) g_pattern_spec_free(itd->role);
1218 if (itd->title) g_pattern_spec_free(itd->title);
1219 if (itd->class) g_pattern_spec_free(itd->class);
1220 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1221 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1222 g_slice_free(ObAppSettings, it->data);
1224 g_slist_free(config_per_app_settings);