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.
21 #include "config_parser.h"
25 #include "action_list.h"
26 #include "action_parser.h"
27 #include "translate.h"
32 #include "obt/paths.h"
34 gboolean config_focus_new;
35 gboolean config_focus_follow;
36 guint config_focus_delay;
37 gboolean config_focus_raise;
38 gboolean config_focus_last;
39 gboolean config_focus_under_mouse;
40 gboolean config_unfocus_leave;
42 ObPlacePolicy config_place_policy;
43 gboolean config_place_center;
44 ObPlaceMonitor config_place_monitor;
46 guint config_primary_monitor_index;
47 ObPlaceMonitor config_primary_monitor;
49 StrutPartial config_margins;
52 gboolean config_theme_keepborder;
53 guint config_theme_window_list_icon_size;
55 gchar *config_title_layout;
57 gboolean config_animate_iconify;
59 RrFont *config_font_activewindow;
60 RrFont *config_font_inactivewindow;
61 RrFont *config_font_menuitem;
62 RrFont *config_font_menutitle;
63 RrFont *config_font_activeosd;
64 RrFont *config_font_inactiveosd;
66 guint config_desktops_num;
67 GSList *config_desktops_names;
68 guint config_screen_firstdesk;
69 guint config_desktop_popup_time;
71 gboolean config_resize_redraw;
72 gint config_resize_popup_show;
73 ObResizePopupPos config_resize_popup_pos;
74 GravityPoint config_resize_popup_fixed;
76 ObStackingLayer config_dock_layer;
77 gboolean config_dock_floating;
78 gboolean config_dock_nostrut;
79 ObDirection config_dock_pos;
82 ObOrientation config_dock_orient;
83 gboolean config_dock_hide;
84 guint config_dock_hide_delay;
85 guint config_dock_show_delay;
86 ObMouseButton config_dock_app_move_button;
88 ObKeyboardKey config_keyboard_reset_key;
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 = -1;
116 settings->focus = -1;
117 settings->desktop = 0;
118 settings->layer = -2;
119 settings->iconic = -1;
120 settings->skip_pager = -1;
121 settings->skip_taskbar = -1;
122 settings->fullscreen = -1;
123 settings->max_horz = -1;
124 settings->max_vert = -1;
128 #define copy_if(setting, default) \
129 if (src->setting != default) dst->setting = src->setting
130 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
133 g_assert(src != NULL);
134 g_assert(dst != NULL);
136 copy_if(type, (ObClientType)-1);
139 copy_if(monitor, -1);
144 copy_if(skip_pager, -1);
145 copy_if(skip_taskbar, -1);
146 copy_if(fullscreen, -1);
147 copy_if(max_horz, -1);
148 copy_if(max_vert, -1);
150 if (src->pos_given) {
151 dst->pos_given = TRUE;
152 dst->pos_force = src->pos_force;
153 dst->position = src->position;
154 /* monitor is copied above */
160 <application name="aterm">
163 <application name="Rhythmbox">
170 .. there is a lot more settings available
175 /* Manages settings for individual applications.
176 Some notes: monitor is the screen number in a multi monitor
177 (Xinerama) setup (starting from 0) or mouse, meaning the
178 monitor the pointer is on. Default: mouse.
179 Layer can be three values, above (Always on top), below
180 (Always on bottom) and everything else (normal behaviour).
181 Positions can be an integer value or center, which will
182 center the window in the specified axis. Position is within
183 the monitor, so <position><x>center</x></position><monitor>2</monitor>
184 will center the window on the second monitor.
186 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
188 xmlNodePtr app = obt_xml_find_sibling(node->children, "application");
189 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
191 gboolean name_set, class_set, type_set, role_set, title_set;
193 gboolean x_pos_given;
198 class_set = obt_xml_attr_string(app, "class", &class);
199 name_set = obt_xml_attr_string(app, "name", &name);
200 type_set = obt_xml_attr_string(app, "type", &type_str);
201 role_set = obt_xml_attr_string(app, "role", &role);
202 title_set = obt_xml_attr_string(app, "title", &title);
204 /* validate the type tho */
206 if (!g_ascii_strcasecmp(type_str, "normal"))
207 type = OB_CLIENT_TYPE_NORMAL;
208 else if (!g_ascii_strcasecmp(type_str, "dialog"))
209 type = OB_CLIENT_TYPE_DIALOG;
210 else if (!g_ascii_strcasecmp(type_str, "splash"))
211 type = OB_CLIENT_TYPE_SPLASH;
212 else if (!g_ascii_strcasecmp(type_str, "utility"))
213 type = OB_CLIENT_TYPE_UTILITY;
214 else if (!g_ascii_strcasecmp(type_str, "menu"))
215 type = OB_CLIENT_TYPE_MENU;
216 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
217 type = OB_CLIENT_TYPE_TOOLBAR;
218 else if (!g_ascii_strcasecmp(type_str, "dock"))
219 type = OB_CLIENT_TYPE_DOCK;
220 else if (!g_ascii_strcasecmp(type_str, "desktop"))
221 type = OB_CLIENT_TYPE_DESKTOP;
223 type_set = FALSE; /* not valid! */
226 if (class_set || name_set || role_set || title_set || type_set) {
228 ObAppSettings *settings = config_create_app_settings();
231 settings->name = g_pattern_spec_new(name);
234 settings->class = g_pattern_spec_new(class);
237 settings->role = g_pattern_spec_new(role);
240 settings->title = g_pattern_spec_new(title);
243 settings->type = type;
245 if ((n = obt_xml_find_sibling(app->children, "decor")))
246 if (!obt_xml_node_contains(n, "default"))
247 settings->decor = obt_xml_node_bool(n);
249 if ((n = obt_xml_find_sibling(app->children, "shade")))
250 if (!obt_xml_node_contains(n, "default"))
251 settings->shade = obt_xml_node_bool(n);
253 if ((n = obt_xml_find_sibling(app->children, "position"))) {
254 if ((c = obt_xml_find_sibling(n->children, "x")))
255 if (!obt_xml_node_contains(c, "default")) {
256 ObConfigValue *v = config_value_new_string(
257 obt_xml_node_string(node));
258 config_value_gravity_coord(v, &settings->position.x);
259 config_value_unref(v);
263 if (x_pos_given && (c = obt_xml_find_sibling(n->children, "y")))
264 if (!obt_xml_node_contains(c, "default")) {
265 ObConfigValue *v = config_value_new_string(
266 obt_xml_node_string(node));
267 config_value_gravity_coord(v, &settings->position.y);
268 config_value_unref(v);
269 settings->pos_given = TRUE;
272 if (settings->pos_given &&
273 (c = obt_xml_find_sibling(n->children, "monitor")))
274 if (!obt_xml_node_contains(c, "default")) {
275 gchar *s = obt_xml_node_string(c);
276 if (!g_ascii_strcasecmp(s, "mouse"))
277 settings->monitor = 0;
279 settings->monitor = obt_xml_node_int(c);
283 obt_xml_attr_bool(n, "force", &settings->pos_force);
286 if ((n = obt_xml_find_sibling(app->children, "focus")))
287 if (!obt_xml_node_contains(n, "default"))
288 settings->focus = obt_xml_node_bool(n);
290 if ((n = obt_xml_find_sibling(app->children, "desktop"))) {
291 if (!obt_xml_node_contains(n, "default")) {
292 gchar *s = obt_xml_node_string(n);
293 if (!g_ascii_strcasecmp(s, "all"))
294 settings->desktop = DESKTOP_ALL;
296 gint i = obt_xml_node_int(n);
298 settings->desktop = i;
304 if ((n = obt_xml_find_sibling(app->children, "layer")))
305 if (!obt_xml_node_contains(n, "default")) {
306 gchar *s = obt_xml_node_string(n);
307 if (!g_ascii_strcasecmp(s, "above"))
309 else if (!g_ascii_strcasecmp(s, "below"))
310 settings->layer = -1;
316 if ((n = obt_xml_find_sibling(app->children, "iconic")))
317 if (!obt_xml_node_contains(n, "default"))
318 settings->iconic = obt_xml_node_bool(n);
320 if ((n = obt_xml_find_sibling(app->children, "skip_pager")))
321 if (!obt_xml_node_contains(n, "default"))
322 settings->skip_pager = obt_xml_node_bool(n);
324 if ((n = obt_xml_find_sibling(app->children, "skip_taskbar")))
325 if (!obt_xml_node_contains(n, "default"))
326 settings->skip_taskbar = obt_xml_node_bool(n);
328 if ((n = obt_xml_find_sibling(app->children, "fullscreen")))
329 if (!obt_xml_node_contains(n, "default"))
330 settings->fullscreen = obt_xml_node_bool(n);
332 if ((n = obt_xml_find_sibling(app->children, "maximized")))
333 if (!obt_xml_node_contains(n, "default")) {
334 gchar *s = obt_xml_node_string(n);
335 if (!g_ascii_strcasecmp(s, "horizontal")) {
336 settings->max_horz = TRUE;
337 settings->max_vert = FALSE;
338 } else if (!g_ascii_strcasecmp(s, "vertical")) {
339 settings->max_horz = FALSE;
340 settings->max_vert = TRUE;
342 settings->max_horz = settings->max_vert =
343 obt_xml_node_bool(n);
347 config_per_app_settings = g_slist_append(config_per_app_settings,
348 (gpointer) settings);
354 name = class = role = title = type_str = NULL;
357 app = obt_xml_find_sibling(app->next, "application");
364 <action name="ChangeDesktop">
371 static void parse_key(xmlNodePtr node, GList *keylist)
373 gchar *keystring, **keys, **key;
375 gboolean is_chroot = FALSE;
377 if (!obt_xml_attr_string(node, "key", &keystring))
380 obt_xml_attr_bool(node, "chroot", &is_chroot);
382 keys = g_strsplit(keystring, " ", 0);
383 for (key = keys; *key; ++key) {
384 keylist = g_list_append(keylist, *key);
386 if ((n = obt_xml_find_sibling(node->children, "keybind"))) {
388 parse_key(n, keylist);
389 n = obt_xml_find_sibling(n->next, "keybind");
392 else if ((n = obt_xml_find_sibling(node->children, "action"))) {
395 ObActionList *actions;
398 c = xmlNodeGetContent(node);
399 p = action_parser_new();
400 actions = action_parser_read_string(p, (gchar*)c);
402 action_parser_unref(p);
405 keyboard_bind(keylist, actions);
407 action_list_unref(actions);
408 n = obt_xml_find_sibling(n->next, "action");
414 keyboard_chroot(keylist);
415 keylist = g_list_delete_link(keylist, g_list_last(keylist));
422 static void parse_keyboard(xmlNodePtr node, gpointer d)
427 keyboard_unbind_all();
429 if ((n = obt_xml_find_sibling(node->children, "chainQuitKey"))) {
430 key = obt_xml_node_string(n);
431 translate_key(key, &config_keyboard_reset_key.modifiers,
432 &config_keyboard_reset_key.keycode);
436 if ((n = obt_xml_find_sibling(node->children, "keybind")))
439 n = obt_xml_find_sibling(n->next, "keybind");
445 <context name="Titlebar">
446 <mousebind button="Left" action="Press">
447 <action name="Raise"></action>
453 static void parse_mouse(xmlNodePtr node, gpointer d)
455 xmlNodePtr n, nbut, nact;
462 node = node->children;
464 if ((n = obt_xml_find_sibling(node, "dragThreshold")))
465 config_mouse_threshold = obt_xml_node_int(n);
466 if ((n = obt_xml_find_sibling(node, "doubleClickTime")))
467 config_mouse_dclicktime = obt_xml_node_int(n);
468 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpTime"))) {
469 config_mouse_screenedgetime = obt_xml_node_int(n);
470 /* minimum value of 25 for this property, when it is 1 and you hit the
471 edge it basically never stops */
472 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
473 config_mouse_screenedgetime = 25;
475 if ((n = obt_xml_find_sibling(node, "screenEdgeWarpMouse")))
476 config_mouse_screenedgewarp = obt_xml_node_bool(n);
478 n = obt_xml_find_sibling(node, "context");
483 if (!obt_xml_attr_string(n, "name", &cxstr))
486 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
487 while (frame_next_context_from_string(modcxstr, &cx)) {
489 gchar *s = strchr(modcxstr, ' ');
492 g_message(_("Invalid context \"%s\" in mouse binding"),
499 nbut = obt_xml_find_sibling(n->children, "mousebind");
501 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
503 if (obt_xml_attr_contains(nbut, "action", "press"))
504 mact = OB_MOUSE_ACTION_PRESS;
505 else if (obt_xml_attr_contains(nbut, "action", "release"))
506 mact = OB_MOUSE_ACTION_RELEASE;
507 else if (obt_xml_attr_contains(nbut, "action", "click"))
508 mact = OB_MOUSE_ACTION_CLICK;
509 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
510 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
511 else if (obt_xml_attr_contains(nbut, "action", "drag"))
512 mact = OB_MOUSE_ACTION_MOTION;
516 nact = obt_xml_find_sibling(nbut->children, "action");
518 ObActionList *actions;
522 c = xmlNodeGetContent(nact);
523 p = action_parser_new();
524 if ((actions = action_parser_read_string(p, (gchar*)c)))
525 mouse_bind(buttonstr, cx, mact, actions);
526 nact = obt_xml_find_sibling(nact->next, "action");
527 action_list_unref(actions);
529 action_parser_unref(p);
533 nbut = obt_xml_find_sibling(nbut->next, "mousebind");
539 n = obt_xml_find_sibling(n->next, "context");
543 static void parse_margins(xmlNodePtr node, gpointer d)
547 node = node->children;
549 if ((n = obt_xml_find_sibling(node, "top")))
550 config_margins.top = MAX(0, obt_xml_node_int(n));
551 if ((n = obt_xml_find_sibling(node, "left")))
552 config_margins.left = MAX(0, obt_xml_node_int(n));
553 if ((n = obt_xml_find_sibling(node, "right")))
554 config_margins.right = MAX(0, obt_xml_node_int(n));
555 if ((n = obt_xml_find_sibling(node, "bottom")))
556 config_margins.bottom = MAX(0, obt_xml_node_int(n));
559 static void parse_theme(xmlNodePtr node, gpointer d)
563 node = node->children;
565 if ((n = obt_xml_find_sibling(node, "name"))) {
568 g_free(config_theme);
569 c = obt_xml_node_string(n);
570 config_theme = obt_paths_expand_tilde(c);
573 if ((n = obt_xml_find_sibling(node, "titleLayout"))) {
576 g_free(config_title_layout);
577 config_title_layout = obt_xml_node_string(n);
579 /* replace duplicates with spaces */
580 for (c = config_title_layout; *c != '\0'; ++c)
581 for (d = c+1; *d != '\0'; ++d)
582 if (*c == *d) *d = ' ';
584 if ((n = obt_xml_find_sibling(node, "keepBorder")))
585 config_theme_keepborder = obt_xml_node_bool(n);
586 if ((n = obt_xml_find_sibling(node, "animateIconify")))
587 config_animate_iconify = obt_xml_node_bool(n);
588 if ((n = obt_xml_find_sibling(node, "windowListIconSize"))) {
589 config_theme_window_list_icon_size = obt_xml_node_int(n);
590 if (config_theme_window_list_icon_size < 16)
591 config_theme_window_list_icon_size = 16;
592 else if (config_theme_window_list_icon_size > 96)
593 config_theme_window_list_icon_size = 96;
596 n = obt_xml_find_sibling(node, "font");
600 gchar *name = g_strdup(RrDefaultFontFamily);
601 gint size = RrDefaultFontSize;
602 RrFontWeight weight = RrDefaultFontWeight;
603 RrFontSlant slant = RrDefaultFontSlant;
605 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
606 font = &config_font_activewindow;
607 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
608 font = &config_font_inactivewindow;
609 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
610 font = &config_font_menutitle;
611 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
612 font = &config_font_menuitem;
613 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
614 font = &config_font_activeosd;
615 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
616 font = &config_font_activeosd;
617 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
618 font = &config_font_inactiveosd;
622 if ((fnode = obt_xml_find_sibling(n->children, "name"))) {
624 name = obt_xml_node_string(fnode);
626 if ((fnode = obt_xml_find_sibling(n->children, "size"))) {
627 int s = obt_xml_node_int(fnode);
630 if ((fnode = obt_xml_find_sibling(n->children, "weight"))) {
631 gchar *w = obt_xml_node_string(fnode);
632 if (!g_ascii_strcasecmp(w, "Bold"))
633 weight = RR_FONTWEIGHT_BOLD;
636 if ((fnode = obt_xml_find_sibling(n->children, "slant"))) {
637 gchar *s = obt_xml_node_string(fnode);
638 if (!g_ascii_strcasecmp(s, "Italic"))
639 slant = RR_FONTSLANT_ITALIC;
640 if (!g_ascii_strcasecmp(s, "Oblique"))
641 slant = RR_FONTSLANT_OBLIQUE;
645 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
648 n = obt_xml_find_sibling(n->next, "font");
652 static void parse_desktops(xmlNodePtr node, gpointer d)
656 node = node->children;
658 if ((n = obt_xml_find_sibling(node, "number"))) {
659 gint d = obt_xml_node_int(n);
661 config_desktops_num = (unsigned) d;
663 if ((n = obt_xml_find_sibling(node, "firstdesk"))) {
664 gint d = obt_xml_node_int(n);
666 config_screen_firstdesk = (unsigned) d;
668 if ((n = obt_xml_find_sibling(node, "names"))) {
672 for (it = config_desktops_names; it; it = it->next)
674 g_slist_free(config_desktops_names);
675 config_desktops_names = NULL;
677 nname = obt_xml_find_sibling(n->children, "name");
679 config_desktops_names =
680 g_slist_append(config_desktops_names,
681 obt_xml_node_string(nname));
682 nname = obt_xml_find_sibling(nname->next, "name");
685 if ((n = obt_xml_find_sibling(node, "popupTime")))
686 config_desktop_popup_time = obt_xml_node_int(n);
689 static void parse_resize(xmlNodePtr node, gpointer d)
693 node = node->children;
695 if ((n = obt_xml_find_sibling(node, "drawContents")))
696 config_resize_redraw = obt_xml_node_bool(n);
697 if ((n = obt_xml_find_sibling(node, "popupShow"))) {
698 config_resize_popup_show = obt_xml_node_int(n);
699 if (obt_xml_node_contains(n, "Always"))
700 config_resize_popup_show = 2;
701 else if (obt_xml_node_contains(n, "Never"))
702 config_resize_popup_show = 0;
703 else if (obt_xml_node_contains(n, "Nonpixel"))
704 config_resize_popup_show = 1;
706 if ((n = obt_xml_find_sibling(node, "popupPosition"))) {
707 if (obt_xml_node_contains(n, "Top"))
708 config_resize_popup_pos = OB_RESIZE_POS_TOP;
709 else if (obt_xml_node_contains(n, "Center"))
710 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
711 else if (obt_xml_node_contains(n, "Fixed")) {
712 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
714 if ((n = obt_xml_find_sibling(node, "popupFixedPosition"))) {
717 if ((n2 = obt_xml_find_sibling(n->children, "x"))) {
718 ObConfigValue *v = config_value_new_string(
719 obt_xml_node_string(n2));
720 config_value_gravity_coord(v,
721 &config_resize_popup_fixed.x);
722 config_value_unref(v);
724 if ((n2 = obt_xml_find_sibling(n->children, "y"))) {
725 ObConfigValue *v = config_value_new_string(
726 obt_xml_node_string(n2));
727 config_value_gravity_coord(v,
728 &config_resize_popup_fixed.y);
729 config_value_unref(v);
732 config_resize_popup_fixed.x.pos =
733 MAX(config_resize_popup_fixed.x.pos, 0);
734 config_resize_popup_fixed.y.pos =
735 MAX(config_resize_popup_fixed.y.pos, 0);
741 static void parse_dock(xmlNodePtr node, gpointer d)
745 node = node->children;
747 if ((n = obt_xml_find_sibling(node, "position"))) {
748 if (obt_xml_node_contains(n, "TopLeft"))
749 config_dock_floating = FALSE,
750 config_dock_pos = OB_DIRECTION_NORTHWEST;
751 else if (obt_xml_node_contains(n, "Top"))
752 config_dock_floating = FALSE,
753 config_dock_pos = OB_DIRECTION_NORTH;
754 else if (obt_xml_node_contains(n, "TopRight"))
755 config_dock_floating = FALSE,
756 config_dock_pos = OB_DIRECTION_NORTHEAST;
757 else if (obt_xml_node_contains(n, "Right"))
758 config_dock_floating = FALSE,
759 config_dock_pos = OB_DIRECTION_EAST;
760 else if (obt_xml_node_contains(n, "BottomRight"))
761 config_dock_floating = FALSE,
762 config_dock_pos = OB_DIRECTION_SOUTHEAST;
763 else if (obt_xml_node_contains(n, "Bottom"))
764 config_dock_floating = FALSE,
765 config_dock_pos = OB_DIRECTION_SOUTH;
766 else if (obt_xml_node_contains(n, "BottomLeft"))
767 config_dock_floating = FALSE,
768 config_dock_pos = OB_DIRECTION_SOUTHWEST;
769 else if (obt_xml_node_contains(n, "Left"))
770 config_dock_floating = FALSE,
771 config_dock_pos = OB_DIRECTION_WEST;
772 else if (obt_xml_node_contains(n, "Floating"))
773 config_dock_floating = TRUE;
775 if (config_dock_floating) {
776 if ((n = obt_xml_find_sibling(node, "floatingX")))
777 config_dock_x = obt_xml_node_int(n);
778 if ((n = obt_xml_find_sibling(node, "floatingY")))
779 config_dock_y = obt_xml_node_int(n);
781 if ((n = obt_xml_find_sibling(node, "noStrut")))
782 config_dock_nostrut = obt_xml_node_bool(n);
784 if ((n = obt_xml_find_sibling(node, "stacking"))) {
785 if (obt_xml_node_contains(n, "normal"))
786 config_dock_layer = OB_STACKING_LAYER_NORMAL;
787 else if (obt_xml_node_contains(n, "below"))
788 config_dock_layer = OB_STACKING_LAYER_BELOW;
789 else if (obt_xml_node_contains(n, "above"))
790 config_dock_layer = OB_STACKING_LAYER_ABOVE;
792 if ((n = obt_xml_find_sibling(node, "direction"))) {
793 if (obt_xml_node_contains(n, "horizontal"))
794 config_dock_orient = OB_ORIENTATION_HORZ;
795 else if (obt_xml_node_contains(n, "vertical"))
796 config_dock_orient = OB_ORIENTATION_VERT;
798 if ((n = obt_xml_find_sibling(node, "autoHide")))
799 config_dock_hide = obt_xml_node_bool(n);
800 if ((n = obt_xml_find_sibling(node, "hideDelay")))
801 config_dock_hide_delay = obt_xml_node_int(n);
802 if ((n = obt_xml_find_sibling(node, "showDelay")))
803 config_dock_show_delay = obt_xml_node_int(n);
804 if ((n = obt_xml_find_sibling(node, "moveButton"))) {
805 gchar *str = obt_xml_node_string(n);
807 if (translate_button(str, &s, &b)) {
808 config_dock_app_move_button.button = b;
809 config_dock_app_move_button.modifiers = s;
811 g_message(_("Invalid button \"%s\" specified in config file"), str);
817 static void parse_menu(xmlNodePtr node, gpointer d)
820 node = node->children;
822 if ((n = obt_xml_find_sibling(node, "hideDelay")))
823 config_menu_hide_delay = obt_xml_node_int(n);
824 if ((n = obt_xml_find_sibling(node, "middle")))
825 config_menu_middle = obt_xml_node_bool(n);
826 if ((n = obt_xml_find_sibling(node, "submenuShowDelay")))
827 config_submenu_show_delay = obt_xml_node_int(n);
828 if ((n = obt_xml_find_sibling(node, "submenuHideDelay")))
829 config_submenu_hide_delay = obt_xml_node_int(n);
830 if ((n = obt_xml_find_sibling(node, "manageDesktops")))
831 config_menu_manage_desktops = obt_xml_node_bool(n);
832 if ((n = obt_xml_find_sibling(node, "showIcons"))) {
833 config_menu_show_icons = obt_xml_node_bool(n);
835 if (config_menu_show_icons)
836 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
840 while ((node = obt_xml_find_sibling(node, "file"))) {
841 gchar *c = obt_xml_node_string(node);
842 config_menu_files = g_slist_append(config_menu_files,
843 obt_paths_expand_tilde(c));
849 static void parse_resistance(xmlNodePtr node, gpointer d)
853 node = node->children;
854 if ((n = obt_xml_find_sibling(node, "strength")))
855 config_resist_win = obt_xml_node_int(n);
856 if ((n = obt_xml_find_sibling(node, "screen_edge_strength")))
857 config_resist_edge = obt_xml_node_int(n);
863 const gchar *actiontext;
866 static void bind_default_keyboard(void)
869 ObDefKeyBind binds[] = {
871 "Execute startupnotify:yes name:Konqueror \\\n"
872 " command:(kfmclient openProfile filemanagement)" },
873 { "A-Tab", "NextWindow" },
874 { "S-A-Tab", "PreviousWindow" },
880 p = action_parser_new();
881 for (it = binds; it->key; ++it) {
882 GList *l = g_list_append(NULL, g_strdup(it->key));
883 ObActionList *actions = action_parser_read_string(p, it->actiontext);
884 keyboard_bind(l, actions);
885 action_list_unref(actions);
887 action_parser_unref(p);
893 const gchar *context;
894 const ObMouseAction mact;
895 const gchar *actname;
898 static void bind_default_mouse(void)
901 ObDefMouseBind binds[] = {
902 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
903 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
904 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
905 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
906 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
907 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
908 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
909 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
910 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
911 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
912 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
913 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
914 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
915 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
916 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
917 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
918 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
919 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
920 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
921 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
922 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
923 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
924 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
925 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
926 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
927 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
928 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
929 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
930 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
931 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
932 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
933 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
934 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Maximize" },
935 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
936 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Omnipresent" },
937 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Shade" },
938 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
939 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
940 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
941 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
942 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
943 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
944 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
945 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
946 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
947 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
948 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
949 { NULL, NULL, 0, NULL }
952 ObActionList *actions;
954 p = action_parser_new();
955 for (it = binds; it->button; ++it) {
956 actions = action_parser_read_string(p, it->actname);
957 mouse_bind(it->button, frame_context_from_string(it->context),
959 action_list_unref(actions);
961 action_parser_unref(p);
964 #define BOOL config_parser_bool
965 #define INT config_parser_int
966 #define STRING config_parser_string
967 #define ENUM config_parser_enum
969 void config_startup(ObConfigParser *p, ObtXmlInst *i)
971 BOOL(p, "focus/focusNew", "yes", &config_focus_new);
972 BOOL(p, "focus/followMouse", "no", &config_focus_follow);
973 INT(p, "focus/focusDelay", "0", &config_focus_delay);
974 BOOL(p, "focus/raiseOnFocus", "no", &config_focus_raise);
975 BOOL(p, "focus/focusLast", "yes", &config_focus_last);
976 BOOL(p, "focus/underMouse", "no", &config_focus_under_mouse);
977 BOOL(p, "focus/unfocusOnLeave", "no", &config_unfocus_leave);
980 static ObConfigValueEnum policies[] = {
981 {"smart", OB_PLACE_POLICY_SMART},
982 {"undermouse", OB_PLACE_POLICY_MOUSE},
984 ENUM(p, "placement/policy", "smart", &config_place_policy, policies);
986 BOOL(p, "placement/center", "true", &config_place_center);
988 static ObConfigValueEnum monitors[] = {
989 {"any", OB_PLACE_MONITOR_ANY},
990 {"active", OB_PLACE_MONITOR_ACTIVE},
991 {"mouse", OB_PLACE_MONITOR_MOUSE},
992 {"primary", OB_PLACE_MONITOR_PRIMARY},
994 ENUM(p, "placement/monitor", "primary", &config_place_monitor,
997 INT(p, "placement/primaryMonitor", "1",
998 &config_primary_monitor_index);
1000 static ObConfigValueEnum primaries[] = {
1001 {"active", OB_PLACE_MONITOR_ACTIVE},
1002 {"mouse", OB_PLACE_MONITOR_MOUSE},
1004 ENUM(p, "placement/primaryMonitorType", "fixed",
1005 &config_primary_monitor, primaries);
1008 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1010 obt_xml_register(i, "margins", parse_margins, NULL);
1012 config_theme = NULL;
1014 config_animate_iconify = TRUE;
1015 config_title_layout = g_strdup("NLIMC");
1016 config_theme_keepborder = TRUE;
1017 config_theme_window_list_icon_size = 36;
1019 config_font_activewindow = NULL;
1020 config_font_inactivewindow = NULL;
1021 config_font_menuitem = NULL;
1022 config_font_menutitle = NULL;
1023 config_font_activeosd = NULL;
1024 config_font_inactiveosd = NULL;
1026 obt_xml_register(i, "theme", parse_theme, NULL);
1028 config_desktops_num = 4;
1029 config_screen_firstdesk = 1;
1030 config_desktops_names = NULL;
1031 config_desktop_popup_time = 875;
1033 obt_xml_register(i, "desktops", parse_desktops, NULL);
1035 config_resize_redraw = TRUE;
1036 config_resize_popup_show = 1; /* nonpixel increments */
1037 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1038 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1039 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1041 obt_xml_register(i, "resize", parse_resize, NULL);
1043 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1044 config_dock_pos = OB_DIRECTION_NORTHEAST;
1045 config_dock_floating = FALSE;
1046 config_dock_nostrut = FALSE;
1049 config_dock_orient = OB_ORIENTATION_VERT;
1050 config_dock_hide = FALSE;
1051 config_dock_hide_delay = 300;
1052 config_dock_show_delay = 300;
1053 config_dock_app_move_button.button = 2; /* middle */
1054 config_dock_app_move_button.modifiers = 0;
1056 obt_xml_register(i, "dock", parse_dock, NULL);
1058 translate_key("C-g", &config_keyboard_reset_key.modifiers,
1059 &config_keyboard_reset_key.keycode);
1061 bind_default_keyboard();
1063 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1065 config_mouse_threshold = 8;
1066 config_mouse_dclicktime = 200;
1067 config_mouse_screenedgetime = 400;
1068 config_mouse_screenedgewarp = FALSE;
1070 bind_default_mouse();
1072 obt_xml_register(i, "mouse", parse_mouse, NULL);
1074 config_resist_win = 10;
1075 config_resist_edge = 20;
1077 obt_xml_register(i, "resistance", parse_resistance, NULL);
1079 config_menu_hide_delay = 250;
1080 config_menu_middle = FALSE;
1081 config_submenu_show_delay = 100;
1082 config_submenu_hide_delay = 400;
1083 config_menu_manage_desktops = TRUE;
1084 config_menu_files = NULL;
1085 config_menu_show_icons = TRUE;
1087 obt_xml_register(i, "menu", parse_menu, NULL);
1089 config_per_app_settings = NULL;
1091 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1094 void config_shutdown(void)
1098 g_free(config_theme);
1100 g_free(config_title_layout);
1102 RrFontClose(config_font_activewindow);
1103 RrFontClose(config_font_inactivewindow);
1104 RrFontClose(config_font_menuitem);
1105 RrFontClose(config_font_menutitle);
1106 RrFontClose(config_font_activeosd);
1107 RrFontClose(config_font_inactiveosd);
1109 for (it = config_desktops_names; it; it = g_slist_next(it))
1111 g_slist_free(config_desktops_names);
1113 for (it = config_menu_files; it; it = g_slist_next(it))
1115 g_slist_free(config_menu_files);
1117 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1118 ObAppSettings *itd = (ObAppSettings *)it->data;
1119 if (itd->name) g_pattern_spec_free(itd->name);
1120 if (itd->role) g_pattern_spec_free(itd->role);
1121 if (itd->title) g_pattern_spec_free(itd->title);
1122 if (itd->class) g_pattern_spec_free(itd->class);
1123 g_slice_free(ObAppSettings, it->data);
1125 g_slist_free(config_per_app_settings);