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"
30 #include "obt/paths.h"
32 gboolean config_focus_new;
33 gboolean config_focus_follow;
34 guint config_focus_delay;
35 gboolean config_focus_raise;
36 gboolean config_focus_last;
37 gboolean config_focus_under_mouse;
38 gboolean config_focus_dontstop;
40 ObPlacePolicy config_place_policy;
41 gboolean config_place_center;
42 ObPlaceMonitor config_place_monitor;
44 StrutPartial config_margins;
47 gboolean config_theme_keepborder;
48 guint config_theme_window_list_icon_size;
50 gchar *config_title_layout;
52 gboolean config_animate_iconify;
54 RrFont *config_font_activewindow;
55 RrFont *config_font_inactivewindow;
56 RrFont *config_font_menuitem;
57 RrFont *config_font_menutitle;
58 RrFont *config_font_osd;
60 guint config_desktops_num;
61 GSList *config_desktops_names;
62 guint config_screen_firstdesk;
63 guint config_desktop_popup_time;
65 gboolean config_resize_redraw;
66 gint config_resize_popup_show;
67 ObResizePopupPos config_resize_popup_pos;
68 GravityPoint config_resize_popup_fixed;
70 ObStackingLayer config_dock_layer;
71 gboolean config_dock_floating;
72 gboolean config_dock_nostrut;
73 ObDirection config_dock_pos;
76 ObOrientation config_dock_orient;
77 gboolean config_dock_hide;
78 guint config_dock_hide_delay;
79 guint config_dock_show_delay;
80 guint config_dock_app_move_button;
81 guint config_dock_app_move_modifiers;
83 guint config_keyboard_reset_keycode;
84 guint config_keyboard_reset_state;
86 gint config_mouse_threshold;
87 gint config_mouse_dclicktime;
88 gint config_mouse_screenedgetime;
90 guint config_menu_hide_delay;
91 gboolean config_menu_middle;
92 guint config_submenu_show_delay;
93 gboolean config_menu_client_list_icons;
94 gboolean config_menu_manage_desktops;
95 gboolean config_menu_user_show_icons;
97 GSList *config_menu_files;
99 gint config_resist_win;
100 gint config_resist_edge;
102 GSList *config_per_app_settings;
104 ObAppSettings* config_create_app_settings(void)
106 ObAppSettings *settings = g_new0(ObAppSettings, 1);
108 settings->decor = -1;
109 settings->shade = -1;
110 settings->monitor = -1;
111 settings->focus = -1;
112 settings->desktop = 0;
113 settings->layer = -2;
114 settings->iconic = -1;
115 settings->skip_pager = -1;
116 settings->skip_taskbar = -1;
117 settings->fullscreen = -1;
118 settings->max_horz = -1;
119 settings->max_vert = -1;
123 #define copy_if(setting, default) \
124 if (src->setting != default) dst->setting = src->setting
125 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
128 g_assert(src != NULL);
129 g_assert(dst != NULL);
131 copy_if(type, (ObClientType)-1);
138 copy_if(skip_pager, -1);
139 copy_if(skip_taskbar, -1);
140 copy_if(fullscreen, -1);
141 copy_if(max_horz, -1);
142 copy_if(max_vert, -1);
144 if (src->pos_given) {
145 dst->pos_given = TRUE;
146 dst->pos_force = src->pos_force;
147 dst->position = src->position;
148 dst->monitor = src->monitor;
152 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
154 gchar *s = obt_parse_node_string(node);
155 if (!g_ascii_strcasecmp(s, "center"))
160 if (s[0] == '-' || s[0] == '+')
170 <application name="aterm">
173 <application name="Rhythmbox">
180 .. there is a lot more settings available
185 /* Manages settings for individual applications.
186 Some notes: monitor is the screen number in a multi monitor
187 (Xinerama) setup (starting from 0) or mouse, meaning the
188 monitor the pointer is on. Default: mouse.
189 Layer can be three values, above (Always on top), below
190 (Always on bottom) and everything else (normal behaviour).
191 Positions can be an integer value or center, which will
192 center the window in the specified axis. Position is within
193 the monitor, so <position><x>center</x></position><monitor>2</monitor>
194 will center the window on the second monitor.
196 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
198 xmlNodePtr app = obt_parse_find_node(node->children, "application");
199 gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
200 gboolean name_set, class_set, type_set;
201 gboolean x_pos_given;
204 name_set = class_set = type_set = x_pos_given = FALSE;
206 class_set = obt_parse_attr_string(app, "class", &class);
207 name_set = obt_parse_attr_string(app, "name", &name);
208 type_set = obt_parse_attr_string(app, "type", &type);
209 if (class_set || name_set) {
211 ObAppSettings *settings = config_create_app_settings();;
214 settings->name = g_pattern_spec_new(name);
217 settings->class = g_pattern_spec_new(class);
220 if (!g_ascii_strcasecmp(type, "normal"))
221 settings->type = OB_CLIENT_TYPE_NORMAL;
222 else if (!g_ascii_strcasecmp(type, "dialog"))
223 settings->type = OB_CLIENT_TYPE_DIALOG;
224 else if (!g_ascii_strcasecmp(type, "splash"))
225 settings->type = OB_CLIENT_TYPE_SPLASH;
226 else if (!g_ascii_strcasecmp(type, "utility"))
227 settings->type = OB_CLIENT_TYPE_UTILITY;
228 else if (!g_ascii_strcasecmp(type, "menu"))
229 settings->type = OB_CLIENT_TYPE_MENU;
230 else if (!g_ascii_strcasecmp(type, "toolbar"))
231 settings->type = OB_CLIENT_TYPE_TOOLBAR;
232 else if (!g_ascii_strcasecmp(type, "dock"))
233 settings->type = OB_CLIENT_TYPE_DOCK;
234 else if (!g_ascii_strcasecmp(type, "desktop"))
235 settings->type = OB_CLIENT_TYPE_DESKTOP;
238 if (obt_parse_attr_string(app, "role", &role))
239 settings->role = g_pattern_spec_new(role);
241 if ((n = obt_parse_find_node(app->children, "decor")))
242 if (!obt_parse_node_contains(n, "default"))
243 settings->decor = obt_parse_node_bool(n);
245 if ((n = obt_parse_find_node(app->children, "shade")))
246 if (!obt_parse_node_contains(n, "default"))
247 settings->shade = obt_parse_node_bool(n);
249 if ((n = obt_parse_find_node(app->children, "position"))) {
250 if ((c = obt_parse_find_node(n->children, "x")))
251 if (!obt_parse_node_contains(c, "default")) {
252 config_parse_gravity_coord(c, &settings->position.x);
256 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
257 if (!obt_parse_node_contains(c, "default")) {
258 config_parse_gravity_coord(c, &settings->position.y);
259 settings->pos_given = TRUE;
262 if (settings->pos_given &&
263 (c = obt_parse_find_node(n->children, "monitor")))
264 if (!obt_parse_node_contains(c, "default")) {
265 gchar *s = obt_parse_node_string(c);
266 if (!g_ascii_strcasecmp(s, "mouse"))
267 settings->monitor = 0;
269 settings->monitor = obt_parse_node_int(c) + 1;
273 obt_parse_attr_bool(n, "force", &settings->pos_force);
276 if ((n = obt_parse_find_node(app->children, "focus")))
277 if (!obt_parse_node_contains(n, "default"))
278 settings->focus = obt_parse_node_bool(n);
280 if ((n = obt_parse_find_node(app->children, "desktop"))) {
281 if (!obt_parse_node_contains(n, "default")) {
282 gchar *s = obt_parse_node_string(n);
283 if (!g_ascii_strcasecmp(s, "all"))
284 settings->desktop = DESKTOP_ALL;
286 gint i = obt_parse_node_int(n);
288 settings->desktop = i;
294 if ((n = obt_parse_find_node(app->children, "layer")))
295 if (!obt_parse_node_contains(n, "default")) {
296 gchar *s = obt_parse_node_string(n);
297 if (!g_ascii_strcasecmp(s, "above"))
299 else if (!g_ascii_strcasecmp(s, "below"))
300 settings->layer = -1;
306 if ((n = obt_parse_find_node(app->children, "iconic")))
307 if (!obt_parse_node_contains(n, "default"))
308 settings->iconic = obt_parse_node_bool(n);
310 if ((n = obt_parse_find_node(app->children, "skip_pager")))
311 if (!obt_parse_node_contains(n, "default"))
312 settings->skip_pager = obt_parse_node_bool(n);
314 if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
315 if (!obt_parse_node_contains(n, "default"))
316 settings->skip_taskbar = obt_parse_node_bool(n);
318 if ((n = obt_parse_find_node(app->children, "fullscreen")))
319 if (!obt_parse_node_contains(n, "default"))
320 settings->fullscreen = obt_parse_node_bool(n);
322 if ((n = obt_parse_find_node(app->children, "maximized")))
323 if (!obt_parse_node_contains(n, "default")) {
324 gchar *s = obt_parse_node_string(n);
325 if (!g_ascii_strcasecmp(s, "horizontal")) {
326 settings->max_horz = TRUE;
327 settings->max_vert = FALSE;
328 } else if (!g_ascii_strcasecmp(s, "vertical")) {
329 settings->max_horz = FALSE;
330 settings->max_vert = TRUE;
332 settings->max_horz = settings->max_vert =
333 obt_parse_node_bool(n);
337 config_per_app_settings = g_slist_append(config_per_app_settings,
338 (gpointer) settings);
342 name = class = role = NULL;
345 app = obt_parse_find_node(app->next, "application");
349 static void parse_hook(xmlNodePtr node, gpointer d)
356 if (!obt_parse_attr_string(node, "name", &name)) {
357 g_message(_("Hook in config file is missing a name"));
361 hook = hooks_hook_from_name(name);
363 g_message(_("Unknown hook \"%s\" in config file"), name);
365 if ((n = obt_parse_find_node(node->children, "action")))
367 ObActionsAct *action;
369 action = actions_parse(n);
371 hooks_add(hook, action);
372 n = obt_parse_find_node(n->next, "action");
379 static void parse_hooks(xmlNodePtr node, gpointer d)
383 if ((n = obt_parse_find_node(node->children, "hook")))
386 n = obt_parse_find_node(n->next, "hook");
393 <action name="ChangeDesktop">
400 static void parse_key(xmlNodePtr node, GList *keylist)
404 gboolean is_chroot = FALSE;
405 gboolean grab = TRUE;
407 if (!obt_parse_attr_string(node, "key", &key))
410 obt_parse_attr_bool(node, "chroot", &is_chroot);
411 obt_parse_attr_bool(node, "grab", &grab);
413 keylist = g_list_append(keylist, key);
415 if ((n = obt_parse_find_node(node->children, "keybind"))) {
417 parse_key(n, keylist);
418 n = obt_parse_find_node(n->next, "keybind");
421 else if ((n = obt_parse_find_node(node->children, "action"))) {
423 ObActionsAct *action;
425 action = actions_parse(n);
427 keyboard_bind(keylist, action, grab);
428 n = obt_parse_find_node(n->next, "action");
433 keyboard_chroot(keylist);
436 keylist = g_list_delete_link(keylist, g_list_last(keylist));
439 static void parse_keyboard(xmlNodePtr node, gpointer d)
444 keyboard_unbind_all();
446 if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
447 key = obt_parse_node_string(n);
448 translate_key(key, &config_keyboard_reset_state,
449 &config_keyboard_reset_keycode);
453 if ((n = obt_parse_find_node(node->children, "keybind")))
456 n = obt_parse_find_node(n->next, "keybind");
462 <context name="Titlebar">
463 <mousebind button="Left" action="Press">
464 <action name="Raise"></action>
470 static void parse_mouse(xmlNodePtr node, gpointer d)
472 xmlNodePtr n, nbut, nact;
479 node = node->children;
481 if ((n = obt_parse_find_node(node, "dragThreshold")))
482 config_mouse_threshold = obt_parse_node_int(n);
483 if ((n = obt_parse_find_node(node, "doubleClickTime")))
484 config_mouse_dclicktime = obt_parse_node_int(n);
485 if ((n = obt_parse_find_node(node, "screenEdgeWarpTime")))
486 config_mouse_screenedgetime = obt_parse_node_int(n);
488 n = obt_parse_find_node(node, "context");
490 if (!obt_parse_attr_string(n, "name", &contextstr))
492 nbut = obt_parse_find_node(n->children, "mousebind");
494 if (!obt_parse_attr_string(nbut, "button", &buttonstr))
496 if (obt_parse_attr_contains(nbut, "action", "press")) {
497 mact = OB_MOUSE_ACTION_PRESS;
498 } else if (obt_parse_attr_contains(nbut, "action", "release")) {
499 mact = OB_MOUSE_ACTION_RELEASE;
500 } else if (obt_parse_attr_contains(nbut, "action", "click")) {
501 mact = OB_MOUSE_ACTION_CLICK;
502 } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
503 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
504 } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
505 mact = OB_MOUSE_ACTION_MOTION;
508 nact = obt_parse_find_node(nbut->children, "action");
510 ObActionsAct *action;
512 if ((action = actions_parse(nact)))
513 mouse_bind(buttonstr, contextstr, mact, action);
514 nact = obt_parse_find_node(nact->next, "action");
518 nbut = obt_parse_find_node(nbut->next, "mousebind");
522 n = obt_parse_find_node(n->next, "context");
526 static void parse_focus(xmlNodePtr node, gpointer d)
530 node = node->children;
532 if ((n = obt_parse_find_node(node, "focusNew")))
533 config_focus_new = obt_parse_node_bool(n);
534 if ((n = obt_parse_find_node(node, "followMouse")))
535 config_focus_follow = obt_parse_node_bool(n);
536 if ((n = obt_parse_find_node(node, "focusDelay")))
537 config_focus_delay = obt_parse_node_int(n);
538 if ((n = obt_parse_find_node(node, "raiseOnFocus")))
539 config_focus_raise = obt_parse_node_bool(n);
540 if ((n = obt_parse_find_node(node, "focusLast")))
541 config_focus_last = obt_parse_node_bool(n);
542 if ((n = obt_parse_find_node(node, "underMouse")))
543 config_focus_under_mouse = obt_parse_node_bool(n);
544 if ((n = obt_parse_find_node(node, "dontStop")))
545 config_focus_dontstop = obt_parse_node_bool(n);
548 static void parse_placement(xmlNodePtr node, gpointer d)
552 node = node->children;
554 if ((n = obt_parse_find_node(node, "policy")))
555 if (obt_parse_node_contains(n, "UnderMouse"))
556 config_place_policy = OB_PLACE_POLICY_MOUSE;
557 if ((n = obt_parse_find_node(node, "center")))
558 config_place_center = obt_parse_node_bool(n);
559 if ((n = obt_parse_find_node(node, "monitor"))) {
560 if (obt_parse_node_contains(n, "active"))
561 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
562 else if (obt_parse_node_contains(n, "mouse"))
563 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
567 static void parse_margins(xmlNodePtr node, gpointer d)
571 node = node->children;
573 if ((n = obt_parse_find_node(node, "top")))
574 config_margins.top = MAX(0, obt_parse_node_int(n));
575 if ((n = obt_parse_find_node(node, "left")))
576 config_margins.left = MAX(0, obt_parse_node_int(n));
577 if ((n = obt_parse_find_node(node, "right")))
578 config_margins.right = MAX(0, obt_parse_node_int(n));
579 if ((n = obt_parse_find_node(node, "bottom")))
580 config_margins.bottom = MAX(0, obt_parse_node_int(n));
583 static void parse_theme(xmlNodePtr node, gpointer d)
587 node = node->children;
589 if ((n = obt_parse_find_node(node, "name"))) {
592 g_free(config_theme);
593 c = obt_parse_node_string(n);
594 config_theme = obt_paths_expand_tilde(c);
597 if ((n = obt_parse_find_node(node, "titleLayout"))) {
600 g_free(config_title_layout);
601 config_title_layout = obt_parse_node_string(n);
603 /* replace duplicates with spaces */
604 for (c = config_title_layout; *c != '\0'; ++c)
605 for (d = c+1; *d != '\0'; ++d)
606 if (*c == *d) *d = ' ';
608 if ((n = obt_parse_find_node(node, "keepBorder")))
609 config_theme_keepborder = obt_parse_node_bool(n);
610 if ((n = obt_parse_find_node(node, "animateIconify")))
611 config_animate_iconify = obt_parse_node_bool(n);
612 if ((n = obt_parse_find_node(node, "windowListIconSize"))) {
613 config_theme_window_list_icon_size = obt_parse_node_int(n);
614 if (config_theme_window_list_icon_size < 16)
615 config_theme_window_list_icon_size = 16;
616 else if (config_theme_window_list_icon_size > 96)
617 config_theme_window_list_icon_size = 96;
620 n = obt_parse_find_node(node, "font");
624 gchar *name = g_strdup(RrDefaultFontFamily);
625 gint size = RrDefaultFontSize;
626 RrFontWeight weight = RrDefaultFontWeight;
627 RrFontSlant slant = RrDefaultFontSlant;
629 if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
630 font = &config_font_activewindow;
631 else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
632 font = &config_font_inactivewindow;
633 else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
634 font = &config_font_menutitle;
635 else if (obt_parse_attr_contains(n, "place", "MenuItem"))
636 font = &config_font_menuitem;
637 else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
638 font = &config_font_osd;
642 if ((fnode = obt_parse_find_node(n->children, "name"))) {
644 name = obt_parse_node_string(fnode);
646 if ((fnode = obt_parse_find_node(n->children, "size"))) {
647 int s = obt_parse_node_int(fnode);
650 if ((fnode = obt_parse_find_node(n->children, "weight"))) {
651 gchar *w = obt_parse_node_string(fnode);
652 if (!g_ascii_strcasecmp(w, "Bold"))
653 weight = RR_FONTWEIGHT_BOLD;
656 if ((fnode = obt_parse_find_node(n->children, "slant"))) {
657 gchar *s = obt_parse_node_string(fnode);
658 if (!g_ascii_strcasecmp(s, "Italic"))
659 slant = RR_FONTSLANT_ITALIC;
660 if (!g_ascii_strcasecmp(s, "Oblique"))
661 slant = RR_FONTSLANT_OBLIQUE;
665 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
668 if ((fnode = obt_parse_find_node(n->children, "description"))) {
669 gchar *s = obt_parse_node_string(fnode);
670 RrFontDescriptionFromString(*font, s);
675 n = obt_parse_find_node(n->next, "font");
679 static void parse_desktops(xmlNodePtr node, gpointer d)
683 node = node->children;
685 if ((n = obt_parse_find_node(node, "number"))) {
686 gint d = obt_parse_node_int(n);
688 config_desktops_num = (unsigned) d;
690 if ((n = obt_parse_find_node(node, "firstdesk"))) {
691 gint d = obt_parse_node_int(n);
693 config_screen_firstdesk = (unsigned) d;
695 if ((n = obt_parse_find_node(node, "names"))) {
699 for (it = config_desktops_names; it; it = it->next)
701 g_slist_free(config_desktops_names);
702 config_desktops_names = NULL;
704 nname = obt_parse_find_node(n->children, "name");
706 config_desktops_names =
707 g_slist_append(config_desktops_names,
708 obt_parse_node_string(nname));
709 nname = obt_parse_find_node(nname->next, "name");
712 if ((n = obt_parse_find_node(node, "popupTime")))
713 config_desktop_popup_time = obt_parse_node_int(n);
716 static void parse_resize(xmlNodePtr node, gpointer d)
720 node = node->children;
722 if ((n = obt_parse_find_node(node, "drawContents")))
723 config_resize_redraw = obt_parse_node_bool(n);
724 if ((n = obt_parse_find_node(node, "popupShow"))) {
725 config_resize_popup_show = obt_parse_node_int(n);
726 if (obt_parse_node_contains(n, "Always"))
727 config_resize_popup_show = 2;
728 else if (obt_parse_node_contains(n, "Never"))
729 config_resize_popup_show = 0;
730 else if (obt_parse_node_contains(n, "Nonpixel"))
731 config_resize_popup_show = 1;
733 if ((n = obt_parse_find_node(node, "popupPosition"))) {
734 if (obt_parse_node_contains(n, "Top"))
735 config_resize_popup_pos = OB_RESIZE_POS_TOP;
736 else if (obt_parse_node_contains(n, "Center"))
737 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
738 else if (obt_parse_node_contains(n, "Fixed")) {
739 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
741 if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
744 if ((n2 = obt_parse_find_node(n->children, "x")))
745 config_parse_gravity_coord(n2,
746 &config_resize_popup_fixed.x);
747 if ((n2 = obt_parse_find_node(n->children, "y")))
748 config_parse_gravity_coord(n2,
749 &config_resize_popup_fixed.y);
751 config_resize_popup_fixed.x.pos =
752 MAX(config_resize_popup_fixed.x.pos, 0);
753 config_resize_popup_fixed.y.pos =
754 MAX(config_resize_popup_fixed.y.pos, 0);
760 static void parse_dock(xmlNodePtr node, gpointer d)
764 node = node->children;
766 if ((n = obt_parse_find_node(node, "position"))) {
767 if (obt_parse_node_contains(n, "TopLeft"))
768 config_dock_floating = FALSE,
769 config_dock_pos = OB_DIRECTION_NORTHWEST;
770 else if (obt_parse_node_contains(n, "Top"))
771 config_dock_floating = FALSE,
772 config_dock_pos = OB_DIRECTION_NORTH;
773 else if (obt_parse_node_contains(n, "TopRight"))
774 config_dock_floating = FALSE,
775 config_dock_pos = OB_DIRECTION_NORTHEAST;
776 else if (obt_parse_node_contains(n, "Right"))
777 config_dock_floating = FALSE,
778 config_dock_pos = OB_DIRECTION_EAST;
779 else if (obt_parse_node_contains(n, "BottomRight"))
780 config_dock_floating = FALSE,
781 config_dock_pos = OB_DIRECTION_SOUTHEAST;
782 else if (obt_parse_node_contains(n, "Bottom"))
783 config_dock_floating = FALSE,
784 config_dock_pos = OB_DIRECTION_SOUTH;
785 else if (obt_parse_node_contains(n, "BottomLeft"))
786 config_dock_floating = FALSE,
787 config_dock_pos = OB_DIRECTION_SOUTHWEST;
788 else if (obt_parse_node_contains(n, "Left"))
789 config_dock_floating = FALSE,
790 config_dock_pos = OB_DIRECTION_WEST;
791 else if (obt_parse_node_contains(n, "Floating"))
792 config_dock_floating = TRUE;
794 if (config_dock_floating) {
795 if ((n = obt_parse_find_node(node, "floatingX")))
796 config_dock_x = obt_parse_node_int(n);
797 if ((n = obt_parse_find_node(node, "floatingY")))
798 config_dock_y = obt_parse_node_int(n);
800 if ((n = obt_parse_find_node(node, "noStrut")))
801 config_dock_nostrut = obt_parse_node_bool(n);
803 if ((n = obt_parse_find_node(node, "stacking"))) {
804 if (obt_parse_node_contains(n, "normal"))
805 config_dock_layer = OB_STACKING_LAYER_NORMAL;
806 else if (obt_parse_node_contains(n, "below"))
807 config_dock_layer = OB_STACKING_LAYER_BELOW;
808 else if (obt_parse_node_contains(n, "above"))
809 config_dock_layer = OB_STACKING_LAYER_ABOVE;
811 if ((n = obt_parse_find_node(node, "direction"))) {
812 if (obt_parse_node_contains(n, "horizontal"))
813 config_dock_orient = OB_ORIENTATION_HORZ;
814 else if (obt_parse_node_contains(n, "vertical"))
815 config_dock_orient = OB_ORIENTATION_VERT;
817 if ((n = obt_parse_find_node(node, "autoHide")))
818 config_dock_hide = obt_parse_node_bool(n);
819 if ((n = obt_parse_find_node(node, "hideDelay")))
820 config_dock_hide_delay = obt_parse_node_int(n);
821 if ((n = obt_parse_find_node(node, "showDelay")))
822 config_dock_show_delay = obt_parse_node_int(n);
823 if ((n = obt_parse_find_node(node, "moveButton"))) {
824 gchar *str = obt_parse_node_string(n);
826 if (translate_button(str, &s, &b)) {
827 config_dock_app_move_button = b;
828 config_dock_app_move_modifiers = s;
830 g_message(_("Invalid button \"%s\" specified in config file"), str);
836 static void parse_menu(xmlNodePtr node, gpointer d)
839 node = node->children;
841 if ((n = obt_parse_find_node(node, "hideDelay")))
842 config_menu_hide_delay = obt_parse_node_int(n);
843 if ((n = obt_parse_find_node(node, "middle")))
844 config_menu_middle = obt_parse_node_bool(n);
845 if ((n = obt_parse_find_node(node, "submenuShowDelay")))
846 config_submenu_show_delay = obt_parse_node_int(n);
847 if ((n = obt_parse_find_node(node, "applicationIcons")))
848 config_menu_client_list_icons = obt_parse_node_bool(n);
849 if ((n = obt_parse_find_node(node, "manageDesktops")))
850 config_menu_manage_desktops = obt_parse_node_bool(n);
852 if ((n = obt_parse_find_node(node, "showIcons"))) {
853 config_menu_user_show_icons = obt_parse_node_bool(n);
855 if (config_menu_user_show_icons)
856 g_message(_("Openbox was compiled without Imlib2."
857 " Icons in user-defined menus will NOT be loaded."));
861 while ((node = obt_parse_find_node(node, "file"))) {
862 gchar *c = obt_parse_node_string(node);
863 config_menu_files = g_slist_append(config_menu_files,
864 obt_paths_expand_tilde(c));
870 static void parse_resistance(xmlNodePtr node, gpointer d)
874 node = node->children;
875 if ((n = obt_parse_find_node(node, "strength")))
876 config_resist_win = obt_parse_node_int(n);
877 if ((n = obt_parse_find_node(node, "screen_edge_strength")))
878 config_resist_edge = obt_parse_node_int(n);
884 const gchar *actname;
887 static void bind_default_keyboard(void)
890 ObDefKeyBind binds[] = {
891 { "A-Tab", "NextWindow" },
892 { "S-A-Tab", "PreviousWindow" },
896 for (it = binds; it->key; ++it) {
897 GList *l = g_list_append(NULL, g_strdup(it->key));
898 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
905 const gchar *context;
906 const ObMouseAction mact;
907 const gchar *actname;
910 static void bind_default_mouse(void)
913 ObDefMouseBind binds[] = {
914 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
915 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
916 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
917 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
918 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
919 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
920 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
921 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
922 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
923 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
924 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
925 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
926 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
927 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
928 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
929 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
930 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
931 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
932 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
933 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
934 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
935 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
936 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
937 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
938 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
939 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
940 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
941 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
942 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
943 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
944 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
945 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
946 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
947 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
948 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
949 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
950 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
951 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
952 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
953 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
954 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
955 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
956 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
957 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
958 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
959 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
960 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
961 { NULL, NULL, 0, NULL }
964 for (it = binds; it->button; ++it)
965 mouse_bind(it->button, it->context, it->mact,
966 actions_parse_string(it->actname));
969 void config_startup(ObtParseInst *i)
971 config_focus_new = TRUE;
972 config_focus_follow = FALSE;
973 config_focus_delay = 0;
974 config_focus_raise = FALSE;
975 config_focus_last = TRUE;
976 config_focus_under_mouse = FALSE;
977 config_focus_dontstop = FALSE;
979 obt_parse_register(i, "focus", parse_focus, NULL);
981 config_place_policy = OB_PLACE_POLICY_SMART;
982 config_place_center = TRUE;
983 config_place_monitor = OB_PLACE_MONITOR_ANY;
985 obt_parse_register(i, "placement", parse_placement, NULL);
987 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
989 obt_parse_register(i, "margins", parse_margins, NULL);
993 config_animate_iconify = TRUE;
994 config_title_layout = g_strdup("NLIMC");
995 config_theme_keepborder = TRUE;
996 config_theme_window_list_icon_size = 36;
998 config_font_activewindow = NULL;
999 config_font_inactivewindow = NULL;
1000 config_font_menuitem = NULL;
1001 config_font_menutitle = NULL;
1003 obt_parse_register(i, "theme", parse_theme, NULL);
1005 config_desktops_num = 4;
1006 config_screen_firstdesk = 1;
1007 config_desktops_names = NULL;
1008 config_desktop_popup_time = 875;
1010 obt_parse_register(i, "desktops", parse_desktops, NULL);
1012 config_resize_redraw = TRUE;
1013 config_resize_popup_show = 1; /* nonpixel increments */
1014 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1015 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1016 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1018 obt_parse_register(i, "resize", parse_resize, NULL);
1020 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1021 config_dock_pos = OB_DIRECTION_NORTHEAST;
1022 config_dock_floating = FALSE;
1023 config_dock_nostrut = FALSE;
1026 config_dock_orient = OB_ORIENTATION_VERT;
1027 config_dock_hide = FALSE;
1028 config_dock_hide_delay = 300;
1029 config_dock_show_delay = 300;
1030 config_dock_app_move_button = 2; /* middle */
1031 config_dock_app_move_modifiers = 0;
1033 obt_parse_register(i, "dock", parse_dock, NULL);
1035 translate_key("C-g", &config_keyboard_reset_state,
1036 &config_keyboard_reset_keycode);
1038 bind_default_keyboard();
1040 obt_parse_register(i, "keyboard", parse_keyboard, NULL);
1042 config_mouse_threshold = 8;
1043 config_mouse_dclicktime = 200;
1044 config_mouse_screenedgetime = 400;
1046 bind_default_mouse();
1048 obt_parse_register(i, "mouse", parse_mouse, NULL);
1050 config_resist_win = 10;
1051 config_resist_edge = 20;
1053 obt_parse_register(i, "resistance", parse_resistance, NULL);
1055 config_menu_hide_delay = 250;
1056 config_menu_middle = FALSE;
1057 config_submenu_show_delay = 0;
1058 config_menu_client_list_icons = TRUE;
1059 config_menu_manage_desktops = TRUE;
1060 config_menu_files = NULL;
1061 config_menu_user_show_icons = TRUE;
1063 obt_parse_register(i, "menu", parse_menu, NULL);
1065 obt_parse_register(i, "hooks", parse_hooks, NULL);
1067 config_per_app_settings = NULL;
1069 obt_parse_register(i, "applications", parse_per_app_settings, NULL);
1072 void config_shutdown(void)
1076 g_free(config_theme);
1078 g_free(config_title_layout);
1080 RrFontClose(config_font_activewindow);
1081 RrFontClose(config_font_inactivewindow);
1082 RrFontClose(config_font_menuitem);
1083 RrFontClose(config_font_menutitle);
1084 RrFontClose(config_font_osd);
1086 for (it = config_desktops_names; it; it = g_slist_next(it))
1088 g_slist_free(config_desktops_names);
1090 for (it = config_menu_files; it; it = g_slist_next(it))
1092 g_slist_free(config_menu_files);
1094 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1095 ObAppSettings *itd = (ObAppSettings *)it->data;
1096 if (itd->name) g_pattern_spec_free(itd->name);
1097 if (itd->role) g_pattern_spec_free(itd->role);
1098 if (itd->class) g_pattern_spec_free(itd->class);
1101 g_slist_free(config_per_app_settings);