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 guint config_window_margin;
104 GSList *config_per_app_settings;
106 ObAppSettings* config_create_app_settings(void)
108 ObAppSettings *settings = g_new0(ObAppSettings, 1);
110 settings->decor = -1;
111 settings->shade = -1;
112 settings->monitor = -1;
113 settings->focus = -1;
114 settings->desktop = 0;
115 settings->layer = -2;
116 settings->iconic = -1;
117 settings->skip_pager = -1;
118 settings->skip_taskbar = -1;
119 settings->fullscreen = -1;
120 settings->max_horz = -1;
121 settings->max_vert = -1;
125 #define copy_if(setting, default) \
126 if (src->setting != default) dst->setting = src->setting
127 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
130 g_assert(src != NULL);
131 g_assert(dst != NULL);
133 copy_if(type, (ObClientType)-1);
140 copy_if(skip_pager, -1);
141 copy_if(skip_taskbar, -1);
142 copy_if(fullscreen, -1);
143 copy_if(max_horz, -1);
144 copy_if(max_vert, -1);
146 if (src->pos_given) {
147 dst->pos_given = TRUE;
148 dst->pos_force = src->pos_force;
149 dst->position = src->position;
150 dst->monitor = src->monitor;
154 static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
156 gchar *s = obt_parse_node_string(node);
157 if (!g_ascii_strcasecmp(s, "center"))
162 if (s[0] == '-' || s[0] == '+')
172 <application name="aterm">
175 <application name="Rhythmbox">
182 .. there is a lot more settings available
187 /* Manages settings for individual applications.
188 Some notes: monitor is the screen number in a multi monitor
189 (Xinerama) setup (starting from 0) or mouse, meaning the
190 monitor the pointer is on. Default: mouse.
191 Layer can be three values, above (Always on top), below
192 (Always on bottom) and everything else (normal behaviour).
193 Positions can be an integer value or center, which will
194 center the window in the specified axis. Position is within
195 the monitor, so <position><x>center</x></position><monitor>2</monitor>
196 will center the window on the second monitor.
198 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
200 xmlNodePtr app = obt_parse_find_node(node->children, "application");
201 gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
202 gboolean name_set, class_set, type_set;
203 gboolean x_pos_given;
206 name_set = class_set = type_set = x_pos_given = FALSE;
208 class_set = obt_parse_attr_string(app, "class", &class);
209 name_set = obt_parse_attr_string(app, "name", &name);
210 type_set = obt_parse_attr_string(app, "type", &type);
211 if (class_set || name_set) {
213 ObAppSettings *settings = config_create_app_settings();;
216 settings->name = g_pattern_spec_new(name);
219 settings->class = g_pattern_spec_new(class);
222 if (!g_ascii_strcasecmp(type, "normal"))
223 settings->type = OB_CLIENT_TYPE_NORMAL;
224 else if (!g_ascii_strcasecmp(type, "dialog"))
225 settings->type = OB_CLIENT_TYPE_DIALOG;
226 else if (!g_ascii_strcasecmp(type, "splash"))
227 settings->type = OB_CLIENT_TYPE_SPLASH;
228 else if (!g_ascii_strcasecmp(type, "utility"))
229 settings->type = OB_CLIENT_TYPE_UTILITY;
230 else if (!g_ascii_strcasecmp(type, "menu"))
231 settings->type = OB_CLIENT_TYPE_MENU;
232 else if (!g_ascii_strcasecmp(type, "toolbar"))
233 settings->type = OB_CLIENT_TYPE_TOOLBAR;
234 else if (!g_ascii_strcasecmp(type, "dock"))
235 settings->type = OB_CLIENT_TYPE_DOCK;
236 else if (!g_ascii_strcasecmp(type, "desktop"))
237 settings->type = OB_CLIENT_TYPE_DESKTOP;
240 if (obt_parse_attr_string(app, "role", &role))
241 settings->role = g_pattern_spec_new(role);
243 if ((n = obt_parse_find_node(app->children, "decor")))
244 if (!obt_parse_node_contains(n, "default"))
245 settings->decor = obt_parse_node_bool(n);
247 if ((n = obt_parse_find_node(app->children, "shade")))
248 if (!obt_parse_node_contains(n, "default"))
249 settings->shade = obt_parse_node_bool(n);
251 if ((n = obt_parse_find_node(app->children, "position"))) {
252 if ((c = obt_parse_find_node(n->children, "x")))
253 if (!obt_parse_node_contains(c, "default")) {
254 config_parse_gravity_coord(c, &settings->position.x);
258 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
259 if (!obt_parse_node_contains(c, "default")) {
260 config_parse_gravity_coord(c, &settings->position.y);
261 settings->pos_given = TRUE;
264 if (settings->pos_given &&
265 (c = obt_parse_find_node(n->children, "monitor")))
266 if (!obt_parse_node_contains(c, "default")) {
267 gchar *s = obt_parse_node_string(c);
268 if (!g_ascii_strcasecmp(s, "mouse"))
269 settings->monitor = 0;
271 settings->monitor = obt_parse_node_int(c) + 1;
275 obt_parse_attr_bool(n, "force", &settings->pos_force);
278 if ((n = obt_parse_find_node(app->children, "focus")))
279 if (!obt_parse_node_contains(n, "default"))
280 settings->focus = obt_parse_node_bool(n);
282 if ((n = obt_parse_find_node(app->children, "desktop"))) {
283 if (!obt_parse_node_contains(n, "default")) {
284 gchar *s = obt_parse_node_string(n);
285 if (!g_ascii_strcasecmp(s, "all"))
286 settings->desktop = DESKTOP_ALL;
288 gint i = obt_parse_node_int(n);
290 settings->desktop = i;
296 if ((n = obt_parse_find_node(app->children, "layer")))
297 if (!obt_parse_node_contains(n, "default")) {
298 gchar *s = obt_parse_node_string(n);
299 if (!g_ascii_strcasecmp(s, "above"))
301 else if (!g_ascii_strcasecmp(s, "below"))
302 settings->layer = -1;
308 if ((n = obt_parse_find_node(app->children, "iconic")))
309 if (!obt_parse_node_contains(n, "default"))
310 settings->iconic = obt_parse_node_bool(n);
312 if ((n = obt_parse_find_node(app->children, "skip_pager")))
313 if (!obt_parse_node_contains(n, "default"))
314 settings->skip_pager = obt_parse_node_bool(n);
316 if ((n = obt_parse_find_node(app->children, "skip_taskbar")))
317 if (!obt_parse_node_contains(n, "default"))
318 settings->skip_taskbar = obt_parse_node_bool(n);
320 if ((n = obt_parse_find_node(app->children, "fullscreen")))
321 if (!obt_parse_node_contains(n, "default"))
322 settings->fullscreen = obt_parse_node_bool(n);
324 if ((n = obt_parse_find_node(app->children, "maximized")))
325 if (!obt_parse_node_contains(n, "default")) {
326 gchar *s = obt_parse_node_string(n);
327 if (!g_ascii_strcasecmp(s, "horizontal")) {
328 settings->max_horz = TRUE;
329 settings->max_vert = FALSE;
330 } else if (!g_ascii_strcasecmp(s, "vertical")) {
331 settings->max_horz = FALSE;
332 settings->max_vert = TRUE;
334 settings->max_horz = settings->max_vert =
335 obt_parse_node_bool(n);
339 config_per_app_settings = g_slist_append(config_per_app_settings,
340 (gpointer) settings);
344 name = class = role = NULL;
347 app = obt_parse_find_node(app->next, "application");
351 static void parse_hook(xmlNodePtr node, gpointer d)
358 if (!obt_parse_attr_string(node, "name", &name)) {
359 g_message(_("Hook in config file is missing a name"));
363 hook = hooks_hook_from_name(name);
365 g_message(_("Unknown hook \"%s\" in config file"), name);
367 if ((n = obt_parse_find_node(node->children, "action")))
369 ObActionsAct *action;
371 action = actions_parse(n);
373 hooks_add(hook, action);
374 n = obt_parse_find_node(n->next, "action");
381 static void parse_hooks(xmlNodePtr node, gpointer d)
385 if ((n = obt_parse_find_node(node->children, "hook")))
388 n = obt_parse_find_node(n->next, "hook");
395 <action name="ChangeDesktop">
402 static void parse_key(xmlNodePtr node, GList *keylist)
406 gboolean is_chroot = FALSE;
407 gboolean grab = TRUE;
409 if (!obt_parse_attr_string(node, "key", &key))
412 obt_parse_attr_bool(node, "chroot", &is_chroot);
413 obt_parse_attr_bool(node, "grab", &grab);
415 keylist = g_list_append(keylist, key);
417 if ((n = obt_parse_find_node(node->children, "keybind"))) {
419 parse_key(n, keylist);
420 n = obt_parse_find_node(n->next, "keybind");
423 else if ((n = obt_parse_find_node(node->children, "action"))) {
425 ObActionsAct *action;
427 action = actions_parse(n);
429 keyboard_bind(keylist, action, grab);
430 n = obt_parse_find_node(n->next, "action");
435 keyboard_chroot(keylist);
438 keylist = g_list_delete_link(keylist, g_list_last(keylist));
441 static void parse_keyboard(xmlNodePtr node, gpointer d)
446 keyboard_unbind_all();
448 if ((n = obt_parse_find_node(node->children, "chainQuitKey"))) {
449 key = obt_parse_node_string(n);
450 translate_key(key, &config_keyboard_reset_state,
451 &config_keyboard_reset_keycode);
455 if ((n = obt_parse_find_node(node->children, "keybind")))
458 n = obt_parse_find_node(n->next, "keybind");
464 <context name="Titlebar">
465 <mousebind button="Left" action="Press">
466 <action name="Raise"></action>
472 static void parse_mouse(xmlNodePtr node, gpointer d)
474 xmlNodePtr n, nbut, nact;
481 node = node->children;
483 if ((n = obt_parse_find_node(node, "dragThreshold")))
484 config_mouse_threshold = obt_parse_node_int(n);
485 if ((n = obt_parse_find_node(node, "doubleClickTime")))
486 config_mouse_dclicktime = obt_parse_node_int(n);
487 if ((n = obt_parse_find_node(node, "screenEdgeWarpTime")))
488 config_mouse_screenedgetime = obt_parse_node_int(n);
490 n = obt_parse_find_node(node, "context");
492 if (!obt_parse_attr_string(n, "name", &contextstr))
494 nbut = obt_parse_find_node(n->children, "mousebind");
496 if (!obt_parse_attr_string(nbut, "button", &buttonstr))
498 if (obt_parse_attr_contains(nbut, "action", "press")) {
499 mact = OB_MOUSE_ACTION_PRESS;
500 } else if (obt_parse_attr_contains(nbut, "action", "release")) {
501 mact = OB_MOUSE_ACTION_RELEASE;
502 } else if (obt_parse_attr_contains(nbut, "action", "click")) {
503 mact = OB_MOUSE_ACTION_CLICK;
504 } else if (obt_parse_attr_contains(nbut, "action","doubleclick")) {
505 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
506 } else if (obt_parse_attr_contains(nbut, "action", "drag")) {
507 mact = OB_MOUSE_ACTION_MOTION;
510 nact = obt_parse_find_node(nbut->children, "action");
512 ObActionsAct *action;
514 if ((action = actions_parse(nact)))
515 mouse_bind(buttonstr, contextstr, mact, action);
516 nact = obt_parse_find_node(nact->next, "action");
520 nbut = obt_parse_find_node(nbut->next, "mousebind");
524 n = obt_parse_find_node(n->next, "context");
528 static void parse_focus(xmlNodePtr node, gpointer d)
532 node = node->children;
534 if ((n = obt_parse_find_node(node, "focusNew")))
535 config_focus_new = obt_parse_node_bool(n);
536 if ((n = obt_parse_find_node(node, "followMouse")))
537 config_focus_follow = obt_parse_node_bool(n);
538 if ((n = obt_parse_find_node(node, "focusDelay")))
539 config_focus_delay = obt_parse_node_int(n);
540 if ((n = obt_parse_find_node(node, "raiseOnFocus")))
541 config_focus_raise = obt_parse_node_bool(n);
542 if ((n = obt_parse_find_node(node, "focusLast")))
543 config_focus_last = obt_parse_node_bool(n);
544 if ((n = obt_parse_find_node(node, "underMouse")))
545 config_focus_under_mouse = obt_parse_node_bool(n);
546 if ((n = obt_parse_find_node(node, "dontStop")))
547 config_focus_dontstop = obt_parse_node_bool(n);
550 static void parse_placement(xmlNodePtr node, gpointer d)
554 node = node->children;
556 if ((n = obt_parse_find_node(node, "policy")))
557 if (obt_parse_node_contains(n, "UnderMouse"))
558 config_place_policy = OB_PLACE_POLICY_MOUSE;
559 if ((n = obt_parse_find_node(node, "center")))
560 config_place_center = obt_parse_node_bool(n);
561 if ((n = obt_parse_find_node(node, "monitor"))) {
562 if (obt_parse_node_contains(n, "active"))
563 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
564 else if (obt_parse_node_contains(n, "mouse"))
565 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
569 static void parse_margins(xmlNodePtr node, gpointer d)
573 node = node->children;
575 if ((n = obt_parse_find_node(node, "top")))
576 config_margins.top = MAX(0, obt_parse_node_int(n));
577 if ((n = obt_parse_find_node(node, "left")))
578 config_margins.left = MAX(0, obt_parse_node_int(n));
579 if ((n = obt_parse_find_node(node, "right")))
580 config_margins.right = MAX(0, obt_parse_node_int(n));
581 if ((n = obt_parse_find_node(node, "bottom")))
582 config_margins.bottom = MAX(0, obt_parse_node_int(n));
585 static void parse_theme(xmlNodePtr node, gpointer d)
589 node = node->children;
591 if ((n = obt_parse_find_node(node, "name"))) {
594 g_free(config_theme);
595 c = obt_parse_node_string(n);
596 config_theme = obt_paths_expand_tilde(c);
599 if ((n = obt_parse_find_node(node, "titleLayout"))) {
602 g_free(config_title_layout);
603 config_title_layout = obt_parse_node_string(n);
605 /* replace duplicates with spaces */
606 for (c = config_title_layout; *c != '\0'; ++c)
607 for (d = c+1; *d != '\0'; ++d)
608 if (*c == *d) *d = ' ';
610 if ((n = obt_parse_find_node(node, "keepBorder")))
611 config_theme_keepborder = obt_parse_node_bool(n);
612 if ((n = obt_parse_find_node(node, "animateIconify")))
613 config_animate_iconify = obt_parse_node_bool(n);
614 if ((n = obt_parse_find_node(node, "windowListIconSize"))) {
615 config_theme_window_list_icon_size = obt_parse_node_int(n);
616 if (config_theme_window_list_icon_size < 16)
617 config_theme_window_list_icon_size = 16;
618 else if (config_theme_window_list_icon_size > 96)
619 config_theme_window_list_icon_size = 96;
622 n = obt_parse_find_node(node, "font");
626 gchar *name = g_strdup(RrDefaultFontFamily);
627 gint size = RrDefaultFontSize;
628 RrFontWeight weight = RrDefaultFontWeight;
629 RrFontSlant slant = RrDefaultFontSlant;
631 if (obt_parse_attr_contains(n, "place", "ActiveWindow"))
632 font = &config_font_activewindow;
633 else if (obt_parse_attr_contains(n, "place", "InactiveWindow"))
634 font = &config_font_inactivewindow;
635 else if (obt_parse_attr_contains(n, "place", "MenuHeader"))
636 font = &config_font_menutitle;
637 else if (obt_parse_attr_contains(n, "place", "MenuItem"))
638 font = &config_font_menuitem;
639 else if (obt_parse_attr_contains(n, "place", "OnScreenDisplay"))
640 font = &config_font_osd;
644 if ((fnode = obt_parse_find_node(n->children, "name"))) {
646 name = obt_parse_node_string(fnode);
648 if ((fnode = obt_parse_find_node(n->children, "size"))) {
649 int s = obt_parse_node_int(fnode);
652 if ((fnode = obt_parse_find_node(n->children, "weight"))) {
653 gchar *w = obt_parse_node_string(fnode);
654 if (!g_ascii_strcasecmp(w, "Bold"))
655 weight = RR_FONTWEIGHT_BOLD;
658 if ((fnode = obt_parse_find_node(n->children, "slant"))) {
659 gchar *s = obt_parse_node_string(fnode);
660 if (!g_ascii_strcasecmp(s, "Italic"))
661 slant = RR_FONTSLANT_ITALIC;
662 if (!g_ascii_strcasecmp(s, "Oblique"))
663 slant = RR_FONTSLANT_OBLIQUE;
667 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
670 if ((fnode = obt_parse_find_node(n->children, "description"))) {
671 gchar *s = obt_parse_node_string(fnode);
672 RrFontDescriptionFromString(*font, s);
677 n = obt_parse_find_node(n->next, "font");
681 static void parse_desktops(xmlNodePtr node, gpointer d)
685 node = node->children;
687 if ((n = obt_parse_find_node(node, "number"))) {
688 gint d = obt_parse_node_int(n);
690 config_desktops_num = (unsigned) d;
692 if ((n = obt_parse_find_node(node, "firstdesk"))) {
693 gint d = obt_parse_node_int(n);
695 config_screen_firstdesk = (unsigned) d;
697 if ((n = obt_parse_find_node(node, "names"))) {
701 for (it = config_desktops_names; it; it = it->next)
703 g_slist_free(config_desktops_names);
704 config_desktops_names = NULL;
706 nname = obt_parse_find_node(n->children, "name");
708 config_desktops_names =
709 g_slist_append(config_desktops_names,
710 obt_parse_node_string(nname));
711 nname = obt_parse_find_node(nname->next, "name");
714 if ((n = obt_parse_find_node(node, "popupTime")))
715 config_desktop_popup_time = obt_parse_node_int(n);
718 static void parse_resize(xmlNodePtr node, gpointer d)
722 node = node->children;
724 if ((n = obt_parse_find_node(node, "drawContents")))
725 config_resize_redraw = obt_parse_node_bool(n);
726 if ((n = obt_parse_find_node(node, "popupShow"))) {
727 config_resize_popup_show = obt_parse_node_int(n);
728 if (obt_parse_node_contains(n, "Always"))
729 config_resize_popup_show = 2;
730 else if (obt_parse_node_contains(n, "Never"))
731 config_resize_popup_show = 0;
732 else if (obt_parse_node_contains(n, "Nonpixel"))
733 config_resize_popup_show = 1;
735 if ((n = obt_parse_find_node(node, "popupPosition"))) {
736 if (obt_parse_node_contains(n, "Top"))
737 config_resize_popup_pos = OB_RESIZE_POS_TOP;
738 else if (obt_parse_node_contains(n, "Center"))
739 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
740 else if (obt_parse_node_contains(n, "Fixed")) {
741 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
743 if ((n = obt_parse_find_node(node, "popupFixedPosition"))) {
746 if ((n2 = obt_parse_find_node(n->children, "x")))
747 config_parse_gravity_coord(n2,
748 &config_resize_popup_fixed.x);
749 if ((n2 = obt_parse_find_node(n->children, "y")))
750 config_parse_gravity_coord(n2,
751 &config_resize_popup_fixed.y);
753 config_resize_popup_fixed.x.pos =
754 MAX(config_resize_popup_fixed.x.pos, 0);
755 config_resize_popup_fixed.y.pos =
756 MAX(config_resize_popup_fixed.y.pos, 0);
762 static void parse_dock(xmlNodePtr node, gpointer d)
766 node = node->children;
768 if ((n = obt_parse_find_node(node, "position"))) {
769 if (obt_parse_node_contains(n, "TopLeft"))
770 config_dock_floating = FALSE,
771 config_dock_pos = OB_DIRECTION_NORTHWEST;
772 else if (obt_parse_node_contains(n, "Top"))
773 config_dock_floating = FALSE,
774 config_dock_pos = OB_DIRECTION_NORTH;
775 else if (obt_parse_node_contains(n, "TopRight"))
776 config_dock_floating = FALSE,
777 config_dock_pos = OB_DIRECTION_NORTHEAST;
778 else if (obt_parse_node_contains(n, "Right"))
779 config_dock_floating = FALSE,
780 config_dock_pos = OB_DIRECTION_EAST;
781 else if (obt_parse_node_contains(n, "BottomRight"))
782 config_dock_floating = FALSE,
783 config_dock_pos = OB_DIRECTION_SOUTHEAST;
784 else if (obt_parse_node_contains(n, "Bottom"))
785 config_dock_floating = FALSE,
786 config_dock_pos = OB_DIRECTION_SOUTH;
787 else if (obt_parse_node_contains(n, "BottomLeft"))
788 config_dock_floating = FALSE,
789 config_dock_pos = OB_DIRECTION_SOUTHWEST;
790 else if (obt_parse_node_contains(n, "Left"))
791 config_dock_floating = FALSE,
792 config_dock_pos = OB_DIRECTION_WEST;
793 else if (obt_parse_node_contains(n, "Floating"))
794 config_dock_floating = TRUE;
796 if (config_dock_floating) {
797 if ((n = obt_parse_find_node(node, "floatingX")))
798 config_dock_x = obt_parse_node_int(n);
799 if ((n = obt_parse_find_node(node, "floatingY")))
800 config_dock_y = obt_parse_node_int(n);
802 if ((n = obt_parse_find_node(node, "noStrut")))
803 config_dock_nostrut = obt_parse_node_bool(n);
805 if ((n = obt_parse_find_node(node, "stacking"))) {
806 if (obt_parse_node_contains(n, "normal"))
807 config_dock_layer = OB_STACKING_LAYER_NORMAL;
808 else if (obt_parse_node_contains(n, "below"))
809 config_dock_layer = OB_STACKING_LAYER_BELOW;
810 else if (obt_parse_node_contains(n, "above"))
811 config_dock_layer = OB_STACKING_LAYER_ABOVE;
813 if ((n = obt_parse_find_node(node, "direction"))) {
814 if (obt_parse_node_contains(n, "horizontal"))
815 config_dock_orient = OB_ORIENTATION_HORZ;
816 else if (obt_parse_node_contains(n, "vertical"))
817 config_dock_orient = OB_ORIENTATION_VERT;
819 if ((n = obt_parse_find_node(node, "autoHide")))
820 config_dock_hide = obt_parse_node_bool(n);
821 if ((n = obt_parse_find_node(node, "hideDelay")))
822 config_dock_hide_delay = obt_parse_node_int(n);
823 if ((n = obt_parse_find_node(node, "showDelay")))
824 config_dock_show_delay = obt_parse_node_int(n);
825 if ((n = obt_parse_find_node(node, "moveButton"))) {
826 gchar *str = obt_parse_node_string(n);
828 if (translate_button(str, &s, &b)) {
829 config_dock_app_move_button = b;
830 config_dock_app_move_modifiers = s;
832 g_message(_("Invalid button \"%s\" specified in config file"), str);
838 static void parse_menu(xmlNodePtr node, gpointer d)
841 node = node->children;
843 if ((n = obt_parse_find_node(node, "hideDelay")))
844 config_menu_hide_delay = obt_parse_node_int(n);
845 if ((n = obt_parse_find_node(node, "middle")))
846 config_menu_middle = obt_parse_node_bool(n);
847 if ((n = obt_parse_find_node(node, "submenuShowDelay")))
848 config_submenu_show_delay = obt_parse_node_int(n);
849 if ((n = obt_parse_find_node(node, "applicationIcons")))
850 config_menu_client_list_icons = obt_parse_node_bool(n);
851 if ((n = obt_parse_find_node(node, "manageDesktops")))
852 config_menu_manage_desktops = obt_parse_node_bool(n);
854 if ((n = obt_parse_find_node(node, "showIcons"))) {
855 config_menu_user_show_icons = obt_parse_node_bool(n);
857 if (config_menu_user_show_icons)
858 g_message(_("Openbox was compiled without Imlib2."
859 " Icons in user-defined menus will NOT be loaded."));
863 while ((node = obt_parse_find_node(node, "file"))) {
864 gchar *c = obt_parse_node_string(node);
865 config_menu_files = g_slist_append(config_menu_files,
866 obt_paths_expand_tilde(c));
872 static void parse_resistance(xmlNodePtr node, gpointer d)
876 node = node->children;
877 if ((n = obt_parse_find_node(node, "strength")))
878 config_resist_win = obt_parse_node_int(n);
879 if ((n = obt_parse_find_node(node, "screen_edge_strength")))
880 config_resist_edge = obt_parse_node_int(n);
883 static void parse_window_margin(xmlNodePtr node, gpointer d)
885 config_window_margin = obt_parse_node_int(node);
891 const gchar *actname;
894 static void bind_default_keyboard(void)
897 ObDefKeyBind binds[] = {
898 { "A-Tab", "NextWindow" },
899 { "S-A-Tab", "PreviousWindow" },
903 for (it = binds; it->key; ++it) {
904 GList *l = g_list_append(NULL, g_strdup(it->key));
905 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
912 const gchar *context;
913 const ObMouseAction mact;
914 const gchar *actname;
917 static void bind_default_mouse(void)
920 ObDefMouseBind binds[] = {
921 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
922 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
923 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
924 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
925 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
926 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
927 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
928 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
929 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
930 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
931 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
932 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
933 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
934 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
935 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
936 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
937 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
938 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
939 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
940 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
941 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
942 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
943 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
944 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
945 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
946 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
947 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
948 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
949 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
950 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
951 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
952 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
953 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
954 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
955 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
956 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
957 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
958 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
959 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
960 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
961 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
962 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
963 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
964 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
965 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
966 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
967 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
968 { NULL, NULL, 0, NULL }
971 for (it = binds; it->button; ++it)
972 mouse_bind(it->button, it->context, it->mact,
973 actions_parse_string(it->actname));
976 void config_startup(ObtParseInst *i)
978 config_focus_new = TRUE;
979 config_focus_follow = FALSE;
980 config_focus_delay = 0;
981 config_focus_raise = FALSE;
982 config_focus_last = TRUE;
983 config_focus_under_mouse = FALSE;
984 config_focus_dontstop = FALSE;
986 obt_parse_register(i, "focus", parse_focus, NULL);
988 config_place_policy = OB_PLACE_POLICY_SMART;
989 config_place_center = TRUE;
990 config_place_monitor = OB_PLACE_MONITOR_ANY;
992 obt_parse_register(i, "placement", parse_placement, NULL);
994 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
996 obt_parse_register(i, "margins", parse_margins, NULL);
1000 config_animate_iconify = TRUE;
1001 config_title_layout = g_strdup("NLIMC");
1002 config_theme_keepborder = TRUE;
1003 config_theme_window_list_icon_size = 36;
1005 config_font_activewindow = NULL;
1006 config_font_inactivewindow = NULL;
1007 config_font_menuitem = NULL;
1008 config_font_menutitle = NULL;
1010 obt_parse_register(i, "theme", parse_theme, NULL);
1012 config_desktops_num = 4;
1013 config_screen_firstdesk = 1;
1014 config_desktops_names = NULL;
1015 config_desktop_popup_time = 875;
1017 obt_parse_register(i, "desktops", parse_desktops, NULL);
1019 config_resize_redraw = TRUE;
1020 config_resize_popup_show = 1; /* nonpixel increments */
1021 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1022 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1023 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1025 obt_parse_register(i, "resize", parse_resize, NULL);
1027 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1028 config_dock_pos = OB_DIRECTION_NORTHEAST;
1029 config_dock_floating = FALSE;
1030 config_dock_nostrut = FALSE;
1033 config_dock_orient = OB_ORIENTATION_VERT;
1034 config_dock_hide = FALSE;
1035 config_dock_hide_delay = 300;
1036 config_dock_show_delay = 300;
1037 config_dock_app_move_button = 2; /* middle */
1038 config_dock_app_move_modifiers = 0;
1040 obt_parse_register(i, "dock", parse_dock, NULL);
1042 translate_key("C-g", &config_keyboard_reset_state,
1043 &config_keyboard_reset_keycode);
1045 bind_default_keyboard();
1047 obt_parse_register(i, "keyboard", parse_keyboard, NULL);
1049 config_mouse_threshold = 8;
1050 config_mouse_dclicktime = 200;
1051 config_mouse_screenedgetime = 400;
1053 bind_default_mouse();
1055 obt_parse_register(i, "mouse", parse_mouse, NULL);
1057 config_resist_win = 10;
1058 config_resist_edge = 20;
1060 obt_parse_register(i, "resistance", parse_resistance, NULL);
1062 config_window_margin = 0;
1064 obt_parse_register(i, "windowMargin", parse_window_margin, NULL);
1066 config_menu_hide_delay = 250;
1067 config_menu_middle = FALSE;
1068 config_submenu_show_delay = 0;
1069 config_menu_client_list_icons = TRUE;
1070 config_menu_manage_desktops = TRUE;
1071 config_menu_files = NULL;
1072 config_menu_user_show_icons = TRUE;
1074 obt_parse_register(i, "menu", parse_menu, NULL);
1076 obt_parse_register(i, "hooks", parse_hooks, NULL);
1078 config_per_app_settings = NULL;
1080 obt_parse_register(i, "applications", parse_per_app_settings, NULL);
1083 void config_shutdown(void)
1087 g_free(config_theme);
1089 g_free(config_title_layout);
1091 RrFontClose(config_font_activewindow);
1092 RrFontClose(config_font_inactivewindow);
1093 RrFontClose(config_font_menuitem);
1094 RrFontClose(config_font_menutitle);
1095 RrFontClose(config_font_osd);
1097 for (it = config_desktops_names; it; it = g_slist_next(it))
1099 g_slist_free(config_desktops_names);
1101 for (it = config_menu_files; it; it = g_slist_next(it))
1103 g_slist_free(config_menu_files);
1105 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1106 ObAppSettings *itd = (ObAppSettings *)it->data;
1107 if (itd->name) g_pattern_spec_free(itd->name);
1108 if (itd->role) g_pattern_spec_free(itd->role);
1109 if (itd->class) g_pattern_spec_free(itd->class);
1112 g_slist_free(config_per_app_settings);