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;
67 gint config_emulate_xinerama;
69 gboolean config_resize_redraw;
70 gint config_resize_popup_show;
71 ObResizePopupPos config_resize_popup_pos;
72 GravityPoint config_resize_popup_fixed;
74 ObStackingLayer config_dock_layer;
75 gboolean config_dock_floating;
76 gboolean config_dock_nostrut;
77 ObDirection config_dock_pos;
80 ObOrientation config_dock_orient;
81 gboolean config_dock_hide;
82 guint config_dock_hide_delay;
83 guint config_dock_show_delay;
84 guint config_dock_app_move_button;
85 guint config_dock_app_move_modifiers;
87 guint config_keyboard_reset_keycode;
88 guint config_keyboard_reset_state;
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_type = OB_PLACE_MONITOR_ANY;
116 settings->monitor = -1;
117 settings->focus = -1;
118 settings->desktop = 0;
119 settings->layer = -2;
120 settings->iconic = -1;
121 settings->skip_pager = -1;
122 settings->skip_taskbar = -1;
123 settings->fullscreen = -1;
124 settings->max_horz = -1;
125 settings->max_vert = -1;
129 #define copy_if(setting, default) \
130 if (src->setting != default) dst->setting = src->setting
131 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
134 g_assert(src != NULL);
135 g_assert(dst != NULL);
137 copy_if(type, (ObClientType)-1);
140 copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
141 copy_if(monitor, -1);
146 copy_if(skip_pager, -1);
147 copy_if(skip_taskbar, -1);
148 copy_if(fullscreen, -1);
149 copy_if(max_horz, -1);
150 copy_if(max_vert, -1);
152 if (src->pos_given) {
153 dst->pos_given = TRUE;
154 dst->pos_force = src->pos_force;
155 dst->position = src->position;
156 /* monitor is copied above */
159 dst->width_num = src->width_num;
160 dst->width_denom = src->width_denom;
161 dst->height_num = src->height_num;
162 dst->height_denom = src->height_denom;
165 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
167 *num = strtol(s, &s, 10);
171 } else if (*s == '/') {
176 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
178 gchar *s = obt_xml_node_string(node);
179 if (!g_ascii_strcasecmp(s, "center"))
185 if (s[0] == '-' || s[0] == '+')
187 config_parse_relative_number(ps, &c->pos, &c->denom);
194 <application name="aterm">
197 <application name="Rhythmbox">
204 .. there is a lot more settings available
209 static void parse_single_per_app_settings(xmlNodePtr app,
210 ObAppSettings *settings)
213 gboolean x_pos_given = FALSE;
215 if ((n = obt_xml_find_node(app->children, "decor")))
216 if (!obt_xml_node_contains(n, "default"))
217 settings->decor = obt_xml_node_bool(n);
219 if ((n = obt_xml_find_node(app->children, "shade")))
220 if (!obt_xml_node_contains(n, "default"))
221 settings->shade = obt_xml_node_bool(n);
223 if ((n = obt_xml_find_node(app->children, "position"))) {
224 if ((c = obt_xml_find_node(n->children, "x"))) {
225 if (!obt_xml_node_contains(c, "default")) {
226 config_parse_gravity_coord(c, &settings->position.x);
231 if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
232 if (!obt_xml_node_contains(c, "default")) {
233 config_parse_gravity_coord(c, &settings->position.y);
234 settings->pos_given = TRUE;
238 /* monitor can be set without setting x or y */
239 if ((c = obt_xml_find_node(n->children, "monitor"))) {
240 if (!obt_xml_node_contains(c, "default")) {
241 gchar *s = obt_xml_node_string(c);
242 if (!g_ascii_strcasecmp(s, "mouse"))
243 settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
244 else if (!g_ascii_strcasecmp(s, "active"))
245 settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
246 else if (!g_ascii_strcasecmp(s, "primary"))
247 settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
249 settings->monitor = obt_xml_node_int(c);
254 obt_xml_attr_bool(n, "force", &settings->pos_force);
257 if ((n = obt_xml_find_node(app->children, "size"))) {
258 if ((c = obt_xml_find_node(n->children, "width"))) {
259 if (!obt_xml_node_contains(c, "default")) {
260 gchar *s = obt_xml_node_string(c);
261 config_parse_relative_number(s,
262 &settings->width_num,
263 &settings->width_denom);
264 if (settings->width_num <= 0 || settings->width_denom < 0)
265 settings->width_num = settings->width_denom = 0;
270 if ((c = obt_xml_find_node(n->children, "height"))) {
271 if (!obt_xml_node_contains(c, "default")) {
272 gchar *s = obt_xml_node_string(c);
273 config_parse_relative_number(s,
274 &settings->height_num,
275 &settings->height_denom);
276 if (settings->height_num <= 0 || settings->height_denom < 0)
277 settings->height_num = settings->height_denom = 0;
283 if ((n = obt_xml_find_node(app->children, "focus"))) {
284 if (!obt_xml_node_contains(n, "default"))
285 settings->focus = obt_xml_node_bool(n);
288 if ((n = obt_xml_find_node(app->children, "desktop"))) {
289 if (!obt_xml_node_contains(n, "default")) {
290 gchar *s = obt_xml_node_string(n);
291 if (!g_ascii_strcasecmp(s, "all"))
292 settings->desktop = DESKTOP_ALL;
294 gint i = obt_xml_node_int(n);
296 settings->desktop = i;
302 if ((n = obt_xml_find_node(app->children, "layer"))) {
303 if (!obt_xml_node_contains(n, "default")) {
304 gchar *s = obt_xml_node_string(n);
305 if (!g_ascii_strcasecmp(s, "above"))
307 else if (!g_ascii_strcasecmp(s, "below"))
308 settings->layer = -1;
315 if ((n = obt_xml_find_node(app->children, "iconic")))
316 if (!obt_xml_node_contains(n, "default"))
317 settings->iconic = obt_xml_node_bool(n);
319 if ((n = obt_xml_find_node(app->children, "skip_pager")))
320 if (!obt_xml_node_contains(n, "default"))
321 settings->skip_pager = obt_xml_node_bool(n);
323 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
324 if (!obt_xml_node_contains(n, "default"))
325 settings->skip_taskbar = obt_xml_node_bool(n);
327 if ((n = obt_xml_find_node(app->children, "fullscreen")))
328 if (!obt_xml_node_contains(n, "default"))
329 settings->fullscreen = obt_xml_node_bool(n);
331 if ((n = obt_xml_find_node(app->children, "maximized"))) {
332 if (!obt_xml_node_contains(n, "default")) {
333 gchar *s = obt_xml_node_string(n);
334 if (!g_ascii_strcasecmp(s, "horizontal")) {
335 settings->max_horz = TRUE;
336 settings->max_vert = FALSE;
337 } else if (!g_ascii_strcasecmp(s, "vertical")) {
338 settings->max_horz = FALSE;
339 settings->max_vert = TRUE;
341 settings->max_horz = settings->max_vert =
342 obt_xml_node_bool(n);
348 /* Manages settings for individual applications.
349 Some notes: monitor is the screen number in a multi monitor
350 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
351 is on, active: the active monitor, primary: the primary monitor.
352 Layer can be three values, above (Always on top), below
353 (Always on bottom) and everything else (normal behaviour).
354 Positions can be an integer value or center, which will
355 center the window in the specified axis. Position is within
356 the monitor, so <position><x>center</x></position><monitor>2</monitor>
357 will center the window on the second monitor.
359 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
361 xmlNodePtr app = obt_xml_find_node(node->children, "application");
362 for (; app; app = obt_xml_find_node(app->next, "application")) {
363 ObAppSettings *settings;
365 gboolean name_set, class_set, role_set, title_set,
366 type_set, group_name_set, group_class_set;
367 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
368 *type_str = NULL, *group_name = NULL, *group_class = NULL;
371 class_set = obt_xml_attr_string(app, "class", &class);
372 name_set = obt_xml_attr_string(app, "name", &name);
373 group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
374 group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
375 type_set = obt_xml_attr_string(app, "type", &type_str);
376 role_set = obt_xml_attr_string(app, "role", &role);
377 title_set = obt_xml_attr_string(app, "title", &title);
379 /* validate the type tho */
381 if (!g_ascii_strcasecmp(type_str, "normal"))
382 type = OB_CLIENT_TYPE_NORMAL;
383 else if (!g_ascii_strcasecmp(type_str, "dialog"))
384 type = OB_CLIENT_TYPE_DIALOG;
385 else if (!g_ascii_strcasecmp(type_str, "splash"))
386 type = OB_CLIENT_TYPE_SPLASH;
387 else if (!g_ascii_strcasecmp(type_str, "utility"))
388 type = OB_CLIENT_TYPE_UTILITY;
389 else if (!g_ascii_strcasecmp(type_str, "menu"))
390 type = OB_CLIENT_TYPE_MENU;
391 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
392 type = OB_CLIENT_TYPE_TOOLBAR;
393 else if (!g_ascii_strcasecmp(type_str, "dock"))
394 type = OB_CLIENT_TYPE_DOCK;
395 else if (!g_ascii_strcasecmp(type_str, "desktop"))
396 type = OB_CLIENT_TYPE_DESKTOP;
398 type_set = FALSE; /* not valid! */
401 if (!(class_set || name_set || role_set || title_set ||
402 type_set || group_class_set || group_name_set))
405 settings = config_create_app_settings();
408 settings->name = g_pattern_spec_new(name);
410 settings->class = g_pattern_spec_new(class);
412 settings->group_name = g_pattern_spec_new(group_name);
414 settings->group_class = g_pattern_spec_new(group_class);
416 settings->role = g_pattern_spec_new(role);
418 settings->title = g_pattern_spec_new(title);
420 settings->type = type;
430 parse_single_per_app_settings(app, settings);
431 config_per_app_settings = g_slist_append(config_per_app_settings,
439 <action name="ChangeDesktop">
446 static void parse_key(xmlNodePtr node, GList *keylist)
448 gchar *keystring, **keys, **key;
450 gboolean is_chroot = FALSE;
452 if (!obt_xml_attr_string(node, "key", &keystring))
455 obt_xml_attr_bool(node, "chroot", &is_chroot);
457 keys = g_strsplit(keystring, " ", 0);
458 for (key = keys; *key; ++key) {
459 keylist = g_list_append(keylist, *key);
461 if ((n = obt_xml_find_node(node->children, "keybind"))) {
463 parse_key(n, keylist);
464 n = obt_xml_find_node(n->next, "keybind");
467 else if ((n = obt_xml_find_node(node->children, "action"))) {
469 ObActionsAct *action;
471 action = actions_parse(n);
473 keyboard_bind(keylist, action);
474 n = obt_xml_find_node(n->next, "action");
480 keyboard_chroot(keylist);
481 keylist = g_list_delete_link(keylist, g_list_last(keylist));
488 static void parse_keyboard(xmlNodePtr node, gpointer d)
493 keyboard_unbind_all();
495 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
496 key = obt_xml_node_string(n);
497 translate_key(key, &config_keyboard_reset_state,
498 &config_keyboard_reset_keycode);
502 if ((n = obt_xml_find_node(node->children, "keybind")))
505 n = obt_xml_find_node(n->next, "keybind");
511 <context name="Titlebar">
512 <mousebind button="Left" action="Press">
513 <action name="Raise"></action>
519 static void parse_mouse(xmlNodePtr node, gpointer d)
521 xmlNodePtr n, nbut, nact;
528 node = node->children;
530 if ((n = obt_xml_find_node(node, "dragThreshold")))
531 config_mouse_threshold = obt_xml_node_int(n);
532 if ((n = obt_xml_find_node(node, "doubleClickTime")))
533 config_mouse_dclicktime = obt_xml_node_int(n);
534 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
535 config_mouse_screenedgetime = obt_xml_node_int(n);
536 /* minimum value of 25 for this property, when it is 1 and you hit the
537 edge it basically never stops */
538 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
539 config_mouse_screenedgetime = 25;
541 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
542 config_mouse_screenedgewarp = obt_xml_node_bool(n);
544 n = obt_xml_find_node(node, "context");
549 if (!obt_xml_attr_string(n, "name", &cxstr))
552 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
553 while (frame_next_context_from_string(modcxstr, &cx)) {
555 gchar *s = strchr(modcxstr, ' ');
558 g_message(_("Invalid context \"%s\" in mouse binding"),
565 nbut = obt_xml_find_node(n->children, "mousebind");
567 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
569 if (obt_xml_attr_contains(nbut, "action", "press"))
570 mact = OB_MOUSE_ACTION_PRESS;
571 else if (obt_xml_attr_contains(nbut, "action", "release"))
572 mact = OB_MOUSE_ACTION_RELEASE;
573 else if (obt_xml_attr_contains(nbut, "action", "click"))
574 mact = OB_MOUSE_ACTION_CLICK;
575 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
576 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
577 else if (obt_xml_attr_contains(nbut, "action", "drag"))
578 mact = OB_MOUSE_ACTION_MOTION;
582 nact = obt_xml_find_node(nbut->children, "action");
584 ObActionsAct *action;
586 if ((action = actions_parse(nact)))
587 mouse_bind(buttonstr, cx, mact, action);
588 nact = obt_xml_find_node(nact->next, "action");
592 nbut = obt_xml_find_node(nbut->next, "mousebind");
598 n = obt_xml_find_node(n->next, "context");
602 static void parse_focus(xmlNodePtr node, gpointer d)
606 node = node->children;
608 if ((n = obt_xml_find_node(node, "focusNew")))
609 config_focus_new = obt_xml_node_bool(n);
610 if ((n = obt_xml_find_node(node, "followMouse")))
611 config_focus_follow = obt_xml_node_bool(n);
612 if ((n = obt_xml_find_node(node, "focusDelay")))
613 config_focus_delay = obt_xml_node_int(n);
614 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
615 config_focus_raise = obt_xml_node_bool(n);
616 if ((n = obt_xml_find_node(node, "focusLast")))
617 config_focus_last = obt_xml_node_bool(n);
618 if ((n = obt_xml_find_node(node, "underMouse")))
619 config_focus_under_mouse = obt_xml_node_bool(n);
620 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
621 config_unfocus_leave = obt_xml_node_bool(n);
624 static void parse_placement(xmlNodePtr node, gpointer d)
628 node = node->children;
630 if ((n = obt_xml_find_node(node, "policy"))) {
631 if (obt_xml_node_contains(n, "UnderMouse"))
632 config_place_policy = OB_PLACE_POLICY_MOUSE;
633 if (obt_xml_node_contains(n, "Random"))
634 config_place_policy = OB_PLACE_POLICY_RANDOM;
636 if ((n = obt_xml_find_node(node, "center"))) {
637 config_place_center = obt_xml_node_bool(n);
639 if ((n = obt_xml_find_node(node, "monitor"))) {
640 if (obt_xml_node_contains(n, "active"))
641 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
642 else if (obt_xml_node_contains(n, "mouse"))
643 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
644 else if (obt_xml_node_contains(n, "any"))
645 config_place_monitor = OB_PLACE_MONITOR_ANY;
647 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
648 config_primary_monitor_index = obt_xml_node_int(n);
649 if (!config_primary_monitor_index) {
650 if (obt_xml_node_contains(n, "mouse"))
651 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
656 static void parse_margins(xmlNodePtr node, gpointer d)
660 node = node->children;
662 if ((n = obt_xml_find_node(node, "top")))
663 config_margins.top = MAX(0, obt_xml_node_int(n));
664 if ((n = obt_xml_find_node(node, "left")))
665 config_margins.left = MAX(0, obt_xml_node_int(n));
666 if ((n = obt_xml_find_node(node, "right")))
667 config_margins.right = MAX(0, obt_xml_node_int(n));
668 if ((n = obt_xml_find_node(node, "bottom")))
669 config_margins.bottom = MAX(0, obt_xml_node_int(n));
672 static void parse_theme(xmlNodePtr node, gpointer d)
676 node = node->children;
678 if ((n = obt_xml_find_node(node, "name"))) {
681 g_free(config_theme);
682 c = obt_xml_node_string(n);
683 config_theme = obt_paths_expand_tilde(c);
686 if ((n = obt_xml_find_node(node, "titleLayout"))) {
689 g_free(config_title_layout);
690 config_title_layout = obt_xml_node_string(n);
692 /* replace duplicates with spaces */
693 for (c = config_title_layout; *c != '\0'; ++c)
694 for (d = c+1; *d != '\0'; ++d)
695 if (*c == *d) *d = ' ';
697 if ((n = obt_xml_find_node(node, "keepBorder")))
698 config_theme_keepborder = obt_xml_node_bool(n);
699 if ((n = obt_xml_find_node(node, "animateIconify")))
700 config_animate_iconify = obt_xml_node_bool(n);
701 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
702 config_theme_window_list_icon_size = obt_xml_node_int(n);
703 if (config_theme_window_list_icon_size < 16)
704 config_theme_window_list_icon_size = 16;
705 else if (config_theme_window_list_icon_size > 96)
706 config_theme_window_list_icon_size = 96;
709 n = obt_xml_find_node(node, "font");
713 gchar *name = g_strdup(RrDefaultFontFamily);
714 gint size = RrDefaultFontSize;
715 RrFontWeight weight = RrDefaultFontWeight;
716 RrFontSlant slant = RrDefaultFontSlant;
718 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
719 font = &config_font_activewindow;
720 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
721 font = &config_font_inactivewindow;
722 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
723 font = &config_font_menutitle;
724 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
725 font = &config_font_menuitem;
726 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
727 font = &config_font_activeosd;
728 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
729 font = &config_font_activeosd;
730 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
731 font = &config_font_inactiveosd;
735 if ((fnode = obt_xml_find_node(n->children, "name"))) {
737 name = obt_xml_node_string(fnode);
739 if ((fnode = obt_xml_find_node(n->children, "size"))) {
740 int s = obt_xml_node_int(fnode);
743 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
744 gchar *w = obt_xml_node_string(fnode);
745 if (!g_ascii_strcasecmp(w, "Bold"))
746 weight = RR_FONTWEIGHT_BOLD;
749 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
750 gchar *s = obt_xml_node_string(fnode);
751 if (!g_ascii_strcasecmp(s, "Italic"))
752 slant = RR_FONTSLANT_ITALIC;
753 if (!g_ascii_strcasecmp(s, "Oblique"))
754 slant = RR_FONTSLANT_OBLIQUE;
758 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
761 n = obt_xml_find_node(n->next, "font");
765 static void parse_desktops(xmlNodePtr node, gpointer d)
769 node = node->children;
771 if ((n = obt_xml_find_node(node, "number"))) {
772 gint d = obt_xml_node_int(n);
774 config_desktops_num = (unsigned) d;
776 if ((n = obt_xml_find_node(node, "firstdesk"))) {
777 gint d = obt_xml_node_int(n);
779 config_screen_firstdesk = (unsigned) d;
781 if ((n = obt_xml_find_node(node, "emulatexinerama")))
782 config_emulate_xinerama = obt_xml_node_bool(n);
783 if ((n = obt_xml_find_node(node, "names"))) {
787 for (it = config_desktops_names; it; it = it->next)
789 g_slist_free(config_desktops_names);
790 config_desktops_names = NULL;
792 nname = obt_xml_find_node(n->children, "name");
794 config_desktops_names =
795 g_slist_append(config_desktops_names,
796 obt_xml_node_string(nname));
797 nname = obt_xml_find_node(nname->next, "name");
800 if ((n = obt_xml_find_node(node, "popupTime")))
801 config_desktop_popup_time = obt_xml_node_int(n);
804 static void parse_resize(xmlNodePtr node, gpointer d)
808 node = node->children;
810 if ((n = obt_xml_find_node(node, "drawContents")))
811 config_resize_redraw = obt_xml_node_bool(n);
812 if ((n = obt_xml_find_node(node, "popupShow"))) {
813 config_resize_popup_show = obt_xml_node_int(n);
814 if (obt_xml_node_contains(n, "Always"))
815 config_resize_popup_show = 2;
816 else if (obt_xml_node_contains(n, "Never"))
817 config_resize_popup_show = 0;
818 else if (obt_xml_node_contains(n, "Nonpixel"))
819 config_resize_popup_show = 1;
821 if ((n = obt_xml_find_node(node, "popupPosition"))) {
822 if (obt_xml_node_contains(n, "Top"))
823 config_resize_popup_pos = OB_RESIZE_POS_TOP;
824 else if (obt_xml_node_contains(n, "Center"))
825 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
826 else if (obt_xml_node_contains(n, "Fixed")) {
827 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
829 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
832 if ((n2 = obt_xml_find_node(n->children, "x")))
833 config_parse_gravity_coord(n2,
834 &config_resize_popup_fixed.x);
835 if ((n2 = obt_xml_find_node(n->children, "y")))
836 config_parse_gravity_coord(n2,
837 &config_resize_popup_fixed.y);
839 config_resize_popup_fixed.x.pos =
840 MAX(config_resize_popup_fixed.x.pos, 0);
841 config_resize_popup_fixed.y.pos =
842 MAX(config_resize_popup_fixed.y.pos, 0);
848 static void parse_dock(xmlNodePtr node, gpointer d)
852 node = node->children;
854 if ((n = obt_xml_find_node(node, "position"))) {
855 if (obt_xml_node_contains(n, "TopLeft"))
856 config_dock_floating = FALSE,
857 config_dock_pos = OB_DIRECTION_NORTHWEST;
858 else if (obt_xml_node_contains(n, "Top"))
859 config_dock_floating = FALSE,
860 config_dock_pos = OB_DIRECTION_NORTH;
861 else if (obt_xml_node_contains(n, "TopRight"))
862 config_dock_floating = FALSE,
863 config_dock_pos = OB_DIRECTION_NORTHEAST;
864 else if (obt_xml_node_contains(n, "Right"))
865 config_dock_floating = FALSE,
866 config_dock_pos = OB_DIRECTION_EAST;
867 else if (obt_xml_node_contains(n, "BottomRight"))
868 config_dock_floating = FALSE,
869 config_dock_pos = OB_DIRECTION_SOUTHEAST;
870 else if (obt_xml_node_contains(n, "Bottom"))
871 config_dock_floating = FALSE,
872 config_dock_pos = OB_DIRECTION_SOUTH;
873 else if (obt_xml_node_contains(n, "BottomLeft"))
874 config_dock_floating = FALSE,
875 config_dock_pos = OB_DIRECTION_SOUTHWEST;
876 else if (obt_xml_node_contains(n, "Left"))
877 config_dock_floating = FALSE,
878 config_dock_pos = OB_DIRECTION_WEST;
879 else if (obt_xml_node_contains(n, "Floating"))
880 config_dock_floating = TRUE;
882 if (config_dock_floating) {
883 if ((n = obt_xml_find_node(node, "floatingX")))
884 config_dock_x = obt_xml_node_int(n);
885 if ((n = obt_xml_find_node(node, "floatingY")))
886 config_dock_y = obt_xml_node_int(n);
888 if ((n = obt_xml_find_node(node, "noStrut")))
889 config_dock_nostrut = obt_xml_node_bool(n);
891 if ((n = obt_xml_find_node(node, "stacking"))) {
892 if (obt_xml_node_contains(n, "normal"))
893 config_dock_layer = OB_STACKING_LAYER_NORMAL;
894 else if (obt_xml_node_contains(n, "below"))
895 config_dock_layer = OB_STACKING_LAYER_BELOW;
896 else if (obt_xml_node_contains(n, "above"))
897 config_dock_layer = OB_STACKING_LAYER_ABOVE;
899 if ((n = obt_xml_find_node(node, "direction"))) {
900 if (obt_xml_node_contains(n, "horizontal"))
901 config_dock_orient = OB_ORIENTATION_HORZ;
902 else if (obt_xml_node_contains(n, "vertical"))
903 config_dock_orient = OB_ORIENTATION_VERT;
905 if ((n = obt_xml_find_node(node, "autoHide")))
906 config_dock_hide = obt_xml_node_bool(n);
907 if ((n = obt_xml_find_node(node, "hideDelay")))
908 config_dock_hide_delay = obt_xml_node_int(n);
909 if ((n = obt_xml_find_node(node, "showDelay")))
910 config_dock_show_delay = obt_xml_node_int(n);
911 if ((n = obt_xml_find_node(node, "moveButton"))) {
912 gchar *str = obt_xml_node_string(n);
914 if (translate_button(str, &s, &b)) {
915 config_dock_app_move_button = b;
916 config_dock_app_move_modifiers = s;
918 g_message(_("Invalid button \"%s\" specified in config file"), str);
924 static void parse_menu(xmlNodePtr node, gpointer d)
927 node = node->children;
929 if ((n = obt_xml_find_node(node, "hideDelay")))
930 config_menu_hide_delay = obt_xml_node_int(n);
931 if ((n = obt_xml_find_node(node, "middle")))
932 config_menu_middle = obt_xml_node_bool(n);
933 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
934 config_submenu_show_delay = obt_xml_node_int(n);
935 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
936 config_submenu_hide_delay = obt_xml_node_int(n);
937 if ((n = obt_xml_find_node(node, "manageDesktops")))
938 config_menu_manage_desktops = obt_xml_node_bool(n);
939 if ((n = obt_xml_find_node(node, "showIcons"))) {
940 config_menu_show_icons = obt_xml_node_bool(n);
941 #if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
942 if (config_menu_show_icons)
943 g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
947 while ((node = obt_xml_find_node(node, "file"))) {
948 gchar *c = obt_xml_node_string(node);
949 config_menu_files = g_slist_append(config_menu_files,
950 obt_paths_expand_tilde(c));
956 static void parse_resistance(xmlNodePtr node, gpointer d)
960 node = node->children;
961 if ((n = obt_xml_find_node(node, "strength")))
962 config_resist_win = obt_xml_node_int(n);
963 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
964 config_resist_edge = obt_xml_node_int(n);
970 const gchar *actname;
973 static void bind_default_keyboard(void)
976 ObDefKeyBind binds[] = {
977 { "A-Tab", "NextWindow" },
978 { "S-A-Tab", "PreviousWindow" },
982 for (it = binds; it->key; ++it) {
983 GList *l = g_list_append(NULL, g_strdup(it->key));
984 keyboard_bind(l, actions_parse_string(it->actname));
991 const gchar *context;
992 const ObMouseAction mact;
993 const gchar *actname;
996 static void bind_default_mouse(void)
999 ObDefMouseBind binds[] = {
1000 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1001 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1002 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
1003 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1004 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1005 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
1006 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
1007 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
1008 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1009 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1010 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1011 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
1012 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
1013 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
1014 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
1015 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
1016 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
1017 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
1018 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
1019 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
1020 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
1021 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1022 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1023 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1024 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
1025 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
1026 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
1027 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
1028 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
1029 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
1030 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
1031 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
1032 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
1033 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
1034 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
1035 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
1036 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1037 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1038 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1039 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
1040 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
1041 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
1042 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
1043 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
1044 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
1045 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
1046 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
1047 { NULL, NULL, 0, NULL }
1050 for (it = binds; it->button; ++it)
1051 mouse_bind(it->button, frame_context_from_string(it->context),
1052 it->mact, actions_parse_string(it->actname));
1055 void config_startup(ObtXmlInst *i)
1057 config_focus_new = TRUE;
1058 config_focus_follow = FALSE;
1059 config_focus_delay = 0;
1060 config_focus_raise = FALSE;
1061 config_focus_last = TRUE;
1062 config_focus_under_mouse = FALSE;
1063 config_unfocus_leave = FALSE;
1065 obt_xml_register(i, "focus", parse_focus, NULL);
1067 config_place_policy = OB_PLACE_POLICY_SMART;
1068 config_place_center = TRUE;
1069 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1071 config_primary_monitor_index = 1;
1072 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1074 obt_xml_register(i, "placement", parse_placement, NULL);
1076 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1078 obt_xml_register(i, "margins", parse_margins, NULL);
1080 config_theme = NULL;
1082 config_animate_iconify = TRUE;
1083 config_title_layout = g_strdup("NLIMC");
1084 config_theme_keepborder = TRUE;
1085 config_theme_window_list_icon_size = 36;
1087 config_font_activewindow = NULL;
1088 config_font_inactivewindow = NULL;
1089 config_font_menuitem = NULL;
1090 config_font_menutitle = NULL;
1091 config_font_activeosd = NULL;
1092 config_font_inactiveosd = NULL;
1094 obt_xml_register(i, "theme", parse_theme, NULL);
1096 config_desktops_num = 4;
1097 config_screen_firstdesk = 1;
1098 config_emulate_xinerama = FALSE;
1099 config_desktops_names = NULL;
1100 config_desktop_popup_time = 875;
1102 obt_xml_register(i, "desktops", parse_desktops, NULL);
1104 config_resize_redraw = TRUE;
1105 config_resize_popup_show = 1; /* nonpixel increments */
1106 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1107 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1108 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1110 obt_xml_register(i, "resize", parse_resize, NULL);
1112 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1113 config_dock_pos = OB_DIRECTION_NORTHEAST;
1114 config_dock_floating = FALSE;
1115 config_dock_nostrut = FALSE;
1118 config_dock_orient = OB_ORIENTATION_VERT;
1119 config_dock_hide = FALSE;
1120 config_dock_hide_delay = 300;
1121 config_dock_show_delay = 300;
1122 config_dock_app_move_button = 2; /* middle */
1123 config_dock_app_move_modifiers = 0;
1125 obt_xml_register(i, "dock", parse_dock, NULL);
1127 translate_key("C-g", &config_keyboard_reset_state,
1128 &config_keyboard_reset_keycode);
1130 bind_default_keyboard();
1132 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1134 config_mouse_threshold = 8;
1135 config_mouse_dclicktime = 500;
1136 config_mouse_screenedgetime = 400;
1137 config_mouse_screenedgewarp = FALSE;
1139 bind_default_mouse();
1141 obt_xml_register(i, "mouse", parse_mouse, NULL);
1143 config_resist_win = 10;
1144 config_resist_edge = 20;
1146 obt_xml_register(i, "resistance", parse_resistance, NULL);
1148 config_menu_hide_delay = 250;
1149 config_menu_middle = FALSE;
1150 config_submenu_show_delay = 100;
1151 config_submenu_hide_delay = 400;
1152 config_menu_manage_desktops = TRUE;
1153 config_menu_files = NULL;
1154 config_menu_show_icons = TRUE;
1156 obt_xml_register(i, "menu", parse_menu, NULL);
1158 config_per_app_settings = NULL;
1160 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1163 void config_shutdown(void)
1167 g_free(config_theme);
1169 g_free(config_title_layout);
1171 RrFontClose(config_font_activewindow);
1172 RrFontClose(config_font_inactivewindow);
1173 RrFontClose(config_font_menuitem);
1174 RrFontClose(config_font_menutitle);
1175 RrFontClose(config_font_activeosd);
1176 RrFontClose(config_font_inactiveosd);
1178 for (it = config_desktops_names; it; it = g_slist_next(it))
1180 g_slist_free(config_desktops_names);
1182 for (it = config_menu_files; it; it = g_slist_next(it))
1184 g_slist_free(config_menu_files);
1186 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1187 ObAppSettings *itd = (ObAppSettings *)it->data;
1188 if (itd->name) g_pattern_spec_free(itd->name);
1189 if (itd->role) g_pattern_spec_free(itd->role);
1190 if (itd->title) g_pattern_spec_free(itd->title);
1191 if (itd->class) g_pattern_spec_free(itd->class);
1192 if (itd->group_name) g_pattern_spec_free(itd->group_name);
1193 if (itd->group_class) g_pattern_spec_free(itd->group_class);
1194 g_slice_free(ObAppSettings, it->data);
1196 g_slist_free(config_per_app_settings);