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 gchar *p = buttonstr;
590 gchar *s = strchr(p, ' ');
598 mouse_bind(p, cx, mact, action);
599 actions_act_ref(action); /* ref the action for each binding */
602 actions_act_unref(action); /* remove the extra ref */
604 nact = obt_xml_find_node(nact->next, "action");
608 nbut = obt_xml_find_node(nbut->next, "mousebind");
614 n = obt_xml_find_node(n->next, "context");
618 static void parse_focus(xmlNodePtr node, gpointer d)
622 node = node->children;
624 if ((n = obt_xml_find_node(node, "focusNew")))
625 config_focus_new = obt_xml_node_bool(n);
626 if ((n = obt_xml_find_node(node, "followMouse")))
627 config_focus_follow = obt_xml_node_bool(n);
628 if ((n = obt_xml_find_node(node, "focusDelay")))
629 config_focus_delay = obt_xml_node_int(n);
630 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
631 config_focus_raise = obt_xml_node_bool(n);
632 if ((n = obt_xml_find_node(node, "focusLast")))
633 config_focus_last = obt_xml_node_bool(n);
634 if ((n = obt_xml_find_node(node, "underMouse")))
635 config_focus_under_mouse = obt_xml_node_bool(n);
636 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
637 config_unfocus_leave = obt_xml_node_bool(n);
640 static void parse_placement(xmlNodePtr node, gpointer d)
644 node = node->children;
646 if ((n = obt_xml_find_node(node, "policy"))) {
647 if (obt_xml_node_contains(n, "UnderMouse"))
648 config_place_policy = OB_PLACE_POLICY_MOUSE;
650 if ((n = obt_xml_find_node(node, "center"))) {
651 config_place_center = obt_xml_node_bool(n);
653 if ((n = obt_xml_find_node(node, "monitor"))) {
654 if (obt_xml_node_contains(n, "active"))
655 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
656 else if (obt_xml_node_contains(n, "mouse"))
657 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
658 else if (obt_xml_node_contains(n, "any"))
659 config_place_monitor = OB_PLACE_MONITOR_ANY;
661 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
662 config_primary_monitor_index = obt_xml_node_int(n);
663 if (!config_primary_monitor_index) {
664 if (obt_xml_node_contains(n, "mouse"))
665 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
670 static void parse_margins(xmlNodePtr node, gpointer d)
674 node = node->children;
676 if ((n = obt_xml_find_node(node, "top")))
677 config_margins.top = MAX(0, obt_xml_node_int(n));
678 if ((n = obt_xml_find_node(node, "left")))
679 config_margins.left = MAX(0, obt_xml_node_int(n));
680 if ((n = obt_xml_find_node(node, "right")))
681 config_margins.right = MAX(0, obt_xml_node_int(n));
682 if ((n = obt_xml_find_node(node, "bottom")))
683 config_margins.bottom = MAX(0, obt_xml_node_int(n));
686 static void parse_theme(xmlNodePtr node, gpointer d)
690 node = node->children;
692 if ((n = obt_xml_find_node(node, "name"))) {
695 g_free(config_theme);
696 c = obt_xml_node_string(n);
697 config_theme = obt_paths_expand_tilde(c);
700 if ((n = obt_xml_find_node(node, "titleLayout"))) {
703 g_free(config_title_layout);
704 config_title_layout = obt_xml_node_string(n);
706 /* replace duplicates with spaces */
707 for (c = config_title_layout; *c != '\0'; ++c)
708 for (d = c+1; *d != '\0'; ++d)
709 if (*c == *d) *d = ' ';
711 if ((n = obt_xml_find_node(node, "keepBorder")))
712 config_theme_keepborder = obt_xml_node_bool(n);
713 if ((n = obt_xml_find_node(node, "animateIconify")))
714 config_animate_iconify = obt_xml_node_bool(n);
715 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
716 config_theme_window_list_icon_size = obt_xml_node_int(n);
717 if (config_theme_window_list_icon_size < 16)
718 config_theme_window_list_icon_size = 16;
719 else if (config_theme_window_list_icon_size > 96)
720 config_theme_window_list_icon_size = 96;
723 n = obt_xml_find_node(node, "font");
727 gchar *name = g_strdup(RrDefaultFontFamily);
728 gint size = RrDefaultFontSize;
729 RrFontWeight weight = RrDefaultFontWeight;
730 RrFontSlant slant = RrDefaultFontSlant;
732 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
733 font = &config_font_activewindow;
734 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
735 font = &config_font_inactivewindow;
736 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
737 font = &config_font_menutitle;
738 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
739 font = &config_font_menuitem;
740 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
741 font = &config_font_activeosd;
742 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
743 font = &config_font_activeosd;
744 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
745 font = &config_font_inactiveosd;
749 if ((fnode = obt_xml_find_node(n->children, "name"))) {
751 name = obt_xml_node_string(fnode);
753 if ((fnode = obt_xml_find_node(n->children, "size"))) {
754 int s = obt_xml_node_int(fnode);
757 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
758 gchar *w = obt_xml_node_string(fnode);
759 if (!g_ascii_strcasecmp(w, "Bold"))
760 weight = RR_FONTWEIGHT_BOLD;
763 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
764 gchar *s = obt_xml_node_string(fnode);
765 if (!g_ascii_strcasecmp(s, "Italic"))
766 slant = RR_FONTSLANT_ITALIC;
767 if (!g_ascii_strcasecmp(s, "Oblique"))
768 slant = RR_FONTSLANT_OBLIQUE;
772 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
775 if ((fnode = obt_xml_find_node(n->children, "description"))) {
776 gchar *s = obt_xml_node_string(fnode);
777 RrFontDescriptionFromString(*font, s);
782 n = obt_xml_find_node(n->next, "font");
786 static void parse_desktops(xmlNodePtr node, gpointer d)
790 node = node->children;
792 if ((n = obt_xml_find_node(node, "number"))) {
793 gint d = obt_xml_node_int(n);
795 config_desktops_num = (unsigned) d;
797 if ((n = obt_xml_find_node(node, "firstdesk"))) {
798 gint d = obt_xml_node_int(n);
800 config_screen_firstdesk = (unsigned) d;
802 if ((n = obt_xml_find_node(node, "names"))) {
806 for (it = config_desktops_names; it; it = it->next)
808 g_slist_free(config_desktops_names);
809 config_desktops_names = NULL;
811 nname = obt_xml_find_node(n->children, "name");
813 config_desktops_names =
814 g_slist_append(config_desktops_names,
815 obt_xml_node_string(nname));
816 nname = obt_xml_find_node(nname->next, "name");
819 if ((n = obt_xml_find_node(node, "popupTime")))
820 config_desktop_popup_time = obt_xml_node_int(n);
823 static void parse_resize(xmlNodePtr node, gpointer d)
827 node = node->children;
829 if ((n = obt_xml_find_node(node, "drawContents")))
830 config_resize_redraw = obt_xml_node_bool(n);
831 if ((n = obt_xml_find_node(node, "popupShow"))) {
832 config_resize_popup_show = obt_xml_node_int(n);
833 if (obt_xml_node_contains(n, "Always"))
834 config_resize_popup_show = 2;
835 else if (obt_xml_node_contains(n, "Never"))
836 config_resize_popup_show = 0;
837 else if (obt_xml_node_contains(n, "Nonpixel"))
838 config_resize_popup_show = 1;
840 if ((n = obt_xml_find_node(node, "popupPosition"))) {
841 if (obt_xml_node_contains(n, "Top"))
842 config_resize_popup_pos = OB_RESIZE_POS_TOP;
843 else if (obt_xml_node_contains(n, "Center"))
844 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
845 else if (obt_xml_node_contains(n, "Fixed")) {
846 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
848 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
851 if ((n2 = obt_xml_find_node(n->children, "x")))
852 config_parse_gravity_coord(n2,
853 &config_resize_popup_fixed.x);
854 if ((n2 = obt_xml_find_node(n->children, "y")))
855 config_parse_gravity_coord(n2,
856 &config_resize_popup_fixed.y);
858 config_resize_popup_fixed.x.pos =
859 MAX(config_resize_popup_fixed.x.pos, 0);
860 config_resize_popup_fixed.y.pos =
861 MAX(config_resize_popup_fixed.y.pos, 0);
867 static void parse_dock(xmlNodePtr node, gpointer d)
871 node = node->children;
873 if ((n = obt_xml_find_node(node, "position"))) {
874 if (obt_xml_node_contains(n, "TopLeft"))
875 config_dock_floating = FALSE,
876 config_dock_pos = OB_DIRECTION_NORTHWEST;
877 else if (obt_xml_node_contains(n, "Top"))
878 config_dock_floating = FALSE,
879 config_dock_pos = OB_DIRECTION_NORTH;
880 else if (obt_xml_node_contains(n, "TopRight"))
881 config_dock_floating = FALSE,
882 config_dock_pos = OB_DIRECTION_NORTHEAST;
883 else if (obt_xml_node_contains(n, "Right"))
884 config_dock_floating = FALSE,
885 config_dock_pos = OB_DIRECTION_EAST;
886 else if (obt_xml_node_contains(n, "BottomRight"))
887 config_dock_floating = FALSE,
888 config_dock_pos = OB_DIRECTION_SOUTHEAST;
889 else if (obt_xml_node_contains(n, "Bottom"))
890 config_dock_floating = FALSE,
891 config_dock_pos = OB_DIRECTION_SOUTH;
892 else if (obt_xml_node_contains(n, "BottomLeft"))
893 config_dock_floating = FALSE,
894 config_dock_pos = OB_DIRECTION_SOUTHWEST;
895 else if (obt_xml_node_contains(n, "Left"))
896 config_dock_floating = FALSE,
897 config_dock_pos = OB_DIRECTION_WEST;
898 else if (obt_xml_node_contains(n, "Floating"))
899 config_dock_floating = TRUE;
901 if (config_dock_floating) {
902 if ((n = obt_xml_find_node(node, "floatingX")))
903 config_dock_x = obt_xml_node_int(n);
904 if ((n = obt_xml_find_node(node, "floatingY")))
905 config_dock_y = obt_xml_node_int(n);
907 if ((n = obt_xml_find_node(node, "noStrut")))
908 config_dock_nostrut = obt_xml_node_bool(n);
910 if ((n = obt_xml_find_node(node, "stacking"))) {
911 if (obt_xml_node_contains(n, "normal"))
912 config_dock_layer = OB_STACKING_LAYER_NORMAL;
913 else if (obt_xml_node_contains(n, "below"))
914 config_dock_layer = OB_STACKING_LAYER_BELOW;
915 else if (obt_xml_node_contains(n, "above"))
916 config_dock_layer = OB_STACKING_LAYER_ABOVE;
918 if ((n = obt_xml_find_node(node, "direction"))) {
919 if (obt_xml_node_contains(n, "horizontal"))
920 config_dock_orient = OB_ORIENTATION_HORZ;
921 else if (obt_xml_node_contains(n, "vertical"))
922 config_dock_orient = OB_ORIENTATION_VERT;
924 if ((n = obt_xml_find_node(node, "autoHide")))
925 config_dock_hide = obt_xml_node_bool(n);
926 if ((n = obt_xml_find_node(node, "hideDelay")))
927 config_dock_hide_delay = obt_xml_node_int(n);
928 if ((n = obt_xml_find_node(node, "showDelay")))
929 config_dock_show_delay = obt_xml_node_int(n);
930 if ((n = obt_xml_find_node(node, "moveButton"))) {
931 gchar *str = obt_xml_node_string(n);
933 if (translate_button(str, &s, &b)) {
934 config_dock_app_move_button = b;
935 config_dock_app_move_modifiers = s;
937 g_message(_("Invalid button \"%s\" specified in config file"), str);
943 static void parse_menu(xmlNodePtr node, gpointer d)
946 node = node->children;
948 if ((n = obt_xml_find_node(node, "hideDelay")))
949 config_menu_hide_delay = obt_xml_node_int(n);
950 if ((n = obt_xml_find_node(node, "middle")))
951 config_menu_middle = obt_xml_node_bool(n);
952 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
953 config_submenu_show_delay = obt_xml_node_int(n);
954 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
955 config_submenu_hide_delay = obt_xml_node_int(n);
956 if ((n = obt_xml_find_node(node, "manageDesktops")))
957 config_menu_manage_desktops = obt_xml_node_bool(n);
958 if ((n = obt_xml_find_node(node, "showIcons"))) {
959 config_menu_show_icons = obt_xml_node_bool(n);
960 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
961 if (config_menu_show_icons)
962 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
966 while ((node = obt_xml_find_node(node, "file"))) {
967 gchar *c = obt_xml_node_string(node);
968 config_menu_files = g_slist_append(config_menu_files,
969 obt_paths_expand_tilde(c));
975 static void parse_resistance(xmlNodePtr node, gpointer d)
979 node = node->children;
980 if ((n = obt_xml_find_node(node, "strength")))
981 config_resist_win = obt_xml_node_int(n);
982 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
983 config_resist_edge = obt_xml_node_int(n);
989 const gchar *actname;
992 static void bind_default_keyboard(void)
995 ObDefKeyBind binds[] = {
996 { "A-Tab", "NextWindow" },
997 { "S-A-Tab", "PreviousWindow" },
1001 for (it = binds; it->key; ++it) {
1002 GList *l = g_list_append(NULL, g_strdup(it->key));
1003 keyboard_bind(l, actions_parse_string(it->actname), TRUE);
1009 const gchar *button;
1010 const gchar *context;
1011 const ObMouseAction mact;
1012 const gchar *actname;
1015 static void bind_default_mouse(void)
1018 ObDefMouseBind binds[] = {
1019 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1020 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1021 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1022 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1023 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1024 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1025 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1026 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1027 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1028 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1029 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1030 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1031 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1032 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1033 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1034 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1035 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1036 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1037 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1038 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1039 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1040 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1041 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1042 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1043 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1044 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1045 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1046 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1047 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1048 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1049 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1050 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1051 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1052 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1053 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1054 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1055 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1056 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1057 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1058 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1059 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1060 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1061 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1062 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1063 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1064 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1065 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1066 { NULL, NULL, 0, NULL }
1069 for (it = binds; it->button; ++it)
1070 mouse_bind(it->button, frame_context_from_string(it->context),
1071 it->mact, actions_parse_string(it->actname));
1074 void config_startup(ObtXmlInst *i)
1076 config_focus_new = TRUE;
1077 config_focus_follow = FALSE;
1078 config_focus_delay = 0;
1079 config_focus_raise = FALSE;
1080 config_focus_last = TRUE;
1081 config_focus_under_mouse = FALSE;
1082 config_unfocus_leave = FALSE;
1084 obt_xml_register(i, "focus", parse_focus, NULL);
1086 config_place_policy = OB_PLACE_POLICY_SMART;
1087 config_place_center = TRUE;
1088 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1090 config_primary_monitor_index = 1;
1091 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1093 obt_xml_register(i, "placement", parse_placement, NULL);
1095 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1097 obt_xml_register(i, "margins", parse_margins, NULL);
1099 config_theme = NULL;
1101 config_animate_iconify = TRUE;
1102 config_title_layout = g_strdup("NLIMC");
1103 config_theme_keepborder = TRUE;
1104 config_theme_window_list_icon_size = 36;
1106 config_font_activewindow = NULL;
1107 config_font_inactivewindow = NULL;
1108 config_font_menuitem = NULL;
1109 config_font_menutitle = NULL;
1110 config_font_activeosd = NULL;
1111 config_font_inactiveosd = NULL;
1113 obt_xml_register(i, "theme", parse_theme, NULL);
1115 config_desktops_num = 4;
1116 config_screen_firstdesk = 1;
1117 config_desktops_names = NULL;
1118 config_desktop_popup_time = 875;
1120 obt_xml_register(i, "desktops", parse_desktops, NULL);
1122 config_resize_redraw = TRUE;
1123 config_resize_popup_show = 1; /* nonpixel increments */
1124 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1125 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1126 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1128 obt_xml_register(i, "resize", parse_resize, NULL);
1130 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1131 config_dock_pos = OB_DIRECTION_NORTHEAST;
1132 config_dock_floating = FALSE;
1133 config_dock_nostrut = FALSE;
1136 config_dock_orient = OB_ORIENTATION_VERT;
1137 config_dock_hide = FALSE;
1138 config_dock_hide_delay = 300;
1139 config_dock_show_delay = 300;
1140 config_dock_app_move_button = 2; /* middle */
1141 config_dock_app_move_modifiers = 0;
1143 obt_xml_register(i, "dock", parse_dock, NULL);
1145 translate_key("C-g", &config_keyboard_reset_state,
1146 &config_keyboard_reset_keycode);
1148 bind_default_keyboard();
1150 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1152 config_mouse_threshold = 8;
1153 config_mouse_dclicktime = 500;
1154 config_mouse_screenedgetime = 400;
1155 config_mouse_screenedgewarp = FALSE;
1157 bind_default_mouse();
1159 obt_xml_register(i, "mouse", parse_mouse, NULL);
1161 config_resist_win = 10;
1162 config_resist_edge = 20;
1164 obt_xml_register(i, "resistance", parse_resistance, NULL);
1166 config_menu_hide_delay = 250;
1167 config_menu_middle = FALSE;
1168 config_submenu_show_delay = 100;
1169 config_submenu_hide_delay = 400;
1170 config_menu_manage_desktops = TRUE;
1171 config_menu_files = NULL;
1172 config_menu_show_icons = TRUE;
1174 obt_xml_register(i, "menu", parse_menu, NULL);
1176 config_per_app_settings = NULL;
1178 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1181 void config_shutdown(void)
1185 g_free(config_theme);
1187 g_free(config_title_layout);
1189 RrFontClose(config_font_activewindow);
1190 RrFontClose(config_font_inactivewindow);
1191 RrFontClose(config_font_menuitem);
1192 RrFontClose(config_font_menutitle);
1193 RrFontClose(config_font_activeosd);
1194 RrFontClose(config_font_inactiveosd);
1196 for (it = config_desktops_names; it; it = g_slist_next(it))
1198 g_slist_free(config_desktops_names);
1200 for (it = config_menu_files; it; it = g_slist_next(it))
1202 g_slist_free(config_menu_files);
1204 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1205 ObAppSettings *itd = (ObAppSettings *)it->data;
1206 if (itd->name) g_pattern_spec_free(itd->name);
1207 if (itd->role) g_pattern_spec_free(itd->role);
1208 if (itd->title) g_pattern_spec_free(itd->title);
1209 if (itd->class) g_pattern_spec_free(itd->class);
1210 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1211 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1212 g_slice_free(ObAppSettings, it->data);
1214 g_slist_free(config_per_app_settings);