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 */
159 void config_parse_relative_number(gchar *s, gint *num, gint *denom)
161 *num = strtol(s, &s, 10);
165 } else if (*s == '/') {
170 void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
172 gchar *s = obt_xml_node_string(node);
173 if (!g_ascii_strcasecmp(s, "center"))
179 if (s[0] == '-' || s[0] == '+')
181 config_parse_relative_number(ps, &c->pos, &c->denom);
188 <application name="aterm">
191 <application name="Rhythmbox">
198 .. there is a lot more settings available
203 /* Manages settings for individual applications.
204 Some notes: monitor is the screen number in a multi monitor
205 (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
206 is on, active: the active monitor, primary: the primary monitor.
207 Layer can be three values, above (Always on top), below
208 (Always on bottom) and everything else (normal behaviour).
209 Positions can be an integer value or center, which will
210 center the window in the specified axis. Position is within
211 the monitor, so <position><x>center</x></position><monitor>2</monitor>
212 will center the window on the second monitor.
214 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
216 xmlNodePtr app = obt_xml_find_node(node->children, "application");
217 gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
219 gboolean name_set, class_set, type_set, role_set, title_set;
221 gboolean x_pos_given;
226 class_set = obt_xml_attr_string(app, "class", &class);
227 name_set = obt_xml_attr_string(app, "name", &name);
228 type_set = obt_xml_attr_string(app, "type", &type_str);
229 role_set = obt_xml_attr_string(app, "role", &role);
230 title_set = obt_xml_attr_string(app, "title", &title);
232 /* validate the type tho */
234 if (!g_ascii_strcasecmp(type_str, "normal"))
235 type = OB_CLIENT_TYPE_NORMAL;
236 else if (!g_ascii_strcasecmp(type_str, "dialog"))
237 type = OB_CLIENT_TYPE_DIALOG;
238 else if (!g_ascii_strcasecmp(type_str, "splash"))
239 type = OB_CLIENT_TYPE_SPLASH;
240 else if (!g_ascii_strcasecmp(type_str, "utility"))
241 type = OB_CLIENT_TYPE_UTILITY;
242 else if (!g_ascii_strcasecmp(type_str, "menu"))
243 type = OB_CLIENT_TYPE_MENU;
244 else if (!g_ascii_strcasecmp(type_str, "toolbar"))
245 type = OB_CLIENT_TYPE_TOOLBAR;
246 else if (!g_ascii_strcasecmp(type_str, "dock"))
247 type = OB_CLIENT_TYPE_DOCK;
248 else if (!g_ascii_strcasecmp(type_str, "desktop"))
249 type = OB_CLIENT_TYPE_DESKTOP;
251 type_set = FALSE; /* not valid! */
254 if (class_set || name_set || role_set || title_set || type_set) {
256 ObAppSettings *settings = config_create_app_settings();
259 settings->name = g_pattern_spec_new(name);
262 settings->class = g_pattern_spec_new(class);
265 settings->role = g_pattern_spec_new(role);
268 settings->title = g_pattern_spec_new(title);
271 settings->type = type;
273 if ((n = obt_xml_find_node(app->children, "decor")))
274 if (!obt_xml_node_contains(n, "default"))
275 settings->decor = obt_xml_node_bool(n);
277 if ((n = obt_xml_find_node(app->children, "shade")))
278 if (!obt_xml_node_contains(n, "default"))
279 settings->shade = obt_xml_node_bool(n);
281 if ((n = obt_xml_find_node(app->children, "position"))) {
282 if ((c = obt_xml_find_node(n->children, "x")))
283 if (!obt_xml_node_contains(c, "default")) {
284 config_parse_gravity_coord(c, &settings->position.x);
288 if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
289 if (!obt_xml_node_contains(c, "default")) {
290 config_parse_gravity_coord(c, &settings->position.y);
291 settings->pos_given = TRUE;
294 /* monitor can be set without setting x or y */
295 if ((c = obt_xml_find_node(n->children, "monitor")))
296 if (!obt_xml_node_contains(c, "default")) {
297 gchar *s = obt_xml_node_string(c);
298 if (!g_ascii_strcasecmp(s, "mouse"))
299 settings->monitor_type =
300 OB_PLACE_MONITOR_MOUSE;
301 else if (!g_ascii_strcasecmp(s, "active"))
302 settings->monitor_type =
303 OB_PLACE_MONITOR_ACTIVE;
304 else if (!g_ascii_strcasecmp(s, "primary"))
305 settings->monitor_type =
306 OB_PLACE_MONITOR_PRIMARY;
308 settings->monitor = obt_xml_node_int(c);
312 obt_xml_attr_bool(n, "force", &settings->pos_force);
315 if ((n = obt_xml_find_node(app->children, "focus")))
316 if (!obt_xml_node_contains(n, "default"))
317 settings->focus = obt_xml_node_bool(n);
319 if ((n = obt_xml_find_node(app->children, "desktop"))) {
320 if (!obt_xml_node_contains(n, "default")) {
321 gchar *s = obt_xml_node_string(n);
322 if (!g_ascii_strcasecmp(s, "all"))
323 settings->desktop = DESKTOP_ALL;
325 gint i = obt_xml_node_int(n);
327 settings->desktop = i;
333 if ((n = obt_xml_find_node(app->children, "layer")))
334 if (!obt_xml_node_contains(n, "default")) {
335 gchar *s = obt_xml_node_string(n);
336 if (!g_ascii_strcasecmp(s, "above"))
338 else if (!g_ascii_strcasecmp(s, "below"))
339 settings->layer = -1;
345 if ((n = obt_xml_find_node(app->children, "iconic")))
346 if (!obt_xml_node_contains(n, "default"))
347 settings->iconic = obt_xml_node_bool(n);
349 if ((n = obt_xml_find_node(app->children, "skip_pager")))
350 if (!obt_xml_node_contains(n, "default"))
351 settings->skip_pager = obt_xml_node_bool(n);
353 if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
354 if (!obt_xml_node_contains(n, "default"))
355 settings->skip_taskbar = obt_xml_node_bool(n);
357 if ((n = obt_xml_find_node(app->children, "fullscreen")))
358 if (!obt_xml_node_contains(n, "default"))
359 settings->fullscreen = obt_xml_node_bool(n);
361 if ((n = obt_xml_find_node(app->children, "maximized")))
362 if (!obt_xml_node_contains(n, "default")) {
363 gchar *s = obt_xml_node_string(n);
364 if (!g_ascii_strcasecmp(s, "horizontal")) {
365 settings->max_horz = TRUE;
366 settings->max_vert = FALSE;
367 } else if (!g_ascii_strcasecmp(s, "vertical")) {
368 settings->max_horz = FALSE;
369 settings->max_vert = TRUE;
371 settings->max_horz = settings->max_vert =
372 obt_xml_node_bool(n);
376 config_per_app_settings = g_slist_append(config_per_app_settings,
377 (gpointer) settings);
383 name = class = role = title = type_str = NULL;
386 app = obt_xml_find_node(app->next, "application");
393 <action name="ChangeDesktop">
400 static void parse_key(xmlNodePtr node, GList *keylist)
402 gchar *keystring, **keys, **key;
404 gboolean is_chroot = FALSE;
406 if (!obt_xml_attr_string(node, "key", &keystring))
409 obt_xml_attr_bool(node, "chroot", &is_chroot);
411 keys = g_strsplit(keystring, " ", 0);
412 for (key = keys; *key; ++key) {
413 keylist = g_list_append(keylist, *key);
415 if ((n = obt_xml_find_node(node->children, "keybind"))) {
417 parse_key(n, keylist);
418 n = obt_xml_find_node(n->next, "keybind");
421 else if ((n = obt_xml_find_node(node->children, "action"))) {
423 ObActionsAct *action;
425 action = actions_parse(n);
427 keyboard_bind(keylist, action);
428 n = obt_xml_find_node(n->next, "action");
434 keyboard_chroot(keylist);
435 keylist = g_list_delete_link(keylist, g_list_last(keylist));
442 static void parse_keyboard(xmlNodePtr node, gpointer d)
447 keyboard_unbind_all();
449 if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
450 key = obt_xml_node_string(n);
451 translate_key(key, &config_keyboard_reset_state,
452 &config_keyboard_reset_keycode);
456 if ((n = obt_xml_find_node(node->children, "keybind")))
459 n = obt_xml_find_node(n->next, "keybind");
465 <context name="Titlebar">
466 <mousebind button="Left" action="Press">
467 <action name="Raise"></action>
473 static void parse_mouse(xmlNodePtr node, gpointer d)
475 xmlNodePtr n, nbut, nact;
482 node = node->children;
484 if ((n = obt_xml_find_node(node, "dragThreshold")))
485 config_mouse_threshold = obt_xml_node_int(n);
486 if ((n = obt_xml_find_node(node, "doubleClickTime")))
487 config_mouse_dclicktime = obt_xml_node_int(n);
488 if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
489 config_mouse_screenedgetime = obt_xml_node_int(n);
490 /* minimum value of 25 for this property, when it is 1 and you hit the
491 edge it basically never stops */
492 if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
493 config_mouse_screenedgetime = 25;
495 if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
496 config_mouse_screenedgewarp = obt_xml_node_bool(n);
498 n = obt_xml_find_node(node, "context");
503 if (!obt_xml_attr_string(n, "name", &cxstr))
506 modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
507 while (frame_next_context_from_string(modcxstr, &cx)) {
509 gchar *s = strchr(modcxstr, ' ');
512 g_message(_("Invalid context \"%s\" in mouse binding"),
519 nbut = obt_xml_find_node(n->children, "mousebind");
521 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
523 if (obt_xml_attr_contains(nbut, "action", "press"))
524 mact = OB_MOUSE_ACTION_PRESS;
525 else if (obt_xml_attr_contains(nbut, "action", "release"))
526 mact = OB_MOUSE_ACTION_RELEASE;
527 else if (obt_xml_attr_contains(nbut, "action", "click"))
528 mact = OB_MOUSE_ACTION_CLICK;
529 else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
530 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
531 else if (obt_xml_attr_contains(nbut, "action", "drag"))
532 mact = OB_MOUSE_ACTION_MOTION;
536 nact = obt_xml_find_node(nbut->children, "action");
538 ObActionsAct *action;
540 if ((action = actions_parse(nact)))
541 mouse_bind(buttonstr, cx, mact, action);
542 nact = obt_xml_find_node(nact->next, "action");
546 nbut = obt_xml_find_node(nbut->next, "mousebind");
552 n = obt_xml_find_node(n->next, "context");
556 static void parse_focus(xmlNodePtr node, gpointer d)
560 node = node->children;
562 if ((n = obt_xml_find_node(node, "focusNew")))
563 config_focus_new = obt_xml_node_bool(n);
564 if ((n = obt_xml_find_node(node, "followMouse")))
565 config_focus_follow = obt_xml_node_bool(n);
566 if ((n = obt_xml_find_node(node, "focusDelay")))
567 config_focus_delay = obt_xml_node_int(n);
568 if ((n = obt_xml_find_node(node, "raiseOnFocus")))
569 config_focus_raise = obt_xml_node_bool(n);
570 if ((n = obt_xml_find_node(node, "focusLast")))
571 config_focus_last = obt_xml_node_bool(n);
572 if ((n = obt_xml_find_node(node, "underMouse")))
573 config_focus_under_mouse = obt_xml_node_bool(n);
574 if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
575 config_unfocus_leave = obt_xml_node_bool(n);
578 static void parse_placement(xmlNodePtr node, gpointer d)
582 node = node->children;
584 if ((n = obt_xml_find_node(node, "policy"))) {
585 if (obt_xml_node_contains(n, "UnderMouse"))
586 config_place_policy = OB_PLACE_POLICY_MOUSE;
587 else if (obt_xml_node_contains(n, "LeastOverlap"))
588 config_place_policy = OB_PLACE_POLICY_LEASTOVERLAP;
591 if ((n = obt_xml_find_node(node, "center")))
592 config_place_center = obt_xml_node_bool(n);
593 if ((n = obt_xml_find_node(node, "monitor"))) {
594 if (obt_xml_node_contains(n, "active"))
595 config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
596 else if (obt_xml_node_contains(n, "mouse"))
597 config_place_monitor = OB_PLACE_MONITOR_MOUSE;
598 else if (obt_xml_node_contains(n, "any"))
599 config_place_monitor = OB_PLACE_MONITOR_ANY;
601 if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
602 config_primary_monitor_index = obt_xml_node_int(n);
603 if (!config_primary_monitor_index) {
604 if (obt_xml_node_contains(n, "mouse"))
605 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
610 static void parse_margins(xmlNodePtr node, gpointer d)
614 node = node->children;
616 if ((n = obt_xml_find_node(node, "top")))
617 config_margins.top = MAX(0, obt_xml_node_int(n));
618 if ((n = obt_xml_find_node(node, "left")))
619 config_margins.left = MAX(0, obt_xml_node_int(n));
620 if ((n = obt_xml_find_node(node, "right")))
621 config_margins.right = MAX(0, obt_xml_node_int(n));
622 if ((n = obt_xml_find_node(node, "bottom")))
623 config_margins.bottom = MAX(0, obt_xml_node_int(n));
626 static void parse_theme(xmlNodePtr node, gpointer d)
630 node = node->children;
632 if ((n = obt_xml_find_node(node, "name"))) {
635 g_free(config_theme);
636 c = obt_xml_node_string(n);
637 config_theme = obt_paths_expand_tilde(c);
640 if ((n = obt_xml_find_node(node, "titleLayout"))) {
643 g_free(config_title_layout);
644 config_title_layout = obt_xml_node_string(n);
646 /* replace duplicates with spaces */
647 for (c = config_title_layout; *c != '\0'; ++c)
648 for (d = c+1; *d != '\0'; ++d)
649 if (*c == *d) *d = ' ';
651 if ((n = obt_xml_find_node(node, "keepBorder")))
652 config_theme_keepborder = obt_xml_node_bool(n);
653 if ((n = obt_xml_find_node(node, "animateIconify")))
654 config_animate_iconify = obt_xml_node_bool(n);
655 if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
656 config_theme_window_list_icon_size = obt_xml_node_int(n);
657 if (config_theme_window_list_icon_size < 16)
658 config_theme_window_list_icon_size = 16;
659 else if (config_theme_window_list_icon_size > 96)
660 config_theme_window_list_icon_size = 96;
663 n = obt_xml_find_node(node, "font");
667 gchar *name = g_strdup(RrDefaultFontFamily);
668 gint size = RrDefaultFontSize;
669 RrFontWeight weight = RrDefaultFontWeight;
670 RrFontSlant slant = RrDefaultFontSlant;
672 if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
673 font = &config_font_activewindow;
674 else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
675 font = &config_font_inactivewindow;
676 else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
677 font = &config_font_menutitle;
678 else if (obt_xml_attr_contains(n, "place", "MenuItem"))
679 font = &config_font_menuitem;
680 else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
681 font = &config_font_activeosd;
682 else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
683 font = &config_font_activeosd;
684 else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
685 font = &config_font_inactiveosd;
689 if ((fnode = obt_xml_find_node(n->children, "name"))) {
691 name = obt_xml_node_string(fnode);
693 if ((fnode = obt_xml_find_node(n->children, "size"))) {
694 int s = obt_xml_node_int(fnode);
697 if ((fnode = obt_xml_find_node(n->children, "weight"))) {
698 gchar *w = obt_xml_node_string(fnode);
699 if (!g_ascii_strcasecmp(w, "Bold"))
700 weight = RR_FONTWEIGHT_BOLD;
703 if ((fnode = obt_xml_find_node(n->children, "slant"))) {
704 gchar *s = obt_xml_node_string(fnode);
705 if (!g_ascii_strcasecmp(s, "Italic"))
706 slant = RR_FONTSLANT_ITALIC;
707 if (!g_ascii_strcasecmp(s, "Oblique"))
708 slant = RR_FONTSLANT_OBLIQUE;
712 *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
715 n = obt_xml_find_node(n->next, "font");
719 static void parse_desktops(xmlNodePtr node, gpointer d)
723 node = node->children;
725 if ((n = obt_xml_find_node(node, "number"))) {
726 gint d = obt_xml_node_int(n);
728 config_desktops_num = (unsigned) d;
730 if ((n = obt_xml_find_node(node, "firstdesk"))) {
731 gint d = obt_xml_node_int(n);
733 config_screen_firstdesk = (unsigned) d;
735 if ((n = obt_xml_find_node(node, "names"))) {
739 for (it = config_desktops_names; it; it = it->next)
741 g_slist_free(config_desktops_names);
742 config_desktops_names = NULL;
744 nname = obt_xml_find_node(n->children, "name");
746 config_desktops_names =
747 g_slist_append(config_desktops_names,
748 obt_xml_node_string(nname));
749 nname = obt_xml_find_node(nname->next, "name");
752 if ((n = obt_xml_find_node(node, "popupTime")))
753 config_desktop_popup_time = obt_xml_node_int(n);
756 static void parse_resize(xmlNodePtr node, gpointer d)
760 node = node->children;
762 if ((n = obt_xml_find_node(node, "drawContents")))
763 config_resize_redraw = obt_xml_node_bool(n);
764 if ((n = obt_xml_find_node(node, "popupShow"))) {
765 config_resize_popup_show = obt_xml_node_int(n);
766 if (obt_xml_node_contains(n, "Always"))
767 config_resize_popup_show = 2;
768 else if (obt_xml_node_contains(n, "Never"))
769 config_resize_popup_show = 0;
770 else if (obt_xml_node_contains(n, "Nonpixel"))
771 config_resize_popup_show = 1;
773 if ((n = obt_xml_find_node(node, "popupPosition"))) {
774 if (obt_xml_node_contains(n, "Top"))
775 config_resize_popup_pos = OB_RESIZE_POS_TOP;
776 else if (obt_xml_node_contains(n, "Center"))
777 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
778 else if (obt_xml_node_contains(n, "Fixed")) {
779 config_resize_popup_pos = OB_RESIZE_POS_FIXED;
781 if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
784 if ((n2 = obt_xml_find_node(n->children, "x")))
785 config_parse_gravity_coord(n2,
786 &config_resize_popup_fixed.x);
787 if ((n2 = obt_xml_find_node(n->children, "y")))
788 config_parse_gravity_coord(n2,
789 &config_resize_popup_fixed.y);
791 config_resize_popup_fixed.x.pos =
792 MAX(config_resize_popup_fixed.x.pos, 0);
793 config_resize_popup_fixed.y.pos =
794 MAX(config_resize_popup_fixed.y.pos, 0);
800 static void parse_dock(xmlNodePtr node, gpointer d)
804 node = node->children;
806 if ((n = obt_xml_find_node(node, "position"))) {
807 if (obt_xml_node_contains(n, "TopLeft"))
808 config_dock_floating = FALSE,
809 config_dock_pos = OB_DIRECTION_NORTHWEST;
810 else if (obt_xml_node_contains(n, "Top"))
811 config_dock_floating = FALSE,
812 config_dock_pos = OB_DIRECTION_NORTH;
813 else if (obt_xml_node_contains(n, "TopRight"))
814 config_dock_floating = FALSE,
815 config_dock_pos = OB_DIRECTION_NORTHEAST;
816 else if (obt_xml_node_contains(n, "Right"))
817 config_dock_floating = FALSE,
818 config_dock_pos = OB_DIRECTION_EAST;
819 else if (obt_xml_node_contains(n, "BottomRight"))
820 config_dock_floating = FALSE,
821 config_dock_pos = OB_DIRECTION_SOUTHEAST;
822 else if (obt_xml_node_contains(n, "Bottom"))
823 config_dock_floating = FALSE,
824 config_dock_pos = OB_DIRECTION_SOUTH;
825 else if (obt_xml_node_contains(n, "BottomLeft"))
826 config_dock_floating = FALSE,
827 config_dock_pos = OB_DIRECTION_SOUTHWEST;
828 else if (obt_xml_node_contains(n, "Left"))
829 config_dock_floating = FALSE,
830 config_dock_pos = OB_DIRECTION_WEST;
831 else if (obt_xml_node_contains(n, "Floating"))
832 config_dock_floating = TRUE;
834 if (config_dock_floating) {
835 if ((n = obt_xml_find_node(node, "floatingX")))
836 config_dock_x = obt_xml_node_int(n);
837 if ((n = obt_xml_find_node(node, "floatingY")))
838 config_dock_y = obt_xml_node_int(n);
840 if ((n = obt_xml_find_node(node, "noStrut")))
841 config_dock_nostrut = obt_xml_node_bool(n);
843 if ((n = obt_xml_find_node(node, "stacking"))) {
844 if (obt_xml_node_contains(n, "normal"))
845 config_dock_layer = OB_STACKING_LAYER_NORMAL;
846 else if (obt_xml_node_contains(n, "below"))
847 config_dock_layer = OB_STACKING_LAYER_BELOW;
848 else if (obt_xml_node_contains(n, "above"))
849 config_dock_layer = OB_STACKING_LAYER_ABOVE;
851 if ((n = obt_xml_find_node(node, "direction"))) {
852 if (obt_xml_node_contains(n, "horizontal"))
853 config_dock_orient = OB_ORIENTATION_HORZ;
854 else if (obt_xml_node_contains(n, "vertical"))
855 config_dock_orient = OB_ORIENTATION_VERT;
857 if ((n = obt_xml_find_node(node, "autoHide")))
858 config_dock_hide = obt_xml_node_bool(n);
859 if ((n = obt_xml_find_node(node, "hideDelay")))
860 config_dock_hide_delay = obt_xml_node_int(n);
861 if ((n = obt_xml_find_node(node, "showDelay")))
862 config_dock_show_delay = obt_xml_node_int(n);
863 if ((n = obt_xml_find_node(node, "moveButton"))) {
864 gchar *str = obt_xml_node_string(n);
866 if (translate_button(str, &s, &b)) {
867 config_dock_app_move_button = b;
868 config_dock_app_move_modifiers = s;
870 g_message(_("Invalid button \"%s\" specified in config file"), str);
876 static void parse_menu(xmlNodePtr node, gpointer d)
879 node = node->children;
881 if ((n = obt_xml_find_node(node, "hideDelay")))
882 config_menu_hide_delay = obt_xml_node_int(n);
883 if ((n = obt_xml_find_node(node, "middle")))
884 config_menu_middle = obt_xml_node_bool(n);
885 if ((n = obt_xml_find_node(node, "submenuShowDelay")))
886 config_submenu_show_delay = obt_xml_node_int(n);
887 if ((n = obt_xml_find_node(node, "submenuHideDelay")))
888 config_submenu_hide_delay = obt_xml_node_int(n);
889 if ((n = obt_xml_find_node(node, "manageDesktops")))
890 config_menu_manage_desktops = obt_xml_node_bool(n);
891 if ((n = obt_xml_find_node(node, "showIcons"))) {
892 config_menu_show_icons = obt_xml_node_bool(n);
894 if (config_menu_show_icons)
895 g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
899 while ((node = obt_xml_find_node(node, "file"))) {
900 gchar *c = obt_xml_node_string(node);
901 config_menu_files = g_slist_append(config_menu_files,
902 obt_paths_expand_tilde(c));
908 static void parse_resistance(xmlNodePtr node, gpointer d)
912 node = node->children;
913 if ((n = obt_xml_find_node(node, "strength")))
914 config_resist_win = obt_xml_node_int(n);
915 if ((n = obt_xml_find_node(node, "screen_edge_strength")))
916 config_resist_edge = obt_xml_node_int(n);
922 const gchar *actname;
925 static void bind_default_keyboard(void)
928 ObDefKeyBind binds[] = {
929 { "A-Tab", "NextWindow" },
930 { "S-A-Tab", "PreviousWindow" },
934 for (it = binds; it->key; ++it) {
935 GList *l = g_list_append(NULL, g_strdup(it->key));
936 keyboard_bind(l, actions_parse_string(it->actname));
943 const gchar *context;
944 const ObMouseAction mact;
945 const gchar *actname;
948 static void bind_default_mouse(void)
951 ObDefMouseBind binds[] = {
952 { "Left", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
953 { "Middle", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
954 { "Right", "Client", OB_MOUSE_ACTION_PRESS, "Focus" },
955 { "Left", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
956 { "Middle", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
957 { "Right", "Desktop", OB_MOUSE_ACTION_PRESS, "Focus" },
958 { "Left", "Titlebar", OB_MOUSE_ACTION_PRESS, "Focus" },
959 { "Left", "Bottom", OB_MOUSE_ACTION_PRESS, "Focus" },
960 { "Left", "BLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
961 { "Left", "BRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
962 { "Left", "TLCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
963 { "Left", "TRCorner", OB_MOUSE_ACTION_PRESS, "Focus" },
964 { "Left", "Close", OB_MOUSE_ACTION_PRESS, "Focus" },
965 { "Left", "Maximize", OB_MOUSE_ACTION_PRESS, "Focus" },
966 { "Left", "Iconify", OB_MOUSE_ACTION_PRESS, "Focus" },
967 { "Left", "Icon", OB_MOUSE_ACTION_PRESS, "Focus" },
968 { "Left", "AllDesktops", OB_MOUSE_ACTION_PRESS, "Focus" },
969 { "Left", "Shade", OB_MOUSE_ACTION_PRESS, "Focus" },
970 { "Left", "Client", OB_MOUSE_ACTION_CLICK, "Raise" },
971 { "Left", "Titlebar", OB_MOUSE_ACTION_CLICK, "Raise" },
972 { "Middle", "Titlebar", OB_MOUSE_ACTION_CLICK, "Lower" },
973 { "Left", "BLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
974 { "Left", "BRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
975 { "Left", "TLCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
976 { "Left", "TRCorner", OB_MOUSE_ACTION_CLICK, "Raise" },
977 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Raise" },
978 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "Raise" },
979 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Raise" },
980 { "Left", "Icon", OB_MOUSE_ACTION_CLICK, "Raise" },
981 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "Raise" },
982 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "Raise" },
983 { "Left", "Close", OB_MOUSE_ACTION_CLICK, "Close" },
984 { "Left", "Maximize", OB_MOUSE_ACTION_CLICK, "ToggleMaximize" },
985 { "Left", "Iconify", OB_MOUSE_ACTION_CLICK, "Iconify" },
986 { "Left", "AllDesktops", OB_MOUSE_ACTION_CLICK, "ToggleOmnipresent" },
987 { "Left", "Shade", OB_MOUSE_ACTION_CLICK, "ToggleShade" },
988 { "Left", "TLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
989 { "Left", "TRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
990 { "Left", "BLCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
991 { "Left", "BRCorner", OB_MOUSE_ACTION_MOTION, "Resize" },
992 { "Left", "Top", OB_MOUSE_ACTION_MOTION, "Resize" },
993 { "Left", "Bottom", OB_MOUSE_ACTION_MOTION, "Resize" },
994 { "Left", "Left", OB_MOUSE_ACTION_MOTION, "Resize" },
995 { "Left", "Right", OB_MOUSE_ACTION_MOTION, "Resize" },
996 { "Left", "Titlebar", OB_MOUSE_ACTION_MOTION, "Move" },
997 { "A-Left", "Frame", OB_MOUSE_ACTION_MOTION, "Move" },
998 { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" },
999 { NULL, NULL, 0, NULL }
1002 for (it = binds; it->button; ++it)
1003 mouse_bind(it->button, frame_context_from_string(it->context),
1004 it->mact, actions_parse_string(it->actname));
1007 void config_startup(ObtXmlInst *i)
1009 config_focus_new = TRUE;
1010 config_focus_follow = FALSE;
1011 config_focus_delay = 0;
1012 config_focus_raise = FALSE;
1013 config_focus_last = TRUE;
1014 config_focus_under_mouse = FALSE;
1015 config_unfocus_leave = FALSE;
1017 obt_xml_register(i, "focus", parse_focus, NULL);
1019 config_place_policy = OB_PLACE_POLICY_SMART;
1020 config_place_center = TRUE;
1021 config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
1023 config_primary_monitor_index = 1;
1024 config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
1026 obt_xml_register(i, "placement", parse_placement, NULL);
1028 STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1030 obt_xml_register(i, "margins", parse_margins, NULL);
1032 config_theme = NULL;
1034 config_animate_iconify = TRUE;
1035 config_title_layout = g_strdup("NLIMC");
1036 config_theme_keepborder = TRUE;
1037 config_theme_window_list_icon_size = 36;
1039 config_font_activewindow = NULL;
1040 config_font_inactivewindow = NULL;
1041 config_font_menuitem = NULL;
1042 config_font_menutitle = NULL;
1043 config_font_activeosd = NULL;
1044 config_font_inactiveosd = NULL;
1046 obt_xml_register(i, "theme", parse_theme, NULL);
1048 config_desktops_num = 4;
1049 config_screen_firstdesk = 1;
1050 config_desktops_names = NULL;
1051 config_desktop_popup_time = 875;
1053 obt_xml_register(i, "desktops", parse_desktops, NULL);
1055 config_resize_redraw = TRUE;
1056 config_resize_popup_show = 1; /* nonpixel increments */
1057 config_resize_popup_pos = OB_RESIZE_POS_CENTER;
1058 GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
1059 GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
1061 obt_xml_register(i, "resize", parse_resize, NULL);
1063 config_dock_layer = OB_STACKING_LAYER_ABOVE;
1064 config_dock_pos = OB_DIRECTION_NORTHEAST;
1065 config_dock_floating = FALSE;
1066 config_dock_nostrut = FALSE;
1069 config_dock_orient = OB_ORIENTATION_VERT;
1070 config_dock_hide = FALSE;
1071 config_dock_hide_delay = 300;
1072 config_dock_show_delay = 300;
1073 config_dock_app_move_button = 2; /* middle */
1074 config_dock_app_move_modifiers = 0;
1076 obt_xml_register(i, "dock", parse_dock, NULL);
1078 translate_key("C-g", &config_keyboard_reset_state,
1079 &config_keyboard_reset_keycode);
1081 bind_default_keyboard();
1083 obt_xml_register(i, "keyboard", parse_keyboard, NULL);
1085 config_mouse_threshold = 8;
1086 config_mouse_dclicktime = 500;
1087 config_mouse_screenedgetime = 400;
1088 config_mouse_screenedgewarp = FALSE;
1090 bind_default_mouse();
1092 obt_xml_register(i, "mouse", parse_mouse, NULL);
1094 config_resist_win = 10;
1095 config_resist_edge = 20;
1097 obt_xml_register(i, "resistance", parse_resistance, NULL);
1099 config_menu_hide_delay = 250;
1100 config_menu_middle = FALSE;
1101 config_submenu_show_delay = 100;
1102 config_submenu_hide_delay = 400;
1103 config_menu_manage_desktops = TRUE;
1104 config_menu_files = NULL;
1105 config_menu_show_icons = TRUE;
1107 obt_xml_register(i, "menu", parse_menu, NULL);
1109 config_per_app_settings = NULL;
1111 obt_xml_register(i, "applications", parse_per_app_settings, NULL);
1114 void config_shutdown(void)
1118 g_free(config_theme);
1120 g_free(config_title_layout);
1122 RrFontClose(config_font_activewindow);
1123 RrFontClose(config_font_inactivewindow);
1124 RrFontClose(config_font_menuitem);
1125 RrFontClose(config_font_menutitle);
1126 RrFontClose(config_font_activeosd);
1127 RrFontClose(config_font_inactiveosd);
1129 for (it = config_desktops_names; it; it = g_slist_next(it))
1131 g_slist_free(config_desktops_names);
1133 for (it = config_menu_files; it; it = g_slist_next(it))
1135 g_slist_free(config_menu_files);
1137 for (it = config_per_app_settings; it; it = g_slist_next(it)) {
1138 ObAppSettings *itd = (ObAppSettings *)it->data;
1139 if (itd->name) g_pattern_spec_free(itd->name);
1140 if (itd->role) g_pattern_spec_free(itd->role);
1141 if (itd->title) g_pattern_spec_free(itd->title);
1142 if (itd->class) g_pattern_spec_free(itd->class);
1143 g_slice_free(ObAppSettings, it->data);
1145 g_slist_free(config_per_app_settings);