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