1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
24 #include "translate.h"
29 #include "obt/paths.h"
31 gboolean config_focus_new;
32 gboolean config_focus_follow;
33 guint config_focus_delay;
34 gboolean config_focus_raise;
35 gboolean config_focus_last;
36 gboolean config_focus_under_mouse;
37 gboolean config_unfocus_leave;
39 ObPlacePolicy config_place_policy;
40 gboolean config_place_center;
41 ObPlaceMonitor config_place_monitor;
43 guint config_primary_monitor_index;
44 ObPlaceMonitor config_primary_monitor;
46 StrutPartial config_margins;
49 gboolean config_theme_keepborder;
50 guint config_theme_window_list_icon_size;
52 gchar *config_title_layout;
54 gboolean config_animate_iconify;
56 RrFont *config_font_activewindow;
57 RrFont *config_font_inactivewindow;
58 RrFont *config_font_menuitem;
59 RrFont *config_font_menutitle;
60 RrFont *config_font_activeosd;
61 RrFont *config_font_inactiveosd;
63 guint config_desktops_num;
64 GSList *config_desktops_names;
65 guint config_screen_firstdesk;
66 guint config_desktop_popup_time;
68 gboolean config_resize_redraw;
69 gint config_resize_popup_show;
70 ObResizePopupPos config_resize_popup_pos;
71 GravityPoint config_resize_popup_fixed;
73 ObStackingLayer config_dock_layer;
74 gboolean config_dock_floating;
75 gboolean config_dock_nostrut;
76 ObDirection config_dock_pos;
79 ObOrientation config_dock_orient;
80 gboolean config_dock_hide;
81 guint config_dock_hide_delay;
82 guint config_dock_show_delay;
83 guint config_dock_app_move_button;
84 guint config_dock_app_move_modifiers;
86 guint config_keyboard_reset_keycode;
87 guint config_keyboard_reset_state;
89 gint config_mouse_threshold;
90 gint config_mouse_dclicktime;
91 gint config_mouse_screenedgetime;
92 gboolean config_mouse_screenedgewarp;
94 guint config_menu_hide_delay;
95 gboolean config_menu_middle;
96 guint config_submenu_show_delay;
97 guint config_submenu_hide_delay;
98 gboolean config_menu_manage_desktops;
99 gboolean config_menu_show_icons;
101 GSList *config_menu_files;
103 gint config_resist_win;
104 gint config_resist_edge;
106 GSList *config_per_app_settings;
108 ObAppSettings* config_create_app_settings(void)
110 ObAppSettings *settings = g_slice_new0(ObAppSettings);
112 settings->decor = -1;
113 settings->shade = -1;
114 settings->monitor_type = OB_PLACE_MONITOR_ANY;
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_type, OB_PLACE_MONITOR_ANY);
140 copy_if(monitor, -1);
145 copy_if(skip_pager, -1);
146 copy_if(skip_taskbar, -1);
147 copy_if(fullscreen, -1);
148 copy_if(max_horz, -1);
149 copy_if(max_vert, -1);
151 if (src->pos_given) {
152 dst->pos_given = TRUE;
153 dst->pos_force = src->pos_force;
154 dst->position = src->position;
155 /* monitor is copied above */
158 dst->width_num = src->width_num;
159 dst->width_denom = src->width_denom;
160 dst->height_num = src->height_num;
161 dst->height_denom = src->height_denom;
164 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
166 *num = strtol(s, &s, 10);
170 } else if (*s == '/') {
175 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
177 gchar *s = obt_xml_node_string(node);
178 if (!g_ascii_strcasecmp(s, "center"))
184 if (s[0] == '-' || s[0] == '+')
186 config_parse_relative_number(ps, &c->pos, &c->denom);
193 <application name="aterm">
196 <application name="Rhythmbox">
203 .. there is a lot more settings available
208 static void parse_single_per_app_settings(xmlNodePtr app,
209 ObAppSettings *settings)
212 gboolean x_pos_given = FALSE;
214 if ((n = obt_xml_find_node(app->children, "decor")))
215 if (!obt_xml_node_contains(n, "default"))
216 settings->decor = obt_xml_node_bool(n);
218 if ((n = obt_xml_find_node(app->children, "shade")))
219 if (!obt_xml_node_contains(n, "default"))
220 settings->shade = obt_xml_node_bool(n);
222 if ((n = obt_xml_find_node(app->children, "position"))) {
223 if ((c = obt_xml_find_node(n->children, "x"))) {
224 if (!obt_xml_node_contains(c, "default")) {
225 config_parse_gravity_coord(c, &settings->position.x);
230 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
231 if (!obt_xml_node_contains(c, "default")) {
232 config_parse_gravity_coord(c, &settings->position.y);
233 settings->pos_given = TRUE;
237 /* monitor can be set without setting x or y */
238 if ((c = obt_xml_find_node(n->children, "monitor"))) {
239 if (!obt_xml_node_contains(c, "default")) {
240 gchar *s = obt_xml_node_string(c);
241 if (!g_ascii_strcasecmp(s, "mouse"))
242 settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
243 else if (!g_ascii_strcasecmp(s, "active"))
244 settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
245 else if (!g_ascii_strcasecmp(s, "primary"))
246 settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
248 settings->monitor = obt_xml_node_int(c);
253 obt_xml_attr_bool(n, "force", &settings->pos_force);
256 if ((n = obt_xml_find_node(app->children, "size"))) {
257 if ((c = obt_xml_find_node(n->children, "width"))) {
258 if (!obt_xml_node_contains(c, "default")) {
259 gchar *s = obt_xml_node_string(c);
260 config_parse_relative_number(s,
261 &settings->width_num,
262 &settings->width_denom);
263 if (settings->width_num <= 0 || settings->width_denom < 0)
264 settings->width_num = settings->width_denom = 0;
269 if ((c = obt_xml_find_node(n->children, "height"))) {
270 if (!obt_xml_node_contains(c, "default")) {
271 gchar *s = obt_xml_node_string(c);
272 config_parse_relative_number(s,
273 &settings->height_num,
274 &settings->height_denom);
275 if (settings->height_num <= 0 || settings->height_denom < 0)
276 settings->height_num = settings->height_denom = 0;
282 if ((n = obt_xml_find_node(app->children, "focus"))) {
283 if (!obt_xml_node_contains(n, "default"))
284 settings->focus = obt_xml_node_bool(n);
287 if ((n = obt_xml_find_node(app->children, "desktop"))) {
288 if (!obt_xml_node_contains(n, "default")) {
289 gchar *s = obt_xml_node_string(n);
290 if (!g_ascii_strcasecmp(s, "all"))
291 settings->desktop = DESKTOP_ALL;
293 gint i = obt_xml_node_int(n);
295 settings->desktop = i;
301 if ((n = obt_xml_find_node(app->children, "layer"))) {
302 if (!obt_xml_node_contains(n, "default")) {
303 gchar *s = obt_xml_node_string(n);
304 if (!g_ascii_strcasecmp(s, "above"))
306 else if (!g_ascii_strcasecmp(s, "below"))
307 settings->layer = -1;
314 if ((n = obt_xml_find_node(app->children, "iconic")))
315 if (!obt_xml_node_contains(n, "default"))
316 settings->iconic = obt_xml_node_bool(n);
318 if ((n = obt_xml_find_node(app->children, "skip_pager")))
319 if (!obt_xml_node_contains(n, "default"))
320 settings->skip_pager = obt_xml_node_bool(n);
322 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
323 if (!obt_xml_node_contains(n, "default"))
324 settings->skip_taskbar = obt_xml_node_bool(n);
326 if ((n = obt_xml_find_node(app->children, "fullscreen")))
327 if (!obt_xml_node_contains(n, "default"))
328 settings->fullscreen = obt_xml_node_bool(n);
330 if ((n = obt_xml_find_node(app->children, "maximized"))) {
331 if (!obt_xml_node_contains(n, "default")) {
332 gchar *s = obt_xml_node_string(n);
333 if (!g_ascii_strcasecmp(s, "horizontal")) {
334 settings->max_horz = TRUE;
335 settings->max_vert = FALSE;
336 } else if (!g_ascii_strcasecmp(s, "vertical")) {
337 settings->max_horz = FALSE;
338 settings->max_vert = TRUE;
340 settings->max_horz = settings->max_vert =
341 obt_xml_node_bool(n);
347 /* Manages settings for individual applications.
348 Some notes: monitor is the screen number in a multi monitor
349 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
350 is on, active: the active monitor, primary: the primary monitor.
351 Layer can be three values, above (Always on top), below
352 (Always on bottom) and everything else (normal behaviour).
353 Positions can be an integer value or center, which will
354 center the window in the specified axis. Position is within
355 the monitor, so <position><x>center</x></position><monitor>2</monitor>
356 will center the window on the second monitor.
358 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
360 xmlNodePtr app = obt_xml_find_node(node->children, "application");
361 for (; app; app = obt_xml_find_node(app->next, "application")) {
362 ObAppSettings *settings;
364 gboolean name_set, class_set, role_set, title_set,
365 type_set, group_name_set, group_class_set;
366 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
367 *type_str = NULL, *group_name = NULL, *group_class = NULL;
370 class_set = obt_xml_attr_string(app, "class", &class);
371 name_set = obt_xml_attr_string(app, "name", &name);
372 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
373 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
374 type_set = obt_xml_attr_string(app, "type", &type_str);
375 role_set = obt_xml_attr_string(app, "role", &role);
376 title_set = obt_xml_attr_string(app, "title", &title);
378 /* validate the type tho */
380 if (!g_ascii_strcasecmp(type_str, "normal"))
381 type = OB_CLIENT_TYPE_NORMAL;
382 else if (!g_ascii_strcasecmp(type_str, "dialog"))
383 type = OB_CLIENT_TYPE_DIALOG;
384 else if (!g_ascii_strcasecmp(type_str, "splash"))
385 type = OB_CLIENT_TYPE_SPLASH;
386 else if (!g_ascii_strcasecmp(type_str, "utility"))
387 type = OB_CLIENT_TYPE_UTILITY;
388 else if (!g_ascii_strcasecmp(type_str, "menu"))
389 type = OB_CLIENT_TYPE_MENU;
390 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
391 type = OB_CLIENT_TYPE_TOOLBAR;
392 else if (!g_ascii_strcasecmp(type_str, "dock"))
393 type = OB_CLIENT_TYPE_DOCK;
394 else if (!g_ascii_strcasecmp(type_str, "desktop"))
395 type = OB_CLIENT_TYPE_DESKTOP;
397 type_set = FALSE; /* not valid! */
400 if (!(class_set || name_set || role_set || title_set ||
401 type_set || group_class_set || group_name_set))
404 settings = config_create_app_settings();
407 settings->name = g_pattern_spec_new(name);
409 settings->class = g_pattern_spec_new(class);
411 settings->group_name = g_pattern_spec_new(group_name);
413 settings->group_class = g_pattern_spec_new(group_class);
415 settings->role = g_pattern_spec_new(role);
417 settings->title = g_pattern_spec_new(title);
419 settings->type = type;
429 parse_single_per_app_settings(app, settings);
430 config_per_app_settings = g_slist_append(config_per_app_settings,
438 <action name="ChangeDesktop">
445 static void parse_key(xmlNodePtr node, GList *keylist)
447 gchar *keystring, **keys, **key;
449 gboolean is_chroot = FALSE;
450 gboolean grab = TRUE;
452 if (!obt_xml_attr_string(node, "key", &keystring))
455 obt_xml_attr_bool(node, "chroot", &is_chroot);
456 obt_xml_attr_bool(node, "grab", &grab);
458 keys = g_strsplit(keystring, " ", 0);
459 for (key = keys; *key; ++key) {
460 keylist = g_list_append(keylist, *key);
462 if ((n = obt_xml_find_node(node->children, "keybind"))) {
464 parse_key(n, keylist);
465 n = obt_xml_find_node(n->next, "keybind");
468 else if ((n = obt_xml_find_node(node->children, "action"))) {
470 ObActionsAct *action;
472 action = actions_parse(n);
474 keyboard_bind(keylist, action, grab);
475 n = obt_xml_find_node(n->next, "action");
481 keyboard_chroot(keylist);
482 keylist = g_list_delete_link(keylist, g_list_last(keylist));
489 static void parse_keyboard(xmlNodePtr node, gpointer d)
494 keyboard_unbind_all();
496 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
497 key = obt_xml_node_string(n);
498 translate_key(key, &config_keyboard_reset_state,
499 &config_keyboard_reset_keycode);
503 if ((n = obt_xml_find_node(node->children, "keybind")))
506 n = obt_xml_find_node(n->next, "keybind");
512 <context name="Titlebar">
513 <mousebind button="Left" action="Press">
514 <action name="Raise"></action>
520 static void parse_mouse(xmlNodePtr node, gpointer d)
522 xmlNodePtr n, nbut, nact;
529 node = node->children;
531 if ((n = obt_xml_find_node(node, "dragThreshold")))
532 config_mouse_threshold = obt_xml_node_int(n);
533 if ((n = obt_xml_find_node(node, "doubleClickTime")))
534 config_mouse_dclicktime = obt_xml_node_int(n);
535 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
536 config_mouse_screenedgetime = obt_xml_node_int(n);
537 /* minimum value of 25 for this property, when it is 1 and you hit the
538 edge it basically never stops */
539 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
540 config_mouse_screenedgetime = 25;
542 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
543 config_mouse_screenedgewarp = obt_xml_node_bool(n);
545 n = obt_xml_find_node(node, "context");
550 if (!obt_xml_attr_string(n, "name", &cxstr))
553 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
554 while (frame_next_context_from_string(modcxstr, &cx)) {
556 gchar *s = strchr(modcxstr, ' ');
559 g_message(_("Invalid context \"%s\" in mouse binding"),
566 nbut = obt_xml_find_node(n->children, "mousebind");
568 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
570 if (obt_xml_attr_contains(nbut, "action", "press"))
571 mact = OB_MOUSE_ACTION_PRESS;
572 else if (obt_xml_attr_contains(nbut, "action", "release"))
573 mact = OB_MOUSE_ACTION_RELEASE;
574 else if (obt_xml_attr_contains(nbut, "action", "click"))
575 mact = OB_MOUSE_ACTION_CLICK;
576 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
577 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
578 else if (obt_xml_attr_contains(nbut, "action", "drag"))
579 mact = OB_MOUSE_ACTION_MOTION;
583 nact = obt_xml_find_node(nbut->children, "action");
585 ObActionsAct *action;
587 if ((action = actions_parse(nact)))
588 mouse_bind(buttonstr, cx, mact, action);
589 nact = obt_xml_find_node(nact->next, "action");
593 nbut = obt_xml_find_node(nbut->next, "mousebind");
599 n = obt_xml_find_node(n->next, "context");
603 static void parse_focus(xmlNodePtr node, gpointer d)
607 node = node->children;
609 if ((n = obt_xml_find_node(node, "focusNew")))
610 config_focus_new = obt_xml_node_bool(n);
611 if ((n = obt_xml_find_node(node, "followMouse")))
612 config_focus_follow = obt_xml_node_bool(n);
613 if ((n = obt_xml_find_node(node, "focusDelay")))
614 config_focus_delay = obt_xml_node_int(n);
615 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
616 config_focus_raise = obt_xml_node_bool(n);
617 if ((n = obt_xml_find_node(node, "focusLast")))
618 config_focus_last = obt_xml_node_bool(n);
619 if ((n = obt_xml_find_node(node, "underMouse")))
620 config_focus_under_mouse = obt_xml_node_bool(n);
621 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
622 config_unfocus_leave = obt_xml_node_bool(n);
625 static void parse_placement(xmlNodePtr node, gpointer d)
629 node = node->children;
631 if ((n = obt_xml_find_node(node, "policy"))) {
632 if (obt_xml_node_contains(n, "UnderMouse"))
633 config_place_policy = OB_PLACE_POLICY_MOUSE;
635 if ((n = obt_xml_find_node(node, "center"))) {
636 config_place_center = obt_xml_node_bool(n);
638 if ((n = obt_xml_find_node(node, "monitor"))) {
639 if (obt_xml_node_contains(n, "active"))
640 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
641 else if (obt_xml_node_contains(n, "mouse"))
642 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
643 else if (obt_xml_node_contains(n, "any"))
644 config_place_monitor = OB_PLACE_MONITOR_ANY;
646 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
647 config_primary_monitor_index = obt_xml_node_int(n);
648 if (!config_primary_monitor_index) {
649 if (obt_xml_node_contains(n, "mouse"))
650 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
655 static void parse_margins(xmlNodePtr node, gpointer d)
659 node = node->children;
661 if ((n = obt_xml_find_node(node, "top")))
662 config_margins.top = MAX(0, obt_xml_node_int(n));
663 if ((n = obt_xml_find_node(node, "left")))
664 config_margins.left = MAX(0, obt_xml_node_int(n));
665 if ((n = obt_xml_find_node(node, "right")))
666 config_margins.right = MAX(0, obt_xml_node_int(n));
667 if ((n = obt_xml_find_node(node, "bottom")))
668 config_margins.bottom = MAX(0, obt_xml_node_int(n));
671 static void parse_theme(xmlNodePtr node, gpointer d)
675 node = node->children;
677 if ((n = obt_xml_find_node(node, "name"))) {
680 g_free(config_theme);
681 c = obt_xml_node_string(n);
682 config_theme = obt_paths_expand_tilde(c);
685 if ((n = obt_xml_find_node(node, "titleLayout"))) {
688 g_free(config_title_layout);
689 config_title_layout = obt_xml_node_string(n);
691 /* replace duplicates with spaces */
692 for (c = config_title_layout; *c != '\0'; ++c)
693 for (d = c+1; *d != '\0'; ++d)
694 if (*c == *d) *d = ' ';
696 if ((n = obt_xml_find_node(node, "keepBorder")))
697 config_theme_keepborder = obt_xml_node_bool(n);
698 if ((n = obt_xml_find_node(node, "animateIconify")))
699 config_animate_iconify = obt_xml_node_bool(n);
700 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
701 config_theme_window_list_icon_size = obt_xml_node_int(n);
702 if (config_theme_window_list_icon_size < 16)
703 config_theme_window_list_icon_size = 16;
704 else if (config_theme_window_list_icon_size > 96)
705 config_theme_window_list_icon_size = 96;
708 n = obt_xml_find_node(node, "font");
712 gchar *name = g_strdup(RrDefaultFontFamily);
713 gint size = RrDefaultFontSize;
714 RrFontWeight weight = RrDefaultFontWeight;
715 RrFontSlant slant = RrDefaultFontSlant;
717 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
718 font = &config_font_activewindow;
719 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
720 font = &config_font_inactivewindow;
721 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
722 font = &config_font_menutitle;
723 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
724 font = &config_font_menuitem;
725 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
726 font = &config_font_activeosd;
727 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
728 font = &config_font_activeosd;
729 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
730 font = &config_font_inactiveosd;
734 if ((fnode = obt_xml_find_node(n->children, "name"))) {
736 name = obt_xml_node_string(fnode);
738 if ((fnode = obt_xml_find_node(n->children, "size"))) {
739 int s = obt_xml_node_int(fnode);
742 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
743 gchar *w = obt_xml_node_string(fnode);
744 if (!g_ascii_strcasecmp(w, "Bold"))
745 weight = RR_FONTWEIGHT_BOLD;
748 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
749 gchar *s = obt_xml_node_string(fnode);
750 if (!g_ascii_strcasecmp(s, "Italic"))
751 slant = RR_FONTSLANT_ITALIC;
752 if (!g_ascii_strcasecmp(s, "Oblique"))
753 slant = RR_FONTSLANT_OBLIQUE;
757 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
760 if ((fnode = obt_xml_find_node(n->children, "description"))) {
761 gchar *s = obt_xml_node_string(fnode);
762 RrFontDescriptionFromString(*font, s);
767 n = obt_xml_find_node(n->next, "font");
771 static void parse_desktops(xmlNodePtr node, gpointer d)
775 node = node->children;
777 if ((n = obt_xml_find_node(node, "number"))) {
778 gint d = obt_xml_node_int(n);
780 config_desktops_num = (unsigned) d;
782 if ((n = obt_xml_find_node(node, "firstdesk"))) {
783 gint d = obt_xml_node_int(n);
785 config_screen_firstdesk = (unsigned) d;
787 if ((n = obt_xml_find_node(node, "names"))) {
791 for (it = config_desktops_names; it; it = it->next)
793 g_slist_free(config_desktops_names);
794 config_desktops_names = NULL;
796 nname = obt_xml_find_node(n->children, "name");
798 config_desktops_names =
799 g_slist_append(config_desktops_names,
800 obt_xml_node_string(nname));
801 nname = obt_xml_find_node(nname->next, "name");
804 if ((n = obt_xml_find_node(node, "popupTime")))
805 config_desktop_popup_time = obt_xml_node_int(n);
808 static void parse_resize(xmlNodePtr node, gpointer d)
812 node = node->children;
814 if ((n = obt_xml_find_node(node, "drawContents")))
815 config_resize_redraw = obt_xml_node_bool(n);
816 if ((n = obt_xml_find_node(node, "popupShow"))) {
817 config_resize_popup_show = obt_xml_node_int(n);
818 if (obt_xml_node_contains(n, "Always"))
819 config_resize_popup_show = 2;
820 else if (obt_xml_node_contains(n, "Never"))
821 config_resize_popup_show = 0;
822 else if (obt_xml_node_contains(n, "Nonpixel"))
823 config_resize_popup_show = 1;
825 if ((n = obt_xml_find_node(node, "popupPosition"))) {
826 if (obt_xml_node_contains(n, "Top"))
827 config_resize_popup_pos = OB_RESIZE_POS_TOP;
828 else if (obt_xml_node_contains(n, "Center"))
829 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
830 else if (obt_xml_node_contains(n, "Fixed")) {
831 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
833 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
836 if ((n2 = obt_xml_find_node(n->children, "x")))
837 config_parse_gravity_coord(n2,
838 &config_resize_popup_fixed.x);
839 if ((n2 = obt_xml_find_node(n->children, "y")))
840 config_parse_gravity_coord(n2,
841 &config_resize_popup_fixed.y);
843 config_resize_popup_fixed.x.pos =
844 MAX(config_resize_popup_fixed.x.pos, 0);
845 config_resize_popup_fixed.y.pos =
846 MAX(config_resize_popup_fixed.y.pos, 0);
852 static void parse_dock(xmlNodePtr node, gpointer d)
856 node = node->children;
858 if ((n = obt_xml_find_node(node, "position"))) {
859 if (obt_xml_node_contains(n, "TopLeft"))
860 config_dock_floating = FALSE,
861 config_dock_pos = OB_DIRECTION_NORTHWEST;
862 else if (obt_xml_node_contains(n, "Top"))
863 config_dock_floating = FALSE,
864 config_dock_pos = OB_DIRECTION_NORTH;
865 else if (obt_xml_node_contains(n, "TopRight"))
866 config_dock_floating = FALSE,
867 config_dock_pos = OB_DIRECTION_NORTHEAST;
868 else if (obt_xml_node_contains(n, "Right"))
869 config_dock_floating = FALSE,
870 config_dock_pos = OB_DIRECTION_EAST;
871 else if (obt_xml_node_contains(n, "BottomRight"))
872 config_dock_floating = FALSE,
873 config_dock_pos = OB_DIRECTION_SOUTHEAST;
874 else if (obt_xml_node_contains(n, "Bottom"))
875 config_dock_floating = FALSE,
876 config_dock_pos = OB_DIRECTION_SOUTH;
877 else if (obt_xml_node_contains(n, "BottomLeft"))
878 config_dock_floating = FALSE,
879 config_dock_pos = OB_DIRECTION_SOUTHWEST;
880 else if (obt_xml_node_contains(n, "Left"))
881 config_dock_floating = FALSE,
882 config_dock_pos = OB_DIRECTION_WEST;
883 else if (obt_xml_node_contains(n, "Floating"))
884 config_dock_floating = TRUE;
886 if (config_dock_floating) {
887 if ((n = obt_xml_find_node(node, "floatingX")))
888 config_dock_x = obt_xml_node_int(n);
889 if ((n = obt_xml_find_node(node, "floatingY")))
890 config_dock_y = obt_xml_node_int(n);
892 if ((n = obt_xml_find_node(node, "noStrut")))
893 config_dock_nostrut = obt_xml_node_bool(n);
895 if ((n = obt_xml_find_node(node, "stacking"))) {
896 if (obt_xml_node_contains(n, "normal"))
897 config_dock_layer = OB_STACKING_LAYER_NORMAL;
898 else if (obt_xml_node_contains(n, "below"))
899 config_dock_layer = OB_STACKING_LAYER_BELOW;
900 else if (obt_xml_node_contains(n, "above"))
901 config_dock_layer = OB_STACKING_LAYER_ABOVE;
903 if ((n = obt_xml_find_node(node, "direction"))) {
904 if (obt_xml_node_contains(n, "horizontal"))
905 config_dock_orient = OB_ORIENTATION_HORZ;
906 else if (obt_xml_node_contains(n, "vertical"))
907 config_dock_orient = OB_ORIENTATION_VERT;
909 if ((n = obt_xml_find_node(node, "autoHide")))
910 config_dock_hide = obt_xml_node_bool(n);
911 if ((n = obt_xml_find_node(node, "hideDelay")))
912 config_dock_hide_delay = obt_xml_node_int(n);
913 if ((n = obt_xml_find_node(node, "showDelay")))
914 config_dock_show_delay = obt_xml_node_int(n);
915 if ((n = obt_xml_find_node(node, "moveButton"))) {
916 gchar *str = obt_xml_node_string(n);
918 if (translate_button(str, &s, &b)) {
919 config_dock_app_move_button = b;
920 config_dock_app_move_modifiers = s;
922 g_message(_("Invalid button \"%s\" specified in config file"), str);
928 static void parse_menu(xmlNodePtr node, gpointer d)
931 node = node->children;
933 if ((n = obt_xml_find_node(node, "hideDelay")))
934 config_menu_hide_delay = obt_xml_node_int(n);
935 if ((n = obt_xml_find_node(node, "middle")))
936 config_menu_middle = obt_xml_node_bool(n);
937 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
938 config_submenu_show_delay = obt_xml_node_int(n);
939 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
940 config_submenu_hide_delay = obt_xml_node_int(n);
941 if ((n = obt_xml_find_node(node, "manageDesktops")))
942 config_menu_manage_desktops = obt_xml_node_bool(n);
943 if ((n = obt_xml_find_node(node, "showIcons"))) {
944 config_menu_show_icons = obt_xml_node_bool(n);
945 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
946 if (config_menu_show_icons)
947 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
951 while ((node = obt_xml_find_node(node, "file"))) {
952 gchar *c = obt_xml_node_string(node);
953 config_menu_files = g_slist_append(config_menu_files,
954 obt_paths_expand_tilde(c));
960 static void parse_resistance(xmlNodePtr node, gpointer d)
964 node = node->children;
965 if ((n = obt_xml_find_node(node, "strength")))
966 config_resist_win = obt_xml_node_int(n);
967 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
968 config_resist_edge = obt_xml_node_int(n);
974 const gchar *actname;
977 static void bind_default_keyboard(void)
980 ObDefKeyBind binds[] = {
981 { "A-Tab", "NextWindow" },
982 { "S-A-Tab", "PreviousWindow" },
986 for (it = binds; it->key; ++it) {
987 GList *l = g_list_append(NULL, g_strdup(it->key));
988 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
995 const gchar *context;
996 const ObMouseAction mact;
997 const gchar *actname;
1000 static void bind_default_mouse(void)
1003 ObDefMouseBind binds[] = {
1004 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1005 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1006 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1007 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1008 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1009 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1010 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1011 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1012 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1013 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1014 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1015 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1016 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1017 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1018 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1019 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1020 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1021 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1022 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1023 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1024 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1025 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1026 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1027 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1028 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1029 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1030 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1031 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1032 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1033 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1034 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1035 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1036 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1037 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1038 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1039 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1040 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1041 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1042 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1043 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1044 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1045 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1046 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1047 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1048 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1049 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1050 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1051 { NULL, NULL, 0, NULL }
1054 for (it = binds; it->button; ++it)
1055 mouse_bind(it->button, frame_context_from_string(it->context),
1056 it->mact, actions_parse_string(it->actname));
1059 void config_startup(ObtXmlInst *i)
1061 config_focus_new = TRUE;
1062 config_focus_follow = FALSE;
1063 config_focus_delay = 0;
1064 config_focus_raise = FALSE;
1065 config_focus_last = TRUE;
1066 config_focus_under_mouse = FALSE;
1067 config_unfocus_leave = FALSE;
1069 obt_xml_register(i, "focus", parse_focus, NULL);
1071 config_place_policy = OB_PLACE_POLICY_SMART;
1072 config_place_center = TRUE;
1073 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1075 config_primary_monitor_index = 1;
1076 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1078 obt_xml_register(i, "placement", parse_placement, NULL);
1080 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1082 obt_xml_register(i, "margins", parse_margins, NULL);
1084 config_theme = NULL;
1086 config_animate_iconify = TRUE;
1087 config_title_layout = g_strdup("NLIMC");
1088 config_theme_keepborder = TRUE;
1089 config_theme_window_list_icon_size = 36;
1091 config_font_activewindow = NULL;
1092 config_font_inactivewindow = NULL;
1093 config_font_menuitem = NULL;
1094 config_font_menutitle = NULL;
1095 config_font_activeosd = NULL;
1096 config_font_inactiveosd = NULL;
1098 obt_xml_register(i, "theme", parse_theme, NULL);
1100 config_desktops_num = 4;
1101 config_screen_firstdesk = 1;
1102 config_desktops_names = NULL;
1103 config_desktop_popup_time = 875;
1105 obt_xml_register(i, "desktops", parse_desktops, NULL);
1107 config_resize_redraw = TRUE;
1108 config_resize_popup_show = 1; /* nonpixel increments */
1109 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1110 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1111 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1113 obt_xml_register(i, "resize", parse_resize, NULL);
1115 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1116 config_dock_pos = OB_DIRECTION_NORTHEAST;
1117 config_dock_floating = FALSE;
1118 config_dock_nostrut = FALSE;
1121 config_dock_orient = OB_ORIENTATION_VERT;
1122 config_dock_hide = FALSE;
1123 config_dock_hide_delay = 300;
1124 config_dock_show_delay = 300;
1125 config_dock_app_move_button = 2; /* middle */
1126 config_dock_app_move_modifiers = 0;
1128 obt_xml_register(i, "dock", parse_dock, NULL);
1130 translate_key("C-g", &config_keyboard_reset_state,
1131 &config_keyboard_reset_keycode);
1133 bind_default_keyboard();
1135 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1137 config_mouse_threshold = 8;
1138 config_mouse_dclicktime = 500;
1139 config_mouse_screenedgetime = 400;
1140 config_mouse_screenedgewarp = FALSE;
1142 bind_default_mouse();
1144 obt_xml_register(i, "mouse", parse_mouse, NULL);
1146 config_resist_win = 10;
1147 config_resist_edge = 20;
1149 obt_xml_register(i, "resistance", parse_resistance, NULL);
1151 config_menu_hide_delay = 250;
1152 config_menu_middle = FALSE;
1153 config_submenu_show_delay = 100;
1154 config_submenu_hide_delay = 400;
1155 config_menu_manage_desktops = TRUE;
1156 config_menu_files = NULL;
1157 config_menu_show_icons = TRUE;
1159 obt_xml_register(i, "menu", parse_menu, NULL);
1161 config_per_app_settings = NULL;
1163 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1166 void config_shutdown(void)
1170 g_free(config_theme);
1172 g_free(config_title_layout);
1174 RrFontClose(config_font_activewindow);
1175 RrFontClose(config_font_inactivewindow);
1176 RrFontClose(config_font_menuitem);
1177 RrFontClose(config_font_menutitle);
1178 RrFontClose(config_font_activeosd);
1179 RrFontClose(config_font_inactiveosd);
1181 for (it = config_desktops_names; it; it = g_slist_next(it))
1183 g_slist_free(config_desktops_names);
1185 for (it = config_menu_files; it; it = g_slist_next(it))
1187 g_slist_free(config_menu_files);
1189 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1190 ObAppSettings *itd = (ObAppSettings *)it->data;
1191 if (itd->name) g_pattern_spec_free(itd->name);
1192 if (itd->role) g_pattern_spec_free(itd->role);
1193 if (itd->title) g_pattern_spec_free(itd->title);
1194 if (itd->class) g_pattern_spec_free(itd->class);
1195 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1196 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1197 g_slice_free(ObAppSettings, it->data);
1199 g_slist_free(config_per_app_settings);